diff --git a/src/descriptor/bare.rs b/src/descriptor/bare.rs index 2279d6d7f..2224e129e 100644 --- a/src/descriptor/bare.rs +++ b/src/descriptor/bare.rs @@ -63,6 +63,15 @@ impl Bare { } } +impl<'a, Pk: MiniscriptKey> IntoIterator for &'a Bare { + type Item = ForEach<'a, Pk>; + type IntoIter = Box> + 'a>; + + fn into_iter(self) -> Self::IntoIter { + self.ms.into_iter() + } +} + impl fmt::Debug for Bare { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:?}", self.ms) @@ -227,6 +236,15 @@ impl Pkh { } } +impl<'a, Pk: MiniscriptKey> IntoIterator for &'a Pkh { + type Item = ForEach<'a, Pk>; + type IntoIter = Box> + 'a>; + + fn into_iter(self) -> Self::IntoIter { + Box::new(::std::iter::once(ForEach::Key(&self.pk))) + } +} + impl fmt::Debug for Pkh { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "pkh({:?})", self.pk) diff --git a/src/descriptor/mod.rs b/src/descriptor/mod.rs index fa2b1eeda..7c51036cb 100644 --- a/src/descriptor/mod.rs +++ b/src/descriptor/mod.rs @@ -300,6 +300,21 @@ impl Descriptor { } } +impl<'a, Pk: MiniscriptKey> IntoIterator for &'a Descriptor { + type Item = ForEach<'a, Pk>; + type IntoIter = Box> + 'a>; + + fn into_iter(self) -> Self::IntoIter { + match *self { + Descriptor::Bare(ref bare) => bare.into_iter(), + Descriptor::Pkh(ref pk) => pk.into_iter(), + Descriptor::Wpkh(ref pk) => pk.into_iter(), + Descriptor::Sh(ref sh) => sh.into_iter(), + Descriptor::Wsh(ref wsh) => wsh.into_iter(), + } + } +} + impl TranslatePk for Descriptor

