reth_trie/trie_cursor/
subnode.rsuse crate::{BranchNodeCompact, Nibbles, StoredSubNode, CHILD_INDEX_RANGE};
use alloy_primitives::B256;
#[derive(Clone)]
pub struct CursorSubNode {
pub key: Nibbles,
nibble: i8,
pub node: Option<BranchNodeCompact>,
full_key: Nibbles,
}
impl Default for CursorSubNode {
fn default() -> Self {
Self::new(Nibbles::default(), None)
}
}
impl std::fmt::Debug for CursorSubNode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("CursorSubNode")
.field("key", &self.key)
.field("nibble", &self.nibble)
.field("state_flag", &self.state_flag())
.field("tree_flag", &self.tree_flag())
.field("hash_flag", &self.hash_flag())
.field("hash", &self.hash())
.finish()
}
}
impl From<StoredSubNode> for CursorSubNode {
fn from(value: StoredSubNode) -> Self {
let nibble = value.nibble.map_or(-1, |n| n as i8);
let key = Nibbles::from_nibbles_unchecked(value.key);
let full_key = full_key(key.clone(), nibble);
Self { key, nibble, node: value.node, full_key }
}
}
impl From<CursorSubNode> for StoredSubNode {
fn from(value: CursorSubNode) -> Self {
let nibble = (value.nibble >= 0).then_some(value.nibble as u8);
Self { key: value.key.to_vec(), nibble, node: value.node }
}
}
impl CursorSubNode {
pub fn new(key: Nibbles, node: Option<BranchNodeCompact>) -> Self {
let nibble = node.as_ref().filter(|n| n.root_hash.is_none()).map_or(-1, |n| {
CHILD_INDEX_RANGE.clone().find(|i| n.state_mask.is_bit_set(*i)).unwrap() as i8
});
let full_key = full_key(key.clone(), nibble);
Self { key, node, nibble, full_key }
}
#[inline]
pub const fn full_key(&self) -> &Nibbles {
&self.full_key
}
#[inline]
pub fn state_flag(&self) -> bool {
self.node
.as_ref()
.is_none_or(|node| self.nibble < 0 || node.state_mask.is_bit_set(self.nibble as u8))
}
#[inline]
pub fn tree_flag(&self) -> bool {
self.node
.as_ref()
.is_none_or(|node| self.nibble < 0 || node.tree_mask.is_bit_set(self.nibble as u8))
}
pub fn hash_flag(&self) -> bool {
self.node.as_ref().is_some_and(|node| match self.nibble {
-1 => node.root_hash.is_some(),
_ => node.hash_mask.is_bit_set(self.nibble as u8),
})
}
pub fn hash(&self) -> Option<B256> {
if self.hash_flag() {
let node = self.node.as_ref().unwrap();
match self.nibble {
-1 => node.root_hash,
_ => Some(node.hash_for_nibble(self.nibble as u8)),
}
} else {
None
}
}
#[inline]
pub const fn nibble(&self) -> i8 {
self.nibble
}
#[inline]
pub fn inc_nibble(&mut self) {
self.nibble += 1;
update_full_key(&mut self.full_key, self.nibble - 1, self.nibble);
}
#[inline]
pub fn set_nibble(&mut self, nibble: i8) {
let old_nibble = self.nibble;
self.nibble = nibble;
update_full_key(&mut self.full_key, old_nibble, self.nibble);
}
}
#[inline]
fn full_key(mut key: Nibbles, nibble: i8) -> Nibbles {
if nibble >= 0 {
key.push(nibble as u8);
}
key
}
#[inline]
fn update_full_key(key: &mut Nibbles, old_nibble: i8, new_nibble: i8) {
if new_nibble >= 0 {
if old_nibble >= 0 {
let last_index = key.len() - 1;
key.set_at(last_index, new_nibble as u8);
} else {
key.push(new_nibble as u8);
}
} else if old_nibble >= 0 {
key.pop();
}
}