diff --git a/miden-crypto/src/merkle/sparse_path.rs b/miden-crypto/src/merkle/sparse_path.rs index dfd7cff..c8f3b34 100644 --- a/miden-crypto/src/merkle/sparse_path.rs +++ b/miden-crypto/src/merkle/sparse_path.rs @@ -3,6 +3,7 @@ use core::{ iter::{self, FusedIterator}, num::NonZero, }; +use std::borrow::Cow; use winter_utils::{Deserializable, DeserializationError, Serializable}; @@ -252,20 +253,10 @@ impl From for Vec { // ITERATORS // ================================================================================================ -impl<'p> IntoIterator for &'p SparseMerklePath { - type Item = as Iterator>::Item; - type IntoIter = SparseMerklePathIter<'p>; - - fn into_iter(self) -> SparseMerklePathIter<'p> { - let tree_depth = self.depth(); - SparseMerklePathIter { path: self, next_depth: tree_depth } - } -} - -/// Borrowing iterator for [`SparseMerklePath`]. +/// Iterator for [`SparseMerklePath`]. pub struct SparseMerklePathIter<'p> { /// The "inner" value we're iterating over. - path: &'p SparseMerklePath, + path: Cow<'p, SparseMerklePath>, /// The depth a `next()` call will get. `next_depth == 0` indicates that the iterator has been /// exhausted. @@ -306,57 +297,32 @@ impl FusedIterator for SparseMerklePathIter<'_> {} // TODO: impl DoubleEndedIterator. -/// Owning iterator for [SparseMerklePath]. -pub struct IntoIter { - /// The "inner" value we're iterating over. - path: SparseMerklePath, - - /// The depth a `next()` call will get. `next_depth == 0` indicates that the iterator has been - /// exhausted. - next_depth: u8, -} - impl IntoIterator for SparseMerklePath { - type IntoIter = IntoIter; + type IntoIter = SparseMerklePathIter<'static>; type Item = ::Item; - fn into_iter(self) -> IntoIter { + fn into_iter(self) -> SparseMerklePathIter<'static> { let tree_depth = self.depth(); - IntoIter { path: self, next_depth: tree_depth } + SparseMerklePathIter { + path: Cow::Owned(self), + next_depth: tree_depth, + } } } -impl Iterator for IntoIter { - type Item = RpoDigest; +impl<'p> IntoIterator for &'p SparseMerklePath { + type Item = as Iterator>::Item; + type IntoIter = SparseMerklePathIter<'p>; - fn next(&mut self) -> Option { - let this_depth = self.next_depth; - // Paths don't include the root, so if `this_depth` is 0 then we keep returning `None`. - let this_depth = NonZero::new(this_depth)?; - self.next_depth = this_depth.get() - 1; - - // `this_depth` is only ever decreasing, so it can't ever exceed `self.path.depth()`. - let node = self.path.at_depth(this_depth).unwrap(); - Some(node) - } - - // IntoIter always knows its exact size. - fn size_hint(&self) -> (usize, Option) { - let remaining = ExactSizeIterator::len(self); - (remaining, Some(remaining)) + fn into_iter(self) -> SparseMerklePathIter<'p> { + let tree_depth = self.depth(); + SparseMerklePathIter { + path: Cow::Borrowed(self), + next_depth: tree_depth, + } } } -impl ExactSizeIterator for IntoIter { - fn len(&self) -> usize { - self.next_depth as usize - } -} - -impl FusedIterator for IntoIter {} - -// TODO: impl DoubleEndedIterator. - // COMPARISONS // ================================================================================================ impl PartialEq for SparseMerklePath {