Skip to content

Commit 6b59b91

Browse files
committed
Merge rust-bitcoin/rust-miniscript#651: add conditional formatting for Terminal
395aab8131061f4c24b8d105132ad50e65275189 unify debug/display impl for Terminal (Riccardo Casatta) 752acb378f3c7a6bc9b1f284f7060a1b43d841ab apply immediate dispatch in generic fn (Riccardo Casatta) 426c34d4309e8c7f844958642e651ca68acdb0a8 add conditional formatting for Terminal (Riccardo Casatta) Pull request description: fmt functions produce big binaries. <details> <summary>cargo bloat --release --example big --all-features -n 1000000 --full-fn | grep astelem | grep fmt</summary> 0.0% 0.1% 2.8KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h75ba3ce6da61d374 0.0% 0.1% 2.8KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h6786aa26184b9ff6 0.0% 0.1% 2.8KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h03f9c2155559a440 0.0% 0.1% 2.8KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h00e63af9b88389b4 0.0% 0.1% 2.8KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::hb60190c99fd48d17 0.0% 0.1% 2.8KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::ha9001c527b4cc4d6 0.0% 0.1% 2.8KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::ha726829fe4f3bf2b 0.0% 0.1% 2.8KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h95a7eadaa261d645 0.0% 0.1% 2.8KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h819e09dcb99bbc52 0.0% 0.1% 2.8KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h6ef89d30f9f4cb57 0.0% 0.1% 2.8KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h693edb5e35f9fc08 0.0% 0.1% 2.8KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h27891ccf9609c782 0.0% 0.1% 2.7KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::he0a63893fe76f527 0.0% 0.1% 2.7KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h86eba44cb7298c4f 0.0% 0.1% 2.7KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h37a4628264df8c3b 0.0% 0.1% 2.7KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h2f3a9d297ec35dea 0.0% 0.1% 2.7KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h879ad74922a70f16 0.0% 0.1% 2.7KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h7dc2d9bc27c88fab 0.0% 0.1% 2.7KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h7578352fd420fc88 0.0% 0.1% 2.7KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h1809b9931776159e 0.0% 0.1% 2.7KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::hf7760e0f27d70db4 0.0% 0.1% 2.7KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h9adfe0d7e2bfdd42 0.0% 0.1% 2.7KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h61cdb06e2a061932 0.0% 0.1% 2.7KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h44e1ab5daacde0df 0.0% 0.1% 2.7KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h2646ddd57694241b 0.0% 0.1% 2.7KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::he31fd2e9b12960f9 0.0% 0.1% 2.7KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::hbefb77c4050bd5c9 0.0% 0.1% 2.7KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::hb4deb7ef951af7af 0.0% 0.1% 2.7KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Debug for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h80ee1108b955f2b4 0.0% 0.1% 2.6KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::hc779f37cb81f761a 0.0% 0.1% 2.6KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::hc4ac4a9b598fbdfb 0.0% 0.1% 2.6KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h5cca31d73f30c3c7 0.0% 0.1% 2.6KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h4588410e445d16c6 0.0% 0.1% 2.6KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::heb60f683c9e55e36 0.0% 0.1% 2.6KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::hbe7939a797fcce35 0.0% 0.1% 2.6KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::ha536af3ff4313ed1 0.0% 0.1% 2.6KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h8969ddab726dea7f 0.0% 0.1% 2.6KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h7fca0d80a428dd24 0.0% 0.1% 2.6KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h6b4909db760a4721 0.0% 0.1% 2.6KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h5ed643a399966d49 0.0% 0.1% 2.6KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h1ed7d512c859a5a9 0.0% 0.1% 2.6KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::hfd9775e798913648 0.0% 0.1% 2.6KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::hf87563509ea7253d 0.0% 0.1% 2.6KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::hb8b75c9c988d95c3 0.0% 0.1% 2.6KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h87b650968eb119ba 0.0% 0.1% 2.6KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h9986ae4314d85479 0.0% 0.1% 2.6KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h74343d637646e38a 0.0% 0.1% 2.6KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h680da8fa0ec0142c 0.0% 0.1% 2.6KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h6197658ba03f1fdf 0.0% 0.1% 2.6KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h961e1a4b75732a11 0.0% 0.1% 2.6KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h57b3cd148371177a 0.0% 0.1% 2.6KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h13d43f019a96d314 0.0% 0.1% 2.6KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h008ca416c1ebc0d7 0.0% 0.1% 2.5KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h82a27926db80dc37 0.0% 0.1% 2.5KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::hc12b3098c3979175 0.0% 0.1% 2.5KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h76e624d7abc545ba 0.0% 0.1% 2.5KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h24511846d004e114 0.0% 0.1% 2.5KiB miniscript miniscript::miniscript::astelem::<impl core::fmt::Display for miniscript::miniscript::decode::Terminal<Pk,Ctx>>::fmt::h0d96e9d943f04d7d </details> Since Debug and Display implementations are ~equal except the Debug or Display representation of its child, this introduce conditional fmt trading performance for code size. Since performance shouldn't be that important in string conversion seems an interesting trade-off. This is a PoC since the final impl of `conditional_fmt` is a little tedious, would like a concept ack before proceding ACKs for top commit: apoelstra: ACK 395aab8131061f4c24b8d105132ad50e65275189 Tree-SHA512: 71fbdc55b11d5f5452c810da3934f087ed7d8a26156bfc6e174d29cbf1590dc85e32142dd12c477a2fbe86393429aa55a5b4d7dedbd96f216d083e1614fc1dac
2 parents 25e81f2 + 001b86b commit 6b59b91

