@@ -40,6 +40,35 @@ impl<Pk: MiniscriptKey + FromStr> FromStr for KeyExpr<Pk> {
40
40
}
41
41
}
42
42
43
+ #[ derive( Debug , Clone ) ]
44
+ /// Iterator for keyexpr
45
+ pub struct KeyExprIter < ' a , Pk : MiniscriptKey > {
46
+ stack : Vec < & ' a KeyExpr < Pk > > ,
47
+ }
48
+
49
+ impl < ' a , Pk > Iterator for KeyExprIter < ' a , Pk >
50
+ where
51
+ Pk : MiniscriptKey + ' a ,
52
+ {
53
+ type Item = & ' a Pk ;
54
+
55
+ fn next ( & mut self ) -> Option < Self :: Item > {
56
+ while !self . stack . is_empty ( ) {
57
+ let last = self . stack . pop ( ) . expect ( "Size checked above" ) ;
58
+ match & * last {
59
+ KeyExpr :: MuSig ( key_vec) => {
60
+ // push the elements in reverse order
61
+ for key in key_vec. iter ( ) . rev ( ) {
62
+ self . stack . push ( key)
63
+ }
64
+ }
65
+ KeyExpr :: SingleKey ( ref pk) => return Some ( pk) ,
66
+ }
67
+ }
68
+ None
69
+ }
70
+ }
71
+
43
72
impl < Pk : MiniscriptKey > fmt:: Debug for KeyExpr < Pk > {
44
73
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
45
74
match * self {
@@ -79,6 +108,14 @@ impl<Pk: MiniscriptKey> fmt::Display for KeyExpr<Pk> {
79
108
}
80
109
}
81
110
}
111
+
112
+ impl < Pk : MiniscriptKey > KeyExpr < Pk > {
113
+ /// Iterate over all keys
114
+ pub fn iter ( & self ) -> KeyExprIter < Pk > {
115
+ KeyExprIter { stack : vec ! [ self ] }
116
+ }
117
+ }
118
+
82
119
#[ cfg( test) ]
83
120
mod tests {
84
121
use super :: * ;
@@ -97,4 +134,33 @@ mod tests {
97
134
test_one ( "A" ) ;
98
135
test_one ( "musig(,,)" ) ;
99
136
}
137
+
138
+ #[ test]
139
+ fn test_iterator ( ) {
140
+ let pk = KeyExpr :: < String > :: from_str ( "musig(A,B,musig(C,musig(D,E)))" ) . unwrap ( ) ;
141
+ let mut my_iter = pk. iter ( ) ;
142
+ assert_eq ! ( my_iter. next( ) , Some ( & String :: from( "A" ) ) ) ;
143
+ assert_eq ! ( my_iter. next( ) , Some ( & String :: from( "B" ) ) ) ;
144
+ assert_eq ! ( my_iter. next( ) , Some ( & String :: from( "C" ) ) ) ;
145
+ assert_eq ! ( my_iter. next( ) , Some ( & String :: from( "D" ) ) ) ;
146
+ assert_eq ! ( my_iter. next( ) , Some ( & String :: from( "E" ) ) ) ;
147
+ assert_eq ! ( my_iter. next( ) , None ) ;
148
+ }
149
+
150
+ fn test_helper ( musig_key : & str , comma_separated_key : & str ) {
151
+ let pk = KeyExpr :: < String > :: from_str ( musig_key) . unwrap ( ) ;
152
+ let var: Vec < & str > = comma_separated_key. split ( "," ) . collect ( ) ;
153
+ let key_names: Vec < & String > = pk. iter ( ) . collect ( ) ;
154
+ for ( key1, key2) in key_names. iter ( ) . zip ( var. iter ( ) ) {
155
+ assert_eq ! ( key1, key2) ;
156
+ }
157
+ }
158
+
159
+ #[ test]
160
+ fn test_iterator_multi ( ) {
161
+ test_helper ( "musig(A)" , "A" ) ;
162
+ test_helper ( "A" , "A" ) ;
163
+ test_helper ( "musig(,,)" , "" ) ;
164
+ test_helper ( "musig(musig(A,B),musig(musig(C)))" , "A,B,C" ) ;
165
+ }
100
166
}
0 commit comments