Skip to main content

miniscript/iter/
mod.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! Abstract Tree Iteration
4//!
5//! This module provides functionality to treat Miniscript objects abstractly
6//! as trees, iterating over them in various orders. The iterators in this
7//! module can be used to avoid explicitly recursive algorithms.
8//!
9
10mod tree;
11
12pub use tree::{
13    PostOrderIter, PostOrderIterItem, PreOrderIter, PreOrderIterItem, Tree, TreeLike,
14    VerbosePreOrderIter,
15};
16
17use crate::sync::Arc;
18use crate::{Miniscript, MiniscriptKey, ScriptContext, Terminal};
19
20impl<'a, Pk: MiniscriptKey, Ctx: ScriptContext> TreeLike for &'a Miniscript<Pk, Ctx> {
21    type NaryChildren = &'a [Arc<Miniscript<Pk, Ctx>>];
22
23    fn nary_len(tc: &Self::NaryChildren) -> usize { tc.len() }
24    fn nary_index(tc: Self::NaryChildren, idx: usize) -> Self { Arc::as_ref(&tc[idx]) }
25
26    fn as_node(&self) -> Tree<Self, Self::NaryChildren> {
27        use Terminal::*;
28        match self.node {
29            PkK(..) | PkH(..) | RawPkH(..) | After(..) | Older(..) | Sha256(..) | Hash256(..)
30            | Ripemd160(..) | Hash160(..) | True | False | Multi(..) | MultiA(..) => Tree::Nullary,
31            Alt(ref sub)
32            | Swap(ref sub)
33            | Check(ref sub)
34            | DupIf(ref sub)
35            | Verify(ref sub)
36            | NonZero(ref sub)
37            | ZeroNotEqual(ref sub) => Tree::Unary(sub),
38            AndV(ref left, ref right)
39            | AndB(ref left, ref right)
40            | OrB(ref left, ref right)
41            | OrD(ref left, ref right)
42            | OrC(ref left, ref right)
43            | OrI(ref left, ref right) => Tree::Binary(left, right),
44            AndOr(ref a, ref b, ref c) => Tree::Ternary(a, b, c),
45            Thresh(ref thresh) => Tree::Nary(thresh.data()),
46        }
47    }
48}
49
50impl<'a, Pk: MiniscriptKey, Ctx: ScriptContext> TreeLike for &'a Arc<Miniscript<Pk, Ctx>> {
51    type NaryChildren = &'a [Arc<Miniscript<Pk, Ctx>>];
52
53    fn nary_len(tc: &Self::NaryChildren) -> usize { tc.len() }
54    fn nary_index(tc: Self::NaryChildren, idx: usize) -> Self { &tc[idx] }
55
56    fn as_node(&self) -> Tree<Self, Self::NaryChildren> {
57        use Terminal::*;
58        match self.node {
59            PkK(..) | PkH(..) | RawPkH(..) | After(..) | Older(..) | Sha256(..) | Hash256(..)
60            | Ripemd160(..) | Hash160(..) | True | False | Multi(..) | MultiA(..) => Tree::Nullary,
61            Alt(ref sub)
62            | Swap(ref sub)
63            | Check(ref sub)
64            | DupIf(ref sub)
65            | Verify(ref sub)
66            | NonZero(ref sub)
67            | ZeroNotEqual(ref sub) => Tree::Unary(sub),
68            AndV(ref left, ref right)
69            | AndB(ref left, ref right)
70            | OrB(ref left, ref right)
71            | OrD(ref left, ref right)
72            | OrC(ref left, ref right)
73            | OrI(ref left, ref right) => Tree::Binary(left, right),
74            AndOr(ref a, ref b, ref c) => Tree::Ternary(a, b, c),
75            Thresh(ref thresh) => Tree::Nary(thresh.data()),
76        }
77    }
78}
79
80impl<'a, Pk: MiniscriptKey, Ctx: ScriptContext> TreeLike for &'a Terminal<Pk, Ctx> {
81    type NaryChildren = &'a [Arc<Miniscript<Pk, Ctx>>];
82
83    fn nary_len(tc: &Self::NaryChildren) -> usize { tc.len() }
84    fn nary_index(tc: Self::NaryChildren, idx: usize) -> Self { tc[idx].as_inner() }
85
86    fn as_node(&self) -> Tree<Self, Self::NaryChildren> {
87        use Terminal::*;
88        match self {
89            PkK(..) | PkH(..) | RawPkH(..) | After(..) | Older(..) | Sha256(..) | Hash256(..)
90            | Ripemd160(..) | Hash160(..) | True | False | Multi(..) | MultiA(..) => Tree::Nullary,
91            Alt(ref sub)
92            | Swap(ref sub)
93            | Check(ref sub)
94            | DupIf(ref sub)
95            | Verify(ref sub)
96            | NonZero(ref sub)
97            | ZeroNotEqual(ref sub) => Tree::Unary(sub.as_inner()),
98            AndV(ref left, ref right)
99            | AndB(ref left, ref right)
100            | OrB(ref left, ref right)
101            | OrD(ref left, ref right)
102            | OrC(ref left, ref right)
103            | OrI(ref left, ref right) => Tree::Binary(left.as_inner(), right.as_inner()),
104            AndOr(ref a, ref b, ref c) => Tree::Ternary(a.as_inner(), b.as_inner(), c.as_inner()),
105            Thresh(ref thresh) => Tree::Nary(thresh.data()),
106        }
107    }
108}