diff --git a/src/rlp.rs b/src/rlp.rs index c023b1dfb..b055632b1 100644 --- a/src/rlp.rs +++ b/src/rlp.rs @@ -65,16 +65,16 @@ impl OffsetCache { } } -/// stores basic information about item -struct ItemInfo { - prefix_len: usize, - value_len: usize, +/// Stores basic information about item +pub struct PayloadInfo { + pub header_len: usize, + pub value_len: usize, } -impl ItemInfo { - fn new(prefix_len: usize, value_len: usize) -> ItemInfo { - ItemInfo { - prefix_len: prefix_len, +impl PayloadInfo { + fn new(header_len: usize, value_len: usize) -> PayloadInfo { + PayloadInfo { + header_len: header_len, value_len: value_len, } } @@ -86,7 +86,6 @@ pub enum DecoderError { RlpIsTooShort, RlpExpectedToBeList, RlpExpectedToBeData, - BadRlp, } impl StdError for DecoderError { fn description(&self) -> &str { @@ -170,6 +169,10 @@ impl<'a, 'view> Rlp<'a> where 'a: 'view { self.rlp.raw() } + pub fn payload_info(&self) -> PayloadInfo { + self.rlp.payload_info().unwrap() + } + pub fn data(&'view self) -> &'a [u8] { self.rlp.data() } @@ -354,9 +357,13 @@ impl<'a, 'view> UntrustedRlp<'a> where 'a: 'view { self.bytes } + pub fn payload_info(&self) -> Result { + BasicDecoder::payload_info(self.bytes) + } + pub fn data(&'view self) -> &'a [u8] { - let ii = Self::item_info(self.bytes).unwrap(); - &self.bytes[ii.prefix_len..(ii.prefix_len + ii.value_len)] + let ii = BasicDecoder::payload_info(self.bytes).unwrap(); + &self.bytes[ii.header_len..(ii.header_len + ii.value_len)] } /// Returns number of rlp items. @@ -396,7 +403,7 @@ impl<'a, 'view> UntrustedRlp<'a> where 'a: 'view { /// ``` pub fn size(&self) -> usize { match self.is_data() { - true => Self::item_info(self.bytes).unwrap().value_len, + true => BasicDecoder::payload_info(self.bytes).unwrap().value_len, 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())); // construct new rlp - let found = try!(UntrustedRlp::item_info(bytes)); - Ok(UntrustedRlp::new(&bytes[0..found.prefix_len + found.value_len])) + let found = try!(BasicDecoder::payload_info(bytes)); + Ok(UntrustedRlp::new(&bytes[0..found.header_len + found.value_len])) } /// No value @@ -552,8 +559,8 @@ impl<'a, 'view> UntrustedRlp<'a> where 'a: 'view { /// consumes first found prefix fn consume_list_prefix(&self) -> Result<&'a [u8], DecoderError> { - let item = try!(UntrustedRlp::item_info(self.bytes)); - let bytes = try!(UntrustedRlp::consume(self.bytes, item.prefix_len)); + let item = try!(BasicDecoder::payload_info(self.bytes)); + let bytes = try!(UntrustedRlp::consume(self.bytes, item.header_len)); 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> { let mut result = bytes; for _ in 0..items { - let i = try!(UntrustedRlp::item_info(result)); - result = try!(UntrustedRlp::consume(result, (i.prefix_len + i.value_len))); + let i = try!(BasicDecoder::payload_info(result)); + result = try!(UntrustedRlp::consume(result, (i.header_len + i.value_len))); } Ok(result) } - /// return first item info - /// - /// TODO: move this to decoder (?) - fn item_info(bytes: &[u8]) -> Result { - 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` fn consume(bytes: &'a [u8], len: usize) -> Result<&'a [u8], DecoderError> { @@ -727,6 +705,37 @@ pub trait Decoder { struct BasicDecoder; +impl BasicDecoder { + /// Return first item info + fn payload_info(bytes: &[u8]) -> Result { + 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 { fn read_value(bytes: &[u8], f: F) -> Result where F: FnOnce(&[u8]) -> Result { 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])); 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']); /// } /// ``` - 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 object.encode(&mut self.encoder); diff --git a/src/triehash.rs b/src/triehash.rs index c06cdb249..778dc7f17 100644 --- a/src/triehash.rs +++ b/src/triehash.rs @@ -145,7 +145,6 @@ fn as_nibbles(bytes: &[u8]) -> Vec { fn hash256rlp(input: &[(Vec, Vec)], pre_len: usize, stream: &mut RlpStream) { let inlen = input.len(); - //println!("input: {:?}", input); // in case of empty slice, just append empty data if inlen == 0 { stream.append_empty_data(); @@ -174,7 +173,6 @@ fn hash256rlp(input: &[(Vec, Vec)], pre_len: usize, stream: &mut RlpStre 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 // new part of the key to the stream // then recursively append suffixes of all items who had this key @@ -200,8 +198,8 @@ fn hash256rlp(input: &[(Vec, Vec)], pre_len: usize, stream: &mut RlpStre // cout how many successive elements have same next nibble let len = match begin < input.len() { true => input[begin..].iter() - .take_while(| pair | { /*println!("{:?}", pair.0);*/ pair.0[pre_len] == i }).count(), - //.take_while(|&q| q == i).count(), + .take_while(| pair | pair.0[pre_len] == i ) + .count(), false => 0 }; @@ -280,7 +278,10 @@ fn test_hex_prefix_encode() { #[cfg(test)] mod tests { use std::str::FromStr; + use std::collections::BTreeMap; use rustc_serialize::hex::FromHex; + use rustc_serialize::json::Json; + use bytes::*; use hash::*; use triehash::*; @@ -377,4 +378,19 @@ mod tests { 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); + } + }