From 78965b3c5aaff784bdb6ee9b1cd82884b9f2c7ea Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 30 Nov 2015 11:16:50 +0100 Subject: [PATCH 1/6] RlpStream append_null --- src/rlp.rs | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/rlp.rs b/src/rlp.rs index a24c63b46..f76f1f5b9 100644 --- a/src/rlp.rs +++ b/src/rlp.rs @@ -2,7 +2,7 @@ //! //! Allows encoding, decoding, and view onto rlp-slice //! -//!# When should you use what? +//!# What should you use when? //! //!### Use `encode` function when: //! * You want to encode something inline. @@ -555,7 +555,6 @@ impl RlpStream { /// } /// ``` pub fn append<'a, E>(&'a mut self, object: &E) -> &'a mut RlpStream where E: Encodable + fmt::Debug { - //println!("append: {:?}", object); // encode given value and add it at the end of the stream object.encode(&mut self.encoder); @@ -581,7 +580,6 @@ impl RlpStream { /// } /// ``` pub fn append_list<'a>(&'a mut self, len: usize) -> &'a mut RlpStream { - //println!("append_list: {}", len); // push new list let position = self.encoder.bytes.len(); match len { @@ -597,9 +595,32 @@ impl RlpStream { self } + /// Apends null to the end of stream, chainable. + /// + /// ```rust + /// extern crate ethcore_util as util; + /// use util::rlp::*; + /// + /// fn main () { + /// let mut stream = RlpStream::new_list(2); + /// stream.append_null().append_null(); + /// let out = stream.out().unwrap(); + /// assert_eq!(out, vec![0xc2, 0x80, 0x80]); + /// } + /// ``` + pub fn append_null<'a>(&'a mut self) -> &'a mut RlpStream { + // self push raw item + self.encoder.bytes.push(0x80); + + // try to finish and prepend the length + self.try_to_finish(1); + + // return chainable self + self + } + /// Appends raw (pre-serialised) RLP data. Use with caution. Chainable. pub fn append_raw<'a>(&'a mut self, bytes: &[u8], item_count: usize) -> &'a mut RlpStream { - //println!("append_raw: {:?} len: {}, count: {}", bytes, bytes.len(), item_count); // push raw items self.encoder.bytes.extend(bytes); From 2d7ae3a18a22064f6c95df469ffc37f823fe3dda Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 30 Nov 2015 11:24:03 +0100 Subject: [PATCH 2/6] RlpStream out returns value instead of Result --- src/overlaydb.rs | 2 +- src/rlp.rs | 43 +++++++++++++------------------------------ src/triehash.rs | 4 ++-- 3 files changed, 16 insertions(+), 33 deletions(-) diff --git a/src/overlaydb.rs b/src/overlaydb.rs index b6f2b3eb2..24e4ea8da 100644 --- a/src/overlaydb.rs +++ b/src/overlaydb.rs @@ -130,7 +130,7 @@ impl OverlayDB { let mut s = RlpStream::new_list(2); s.append(&payload.1); s.append(&payload.0); - self.backing.put(&key.bytes(), &s.out().unwrap()).expect("Low-level database error. Some issue with your hard disk?"); + self.backing.put(&key.bytes(), &s.out()).expect("Low-level database error. Some issue with your hard disk?"); } } diff --git a/src/rlp.rs b/src/rlp.rs index f76f1f5b9..737f7f416 100644 --- a/src/rlp.rs +++ b/src/rlp.rs @@ -550,7 +550,7 @@ impl RlpStream { /// fn main () { /// let mut stream = RlpStream::new_list(2); /// stream.append(&"cat").append(&"dog"); - /// let out = stream.out().unwrap(); + /// let out = stream.out(); /// assert_eq!(out, vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']); /// } /// ``` @@ -575,7 +575,7 @@ impl RlpStream { /// let mut stream = RlpStream::new_list(2); /// stream.append_list(2).append(&"cat").append(&"dog"); /// stream.append(&""); - /// let out = stream.out().unwrap(); + /// let out = stream.out(); /// assert_eq!(out, vec![0xca, 0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g', 0x80]); /// } /// ``` @@ -604,7 +604,7 @@ impl RlpStream { /// fn main () { /// let mut stream = RlpStream::new_list(2); /// stream.append_null().append_null(); - /// let out = stream.out().unwrap(); + /// let out = stream.out(); /// assert_eq!(out, vec![0xc2, 0x80, 0x80]); /// } /// ``` @@ -643,7 +643,7 @@ impl RlpStream { /// assert_eq!(stream.is_finished(), false); /// stream.append(&"dog"); /// assert_eq!(stream.is_finished(), true); - /// let out = stream.out().unwrap(); + /// let out = stream.out(); /// assert_eq!(out, vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']); /// } pub fn is_finished(&self) -> bool { @@ -652,11 +652,11 @@ impl RlpStream { /// Streams out encoded bytes. /// - /// Returns an error if stream is not finished. - pub fn out(self) -> Result, EncoderError> { + /// panic! if stream is not finished + pub fn out(self) -> Vec { match self.is_finished() { - true => Ok(self.encoder.out()), - false => Err(EncoderError::StreamIsUnfinished), + true => self.encoder.out(), + false => panic!() } } @@ -701,23 +701,6 @@ pub fn encode(object: &E) -> Vec where E: Encodable encoder.out() } -#[derive(Debug)] -pub enum EncoderError { - StreamIsUnfinished, -} - -impl StdError for EncoderError { - fn description(&self) -> &str { - "encoder error" - } -} - -impl fmt::Display for EncoderError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&self, f) - } -} - pub trait Encodable { fn encode(&self, encoder: &mut E) -> () where E: Encoder; } @@ -1035,7 +1018,7 @@ mod tests { fn rlp_stream() { let mut stream = RlpStream::new_list(2); stream.append(&"cat").append(&"dog"); - let out = stream.out().unwrap(); + let out = stream.out(); assert_eq!(out, vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']); } @@ -1046,7 +1029,7 @@ mod tests { stream.append_list(0); stream.append_list(1).append_list(0); stream.append_list(2).append_list(0).append_list(1).append_list(0); - let out = stream.out().unwrap(); + let out = stream.out(); assert_eq!(out, vec![0xc7, 0xc0, 0xc1, 0xc0, 0xc3, 0xc0, 0xc1, 0xc0]); } @@ -1057,7 +1040,7 @@ mod tests { for _ in 0..17 { stream.append(&""); } - let out = stream.out().unwrap(); + let out = stream.out(); assert_eq!(out, vec![0xd1, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80]); @@ -1073,9 +1056,9 @@ mod tests { stream.append(&"aaa"); res.extend(vec![0x83, b'a', b'a', b'a']); } - let out = stream.out().unwrap(); + let out = stream.out(); assert_eq!(out, res); - } + }; struct DTestPair(T, Vec) where T: rlp::Decodable + fmt::Debug + cmp::Eq; diff --git a/src/triehash.rs b/src/triehash.rs index abc13a39e..aaeef5f65 100644 --- a/src/triehash.rs +++ b/src/triehash.rs @@ -177,7 +177,7 @@ pub fn hash256(vec: &[NibblePair]) -> H256 { _ => { let mut stream = RlpStream::new(); hash256rlp(&vec, 0, &mut stream); - stream.out().unwrap() + stream.out() } }; @@ -251,7 +251,7 @@ fn hash256rlp(vec: &[NibblePair], pre_len: usize, stream: &mut RlpStream) { fn hash256aux(vec: &[NibblePair], pre_len: usize, stream: &mut RlpStream) { let mut s = RlpStream::new(); hash256rlp(vec, pre_len, &mut s); - let out = s.out().unwrap(); + let out = s.out(); match out.len() { 0...31 => stream.append_raw(&out, 1), _ => stream.append(&out.sha3()) From 94a5216513db4b71b64364d8db57360601b5cfa6 Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 30 Nov 2015 11:25:09 +0100 Subject: [PATCH 3/6] removed dangling ; --- src/rlp.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rlp.rs b/src/rlp.rs index 737f7f416..27151295f 100644 --- a/src/rlp.rs +++ b/src/rlp.rs @@ -652,7 +652,7 @@ impl RlpStream { /// Streams out encoded bytes. /// - /// panic! if stream is not finished + /// Returns an error if stream is not finished. pub fn out(self) -> Vec { match self.is_finished() { true => self.encoder.out(), @@ -1058,7 +1058,7 @@ mod tests { } let out = stream.out(); assert_eq!(out, res); - }; + } struct DTestPair(T, Vec) where T: rlp::Decodable + fmt::Debug + cmp::Eq; From 6ee5e1684b10853d5dcd3495e5e3aac5c569e45e Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 30 Nov 2015 11:29:30 +0100 Subject: [PATCH 4/6] rename try_to_finish -> note_appended --- src/rlp.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/rlp.rs b/src/rlp.rs index 27151295f..846281a2b 100644 --- a/src/rlp.rs +++ b/src/rlp.rs @@ -559,7 +559,7 @@ impl RlpStream { object.encode(&mut self.encoder); // if list is finished, prepend the length - self.try_to_finish(1); + self.note_appended(1); // return chainable self self @@ -586,7 +586,7 @@ impl RlpStream { 0 => { // we may finish, if the appended list len is equal 0 self.encoder.bytes.push(0xc0u8); - self.try_to_finish(1); + self.note_appended(1); } _ => self.unfinished_lists.push_back(ListInfo::new(position, len)), } @@ -613,7 +613,7 @@ impl RlpStream { self.encoder.bytes.push(0x80); // try to finish and prepend the length - self.try_to_finish(1); + self.note_appended(1); // return chainable self self @@ -625,7 +625,7 @@ impl RlpStream { self.encoder.bytes.extend(bytes); // try to finish and prepend the length - self.try_to_finish(item_count); + self.note_appended(item_count); // return chainable self self @@ -652,7 +652,7 @@ impl RlpStream { /// Streams out encoded bytes. /// - /// Returns an error if stream is not finished. + /// panic! if stream is not finished. pub fn out(self) -> Vec { match self.is_finished() { true => self.encoder.out(), @@ -660,8 +660,8 @@ impl RlpStream { } } - /// try to finish lists - fn try_to_finish(&mut self, inserted_items: usize) -> () { + /// Try to finish lists + fn note_appended(&mut self, inserted_items: usize) -> () { let should_finish = match self.unfinished_lists.back_mut() { None => false, Some(ref mut x) => { @@ -677,7 +677,7 @@ impl RlpStream { let x = self.unfinished_lists.pop_back().unwrap(); let len = self.encoder.bytes.len() - x.position; self.encoder.insert_list_len_at_pos(len, x.position); - self.try_to_finish(1); + self.note_appended(1); } } } From bd6289756bf0f1c348b8977c891b160bf10b63e2 Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 30 Nov 2015 11:33:08 +0100 Subject: [PATCH 5/6] fixed rlp decoder error names --- src/rlp.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/rlp.rs b/src/rlp.rs index 846281a2b..bf8cbd68e 100644 --- a/src/rlp.rs +++ b/src/rlp.rs @@ -83,10 +83,10 @@ impl ItemInfo { #[derive(Debug, PartialEq, Eq)] pub enum DecoderError { FromBytesError(FromBytesError), - UntrustedRlpIsTooShort, - UntrustedRlpExpectedToBeList, - UntrustedRlpExpectedToBeValue, - BadUntrustedRlp, + RlpIsTooShort, + RlpExpectedToBeList, + RlpExpectedToBeData, + BadRlp, } impl StdError for DecoderError { fn description(&self) -> &str { @@ -230,7 +230,7 @@ impl<'a> UntrustedRlp<'a> { /// ``` pub fn at(&self, index: usize) -> Result, DecoderError> { if !self.is_list() { - return Err(DecoderError::UntrustedRlpExpectedToBeList); + return Err(DecoderError::RlpExpectedToBeList); } // move to cached position if it's index is less or equal to @@ -325,7 +325,7 @@ impl<'a> UntrustedRlp<'a> { /// TODO: move this to decode_untrustedr? fn item_info(bytes: &[u8]) -> Result { let item = match bytes.first().map(|&x| x) { - None => return Err(DecoderError::UntrustedRlpIsTooShort), + 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) => { @@ -341,12 +341,12 @@ impl<'a> UntrustedRlp<'a> { let value_len = try!(usize::from_bytes(&bytes[1..prefix_len])); ItemInfo::new(prefix_len, value_len) } - _ => return Err(DecoderError::BadUntrustedRlp), + _ => return Err(DecoderError::BadRlp), }; match item.prefix_len + item.value_len <= bytes.len() { true => Ok(item), - false => Err(DecoderError::UntrustedRlpIsTooShort), + false => Err(DecoderError::RlpIsTooShort), } } @@ -354,7 +354,7 @@ impl<'a> UntrustedRlp<'a> { fn consume(bytes: &'a [u8], len: usize) -> Result<&'a [u8], DecoderError> { match bytes.len() >= len { true => Ok(&bytes[len..]), - false => Err(DecoderError::UntrustedRlpIsTooShort), + false => Err(DecoderError::RlpIsTooShort), } } } @@ -448,7 +448,7 @@ impl Decodable for T where T: FromBytes { true => BasicDecoder::read_value(rlp.bytes, | bytes | { Ok(try!(T::from_bytes(bytes))) }), - false => Err(DecoderError::UntrustedRlpExpectedToBeValue), + false => Err(DecoderError::RlpExpectedToBeData), } } } @@ -457,7 +457,7 @@ impl Decodable for Vec where T: Decodable { fn decode_untrusted(rlp: &UntrustedRlp) -> Result { match rlp.is_list() { true => rlp.iter().map(|rlp| T::decode_untrusted(&rlp)).collect(), - false => Err(DecoderError::UntrustedRlpExpectedToBeList), + false => Err(DecoderError::RlpExpectedToBeList), } } } @@ -470,7 +470,7 @@ impl Decodable for Vec { res.extend(bytes); Ok(res) }), - false => Err(DecoderError::UntrustedRlpExpectedToBeValue), + false => Err(DecoderError::RlpExpectedToBeData), } } } @@ -485,7 +485,7 @@ impl Decoder for BasicDecoder { fn read_value(bytes: &[u8], f: F) -> Result where F: FnOnce(&[u8]) -> Result { match bytes.first().map(|&x| x) { // rlp is too short - None => Err(DecoderError::UntrustedRlpIsTooShort), + None => Err(DecoderError::RlpIsTooShort), // single byt value Some(l @ 0...0x7f) => Ok(try!(f(&[l]))), // 0-55 bytes @@ -497,7 +497,7 @@ 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::BadUntrustedRlp), + _ => Err(DecoderError::BadRlp), } } } @@ -860,10 +860,10 @@ mod tests { assert!(rlp.is_list()); let cat_err = rlp.at(0).unwrap_err(); - assert_eq!(cat_err, rlp::DecoderError::UntrustedRlpIsTooShort); + assert_eq!(cat_err, rlp::DecoderError::RlpIsTooShort); let dog_err = rlp.at(1).unwrap_err(); - assert_eq!(dog_err, rlp::DecoderError::UntrustedRlpIsTooShort); + assert_eq!(dog_err, rlp::DecoderError::RlpIsTooShort); } } From fac89f784b47f6c1dd9e353083f4c3ea294ab937 Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 30 Nov 2015 11:33:31 +0100 Subject: [PATCH 6/6] updated todo --- src/rlp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rlp.rs b/src/rlp.rs index bf8cbd68e..21f026116 100644 --- a/src/rlp.rs +++ b/src/rlp.rs @@ -322,7 +322,7 @@ impl<'a> UntrustedRlp<'a> { /// return first item info /// - /// TODO: move this to decode_untrustedr? + /// TODO: move this to decoder (?) fn item_info(bytes: &[u8]) -> Result { let item = match bytes.first().map(|&x| x) { None => return Err(DecoderError::RlpIsTooShort),