use hash_db::Hasher;
use crate::nibble::{self, NibbleSlice};
use crate::nibble::nibble_ops;
use crate::node_codec::NodeCodec;
use crate::rstd::{borrow::Borrow, ops::Range};
pub type NodeKey = (usize, nibble::BackingByteVec);
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NodeHandle<'a> {
Hash(&'a [u8]),
Inline(&'a [u8]),
}
pub fn decode_hash<H: Hasher>(data: &[u8]) -> Option<H::Out> {
if data.len() != H::LENGTH {
return None;
}
let mut hash = H::Out::default();
hash.as_mut().copy_from_slice(data);
Some(hash)
}
#[derive(Eq, PartialEq, Clone)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum Node<'a> {
Empty,
Leaf(NibbleSlice<'a>, &'a [u8]),
Extension(NibbleSlice<'a>, NodeHandle<'a>),
Branch([Option<NodeHandle<'a>>; nibble_ops::NIBBLE_LENGTH], Option<&'a [u8]>),
NibbledBranch(NibbleSlice<'a>, [Option<NodeHandle<'a>>; nibble_ops::NIBBLE_LENGTH], Option<&'a [u8]>),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum NodeHandlePlan {
Hash(Range<usize>),
Inline(Range<usize>),
}
impl NodeHandlePlan {
pub fn build<'a, 'b>(&'a self, data: &'b [u8]) -> NodeHandle<'b> {
match self {
NodeHandlePlan::Hash(range) => NodeHandle::Hash(&data[range.clone()]),
NodeHandlePlan::Inline(range) => NodeHandle::Inline(&data[range.clone()]),
}
}
}
#[derive(Eq, PartialEq, Clone)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct NibbleSlicePlan {
bytes: Range<usize>,
offset: usize,
}
impl NibbleSlicePlan {
pub fn new(bytes: Range<usize>, offset: usize) -> Self {
NibbleSlicePlan {
bytes,
offset
}
}
pub fn len(&self) -> usize {
(self.bytes.end - self.bytes.start) * nibble_ops::NIBBLE_PER_BYTE - self.offset
}
pub fn build<'a, 'b>(&'a self, data: &'b [u8]) -> NibbleSlice<'b> {
NibbleSlice::new_offset(&data[self.bytes.clone()], self.offset)
}
}
#[derive(Eq, PartialEq, Clone)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum NodePlan {
Empty,
Leaf {
partial: NibbleSlicePlan,
value: Range<usize>,
},
Extension {
partial: NibbleSlicePlan,
child: NodeHandlePlan,
},
Branch {
value: Option<Range<usize>>,
children: [Option<NodeHandlePlan>; nibble_ops::NIBBLE_LENGTH],
},
NibbledBranch {
partial: NibbleSlicePlan,
value: Option<Range<usize>>,
children: [Option<NodeHandlePlan>; nibble_ops::NIBBLE_LENGTH],
},
}
impl NodePlan {
pub fn build<'a, 'b>(&'a self, data: &'b [u8]) -> Node<'b> {
match self {
NodePlan::Empty => Node::Empty,
NodePlan::Leaf { partial, value } =>
Node::Leaf(partial.build(data), &data[value.clone()]),
NodePlan::Extension { partial, child } =>
Node::Extension(partial.build(data), child.build(data)),
NodePlan::Branch { value, children } => {
let mut child_slices = [None; nibble_ops::NIBBLE_LENGTH];
for i in 0..nibble_ops::NIBBLE_LENGTH {
child_slices[i] = children[i].as_ref().map(|child| child.build(data));
}
let value_slice = value.clone().map(|value| &data[value]);
Node::Branch(child_slices, value_slice)
},
NodePlan::NibbledBranch { partial, value, children } => {
let mut child_slices = [None; nibble_ops::NIBBLE_LENGTH];
for i in 0..nibble_ops::NIBBLE_LENGTH {
child_slices[i] = children[i].as_ref().map(|child| child.build(data));
}
let value_slice = value.clone().map(|value| &data[value]);
Node::NibbledBranch(partial.build(data), child_slices, value_slice)
},
}
}
}
#[cfg_attr(feature = "std", derive(Debug))]
#[derive(PartialEq, Eq)]
pub struct OwnedNode<D: Borrow<[u8]>> {
data: D,
plan: NodePlan,
}
impl<D: Borrow<[u8]>> OwnedNode<D> {
pub fn new<C: NodeCodec>(data: D) -> Result<Self, C::Error> {
let plan = C::decode_plan(data.borrow())?;
Ok(OwnedNode { data, plan })
}
pub fn data(&self) -> &[u8] {
self.data.borrow()
}
pub fn node_plan(&self) -> &NodePlan {
&self.plan
}
pub fn node(&self) -> Node {
self.plan.build(self.data.borrow())
}
}