Merge remote-tracking branch 'parity/master'

This commit is contained in:
keorn
2016-09-27 12:14:40 +02:00
108 changed files with 2478 additions and 1207 deletions

View File

@@ -174,6 +174,8 @@ pub enum FromBytesError {
DataIsTooLong,
/// Integer-representation is non-canonically prefixed with zero byte(s).
ZeroPrefixedInt,
/// String representation is not utf-8
InvalidUtf8,
}
impl StdError for FromBytesError {
@@ -199,7 +201,7 @@ pub trait FromBytes: Sized {
impl FromBytes for String {
fn from_bytes(bytes: &[u8]) -> FromBytesResult<String> {
Ok(::std::str::from_utf8(bytes).unwrap().to_owned())
::std::str::from_utf8(bytes).map(|s| s.to_owned()).map_err(|_| FromBytesError::InvalidUtf8)
}
}

View File

@@ -20,6 +20,7 @@
//! as
use std::fmt;
use std::cmp::min;
use std::ops::{Deref, DerefMut};
/// Slice pretty print helper
@@ -71,6 +72,32 @@ pub enum BytesRef<'a> {
Fixed(&'a mut [u8])
}
impl<'a> BytesRef<'a> {
/// Writes given `input` to this `BytesRef` starting at `offset`.
/// Returns number of bytes written to the ref.
/// NOTE can return number greater then `input.len()` in case flexible vector had to be extended.
pub fn write(&mut self, offset: usize, input: &[u8]) -> usize {
match *self {
BytesRef::Flexible(ref mut data) => {
let data_len = data.len();
let wrote = input.len() + if data_len > offset { 0 } else { offset - data_len };
data.resize(offset, 0);
data.extend_from_slice(input);
wrote
},
BytesRef::Fixed(ref mut data) if offset < data.len() => {
let max = min(data.len() - offset, input.len());
for i in 0..max {
data[offset + i] = input[i];
}
max
},
_ => 0
}
}
}
impl<'a> Deref for BytesRef<'a> {
type Target = [u8];
@@ -92,4 +119,61 @@ impl <'a> DerefMut for BytesRef<'a> {
}
/// Vector of bytes.
pub type Bytes = Vec<u8>;
pub type Bytes = Vec<u8>;
#[cfg(test)]
mod tests {
use super::BytesRef;
#[test]
fn should_write_bytes_to_fixed_bytesref() {
// given
let mut data1 = vec![0, 0, 0];
let mut data2 = vec![0, 0, 0];
let (res1, res2) = {
let mut bytes1 = BytesRef::Fixed(&mut data1[..]);
let mut bytes2 = BytesRef::Fixed(&mut data2[1..2]);
// when
let res1 = bytes1.write(1, &[1, 1, 1]);
let res2 = bytes2.write(3, &[1, 1, 1]);
(res1, res2)
};
// then
assert_eq!(&data1, &[0, 1, 1]);
assert_eq!(res1, 2);
assert_eq!(&data2, &[0, 0, 0]);
assert_eq!(res2, 0);
}
#[test]
fn should_write_bytes_to_flexible_bytesref() {
// given
let mut data1 = vec![0, 0, 0];
let mut data2 = vec![0, 0, 0];
let mut data3 = vec![0, 0, 0];
let (res1, res2, res3) = {
let mut bytes1 = BytesRef::Flexible(&mut data1);
let mut bytes2 = BytesRef::Flexible(&mut data2);
let mut bytes3 = BytesRef::Flexible(&mut data3);
// when
let res1 = bytes1.write(1, &[1, 1, 1]);
let res2 = bytes2.write(3, &[1, 1, 1]);
let res3 = bytes3.write(5, &[1, 1, 1]);
(res1, res2, res3)
};
// then
assert_eq!(&data1, &[0, 1, 1, 1]);
assert_eq!(res1, 3);
assert_eq!(&data2, &[0, 0, 0, 1, 1, 1]);
assert_eq!(res2, 3);
assert_eq!(&data3, &[0, 0, 0, 0, 0, 1, 1, 1]);
assert_eq!(res3, 5);
}
}

View File

@@ -46,8 +46,8 @@ impl<'db> FatDB<'db> {
}
impl<'db> Trie for FatDB<'db> {
fn iter<'a>(&'a self) -> Box<Iterator<Item = TrieItem> + 'a> {
Box::new(FatDBIterator::new(&self.raw))
fn iter<'a>(&'a self) -> super::Result<Box<Iterator<Item = TrieItem> + 'a>> {
FatDBIterator::new(&self.raw).map(|iter| Box::new(iter) as Box<_>)
}
fn root(&self) -> &H256 {
@@ -73,22 +73,24 @@ pub struct FatDBIterator<'db> {
impl<'db> FatDBIterator<'db> {
/// Creates new iterator.
pub fn new(trie: &'db TrieDB) -> Self {
FatDBIterator {
trie_iterator: TrieDBIterator::new(trie),
pub fn new(trie: &'db TrieDB) -> super::Result<Self> {
Ok(FatDBIterator {
trie_iterator: try!(TrieDBIterator::new(trie)),
trie: trie,
}
})
}
}
impl<'db> Iterator for FatDBIterator<'db> {
type Item = (Vec<u8>, &'db [u8]);
type Item = TrieItem<'db>;
fn next(&mut self) -> Option<Self::Item> {
self.trie_iterator.next()
.map(|(hash, value)| {
(self.trie.db().get_aux(&hash).expect("Missing fatdb hash"), value)
})
.map(|res|
res.map(|(hash, value)| {
(self.trie.db().get_aux(&hash).expect("Missing fatdb hash"), value)
})
)
}
}
@@ -105,5 +107,5 @@ fn fatdb_to_trie() {
}
let t = FatDB::new(&memdb, &root).unwrap();
assert_eq!(t.get(&[0x01u8, 0x23]).unwrap().unwrap(), &[0x01u8, 0x23]);
assert_eq!(t.iter().collect::<Vec<_>>(), vec![(vec![0x01u8, 0x23], &[0x01u8, 0x23] as &[u8])]);
assert_eq!(t.iter().unwrap().map(Result::unwrap).collect::<Vec<_>>(), vec![(vec![0x01u8, 0x23], &[0x01u8, 0x23] as &[u8])]);
}

View File

@@ -72,12 +72,12 @@ impl fmt::Display for TrieError {
}
}
/// Trie-Item type.
pub type TrieItem<'a> = (Vec<u8>, &'a [u8]);
/// Trie result type. Boxed to avoid copying around extra space for `H256`s on successful queries.
pub type Result<T> = ::std::result::Result<T, Box<TrieError>>;
/// Trie-Item type.
pub type TrieItem<'a> = Result<(Vec<u8>, &'a [u8])>;
/// A key-value datastore implemented as a database-backed modified Merkle tree.
pub trait Trie {
/// Return the root of the trie.
@@ -102,7 +102,7 @@ pub trait Trie {
where 'a: 'b, R: Recorder;
/// Returns an iterator over elements of trie.
fn iter<'a>(&'a self) -> Box<Iterator<Item = TrieItem> + 'a>;
fn iter<'a>(&'a self) -> Result<Box<Iterator<Item = TrieItem> + 'a>>;
}
/// A key-value datastore implemented as a database-backed modified Merkle tree.
@@ -193,7 +193,7 @@ impl<'db> Trie for TrieKinds<'db> {
wrapper!(self, get_recorded, key, r)
}
fn iter<'a>(&'a self) -> Box<Iterator<Item = TrieItem> + 'a> {
fn iter<'a>(&'a self) -> Result<Box<Iterator<Item = TrieItem> + 'a>> {
wrapper!(self, iter,)
}
}

