reth_trie/trie_cursor/
subnode.rs
1use crate::{BranchNodeCompact, Nibbles, StoredSubNode, CHILD_INDEX_RANGE};
2use alloy_primitives::B256;
3
4#[derive(Clone)]
6pub struct CursorSubNode {
7 pub key: Nibbles,
9 nibble: i8,
11 pub node: Option<BranchNodeCompact>,
13 full_key: Nibbles,
15}
16
17impl Default for CursorSubNode {
18 fn default() -> Self {
19 Self::new(Nibbles::default(), None)
20 }
21}
22
23impl std::fmt::Debug for CursorSubNode {
24 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25 f.debug_struct("CursorSubNode")
26 .field("key", &self.key)
27 .field("nibble", &self.nibble)
28 .field("state_flag", &self.state_flag())
29 .field("tree_flag", &self.tree_flag())
30 .field("hash_flag", &self.hash_flag())
31 .field("hash", &self.hash())
32 .finish()
33 }
34}
35
36impl From<StoredSubNode> for CursorSubNode {
38 fn from(value: StoredSubNode) -> Self {
43 let nibble = value.nibble.map_or(-1, |n| n as i8);
44 let key = Nibbles::from_nibbles_unchecked(value.key);
45 let full_key = full_key(key.clone(), nibble);
46 Self { key, nibble, node: value.node, full_key }
47 }
48}
49
50impl From<CursorSubNode> for StoredSubNode {
51 fn from(value: CursorSubNode) -> Self {
52 let nibble = (value.nibble >= 0).then_some(value.nibble as u8);
53 Self { key: value.key.to_vec(), nibble, node: value.node }
54 }
55}
56
57impl CursorSubNode {
58 pub fn new(key: Nibbles, node: Option<BranchNodeCompact>) -> Self {
60 let nibble = node.as_ref().filter(|n| n.root_hash.is_none()).map_or(-1, |n| {
62 CHILD_INDEX_RANGE.clone().find(|i| n.state_mask.is_bit_set(*i)).unwrap() as i8
63 });
64 let full_key = full_key(key.clone(), nibble);
65 Self { key, node, nibble, full_key }
66 }
67
68 #[inline]
70 pub const fn full_key(&self) -> &Nibbles {
71 &self.full_key
72 }
73
74 #[inline]
76 pub fn state_flag(&self) -> bool {
77 self.node
78 .as_ref()
79 .is_none_or(|node| self.nibble < 0 || node.state_mask.is_bit_set(self.nibble as u8))
80 }
81
82 #[inline]
84 pub fn tree_flag(&self) -> bool {
85 self.node
86 .as_ref()
87 .is_none_or(|node| self.nibble < 0 || node.tree_mask.is_bit_set(self.nibble as u8))
88 }
89
90 pub fn hash_flag(&self) -> bool {
92 self.node.as_ref().is_some_and(|node| match self.nibble {
93 -1 => node.root_hash.is_some(),
95 _ => node.hash_mask.is_bit_set(self.nibble as u8),
97 })
98 }
99
100 pub fn hash(&self) -> Option<B256> {
102 if self.hash_flag() {
103 let node = self.node.as_ref().unwrap();
104 match self.nibble {
105 -1 => node.root_hash,
106 _ => Some(node.hash_for_nibble(self.nibble as u8)),
107 }
108 } else {
109 None
110 }
111 }
112
113 #[inline]
115 pub const fn nibble(&self) -> i8 {
116 self.nibble
117 }
118
119 #[inline]
121 pub fn inc_nibble(&mut self) {
122 self.nibble += 1;
123 update_full_key(&mut self.full_key, self.nibble - 1, self.nibble);
124 }
125
126 #[inline]
128 pub fn set_nibble(&mut self, nibble: i8) {
129 let old_nibble = self.nibble;
130 self.nibble = nibble;
131 update_full_key(&mut self.full_key, old_nibble, self.nibble);
132 }
133}
134
135#[inline]
137fn full_key(mut key: Nibbles, nibble: i8) -> Nibbles {
138 if nibble >= 0 {
139 key.push(nibble as u8);
140 }
141 key
142}
143
144#[inline]
146fn update_full_key(key: &mut Nibbles, old_nibble: i8, new_nibble: i8) {
147 if new_nibble >= 0 {
148 if old_nibble >= 0 {
149 let last_index = key.len() - 1;
150 key.set_at(last_index, new_nibble as u8);
151 } else {
152 key.push(new_nibble as u8);
153 }
154 } else if old_nibble >= 0 {
155 key.pop();
156 }
157}