Skip to content

Commit 6b1058c

Browse files
committed
Add Iterator for KeyExpr
1 parent af960e9 commit 6b1058c

File tree

1 file changed

+49
-0
lines changed

1 file changed

+49
-0
lines changed

src/miniscript/musig_key.rs

+49
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,35 @@ impl<Pk: MiniscriptKey + FromStr> FromStr for KeyExpr<Pk> {
4040
}
4141
}
4242

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+
4372
impl<Pk: MiniscriptKey> fmt::Debug for KeyExpr<Pk> {
4473
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4574
match *self {
@@ -79,6 +108,14 @@ impl<Pk: MiniscriptKey> fmt::Display for KeyExpr<Pk> {
79108
}
80109
}
81110
}
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+
82119
#[cfg(test)]
83120
mod tests {
84121
use super::*;
@@ -97,4 +134,16 @@ mod tests {
97134
test_one("A");
98135
test_one("musig(,,)");
99136
}
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+
}
100149
}

0 commit comments

Comments
 (0)