diff --git a/storage/src/tries/iter.rs b/storage/src/tries/iter.rs index a874d9edca..ed8c9b5c25 100644 --- a/storage/src/tries/iter.rs +++ b/storage/src/tries/iter.rs @@ -20,35 +20,35 @@ pub struct IterDescending; /// respectively. #[derive(Debug)] #[must_use = "iterators are lazy and do nothing unless consumed"] -pub struct TrieEdgeIter<'a, N: ?Sized, V: ?Sized, D> { +pub struct TrieEdgeIter<'root, N, V: ?Sized, D> { leading_path: PathBuf, - stack: Vec>, + stack: Vec>, marker: std::marker::PhantomData, } /// An iterator over the key-value pairs in a key-value trie. #[derive(Debug)] #[must_use = "iterators are lazy and do nothing unless consumed"] -pub struct TrieValueIter<'a, N: ?Sized, V: ?Sized, D> { - edges: TrieEdgeIter<'a, N, V, D>, +pub struct TrieValueIter<'root, N, V: ?Sized, D> { + edges: TrieEdgeIter<'root, N, V, D>, } #[derive(Debug)] -struct Frame<'a, N: ?Sized, V: ?Sized> { - node: &'a N, - hash: Option<&'a HashType>, +struct Frame<'root, N, V: ?Sized> { + node: N, + hash: Option<&'root HashType>, leading_path_len: usize, children: Option>, marker: std::marker::PhantomData, } -impl<'a, N, V, D> TrieEdgeIter<'a, N, V, D> +impl<'root, N, V, D> TrieEdgeIter<'root, N, V, D> where - N: TrieNode + ?Sized, - V: AsRef<[u8]> + ?Sized, + N: TrieNode<'root, V>, + V: AsRef<[u8]> + ?Sized + 'root, { /// Creates a new iterator over the given key-value trie. - pub fn new(root: &'a N, root_hash: Option<&'a HashType>) -> Self { + pub fn new(root: N, root_hash: Option<&'root HashType>) -> Self { let mut this = Self { leading_path: PathBuf::new_const(), stack: Vec::new(), @@ -60,15 +60,15 @@ where /// Transforms this iterator into an iterator over the key-value pairs in /// the trie. - pub const fn node_values(self) -> TrieValueIter<'a, N, V, D> { + pub const fn node_values(self) -> TrieValueIter<'root, N, V, D> { TrieValueIter { edges: self } } fn push_frame( &mut self, leading_component: Option, - node: &'a N, - hash: Option<&'a HashType>, + node: N, + hash: Option<&'root HashType>, ) { let frame = Frame { node, @@ -115,12 +115,12 @@ macro_rules! descend { }; } -impl<'a, N, V> Iterator for TrieEdgeIter<'a, N, V, IterAscending> +impl<'root, N, V> Iterator for TrieEdgeIter<'root, N, V, IterAscending> where - N: TrieNode + ?Sized, - V: AsRef<[u8]> + ?Sized, + N: TrieNode<'root, V>, + V: AsRef<[u8]> + ?Sized + 'root, { - type Item = (PathBuf, TrieEdgeState<'a, N>); + type Item = (PathBuf, TrieEdgeState<'root, N>); fn next(&mut self) -> Option { while let Some(&mut Frame { @@ -157,12 +157,12 @@ where } } -impl<'a, N, V> Iterator for TrieEdgeIter<'a, N, V, IterDescending> +impl<'root, N, V> Iterator for TrieEdgeIter<'root, N, V, IterDescending> where - N: TrieNode + ?Sized, - V: AsRef<[u8]> + ?Sized, + N: TrieNode<'root, V>, + V: AsRef<[u8]> + ?Sized + 'root, { - type Item = (PathBuf, TrieEdgeState<'a, N>); + type Item = (PathBuf, TrieEdgeState<'root, N>); fn next(&mut self) -> Option { while let Some(&mut Frame { @@ -192,12 +192,12 @@ where } } -impl<'a, N, V> Iterator for TrieValueIter<'a, N, V, IterAscending> +impl<'root, N, V> Iterator for TrieValueIter<'root, N, V, IterAscending> where - N: TrieNode + ?Sized, - V: AsRef<[u8]> + ?Sized + 'a, + N: TrieNode<'root, V>, + V: AsRef<[u8]> + ?Sized + 'root, { - type Item = (PathBuf, &'a V); + type Item = (PathBuf, &'root V); fn next(&mut self) -> Option { self.edges @@ -205,12 +205,12 @@ where } } -impl<'a, N, V> Iterator for TrieValueIter<'a, N, V, IterDescending> +impl<'root, N, V> Iterator for TrieValueIter<'root, N, V, IterDescending> where - N: TrieNode + ?Sized, - V: AsRef<[u8]> + ?Sized + 'a, + N: TrieNode<'root, V>, + V: AsRef<[u8]> + ?Sized + 'root, { - type Item = (PathBuf, &'a V); + type Item = (PathBuf, &'root V); fn next(&mut self) -> Option { self.edges @@ -220,7 +220,7 @@ where // auto-derived implementations would require N: Clone, V: Clone which is too much -impl Clone for TrieEdgeIter<'_, N, V, D> { +impl Clone for TrieEdgeIter<'_, N, V, D> { fn clone(&self) -> Self { Self { leading_path: self.leading_path.clone(), @@ -235,7 +235,7 @@ impl Clone for TrieEdgeIter<'_, N, V, D> { } } -impl Clone for TrieValueIter<'_, N, V, D> { +impl Clone for TrieValueIter<'_, N, V, D> { fn clone(&self) -> Self { Self { edges: self.edges.clone(), @@ -247,7 +247,7 @@ impl Clone for TrieValueIter<'_, N, V, D> { } } -impl Clone for Frame<'_, N, V> { +impl Clone for Frame<'_, N, V> { fn clone(&self) -> Self { Self { node: self.node, diff --git a/storage/src/tries/kvp.rs b/storage/src/tries/kvp.rs index 192b316faf..635086b6ea 100644 --- a/storage/src/tries/kvp.rs +++ b/storage/src/tries/kvp.rs @@ -279,67 +279,70 @@ impl<'a, T: AsRef<[u8]> + ?Sized> HashedKeyValueTrieRoot<'a, T> { } } -impl + ?Sized> TrieNode for KeyValueTrieRoot<'_, T> { - type PartialPath<'a> - = PackedPathRef<'a> - where - Self: 'a; +impl<'root, T> TrieNode<'root, T> for &'root KeyValueTrieRoot<'root, T> +where + T: AsRef<[u8]> + ?Sized + 'root, +{ + type PartialPath = PackedPathRef<'root>; - fn partial_path(&self) -> Self::PartialPath<'_> { + fn partial_path(self) -> Self::PartialPath { self.partial_path } - fn value(&self) -> Option<&T> { + fn value(self) -> Option<&'root T> { self.value } - fn child_hash(&self, pc: PathComponent) -> Option<&HashType> { + fn child_hash(self, pc: PathComponent) -> Option<&'root HashType> { let _ = pc; None } - fn child_node(&self, pc: PathComponent) -> Option<&Self> { + fn child_node(self, pc: PathComponent) -> Option { self.children[pc].as_deref() } - fn child_state(&self, pc: PathComponent) -> Option> { + fn child_state(self, pc: PathComponent) -> Option> { self.children[pc] .as_deref() .map(|node| super::TrieEdgeState::UnhashedChild { node }) } } -impl + ?Sized> TrieNode for HashedKeyValueTrieRoot<'_, T> { - type PartialPath<'a> - = PackedPathRef<'a> - where - Self: 'a; +impl<'root, T> TrieNode<'root, T> for &'root HashedKeyValueTrieRoot<'root, T> +where + T: AsRef<[u8]> + ?Sized + 'root, +{ + type PartialPath = PackedPathRef<'root>; - fn partial_path(&self) -> Self::PartialPath<'_> { + fn partial_path(self) -> Self::PartialPath { self.partial_path } - fn value(&self) -> Option<&T> { + fn value(self) -> Option<&'root T> { self.value } - fn child_hash(&self, pc: PathComponent) -> Option<&HashType> { + fn child_hash(self, pc: PathComponent) -> Option<&'root HashType> { self.children[pc].as_deref().map(|c| &c.computed) } - fn child_node(&self, pc: PathComponent) -> Option<&Self> { + fn child_node(self, pc: PathComponent) -> Option { self.children[pc].as_deref() } - fn child_state(&self, pc: PathComponent) -> Option> { + fn child_state(self, pc: PathComponent) -> Option> { self.children[pc] .as_deref() .map(|node| super::TrieEdgeState::from_node(node, Some(&node.computed))) } } -impl + ?Sized> HashedTrieNode for HashedKeyValueTrieRoot<'_, T> { - fn computed(&self) -> &HashType { +impl<'root, T> HashedTrieNode<'root, T> for &'root HashedKeyValueTrieRoot<'root, T> +where + T: AsRef<[u8]> + ?Sized + 'root, +{ + fn computed(self) -> &'root HashType { &self.computed } } diff --git a/storage/src/tries/mod.rs b/storage/src/tries/mod.rs index ce19101964..0399c84679 100644 --- a/storage/src/tries/mod.rs +++ b/storage/src/tries/mod.rs @@ -10,44 +10,42 @@ pub use self::iter::{IterAscending, IterDescending, TrieEdgeIter, TrieValueIter} pub use self::kvp::{DuplicateKeyError, HashedKeyValueTrieRoot, KeyValueTrieRoot}; /// The state of an edge from a parent node to a child node in a trie. -#[derive(Debug, PartialEq, Eq, Hash)] -pub enum TrieEdgeState<'a, N: ?Sized> { +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum TrieEdgeState<'root, N> { /// A child node that is fully known locally, along with its hash. LocalChild { /// The child node at this edge. - node: &'a N, + node: N, /// The hash of the child at this edge, as known to the parent. A locally /// hashed child implements [`HashedTrieNode`]. It is possible for the /// child's computed hash to differ from this hash if the local node has /// incomplete information. - hash: &'a HashType, + hash: &'root HashType, }, /// A child node that is not known locally, but whose hash is known to the /// parent. RemoteChild { /// The hash of the remote child at this edge, as known to the parent. - hash: &'a HashType, + hash: &'root HashType, }, /// A child node that is known locally, but whose hash is not known to the /// parent. UnhashedChild { /// The child node at this edge. - node: &'a N, + node: N, }, } /// A node in a fixed-arity radix trie. -pub trait TrieNode + ?Sized> { +pub trait TrieNode<'root, V: AsRef<[u8]> + ?Sized + 'root>: Copy + 'root { /// The type of path from this node's parent to this node. - type PartialPath<'a>: IntoSplitPath + 'a - where - Self: 'a; + type PartialPath: IntoSplitPath + 'root; /// The path from this node's parent to this node. - fn partial_path(&self) -> Self::PartialPath<'_>; + fn partial_path(self) -> Self::PartialPath; /// The value stored at this node, if any. - fn value(&self) -> Option<&V>; + fn value(self) -> Option<&'root V>; /// The node-local hash of the child at the given path component, if any. /// @@ -64,7 +62,7 @@ pub trait TrieNode + ?Sized> { /// the hashes of sibling nodes that branch off the path. /// /// [`child_node`]: TrieNode::child_node - fn child_hash(&self, pc: PathComponent) -> Option<&HashType>; + fn child_hash(self, pc: PathComponent) -> Option<&'root HashType>; /// The child node at the given path component, if any. /// @@ -72,7 +70,7 @@ pub trait TrieNode + ?Sized> { /// relationship between these two methods. /// /// [`child_hash`]: TrieNode::child_hash - fn child_node(&self, pc: PathComponent) -> Option<&Self>; + fn child_node(self, pc: PathComponent) -> Option; /// A combined view of the child node and its hash at the given path /// component, if any. @@ -83,7 +81,7 @@ pub trait TrieNode + ?Sized> { /// /// [`child_node`]: TrieNode::child_node /// [`child_hash`]: TrieNode::child_hash - fn child_state(&self, pc: PathComponent) -> Option> { + fn child_state(self, pc: PathComponent) -> Option> { match (self.child_node(pc), self.child_hash(pc)) { (Some(node), Some(hash)) => Some(TrieEdgeState::LocalChild { node, hash }), (Some(node), None) => Some(TrieEdgeState::UnhashedChild { node }), @@ -98,7 +96,7 @@ pub trait TrieNode + ?Sized> { /// The returned iterator performs a pre-order traversal of the trie, yielding /// each edge from parent to child before descending into the child node. The /// children of each node are yielded in ascending order by path component. - fn iter_edges(&self) -> TrieEdgeIter<'_, Self, V, IterAscending> { + fn iter_edges(self) -> TrieEdgeIter<'root, Self, V, IterAscending> { TrieEdgeIter::new(self, None) } @@ -108,63 +106,63 @@ pub trait TrieNode + ?Sized> { /// The returned iterator performs a post-order traversal of the trie, yielding /// each edge from parent to child after ascending back from the child node. /// The children of each node are yielded in descending order by path component. - fn iter_edges_desc(&self) -> TrieEdgeIter<'_, Self, V, IterDescending> { + fn iter_edges_desc(self) -> TrieEdgeIter<'root, Self, V, IterDescending> { TrieEdgeIter::new(self, None) } /// Returns an iterator over each key-value pair in this trie in ascending order. - fn iter_values(&self) -> TrieValueIter<'_, Self, V, IterAscending> { + fn iter_values(self) -> TrieValueIter<'root, Self, V, IterAscending> { self.iter_edges().node_values() } /// Returns an iterator over each key-value pair in this trie in descending order. - fn iter_values_desc(&self) -> TrieValueIter<'_, Self, V, IterDescending> { + fn iter_values_desc(self) -> TrieValueIter<'root, Self, V, IterDescending> { self.iter_edges_desc().node_values() } } /// A merkleized node in a fixed-arity radix trie. -pub trait HashedTrieNode + ?Sized>: TrieNode { +pub trait HashedTrieNode<'root, V: AsRef<[u8]> + ?Sized + 'root>: TrieNode<'root, V> { /// The computed hash of this node. - fn computed(&self) -> &HashType; + fn computed(self) -> &'root HashType; } -impl<'a, N: ?Sized> TrieEdgeState<'a, N> { - const fn from_node(node: &'a N, hash: Option<&'a HashType>) -> Self { +impl<'root, N> TrieEdgeState<'root, N> { + const fn from_node(node: N, hash: Option<&'root HashType>) -> Self { match hash { Some(hash) => TrieEdgeState::LocalChild { node, hash }, None => TrieEdgeState::UnhashedChild { node }, } } - fn value + ?Sized>(self) -> Option<&'a V> + fn value + ?Sized + 'root>(self) -> Option<&'root V> where - N: TrieNode, + N: TrieNode<'root, V>, { - self.node().and_then(|n| n.value()) + self.node().and_then(TrieNode::value) } /// Returns `true` if this edge state represents a local child node with a known hash. #[must_use] - pub const fn is_local(self) -> bool { + pub fn is_local(self) -> bool { matches!(self, TrieEdgeState::LocalChild { .. }) } /// Returns `true` if this edge state represents a remote child node with only a known hash. #[must_use] - pub const fn is_remote(self) -> bool { + pub fn is_remote(self) -> bool { matches!(self, TrieEdgeState::RemoteChild { .. }) } /// Returns `true` if this edge state represents a local child node without a known hash. #[must_use] - pub const fn is_unhashed(self) -> bool { + pub fn is_unhashed(self) -> bool { matches!(self, TrieEdgeState::UnhashedChild { .. }) } /// Returns the child node if it is known locally. #[must_use] - pub const fn node(self) -> Option<&'a N> { + pub fn node(self) -> Option { match self { TrieEdgeState::LocalChild { node, .. } | TrieEdgeState::UnhashedChild { node } => { Some(node) @@ -175,7 +173,7 @@ impl<'a, N: ?Sized> TrieEdgeState<'a, N> { /// Returns the hash of the child node if it is known. #[must_use] - pub const fn hash(self) -> Option<&'a HashType> { + pub fn hash(self) -> Option<&'root HashType> { match self { TrieEdgeState::LocalChild { hash, .. } | TrieEdgeState::RemoteChild { hash } => { Some(hash) @@ -184,13 +182,3 @@ impl<'a, N: ?Sized> TrieEdgeState<'a, N> { } } } - -// auto-derived implementations would require N: Clone + Copy which is too much - -impl Clone for TrieEdgeState<'_, N> { - fn clone(&self) -> Self { - *self - } -} - -impl Copy for TrieEdgeState<'_, N> {}