push value into the Branch struct

This commit is contained in:
Johann Tuffe 2018-08-24 16:32:58 +08:00
parent 7ed5f2d4af
commit 3002bffe7d
2 changed files with 38 additions and 18 deletions

View File

@ -35,26 +35,43 @@ pub enum Node<'a> {
Branch([&'a [u8]; 16], Option<&'a [u8]>), Branch([&'a [u8]; 16], Option<&'a [u8]>),
} }
/// A Sparse (non mutable) owned vector struct to hold branch keys /// A Sparse (non mutable) owned vector struct to hold branch keys and value
#[derive(Eq, PartialEq, Debug, Clone)] #[derive(Eq, PartialEq, Debug, Clone)]
pub struct BranchKeys { pub struct Branch {
data: Vec<u8>, data: Vec<u8>,
ubounds: [usize; 17], ubounds: [usize; 18],
has_value: bool,
} }
impl<'a> From<[&'a [u8]; 16]> for BranchKeys { impl Branch {
fn from(a: [&'a [u8]; 16]) -> Self { fn new(a: [&[u8]; 16], value: Option<&[u8]>) -> Self {
let mut data = Vec::with_capacity(a.iter().map(|inner| inner.len()).sum()); let mut data = Vec::with_capacity(a.iter().map(|inner| inner.len()).sum());
let mut ubounds = [0; 17]; let mut ubounds = [0; 18];
for (inner, ub) in a.iter().zip(ubounds.iter_mut().skip(1)) { for (inner, ub) in a.iter().zip(ubounds.iter_mut().skip(1)) {
data.extend_from_slice(inner); data.extend_from_slice(inner);
*ub = data.len(); *ub = data.len();
} }
BranchKeys { data, ubounds } if let Some(value) = value {
data.extend(value);
ubounds[17] = data.len();
}
Branch { data, ubounds, has_value: value.is_some() }
}
pub fn get_value(&self) -> Option<&[u8]> {
if self.has_value {
Some(&self.data[self.ubounds[16]..self.ubounds[17]])
} else {
None
}
}
pub fn has_value(&self) -> bool {
self.has_value
} }
} }
impl ::std::ops::Index<usize> for BranchKeys { impl ::std::ops::Index<usize> for Branch {
type Output = [u8]; type Output = [u8];
fn index(&self, index: usize) -> &[u8] { fn index(&self, index: usize) -> &[u8] {
assert!(index < 16); assert!(index < 16);
@ -72,7 +89,7 @@ pub enum OwnedNode {
/// Extension node: partial key and child node. /// Extension node: partial key and child node.
Extension(NibbleVec, DBValue), Extension(NibbleVec, DBValue),
/// Branch node: 16 children and an optional value. /// Branch node: 16 children and an optional value.
Branch(BranchKeys, Option<DBValue>), Branch(Branch),
} }
impl<'a> From<Node<'a>> for OwnedNode { impl<'a> From<Node<'a>> for OwnedNode {
@ -81,7 +98,7 @@ impl<'a> From<Node<'a>> for OwnedNode {
Node::Empty => OwnedNode::Empty, Node::Empty => OwnedNode::Empty,
Node::Leaf(k, v) => OwnedNode::Leaf(k.into(), DBValue::from_slice(v)), 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::Extension(k, child) => OwnedNode::Extension(k.into(), DBValue::from_slice(child)),
Node::Branch(c, val) => OwnedNode::Branch(c.into(), val.map(DBValue::from_slice)), Node::Branch(c, val) => OwnedNode::Branch(Branch::new(c, val)),
} }
} }
} }

View File

@ -216,8 +216,8 @@ impl Crumb {
self.status = match (&self.status, &self.node) { self.status = match (&self.status, &self.node) {
(_, &OwnedNode::Empty) => Status::Exiting, (_, &OwnedNode::Empty) => Status::Exiting,
(&Status::Entering, _) => Status::At, (&Status::Entering, _) => Status::At,
(&Status::At, &OwnedNode::Branch(_, _)) => Status::AtChild(0), (&Status::At, &OwnedNode::Branch(_)) => Status::AtChild(0),
(&Status::AtChild(x), &OwnedNode::Branch(_, _)) if x < 15 => Status::AtChild(x + 1), (&Status::AtChild(x), &OwnedNode::Branch(_)) if x < 15 => Status::AtChild(x + 1),
_ => Status::Exiting, _ => Status::Exiting,
} }
} }
@ -365,27 +365,30 @@ impl<'a, H: Hasher, C: NodeCodec<H>> Iterator for TrieDBIterator<'a, H, C> {
let l = self.key_nibbles.len(); let l = self.key_nibbles.len();
self.key_nibbles.truncate(l - n.len()); self.key_nibbles.truncate(l - n.len());
}, },
OwnedNode::Branch(_, _) => { self.key_nibbles.pop(); }, OwnedNode::Branch(_) => { self.key_nibbles.pop(); },
_ => {} _ => {}
} }
IterStep::PopTrail IterStep::PopTrail
}, },
(Status::At, &OwnedNode::Leaf(_, ref v)) | (Status::At, &OwnedNode::Branch(_, Some(ref v))) => { (Status::At, &OwnedNode::Branch(ref branch)) if branch.has_value() => {
return Some(Ok((self.key(), DBValue::from_slice(branch.get_value().unwrap()))));
},
(Status::At, &OwnedNode::Leaf(_, ref v)) => {
return Some(Ok((self.key(), v.clone()))); return Some(Ok((self.key(), v.clone())));
}, },
(Status::At, &OwnedNode::Extension(_, ref d)) => { (Status::At, &OwnedNode::Extension(_, ref d)) => {
IterStep::Descend::<H::Out, C::Error>(self.db.get_raw_or_lookup(&*d)) IterStep::Descend::<H::Out, C::Error>(self.db.get_raw_or_lookup(&*d))
}, },
(Status::At, &OwnedNode::Branch(_, _)) => IterStep::Continue, (Status::At, &OwnedNode::Branch(_)) => IterStep::Continue,
(Status::AtChild(i), &OwnedNode::Branch(ref children, _)) if children[i].len() > 0 => { (Status::AtChild(i), &OwnedNode::Branch(ref branch)) if branch[i].len() > 0 => {
match i { match i {
0 => self.key_nibbles.push(0), 0 => self.key_nibbles.push(0),
i => *self.key_nibbles.last_mut() i => *self.key_nibbles.last_mut()
.expect("pushed as 0; moves sequentially; removed afterwards; qed") = i as u8, .expect("pushed as 0; moves sequentially; removed afterwards; qed") = i as u8,
} }
IterStep::Descend::<H::Out, C::Error>(self.db.get_raw_or_lookup(&children[i])) IterStep::Descend::<H::Out, C::Error>(self.db.get_raw_or_lookup(&branch[i]))
}, },
(Status::AtChild(i), &OwnedNode::Branch(_, _)) => { (Status::AtChild(i), &OwnedNode::Branch(_)) => {
if i == 0 { if i == 0 {
self.key_nibbles.push(0); self.key_nibbles.push(0);
} }