File tree

2 files changed

+148
-153
lines changed

2 files changed

+148
-153
lines changed

src/miniscript/astelem.rs

Lines changed: 140 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -42,197 +42,89 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
4242
_ => None,
4343
}
4444
}
45-
}
4645

47-
impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Debug for Terminal<Pk, Ctx> {
48-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
49-
f.write_str("[")?;
50-
if let Ok(type_map) = types::Type::type_check(self) {
51-
f.write_str(match type_map.corr.base {
52-
types::Base::B => "B",
53-
types::Base::K => "K",
54-
types::Base::V => "V",
55-
types::Base::W => "W",
56-
})?;
57-
fmt::Write::write_char(f, '/')?;
58-
f.write_str(match type_map.corr.input {
59-
types::Input::Zero => "z",
60-
types::Input::One => "o",
61-
types::Input::OneNonZero => "on",
62-
types::Input::Any => "",
63-
types::Input::AnyNonZero => "n",
64-
})?;
65-
if type_map.corr.dissatisfiable {
66-
fmt::Write::write_char(f, 'd')?;
67-
}
68-
if type_map.corr.unit {
69-
fmt::Write::write_char(f, 'u')?;
70-
}
71-
f.write_str(match type_map.mall.dissat {
72-
types::Dissat::None => "f",
73-
types::Dissat::Unique => "e",
74-
types::Dissat::Unknown => "",
75-
})?;
76-
if type_map.mall.safe {
77-
fmt::Write::write_char(f, 's')?;
78-
}
79-
if type_map.mall.non_malleable {
80-
fmt::Write::write_char(f, 'm')?;
81-
}
82-
} else {
83-
f.write_str("TYPECHECK FAILED")?;
84-
}
85-
f.write_str("]")?;
86-
if let Some((ch, sub)) = self.wrap_char() {
87-
fmt::Write::write_char(f, ch)?;
88-
if sub.node.wrap_char().is_none() {
89-
fmt::Write::write_char(f, ':')?;
90-
}
91-
write!(f, "{:?}", sub)
92-
} else {
93-
match *self {
94-
Terminal::PkK(ref pk) => write!(f, "pk_k({:?})", pk),
95-
Terminal::PkH(ref pk) => write!(f, "pk_h({:?})", pk),
96-
Terminal::RawPkH(ref pkh) => write!(f, "expr_raw_pk_h({:?})", pkh),
97-
Terminal::After(t) => write!(f, "after({})", t),
98-
Terminal::Older(t) => write!(f, "older({})", t),
99-
Terminal::Sha256(ref h) => write!(f, "sha256({})", h),
100-
Terminal::Hash256(ref h) => write!(f, "hash256({})", h),
101-
Terminal::Ripemd160(ref h) => write!(f, "ripemd160({})", h),
102-
Terminal::Hash160(ref h) => write!(f, "hash160({})", h),
103-
Terminal::True => f.write_str("1"),
104-
Terminal::False => f.write_str("0"),
105-
Terminal::AndV(ref l, ref r) => write!(f, "and_v({:?},{:?})", l, r),
106-
Terminal::AndB(ref l, ref r) => write!(f, "and_b({:?},{:?})", l, r),
107-
Terminal::AndOr(ref a, ref b, ref c) => {
108-
if c.node == Terminal::False {
109-
write!(f, "and_n({:?},{:?})", a, b)
110-
} else {
111-
write!(f, "andor({:?},{:?},{:?})", a, b, c)
112-
}
113-
}
114-
Terminal::OrB(ref l, ref r) => write!(f, "or_b({:?},{:?})", l, r),
115-
Terminal::OrD(ref l, ref r) => write!(f, "or_d({:?},{:?})", l, r),
116-
Terminal::OrC(ref l, ref r) => write!(f, "or_c({:?},{:?})", l, r),
117-
Terminal::OrI(ref l, ref r) => write!(f, "or_i({:?},{:?})", l, r),
118-
Terminal::Thresh(k, ref subs) => {
119-
write!(f, "thresh({}", k)?;
120-
for s in subs {
121-
write!(f, ",{:?}", s)?;
122-
}
123-
f.write_str(")")
124-
}
125-
Terminal::Multi(k, ref keys) => {
126-
write!(f, "multi({}", k)?;
127-
for k in keys {
128-
write!(f, ",{:?}", k)?;
129-
}
130-
f.write_str(")")
131-
}
132-
Terminal::MultiA(k, ref keys) => {
133-
write!(f, "multi_a({}", k)?;
134-
for k in keys {
135-
write!(f, ",{}", k)?;
136-
}
137-
f.write_str(")")
138-
}
139-
_ => unreachable!(),
140-
}
141-
}
142-
}
143-
}
144-
145-
impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Display for Terminal<Pk, Ctx> {
146-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
46+
fn conditional_fmt(&self, f: &mut fmt::Formatter, is_debug: bool) -> fmt::Result {
14747
match *self {
148-
Terminal::PkK(ref pk) => write!(f, "pk_k({})", pk),
149-
Terminal::PkH(ref pk) => write!(f, "pk_h({})", pk),
150-
Terminal::RawPkH(ref pkh) => write!(f, "expr_raw_pk_h({})", pkh),
151-
Terminal::After(t) => write!(f, "after({})", t),
152-
Terminal::Older(t) => write!(f, "older({})", t),
153-
Terminal::Sha256(ref h) => write!(f, "sha256({})", h),
154-
Terminal::Hash256(ref h) => write!(f, "hash256({})", h),
155-
Terminal::Ripemd160(ref h) => write!(f, "ripemd160({})", h),
156-
Terminal::Hash160(ref h) => write!(f, "hash160({})", h),
48+
Terminal::PkK(ref pk) => fmt_1(f, "pk_k(", pk, is_debug),
49+
Terminal::PkH(ref pk) => fmt_1(f, "pk_h(", pk, is_debug),
50+
Terminal::RawPkH(ref pkh) => fmt_1(f, "expr_raw_pk_h(", pkh, is_debug),
51+
Terminal::After(ref t) => fmt_1(f, "after(", t, is_debug),
52+
Terminal::Older(ref t) => fmt_1(f, "older(", t, is_debug),
53+
Terminal::Sha256(ref h) => fmt_1(f, "sha256(", h, is_debug),
54+
Terminal::Hash256(ref h) => fmt_1(f, "hash256(", h, is_debug),
55+
Terminal::Ripemd160(ref h) => fmt_1(f, "ripemd160(", h, is_debug),
56+
Terminal::Hash160(ref h) => fmt_1(f, "hash160(", h, is_debug),
15757
Terminal::True => f.write_str("1"),
15858
Terminal::False => f.write_str("0"),
15959
Terminal::AndV(ref l, ref r) if r.node != Terminal::True => {
160-
write!(f, "and_v({},{})", l, r)
60+
fmt_2(f, "and_v(", l, r, is_debug)
16161
}
162-
Terminal::AndB(ref l, ref r) => write!(f, "and_b({},{})", l, r),
62+
Terminal::AndB(ref l, ref r) => fmt_2(f, "and_b(", l, r, is_debug),
16363
Terminal::AndOr(ref a, ref b, ref c) => {
16464
if c.node == Terminal::False {
165-
write!(f, "and_n({},{})", a, b)
65+
fmt_2(f, "and_b(", a, b, is_debug)
16666
} else {
167-
write!(f, "andor({},{},{})", a, b, c)
67+
f.write_str("andor(")?;
68+
conditional_fmt(f, a, is_debug)?;
69+
f.write_str(",")?;
70+
conditional_fmt(f, b, is_debug)?;
71+
f.write_str(",")?;
72+
conditional_fmt(f, c, is_debug)?;
73+
f.write_str(")")
16874
}
16975
}
170-
Terminal::OrB(ref l, ref r) => write!(f, "or_b({},{})", l, r),
171-
Terminal::OrD(ref l, ref r) => write!(f, "or_d({},{})", l, r),
172-
Terminal::OrC(ref l, ref r) => write!(f, "or_c({},{})", l, r),
76+
Terminal::OrB(ref l, ref r) => fmt_2(f, "or_b(", l, r, is_debug),
77+
Terminal::OrD(ref l, ref r) => fmt_2(f, "or_d(", l, r, is_debug),
78+
Terminal::OrC(ref l, ref r) => fmt_2(f, "or_c(", l, r, is_debug),
17379
Terminal::OrI(ref l, ref r)
17480
if l.node != Terminal::False && r.node != Terminal::False =>
17581
{
176-
write!(f, "or_i({},{})", l, r)
177-
}
178-
Terminal::Thresh(k, ref subs) => {
179-
write!(f, "thresh({}", k)?;
180-
for s in subs {
181-
write!(f, ",{}", s)?;
182-
}
183-
f.write_str(")")
184-
}
185-
Terminal::Multi(k, ref keys) => {
186-
write!(f, "multi({}", k)?;
187-
for k in keys {
188-
write!(f, ",{}", k)?;
189-
}
190-
f.write_str(")")
191-
}
192-
Terminal::MultiA(k, ref keys) => {
193-
write!(f, "multi_a({}", k)?;
194-
for k in keys {
195-
write!(f, ",{}", k)?;
196-
}
197-
f.write_str(")")
82+
fmt_2(f, "or_i(", l, r, is_debug)
19883
}
84+
Terminal::Thresh(k, ref subs) => fmt_n(f, "thresh(", k, subs, is_debug),
85+
Terminal::Multi(k, ref keys) => fmt_n(f, "multi(", k, keys, is_debug),
86+
Terminal::MultiA(k, ref keys) => fmt_n(f, "multi_a(", k, keys, is_debug),
19987
// wrappers
20088
_ => {
20189
if let Some((ch, sub)) = self.wrap_char() {
20290
if ch == 'c' {
20391
if let Terminal::PkK(ref pk) = sub.node {
20492
// alias: pk(K) = c:pk_k(K)
205-
return write!(f, "pk({})", pk);
93+
return fmt_1(f, "pk(", pk, is_debug);
20694
} else if let Terminal::RawPkH(ref pkh) = sub.node {
20795
// `RawPkH` is currently unsupported in the descriptor spec
20896
// alias: pkh(K) = c:pk_h(K)
20997
// We temporarily display there using raw_pkh, but these descriptors
21098
// are not defined in the spec yet. These are prefixed with `expr`
21199
// in the descriptor string.
212100
// We do not support parsing these descriptors yet.
213-
return write!(f, "expr_raw_pkh({})", pkh);
101+
return fmt_1(f, "expr_raw_pkh(", pkh, is_debug);
214102
} else if let Terminal::PkH(ref pk) = sub.node {
215103
// alias: pkh(K) = c:pk_h(K)
216-
return write!(f, "pkh({})", pk);
104+
return fmt_1(f, "pkh(", pk, is_debug);
217105
}
218106
}
219107

220108
fmt::Write::write_char(f, ch)?;
221109
match sub.node.wrap_char() {
222110
None => {
223-
fmt::Write::write_char(f, ':')?;
111+
f.write_str(":")?;
224112
}
225113
// Add a ':' wrapper if there are other wrappers apart from c:pk_k()
226114
// tvc:pk_k() -> tv:pk()
227115
Some(('c', ms)) => match ms.node {
228116
Terminal::PkK(_) | Terminal::PkH(_) | Terminal::RawPkH(_) => {
229-
fmt::Write::write_char(f, ':')?
117+
f.write_str(":")?;
230118
}
231119
_ => {}
232120
},
233121
_ => {}
234122
};
235-
write!(f, "{}", sub)
123+
if is_debug {
124+
write!(f, "{:?}", sub)
125+
} else {
126+
write!(f, "{}", sub)
127+
}
236128
} else {
237129
unreachable!();
238130
}
@@ -241,6 +133,109 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Display for Terminal<Pk, Ctx> {
241133
}
242134
}
243135

136+
fn fmt_1<D: fmt::Debug + fmt::Display>(
137+
f: &mut fmt::Formatter,
138+
name: &str,
139+
a: &D,
140+
is_debug: bool,
141+
) -> fmt::Result {
142+
f.write_str(&name)?;
143+
conditional_fmt(f, a, is_debug)?;
144+
f.write_str(")")
145+
}
146+
fn fmt_2<D: fmt::Debug + fmt::Display>(
147+
f: &mut fmt::Formatter,
148+
name: &str,
149+
a: &D,
150+
b: &D,
151+
is_debug: bool,
152+
) -> fmt::Result {
153+
f.write_str(&name)?;
154+
conditional_fmt(f, a, is_debug)?;
155+
f.write_str(",")?;
156+
conditional_fmt(f, b, is_debug)?;
157+
f.write_str(")")
158+
}
159+
fn fmt_n<D: fmt::Debug + fmt::Display>(
160+
f: &mut fmt::Formatter,
161+
name: &str,
162+
first: usize,
163+
list: &[D],
164+
is_debug: bool,
165+
) -> fmt::Result {
166+
f.write_str(&name)?;
167+
write!(f, "{}", first)?;
168+
for el in list {
169+
f.write_str(",")?;
170+
conditional_fmt(f, el, is_debug)?;
171+
}
172+
f.write_str(")")
173+
}
174+
fn conditional_fmt<D: fmt::Debug + fmt::Display>(
175+
f: &mut fmt::Formatter,
176+
data: &D,
177+
is_debug: bool,
178+
) -> fmt::Result {
179+
if is_debug {
180+
fmt::Debug::fmt(data, f)
181+
} else {
182+
fmt::Display::fmt(data, f)
183+
}
184+
}
185+
186+
impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Debug for Terminal<Pk, Ctx> {
187+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
188+
fn fmt_type_map(f: &mut fmt::Formatter<'_>, type_map: types::Type) -> fmt::Result {
189+
f.write_str(match type_map.corr.base {
190+
types::Base::B => "B",
191+
types::Base::K => "K",
192+
types::Base::V => "V",
193+
types::Base::W => "W",
194+
})?;
195+
f.write_str("/")?;
196+
f.write_str(match type_map.corr.input {
197+
types::Input::Zero => "z",
198+
types::Input::One => "o",
199+
types::Input::OneNonZero => "on",
200+
types::Input::Any => "",
201+
types::Input::AnyNonZero => "n",
202+
})?;
203+
if type_map.corr.dissatisfiable {
204+
f.write_str("d")?;
205+
}
206+
if type_map.corr.unit {
207+
f.write_str("u")?;
208+
}
209+
f.write_str(match type_map.mall.dissat {
210+
types::Dissat::None => "f",
211+
types::Dissat::Unique => "e",
212+
types::Dissat::Unknown => "",
213+
})?;
214+
if type_map.mall.safe {
215+
f.write_str("s")?;
216+
}
217+
if type_map.mall.non_malleable {
218+
f.write_str("m")?;
219+
}
220+
Ok(())
221+
}
222+
223+
f.write_str("[")?;
224+
if let Ok(type_map) = types::Type::type_check(self) {
225+
fmt_type_map(f, type_map)?;
226+
} else {
227+
f.write_str("TYPECHECK FAILED")?;
228+
}
229+
f.write_str("]")?;
230+
231+
self.conditional_fmt(f, true)
232+
}
233+
}
234+
235+
impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Display for Terminal<Pk, Ctx> {
236+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.conditional_fmt(f, false) }
237+
}
238+
244239
impl<Pk: FromStrKey, Ctx: ScriptContext> crate::expression::FromTree for Arc<Terminal<Pk, Ctx>> {
245240
fn from_tree(top: &expression::Tree) -> Result<Arc<Terminal<Pk, Ctx>>, Error> {
246241
Ok(Arc::new(expression::FromTree::from_tree(top)?))

0 commit comments

Comments
 (0)