Merge branch 'master' of github.com:gavofyork/ethcore-util
This commit is contained in:
commit
729968ebeb
108
src/rlp.rs
108
src/rlp.rs
@ -65,16 +65,16 @@ impl OffsetCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// stores basic information about item
|
/// Stores basic information about item
|
||||||
struct ItemInfo {
|
pub struct PayloadInfo {
|
||||||
prefix_len: usize,
|
pub header_len: usize,
|
||||||
value_len: usize,
|
pub value_len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ItemInfo {
|
impl PayloadInfo {
|
||||||
fn new(prefix_len: usize, value_len: usize) -> ItemInfo {
|
fn new(header_len: usize, value_len: usize) -> PayloadInfo {
|
||||||
ItemInfo {
|
PayloadInfo {
|
||||||
prefix_len: prefix_len,
|
header_len: header_len,
|
||||||
value_len: value_len,
|
value_len: value_len,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,7 +86,6 @@ pub enum DecoderError {
|
|||||||
RlpIsTooShort,
|
RlpIsTooShort,
|
||||||
RlpExpectedToBeList,
|
RlpExpectedToBeList,
|
||||||
RlpExpectedToBeData,
|
RlpExpectedToBeData,
|
||||||
BadRlp,
|
|
||||||
}
|
}
|
||||||
impl StdError for DecoderError {
|
impl StdError for DecoderError {
|
||||||
fn description(&self) -> &str {
|
fn description(&self) -> &str {
|
||||||
@ -170,6 +169,10 @@ impl<'a, 'view> Rlp<'a> where 'a: 'view {
|
|||||||
self.rlp.raw()
|
self.rlp.raw()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn payload_info(&self) -> PayloadInfo {
|
||||||
|
self.rlp.payload_info().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn data(&'view self) -> &'a [u8] {
|
pub fn data(&'view self) -> &'a [u8] {
|
||||||
self.rlp.data()
|
self.rlp.data()
|
||||||
}
|
}
|
||||||
@ -354,9 +357,13 @@ impl<'a, 'view> UntrustedRlp<'a> where 'a: 'view {
|
|||||||
self.bytes
|
self.bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn payload_info(&self) -> Result<PayloadInfo, DecoderError> {
|
||||||
|
BasicDecoder::payload_info(self.bytes)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn data(&'view self) -> &'a [u8] {
|
pub fn data(&'view self) -> &'a [u8] {
|
||||||
let ii = Self::item_info(self.bytes).unwrap();
|
let ii = BasicDecoder::payload_info(self.bytes).unwrap();
|
||||||
&self.bytes[ii.prefix_len..(ii.prefix_len + ii.value_len)]
|
&self.bytes[ii.header_len..(ii.header_len + ii.value_len)]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns number of rlp items.
|
/// Returns number of rlp items.
|
||||||
@ -396,7 +403,7 @@ impl<'a, 'view> UntrustedRlp<'a> where 'a: 'view {
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn size(&self) -> usize {
|
pub fn size(&self) -> usize {
|
||||||
match self.is_data() {
|
match self.is_data() {
|
||||||
true => Self::item_info(self.bytes).unwrap().value_len,
|
true => BasicDecoder::payload_info(self.bytes).unwrap().value_len,
|
||||||
false => 0
|
false => 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -437,8 +444,8 @@ impl<'a, 'view> UntrustedRlp<'a> where 'a: 'view {
|
|||||||
self.cache.set(OffsetCache::new(index, self.bytes.len() - bytes.len()));
|
self.cache.set(OffsetCache::new(index, self.bytes.len() - bytes.len()));
|
||||||
|
|
||||||
// construct new rlp
|
// construct new rlp
|
||||||
let found = try!(UntrustedRlp::item_info(bytes));
|
let found = try!(BasicDecoder::payload_info(bytes));
|
||||||
Ok(UntrustedRlp::new(&bytes[0..found.prefix_len + found.value_len]))
|
Ok(UntrustedRlp::new(&bytes[0..found.header_len + found.value_len]))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// No value
|
/// No value
|
||||||
@ -552,8 +559,8 @@ impl<'a, 'view> UntrustedRlp<'a> where 'a: 'view {
|
|||||||
|
|
||||||
/// consumes first found prefix
|
/// consumes first found prefix
|
||||||
fn consume_list_prefix(&self) -> Result<&'a [u8], DecoderError> {
|
fn consume_list_prefix(&self) -> Result<&'a [u8], DecoderError> {
|
||||||
let item = try!(UntrustedRlp::item_info(self.bytes));
|
let item = try!(BasicDecoder::payload_info(self.bytes));
|
||||||
let bytes = try!(UntrustedRlp::consume(self.bytes, item.prefix_len));
|
let bytes = try!(UntrustedRlp::consume(self.bytes, item.header_len));
|
||||||
Ok(bytes)
|
Ok(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -561,41 +568,12 @@ impl<'a, 'view> UntrustedRlp<'a> where 'a: 'view {
|
|||||||
fn consume_items(bytes: &'a [u8], items: usize) -> Result<&'a [u8], DecoderError> {
|
fn consume_items(bytes: &'a [u8], items: usize) -> Result<&'a [u8], DecoderError> {
|
||||||
let mut result = bytes;
|
let mut result = bytes;
|
||||||
for _ in 0..items {
|
for _ in 0..items {
|
||||||
let i = try!(UntrustedRlp::item_info(result));
|
let i = try!(BasicDecoder::payload_info(result));
|
||||||
result = try!(UntrustedRlp::consume(result, (i.prefix_len + i.value_len)));
|
result = try!(UntrustedRlp::consume(result, (i.header_len + i.value_len)));
|
||||||
}
|
}
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// return first item info
|
|
||||||
///
|
|
||||||
/// TODO: move this to decoder (?)
|
|
||||||
fn item_info(bytes: &[u8]) -> Result<ItemInfo, DecoderError> {
|
|
||||||
let item = match bytes.first().map(|&x| x) {
|
|
||||||
None => return Err(DecoderError::RlpIsTooShort),
|
|
||||||
Some(0...0x7f) => ItemInfo::new(0, 1),
|
|
||||||
Some(l @ 0x80...0xb7) => ItemInfo::new(1, l as usize - 0x80),
|
|
||||||
Some(l @ 0xb8...0xbf) => {
|
|
||||||
let len_of_len = l as usize - 0xb7;
|
|
||||||
let prefix_len = 1 + len_of_len;
|
|
||||||
let value_len = try!(usize::from_bytes(&bytes[1..prefix_len]));
|
|
||||||
ItemInfo::new(prefix_len, value_len)
|
|
||||||
}
|
|
||||||
Some(l @ 0xc0...0xf7) => ItemInfo::new(1, l as usize - 0xc0),
|
|
||||||
Some(l @ 0xf8...0xff) => {
|
|
||||||
let len_of_len = l as usize - 0xf7;
|
|
||||||
let prefix_len = 1 + len_of_len;
|
|
||||||
let value_len = try!(usize::from_bytes(&bytes[1..prefix_len]));
|
|
||||||
ItemInfo::new(prefix_len, value_len)
|
|
||||||
}
|
|
||||||
_ => return Err(DecoderError::BadRlp),
|
|
||||||
};
|
|
||||||
|
|
||||||
match item.prefix_len + item.value_len <= bytes.len() {
|
|
||||||
true => Ok(item),
|
|
||||||
false => Err(DecoderError::RlpIsTooShort),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// consumes slice prefix of length `len`
|
/// consumes slice prefix of length `len`
|
||||||
fn consume(bytes: &'a [u8], len: usize) -> Result<&'a [u8], DecoderError> {
|
fn consume(bytes: &'a [u8], len: usize) -> Result<&'a [u8], DecoderError> {
|
||||||
@ -727,6 +705,37 @@ pub trait Decoder {
|
|||||||
|
|
||||||
struct BasicDecoder;
|
struct BasicDecoder;
|
||||||
|
|
||||||
|
impl BasicDecoder {
|
||||||
|
/// Return first item info
|
||||||
|
fn payload_info(bytes: &[u8]) -> Result<PayloadInfo, DecoderError> {
|
||||||
|
let item = match bytes.first().map(|&x| x) {
|
||||||
|
None => return Err(DecoderError::RlpIsTooShort),
|
||||||
|
Some(0...0x7f) => PayloadInfo::new(0, 1),
|
||||||
|
Some(l @ 0x80...0xb7) => PayloadInfo::new(1, l as usize - 0x80),
|
||||||
|
Some(l @ 0xb8...0xbf) => {
|
||||||
|
let len_of_len = l as usize - 0xb7;
|
||||||
|
let header_len = 1 + len_of_len;
|
||||||
|
let value_len = try!(usize::from_bytes(&bytes[1..header_len]));
|
||||||
|
PayloadInfo::new(header_len, value_len)
|
||||||
|
}
|
||||||
|
Some(l @ 0xc0...0xf7) => PayloadInfo::new(1, l as usize - 0xc0),
|
||||||
|
Some(l @ 0xf8...0xff) => {
|
||||||
|
let len_of_len = l as usize - 0xf7;
|
||||||
|
let header_len = 1 + len_of_len;
|
||||||
|
let value_len = try!(usize::from_bytes(&bytes[1..header_len]));
|
||||||
|
PayloadInfo::new(header_len, value_len)
|
||||||
|
},
|
||||||
|
// we cant reach this place, but rust requires _ to be implemented
|
||||||
|
_ => { panic!(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
match item.header_len + item.value_len <= bytes.len() {
|
||||||
|
true => Ok(item),
|
||||||
|
false => Err(DecoderError::RlpIsTooShort),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Decoder for BasicDecoder {
|
impl Decoder for BasicDecoder {
|
||||||
fn read_value<T, F>(bytes: &[u8], f: F) -> Result<T, DecoderError> where F: FnOnce(&[u8]) -> Result<T, DecoderError> {
|
fn read_value<T, F>(bytes: &[u8], f: F) -> Result<T, DecoderError> where F: FnOnce(&[u8]) -> Result<T, DecoderError> {
|
||||||
match bytes.first().map(|&x| x) {
|
match bytes.first().map(|&x| x) {
|
||||||
@ -743,7 +752,8 @@ impl Decoder for BasicDecoder {
|
|||||||
let len = try!(usize::from_bytes(&bytes[1..begin_of_value]));
|
let len = try!(usize::from_bytes(&bytes[1..begin_of_value]));
|
||||||
Ok(try!(f(&bytes[begin_of_value..begin_of_value + len])))
|
Ok(try!(f(&bytes[begin_of_value..begin_of_value + len])))
|
||||||
}
|
}
|
||||||
_ => Err(DecoderError::BadRlp),
|
// we are reading value, not a list!
|
||||||
|
_ => { panic!(); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -800,7 +810,7 @@ impl RlpStream {
|
|||||||
/// assert_eq!(out, vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']);
|
/// assert_eq!(out, vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']);
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn append<'a, E>(&'a mut self, object: &E) -> &'a mut RlpStream where E: Encodable + fmt::Debug {
|
pub fn append<'a, E>(&'a mut self, object: &E) -> &'a mut RlpStream where E: Encodable {
|
||||||
// encode given value and add it at the end of the stream
|
// encode given value and add it at the end of the stream
|
||||||
object.encode(&mut self.encoder);
|
object.encode(&mut self.encoder);
|
||||||
|
|
||||||
|
@ -145,7 +145,6 @@ fn as_nibbles(bytes: &[u8]) -> Vec<u8> {
|
|||||||
fn hash256rlp(input: &[(Vec<u8>, Vec<u8>)], pre_len: usize, stream: &mut RlpStream) {
|
fn hash256rlp(input: &[(Vec<u8>, Vec<u8>)], pre_len: usize, stream: &mut RlpStream) {
|
||||||
let inlen = input.len();
|
let inlen = input.len();
|
||||||
|
|
||||||
//println!("input: {:?}", input);
|
|
||||||
// in case of empty slice, just append empty data
|
// in case of empty slice, just append empty data
|
||||||
if inlen == 0 {
|
if inlen == 0 {
|
||||||
stream.append_empty_data();
|
stream.append_empty_data();
|
||||||
@ -174,7 +173,6 @@ fn hash256rlp(input: &[(Vec<u8>, Vec<u8>)], pre_len: usize, stream: &mut RlpStre
|
|||||||
cmp::min(key.shared_prefix_len(&k), acc)
|
cmp::min(key.shared_prefix_len(&k), acc)
|
||||||
});
|
});
|
||||||
|
|
||||||
// println!("shared_prefix: {}, prefix_len: {}", shared_prefix, pre_len);
|
|
||||||
// if shared prefix is higher than current prefix append its
|
// if shared prefix is higher than current prefix append its
|
||||||
// new part of the key to the stream
|
// new part of the key to the stream
|
||||||
// then recursively append suffixes of all items who had this key
|
// then recursively append suffixes of all items who had this key
|
||||||
@ -200,8 +198,8 @@ fn hash256rlp(input: &[(Vec<u8>, Vec<u8>)], pre_len: usize, stream: &mut RlpStre
|
|||||||
// cout how many successive elements have same next nibble
|
// cout how many successive elements have same next nibble
|
||||||
let len = match begin < input.len() {
|
let len = match begin < input.len() {
|
||||||
true => input[begin..].iter()
|
true => input[begin..].iter()
|
||||||
.take_while(| pair | { /*println!("{:?}", pair.0);*/ pair.0[pre_len] == i }).count(),
|
.take_while(| pair | pair.0[pre_len] == i )
|
||||||
//.take_while(|&q| q == i).count(),
|
.count(),
|
||||||
false => 0
|
false => 0
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -280,7 +278,10 @@ fn test_hex_prefix_encode() {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
use rustc_serialize::hex::FromHex;
|
use rustc_serialize::hex::FromHex;
|
||||||
|
use rustc_serialize::json::Json;
|
||||||
|
use bytes::*;
|
||||||
use hash::*;
|
use hash::*;
|
||||||
use triehash::*;
|
use triehash::*;
|
||||||
|
|
||||||
@ -377,4 +378,19 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(trie_root(v), H256::from_str("9f6221ebb8efe7cff60a716ecb886e67dd042014be444669f0159d8e68b42100").unwrap());
|
assert_eq!(trie_root(v), H256::from_str("9f6221ebb8efe7cff60a716ecb886e67dd042014be444669f0159d8e68b42100").unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_triehash_json_trietest_json() {
|
||||||
|
let data = include_bytes!("../tests/TrieTests/trietest.json");
|
||||||
|
|
||||||
|
let s = String::from_bytes(data).unwrap();
|
||||||
|
let json = Json::from_str(&s).unwrap();
|
||||||
|
let obj = json.as_object().unwrap();
|
||||||
|
|
||||||
|
for (key, value) in obj.iter() {
|
||||||
|
println!("running test: {}", key);
|
||||||
|
}
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user