tetsy_trie_db/
node.rs

1// Copyright 2017, 2018 Parity Technologies
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use tetsy_hash_db::Hasher;
16use crate::nibble::{self, NibbleSlice};
17use crate::nibble::nibble_ops;
18use crate::node_codec::NodeCodec;
19
20use crate::rstd::{borrow::Borrow, ops::Range};
21
22/// Partial node key type: offset and owned value of a nibbleslice.
23/// Offset is applied on first byte of array (bytes are right aligned).
24pub type NodeKey = (usize, nibble::BackingByteVec);
25
26/// A reference to a trie node which may be stored within another trie node.
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub enum NodeHandle<'a> {
29	Hash(&'a [u8]),
30	Inline(&'a [u8]),
31}
32
33/// Read a hash from a slice into a Hasher output. Returns None if the slice is the wrong length.
34pub fn decode_hash<H: Hasher>(data: &[u8]) -> Option<H::Out> {
35	if data.len() != H::LENGTH {
36		return None;
37	}
38	let mut hash = H::Out::default();
39	hash.as_mut().copy_from_slice(data);
40	Some(hash)
41}
42
43/// Type of node in the trie and essential information thereof.
44#[derive(Eq, PartialEq, Clone)]
45#[cfg_attr(feature = "std", derive(Debug))]
46pub enum Node<'a> {
47	/// Null trie node; could be an empty root or an empty branch entry.
48	Empty,
49	/// Leaf node; has key slice and value. Value may not be empty.
50	Leaf(NibbleSlice<'a>, &'a [u8]),
51	/// Extension node; has key slice and node data. Data may not be null.
52	Extension(NibbleSlice<'a>, NodeHandle<'a>),
53	/// Branch node; has slice of child nodes (each possibly null)
54	/// and an optional immediate node data.
55	Branch([Option<NodeHandle<'a>>; nibble_ops::NIBBLE_LENGTH], Option<&'a [u8]>),
56	/// Branch node with support for a nibble (when extension nodes are not used).
57	NibbledBranch(NibbleSlice<'a>, [Option<NodeHandle<'a>>; nibble_ops::NIBBLE_LENGTH], Option<&'a [u8]>),
58}
59
60/// A `NodeHandlePlan` is a decoding plan for constructing a `NodeHandle` from an encoded trie
61/// node. This is used as a substructure of `NodePlan`. See `NodePlan` for details.
62#[derive(Debug, Clone, PartialEq, Eq)]
63pub enum NodeHandlePlan {
64	Hash(Range<usize>),
65	Inline(Range<usize>),
66}
67
68impl NodeHandlePlan {
69	/// Build a node handle by decoding a byte slice according to the node handle plan. It is the
70	/// responsibility of the caller to ensure that the node plan was created for the argument
71	/// data, otherwise the call may decode incorrectly or panic.
72	pub fn build<'a, 'b>(&'a self, data: &'b [u8]) -> NodeHandle<'b> {
73		match self {
74			NodeHandlePlan::Hash(range) => NodeHandle::Hash(&data[range.clone()]),
75			NodeHandlePlan::Inline(range) => NodeHandle::Inline(&data[range.clone()]),
76		}
77	}
78}
79
80/// A `NibbleSlicePlan` is a blueprint for decoding a nibble slice from a byte slice. The
81/// `NibbleSlicePlan` is created by parsing a byte slice and can be reused multiple times.
82#[derive(Eq, PartialEq, Clone)]
83#[cfg_attr(feature = "std", derive(Debug))]
84pub struct NibbleSlicePlan {
85	bytes: Range<usize>,
86	offset: usize,
87}
88
89impl NibbleSlicePlan {
90	/// Construct a nibble slice decode plan.
91	pub fn new(bytes: Range<usize>, offset: usize) -> Self {
92		NibbleSlicePlan {
93			bytes,
94			offset
95		}
96	}
97
98	/// Returns the nibble length of the slice.
99	pub fn len(&self) -> usize {
100		(self.bytes.end - self.bytes.start) * nibble_ops::NIBBLE_PER_BYTE - self.offset
101	}
102
103	/// Build a nibble slice by decoding a byte slice according to the plan. It is the
104	/// responsibility of the caller to ensure that the node plan was created for the argument
105	/// data, otherwise the call may decode incorrectly or panic.
106	pub fn build<'a, 'b>(&'a self, data: &'b [u8]) -> NibbleSlice<'b> {
107		NibbleSlice::new_offset(&data[self.bytes.clone()], self.offset)
108	}
109}
110
111/// A `NodePlan` is a blueprint for decoding a node from a byte slice. The `NodePlan` is created
112/// by parsing an encoded node and can be reused multiple times. This is useful as a `Node` borrows
113/// from a byte slice and this struct does not.
114///
115/// The enum values mirror those of `Node` except that instead of byte slices, this struct stores
116/// ranges that can be used to index into a large byte slice.
117#[derive(Eq, PartialEq, Clone)]
118#[cfg_attr(feature = "std", derive(Debug))]
119pub enum NodePlan {
120	/// Null trie node; could be an empty root or an empty branch entry.
121	Empty,
122	/// Leaf node; has a partial key plan and value.
123	Leaf {
124		partial: NibbleSlicePlan,
125		value: Range<usize>,
126	},
127	/// Extension node; has a partial key plan and child data.
128	Extension {
129		partial: NibbleSlicePlan,
130		child: NodeHandlePlan,
131	},
132	/// Branch node; has slice of child nodes (each possibly null)
133	/// and an optional immediate node data.
134	Branch {
135		value: Option<Range<usize>>,
136		children: [Option<NodeHandlePlan>; nibble_ops::NIBBLE_LENGTH],
137	},
138	/// Branch node with support for a nibble (when extension nodes are not used).
139	NibbledBranch {
140		partial: NibbleSlicePlan,
141		value: Option<Range<usize>>,
142		children: [Option<NodeHandlePlan>; nibble_ops::NIBBLE_LENGTH],
143	},
144}
145
146impl NodePlan {
147	/// Build a node by decoding a byte slice according to the node plan. It is the responsibility
148	/// of the caller to ensure that the node plan was created for the argument data, otherwise the
149	/// call may decode incorrectly or panic.
150	pub fn build<'a, 'b>(&'a self, data: &'b [u8]) -> Node<'b> {
151		match self {
152			NodePlan::Empty => Node::Empty,
153			NodePlan::Leaf { partial, value } =>
154				Node::Leaf(partial.build(data), &data[value.clone()]),
155			NodePlan::Extension { partial, child } =>
156				Node::Extension(partial.build(data), child.build(data)),
157			NodePlan::Branch { value, children } => {
158				let mut child_slices = [None; nibble_ops::NIBBLE_LENGTH];
159				for i in 0..nibble_ops::NIBBLE_LENGTH {
160					child_slices[i] = children[i].as_ref().map(|child| child.build(data));
161				}
162				let value_slice = value.clone().map(|value| &data[value]);
163				Node::Branch(child_slices, value_slice)
164			},
165			NodePlan::NibbledBranch { partial, value, children } => {
166				let mut child_slices = [None; nibble_ops::NIBBLE_LENGTH];
167				for i in 0..nibble_ops::NIBBLE_LENGTH {
168					child_slices[i] = children[i].as_ref().map(|child| child.build(data));
169				}
170				let value_slice = value.clone().map(|value| &data[value]);
171				Node::NibbledBranch(partial.build(data), child_slices, value_slice)
172			},
173		}
174	}
175}
176
177/// An `OwnedNode` is an owned type from which a `Node` can be constructed which borrows data from
178/// the `OwnedNode`. This is useful for trie iterators.
179#[cfg_attr(feature = "std", derive(Debug))]
180#[derive(PartialEq, Eq)]
181pub struct OwnedNode<D: Borrow<[u8]>> {
182	data: D,
183	plan: NodePlan,
184}
185
186impl<D: Borrow<[u8]>> OwnedNode<D> {
187	/// Construct an `OwnedNode` by decoding an owned data source according to some codec.
188	pub fn new<C: NodeCodec>(data: D) -> Result<Self, C::Error> {
189		let plan = C::decode_plan(data.borrow())?;
190		Ok(OwnedNode { data, plan })
191	}
192
193	/// Returns a reference to the backing data.
194	pub fn data(&self) -> &[u8] {
195		self.data.borrow()
196	}
197
198	/// Returns a reference to the node decode plan.
199	pub fn node_plan(&self) -> &NodePlan {
200		&self.plan
201	}
202
203	/// Construct a `Node` by borrowing data from this struct.
204	pub fn node(&self) -> Node {
205		self.plan.build(self.data.borrow())
206	}
207}