View File

@@ -49,8 +49,8 @@ impl<'db> SecTrieDB<'db> {
}
impl<'db> Trie for SecTrieDB<'db> {
fn iter<'a>(&'a self) -> Box<Iterator<Item = TrieItem> + 'a> {
Box::new(TrieDB::iter(&self.raw))
fn iter<'a>(&'a self) -> super::Result<Box<Iterator<Item = TrieItem> + 'a>> {
TrieDB::iter(&self.raw)
}
fn root(&self) -> &H256 { self.raw.root() }

View File

@@ -279,30 +279,38 @@ pub struct TrieDBIterator<'a> {
impl<'a> TrieDBIterator<'a> {
/// Create a new iterator.
pub fn new(db: &'a TrieDB) -> TrieDBIterator<'a> {
pub fn new(db: &'a TrieDB) -> super::Result<TrieDBIterator<'a>> {
let mut r = TrieDBIterator {
db: db,
trail: vec![],
key_nibbles: Vec::new(),
};
r.descend(db.root_data(&mut NoOp).unwrap());
r
try!(db.root_data(&mut NoOp).and_then(|root| r.descend(root)));
Ok(r)
}
/// Descend into a payload.
fn descend(&mut self, d: &'a [u8]) {
fn descend(&mut self, d: &'a [u8]) -> super::Result<()> {
self.trail.push(Crumb {
status: Status::Entering,
node: self.db.get_node(d, &mut NoOp, 0).unwrap(),
node: try!(self.db.get_node(d, &mut NoOp, 0)),
});
match self.trail.last().unwrap().node {
Node::Leaf(n, _) | Node::Extension(n, _) => { self.key_nibbles.extend(n.iter()); },
_ => {}
}
Ok(())
}
/// Descend into a payload and get the next item.
fn descend_next(&mut self, d: &'a [u8]) -> Option<(Bytes, &'a [u8])> { self.descend(d); self.next() }
fn descend_next(&mut self, d: &'a [u8]) -> Option<TrieItem<'a>> {
match self.descend(d) {
Ok(()) => self.next(),
Err(e) => Some(Err(e)),
}
}
/// The present key.
fn key(&self) -> Bytes {
@@ -312,12 +320,12 @@ impl<'a> TrieDBIterator<'a> {
}
impl<'a> Iterator for TrieDBIterator<'a> {
type Item = (Bytes, &'a [u8]);
type Item = TrieItem<'a>;
fn next(&mut self) -> Option<Self::Item> {
let b = match self.trail.last_mut() {
Some(mut b) => { b.increment(); b.clone() },
None => return None
None => return None,
};
match (b.status, b.node) {
(Status::Exiting, n) => {
@@ -332,7 +340,7 @@ impl<'a> Iterator for TrieDBIterator<'a> {
self.trail.pop();
self.next()
},
(Status::At, Node::Leaf(_, v)) | (Status::At, Node::Branch(_, Some(v))) => Some((self.key(), v)),
(Status::At, Node::Leaf(_, v)) | (Status::At, Node::Branch(_, Some(v))) => Some(Ok((self.key(), v))),
(Status::At, Node::Extension(_, d)) => self.descend_next(d),
(Status::At, Node::Branch(_, _)) => self.next(),
(Status::AtChild(i), Node::Branch(children, _)) if children[i].len() > 0 => {
@@ -352,8 +360,8 @@ impl<'a> Iterator for TrieDBIterator<'a> {
}
impl<'db> Trie for TrieDB<'db> {
fn iter<'a>(&'a self) -> Box<Iterator<Item = TrieItem> + 'a> {
Box::new(TrieDBIterator::new(self))
fn iter<'a>(&'a self) -> super::Result<Box<Iterator<Item = TrieItem> + 'a>> {
TrieDBIterator::new(self).map(|iter| Box::new(iter) as Box<_>)
}
fn root(&self) -> &H256 { self.root }
@@ -392,6 +400,6 @@ fn iterator() {
}
let t = TrieDB::new(&memdb, &root).unwrap();
assert_eq!(d.iter().map(|i|i.to_vec()).collect::<Vec<_>>(), t.iter().map(|x|x.0).collect::<Vec<_>>());
assert_eq!(d, t.iter().map(|x|x.1).collect::<Vec<_>>());
assert_eq!(d.iter().map(|i|i.to_vec()).collect::<Vec<_>>(), t.iter().unwrap().map(|x| x.unwrap().0).collect::<Vec<_>>());
assert_eq!(d, t.iter().unwrap().map(|x| x.unwrap().1).collect::<Vec<_>>());
}

View File

@@ -40,7 +40,9 @@ use vector::SharedPrefix;
/// assert_eq!(ordered_trie_root(v), H256::from_str(root).unwrap());
/// }
/// ```
pub fn ordered_trie_root(input: Vec<Vec<u8>>) -> H256 {
pub fn ordered_trie_root<I>(input: I) -> H256
where I: IntoIterator<Item=Vec<u8>>
{
let gen_input = input
// first put elements into btree to sort them by nibbles
// optimize it later