parity-common/patricia_trie/src/node.rs

107 lines
3.2 KiB
Rust

// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use elastic_array::ElasticArray36;
use nibbleslice::NibbleSlice;
use nibblevec::NibbleVec;
use super::DBValue;
/// Partial node key type.
pub type NodeKey = ElasticArray36<u8>;
/// Type of node in the trie and essential information thereof.
#[derive(Eq, PartialEq, Debug, Clone)]
pub enum Node<'a> {
/// Null trie node; could be an empty root or an empty branch entry.
Empty,
/// Leaf node; has key slice and value. Value may not be empty.
Leaf(NibbleSlice<'a>, &'a [u8]),
/// Extension node; has key slice and node data. Data may not be null.
Extension(NibbleSlice<'a>, &'a [u8]),
/// Branch node; has array of 16 child nodes (each possibly null) and an optional immediate node data.
Branch([&'a [u8]; 16], Option<&'a [u8]>),
}
/// A Sparse (non mutable) owned vector struct to hold branch keys and value
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct Branch {
data: Vec<u8>,
ubounds: [usize; 18],
has_value: bool,
}
impl Branch {
fn new(a: [&[u8]; 16], value: Option<&[u8]>) -> Self {
let mut data = Vec::with_capacity(a.iter().map(|inner| inner.len()).sum());
let mut ubounds = [0; 18];
for (inner, ub) in a.iter().zip(ubounds.iter_mut().skip(1)) {
data.extend_from_slice(inner);
*ub = data.len();
}
if let Some(value) = value {
data.extend(value);
ubounds[17] = data.len();
}
Branch { data, ubounds, has_value: value.is_some() }
}
/// Get the node value, if any
pub fn get_value(&self) -> Option<&[u8]> {
if self.has_value {
Some(&self.data[self.ubounds[16]..self.ubounds[17]])
} else {
None
}
}
/// Test if the node has a value
pub fn has_value(&self) -> bool {
self.has_value
}
}
impl ::std::ops::Index<usize> for Branch {
type Output = [u8];
fn index(&self, index: usize) -> &[u8] {
assert!(index < 16);
&self.data[self.ubounds[index]..self.ubounds[index + 1]]
}
}
/// An owning node type. Useful for trie iterators.
#[derive(Debug, PartialEq, Eq)]
pub enum OwnedNode {
/// Empty trie node.
Empty,
/// Leaf node: partial key and value.
Leaf(NibbleVec, DBValue),
/// Extension node: partial key and child node.
Extension(NibbleVec, DBValue),
/// Branch node: 16 children and an optional value.
Branch(Branch),
}
impl<'a> From<Node<'a>> for OwnedNode {
fn from(node: Node<'a>) -> Self {
match node {
Node::Empty => OwnedNode::Empty,
Node::Leaf(k, v) => OwnedNode::Leaf(k.into(), DBValue::from_slice(v)),
Node::Extension(k, child) => OwnedNode::Extension(k.into(), DBValue::from_slice(child)),
Node::Branch(c, val) => OwnedNode::Branch(Branch::new(c, val)),
}
}
}