{ type Output = Descriptor; /// Convert a descriptor using abstract keys to one using specific keys diff --git a/src/descriptor/segwitv0.rs b/src/descriptor/segwitv0.rs index d5b47ce3d..6fc50cc08 100644 --- a/src/descriptor/segwitv0.rs +++ b/src/descriptor/segwitv0.rs @@ -78,6 +78,18 @@ impl Wsh { } } +impl<'a, Pk: MiniscriptKey> IntoIterator for &'a Wsh { + type Item = ForEach<'a, Pk>; + type IntoIter = Box> + 'a>; + + fn into_iter(self) -> Self::IntoIter { + match self.inner { + WshInner::SortedMulti(ref sm) => sm.into_iter(), + WshInner::Ms(ref ms) => ms.into_iter(), + } + } +} + /// Wsh Inner #[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] pub enum WshInner { @@ -315,6 +327,15 @@ impl Wpkh { } } +impl<'a, Pk: MiniscriptKey> IntoIterator for &'a Wpkh { + type Item = ForEach<'a, Pk>; + type IntoIter = Box> + 'a>; + + fn into_iter(self) -> Self::IntoIter { + Box::new(::std::iter::once(ForEach::Key(&self.pk))) + } +} + impl fmt::Debug for Wpkh { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "wpkh({:?})", self.pk) diff --git a/src/descriptor/sh.rs b/src/descriptor/sh.rs index ce382d96f..e6faf4d2e 100644 --- a/src/descriptor/sh.rs +++ b/src/descriptor/sh.rs @@ -193,6 +193,20 @@ impl Sh { } } +impl<'a, Pk: MiniscriptKey> IntoIterator for &'a Sh { + type Item = ForEach<'a, Pk>; + type IntoIter = Box> + 'a>; + + fn into_iter(self) -> Self::IntoIter { + match self.inner { + ShInner::Wsh(ref wsh) => wsh.into_iter(), + ShInner::Wpkh(ref wpkh) => wpkh.into_iter(), + ShInner::SortedMulti(ref smv) => smv.into_iter(), + ShInner::Ms(ref ms) => ms.into_iter(), + } + } +} + impl DescriptorTrait for Sh { fn sanity_check(&self) -> Result<(), Error> { match self.inner { diff --git a/src/descriptor/sortedmulti.rs b/src/descriptor/sortedmulti.rs index 7c8b4af1d..add913b4e 100644 --- a/src/descriptor/sortedmulti.rs +++ b/src/descriptor/sortedmulti.rs @@ -106,6 +106,15 @@ impl SortedMultiVec { } } +impl<'a, Pk: MiniscriptKey, Ctx: ScriptContext> IntoIterator for &'a SortedMultiVec { + type Item = ForEach<'a, Pk>; + type IntoIter = Box> + 'a>; + + fn into_iter(self) -> Self::IntoIter { + Box::new(self.pks.iter().map(|pk| ForEach::Key(pk))) + } +} + impl ForEachKey for SortedMultiVec { fn for_each_key<'a, F: FnMut(ForEach<'a, Pk>) -> bool>(&'a self, mut pred: F) -> bool where diff --git a/src/miniscript/astelem.rs b/src/miniscript/astelem.rs index 76a93c32e..99c3bf330 100644 --- a/src/miniscript/astelem.rs +++ b/src/miniscript/astelem.rs @@ -815,3 +815,45 @@ impl Terminal { } } } + +impl<'a, Pk: MiniscriptKey, Ctx: ScriptContext> IntoIterator for &'a Terminal { + type Item = ForEach<'a, Pk>; + type IntoIter = Box> + 'a>; + + fn into_iter(self) -> Self::IntoIter { + use std::iter; + + match self { + Terminal::PkK(ref pk) => Box::new(iter::once(ForEach::Key(pk))), + Terminal::PkH(ref pkh) => Box::new(iter::once(ForEach::Hash(pkh))), + Terminal::True + | Terminal::False + | Terminal::After(_) + | Terminal::Older(_) + | Terminal::Sha256(_) + | Terminal::Hash256(_) + | Terminal::Ripemd160(_) + | Terminal::Hash160(_) => Box::new(iter::empty()), + Terminal::Alt(ref i) + | Terminal::Swap(ref i) + | Terminal::Check(ref i) + | Terminal::DupIf(ref i) + | Terminal::Verify(ref i) + | Terminal::NonZero(ref i) + | Terminal::ZeroNotEqual(ref i) => i.into_iter(), + Terminal::AndV(ref i1, ref i2) + | Terminal::AndB(ref i1, ref i2) + | Terminal::OrB(ref i1, ref i2) + | Terminal::OrD(ref i1, ref i2) + | Terminal::OrC(ref i1, ref i2) + | Terminal::OrI(ref i1, ref i2) => Box::new(i1.into_iter().chain(i2.into_iter())), + Terminal::AndOr(ref i1, ref i2, ref i3) => { + Box::new(i1.into_iter().chain(i2.into_iter()).chain(i3.into_iter())) + } + Terminal::Thresh(_, ref scripts) => { + Box::new(scripts.iter().map(|s| s.into_iter()).flatten()) + } + Terminal::Multi(_, ref pks) => Box::new(pks.iter().map(|pk| ForEach::Key(pk))), + } + } +} diff --git a/src/miniscript/mod.rs b/src/miniscript/mod.rs index 9812eb184..e76191ed2 100644 --- a/src/miniscript/mod.rs +++ b/src/miniscript/mod.rs @@ -413,6 +413,15 @@ where } } +impl<'a, Pk: MiniscriptKey, Ctx: ScriptContext> IntoIterator for &'a Miniscript { + type Item = ForEach<'a, Pk>; + type IntoIter = Box> + 'a>; + + fn into_iter(self) -> Self::IntoIter { + self.node.into_iter() + } +} + serde_string_impl_pk!(Miniscript, "a miniscript", Ctx; ScriptContext); #[cfg(test)] diff --git a/src/policy/concrete.rs b/src/policy/concrete.rs index 4fe42d11a..7b3d24d07 100644 --- a/src/policy/concrete.rs +++ b/src/policy/concrete.rs @@ -163,6 +163,31 @@ impl ForEachKey for Policy { } } +impl<'a, Pk: MiniscriptKey> IntoIterator for &'a Policy { + type Item = ForEach<'a, Pk>; + type IntoIter = Box> + 'a>; + + fn into_iter(self) -> Self::IntoIter { + use std::iter; + + match *self { + Policy::Key(ref pk) => Box::new(iter::once(ForEach::Key(pk))), + Policy::Threshold(_, ref subs) | Policy::And(ref subs) => { + Box::new(subs.iter().map(|s| s.into_iter()).flatten()) + } + Policy::Or(ref subs) => Box::new(subs.iter().map(|(_, s)| s.into_iter()).flatten()), + Policy::Unsatisfiable + | Policy::Trivial + | Policy::Sha256(..) + | Policy::Hash256(..) + | Policy::Ripemd160(..) + | Policy::Hash160(..) + | Policy::After(..) + | Policy::Older(..) => Box::new(iter::empty()), + } + } +} + impl Policy { /// Convert a policy using one kind of public key to another /// type of public key