|
7 | 7 | //! encoding in Bitcoin script, as well as a datatype. Full details
|
8 | 8 | //! are given on the Miniscript website.
|
9 | 9 |
|
10 |
| -use core::fmt; |
| 10 | +use core::fmt::{self, Write}; |
11 | 11 | use core::str::FromStr;
|
12 | 12 |
|
13 | 13 | use bitcoin::hashes::{hash160, Hash};
|
@@ -41,6 +41,25 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
|
41 | 41 | _ => None,
|
42 | 42 | }
|
43 | 43 | }
|
| 44 | + |
| 45 | + fn conditional_fmt(&self, f: &mut fmt::Formatter, is_debug: bool)-> fmt::Result { |
| 46 | + match *self { |
| 47 | + Terminal::PkK(ref pk) => { |
| 48 | + f.write_str("pk_k(")?; |
| 49 | + conditional_fmt(f, pk, is_debug)?; |
| 50 | + f.write_char(')') |
| 51 | + } |
| 52 | + _ => todo!() |
| 53 | + } |
| 54 | + } |
| 55 | +} |
| 56 | + |
| 57 | +fn conditional_fmt<D: fmt::Debug + fmt::Display>(f: &mut fmt::Formatter, data: &D, is_debug: bool) -> fmt::Result { |
| 58 | + if is_debug { |
| 59 | + fmt::Debug::fmt(data, f) |
| 60 | + } else { |
| 61 | + fmt::Display::fmt(data, f) |
| 62 | + } |
44 | 63 | }
|
45 | 64 |
|
46 | 65 | impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Debug for Terminal<Pk, Ctx> {
|
@@ -89,154 +108,14 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Debug for Terminal<Pk, Ctx> {
|
89 | 108 | }
|
90 | 109 | write!(f, "{:?}", sub)
|
91 | 110 | } else {
|
92 |
| - match *self { |
93 |
| - Terminal::PkK(ref pk) => write!(f, "pk_k({:?})", pk), |
94 |
| - Terminal::PkH(ref pk) => write!(f, "pk_h({:?})", pk), |
95 |
| - Terminal::RawPkH(ref pkh) => write!(f, "expr_raw_pk_h({:?})", pkh), |
96 |
| - Terminal::After(t) => write!(f, "after({})", t), |
97 |
| - Terminal::Older(t) => write!(f, "older({})", t), |
98 |
| - Terminal::Sha256(ref h) => write!(f, "sha256({})", h), |
99 |
| - Terminal::Hash256(ref h) => write!(f, "hash256({})", h), |
100 |
| - Terminal::Ripemd160(ref h) => write!(f, "ripemd160({})", h), |
101 |
| - Terminal::Hash160(ref h) => write!(f, "hash160({})", h), |
102 |
| - Terminal::True => f.write_str("1"), |
103 |
| - Terminal::False => f.write_str("0"), |
104 |
| - Terminal::AndV(ref l, ref r) => write!(f, "and_v({:?},{:?})", l, r), |
105 |
| - Terminal::AndB(ref l, ref r) => write!(f, "and_b({:?},{:?})", l, r), |
106 |
| - Terminal::AndOr(ref a, ref b, ref c) => { |
107 |
| - if c.node == Terminal::False { |
108 |
| - write!(f, "and_n({:?},{:?})", a, b) |
109 |
| - } else { |
110 |
| - write!(f, "andor({:?},{:?},{:?})", a, b, c) |
111 |
| - } |
112 |
| - } |
113 |
| - Terminal::OrB(ref l, ref r) => write!(f, "or_b({:?},{:?})", l, r), |
114 |
| - Terminal::OrD(ref l, ref r) => write!(f, "or_d({:?},{:?})", l, r), |
115 |
| - Terminal::OrC(ref l, ref r) => write!(f, "or_c({:?},{:?})", l, r), |
116 |
| - Terminal::OrI(ref l, ref r) => write!(f, "or_i({:?},{:?})", l, r), |
117 |
| - Terminal::Thresh(k, ref subs) => { |
118 |
| - write!(f, "thresh({}", k)?; |
119 |
| - for s in subs { |
120 |
| - write!(f, ",{:?}", s)?; |
121 |
| - } |
122 |
| - f.write_str(")") |
123 |
| - } |
124 |
| - Terminal::Multi(k, ref keys) => { |
125 |
| - write!(f, "multi({}", k)?; |
126 |
| - for k in keys { |
127 |
| - write!(f, ",{:?}", k)?; |
128 |
| - } |
129 |
| - f.write_str(")") |
130 |
| - } |
131 |
| - Terminal::MultiA(k, ref keys) => { |
132 |
| - write!(f, "multi_a({}", k)?; |
133 |
| - for k in keys { |
134 |
| - write!(f, ",{}", k)?; |
135 |
| - } |
136 |
| - f.write_str(")") |
137 |
| - } |
138 |
| - _ => unreachable!(), |
139 |
| - } |
| 111 | + self.conditional_fmt(f, true) |
140 | 112 | }
|
141 | 113 | }
|
142 | 114 | }
|
143 | 115 |
|
144 | 116 | impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Display for Terminal<Pk, Ctx> {
|
145 | 117 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
146 |
| - match *self { |
147 |
| - Terminal::PkK(ref pk) => write!(f, "pk_k({})", pk), |
148 |
| - Terminal::PkH(ref pk) => write!(f, "pk_h({})", pk), |
149 |
| - Terminal::RawPkH(ref pkh) => write!(f, "expr_raw_pk_h({})", pkh), |
150 |
| - Terminal::After(t) => write!(f, "after({})", t), |
151 |
| - Terminal::Older(t) => write!(f, "older({})", t), |
152 |
| - Terminal::Sha256(ref h) => write!(f, "sha256({})", h), |
153 |
| - Terminal::Hash256(ref h) => write!(f, "hash256({})", h), |
154 |
| - Terminal::Ripemd160(ref h) => write!(f, "ripemd160({})", h), |
155 |
| - Terminal::Hash160(ref h) => write!(f, "hash160({})", h), |
156 |
| - Terminal::True => f.write_str("1"), |
157 |
| - Terminal::False => f.write_str("0"), |
158 |
| - Terminal::AndV(ref l, ref r) if r.node != Terminal::True => { |
159 |
| - write!(f, "and_v({},{})", l, r) |
160 |
| - } |
161 |
| - Terminal::AndB(ref l, ref r) => write!(f, "and_b({},{})", l, r), |
162 |
| - Terminal::AndOr(ref a, ref b, ref c) => { |
163 |
| - if c.node == Terminal::False { |
164 |
| - write!(f, "and_n({},{})", a, b) |
165 |
| - } else { |
166 |
| - write!(f, "andor({},{},{})", a, b, c) |
167 |
| - } |
168 |
| - } |
169 |
| - Terminal::OrB(ref l, ref r) => write!(f, "or_b({},{})", l, r), |
170 |
| - Terminal::OrD(ref l, ref r) => write!(f, "or_d({},{})", l, r), |
171 |
| - Terminal::OrC(ref l, ref r) => write!(f, "or_c({},{})", l, r), |
172 |
| - Terminal::OrI(ref l, ref r) |
173 |
| - if l.node != Terminal::False && r.node != Terminal::False => |
174 |
| - { |
175 |
| - write!(f, "or_i({},{})", l, r) |
176 |
| - } |
177 |
| - Terminal::Thresh(k, ref subs) => { |
178 |
| - write!(f, "thresh({}", k)?; |
179 |
| - for s in subs { |
180 |
| - write!(f, ",{}", s)?; |
181 |
| - } |
182 |
| - f.write_str(")") |
183 |
| - } |
184 |
| - Terminal::Multi(k, ref keys) => { |
185 |
| - write!(f, "multi({}", k)?; |
186 |
| - for k in keys { |
187 |
| - write!(f, ",{}", k)?; |
188 |
| - } |
189 |
| - f.write_str(")") |
190 |
| - } |
191 |
| - Terminal::MultiA(k, ref keys) => { |
192 |
| - write!(f, "multi_a({}", k)?; |
193 |
| - for k in keys { |
194 |
| - write!(f, ",{}", k)?; |
195 |
| - } |
196 |
| - f.write_str(")") |
197 |
| - } |
198 |
| - // wrappers |
199 |
| - _ => { |
200 |
| - if let Some((ch, sub)) = self.wrap_char() { |
201 |
| - if ch == 'c' { |
202 |
| - if let Terminal::PkK(ref pk) = sub.node { |
203 |
| - // alias: pk(K) = c:pk_k(K) |
204 |
| - return write!(f, "pk({})", pk); |
205 |
| - } else if let Terminal::RawPkH(ref pkh) = sub.node { |
206 |
| - // `RawPkH` is currently unsupported in the descriptor spec |
207 |
| - // alias: pkh(K) = c:pk_h(K) |
208 |
| - // We temporarily display there using raw_pkh, but these descriptors |
209 |
| - // are not defined in the spec yet. These are prefixed with `expr` |
210 |
| - // in the descriptor string. |
211 |
| - // We do not support parsing these descriptors yet. |
212 |
| - return write!(f, "expr_raw_pkh({})", pkh); |
213 |
| - } else if let Terminal::PkH(ref pk) = sub.node { |
214 |
| - // alias: pkh(K) = c:pk_h(K) |
215 |
| - return write!(f, "pkh({})", pk); |
216 |
| - } |
217 |
| - } |
218 |
| - |
219 |
| - fmt::Write::write_char(f, ch)?; |
220 |
| - match sub.node.wrap_char() { |
221 |
| - None => { |
222 |
| - fmt::Write::write_char(f, ':')?; |
223 |
| - } |
224 |
| - // Add a ':' wrapper if there are other wrappers apart from c:pk_k() |
225 |
| - // tvc:pk_k() -> tv:pk() |
226 |
| - Some(('c', ms)) => match ms.node { |
227 |
| - Terminal::PkK(_) | Terminal::PkH(_) | Terminal::RawPkH(_) => { |
228 |
| - fmt::Write::write_char(f, ':')? |
229 |
| - } |
230 |
| - _ => {} |
231 |
| - }, |
232 |
| - _ => {} |
233 |
| - }; |
234 |
| - write!(f, "{}", sub) |
235 |
| - } else { |
236 |
| - unreachable!(); |
237 |
| - } |
238 |
| - } |
239 |
| - } |
| 118 | + self.conditional_fmt(f, false) |
240 | 119 | }
|
241 | 120 | }
|
242 | 121 |
|
|
0 commit comments