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> {}