From 0eda699aa57df8fd527ea3f276f0ae91922ecd1e Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 25 Nov 2015 12:46:27 +0100 Subject: [PATCH 01/13] rlp encoder --- src/rlp.rs | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 153 insertions(+), 3 deletions(-) diff --git a/src/rlp.rs b/src/rlp.rs index a0fe455b5..f8422ed7e 100644 --- a/src/rlp.rs +++ b/src/rlp.rs @@ -2,8 +2,10 @@ use std::fmt; use std::cell::Cell; +use std::io::{Write, BufWriter}; +use std::io::Error as IoError; use std::error::Error as StdError; -use bytes::{FromBytes, FromBytesError}; +use bytes::{ToBytes, FromBytes, FromBytesError}; /// rlp container #[derive(Debug)] @@ -26,13 +28,13 @@ impl OffsetCache { } /// stores basic information about item -struct ItemInfo { +pub struct ItemInfo { prefix_len: usize, value_len: usize } impl ItemInfo { - fn new(prefix_len: usize, value_len: usize) -> ItemInfo { + pub fn new(prefix_len: usize, value_len: usize) -> ItemInfo { ItemInfo { prefix_len: prefix_len, value_len: value_len } } } @@ -189,6 +191,154 @@ impl <'a> Iterator for RlpIterator<'a> { } } +/// shortcut function to encode a `T: Encodable` into a Rlp `Vec` +pub fn encode(object: &E) -> Result, EncoderError> where E: Encodable { + let mut ret: Vec = vec![]; + { + let mut encoder = BasicEncoder::new(&mut ret); + try!(object.encode(&mut encoder)); + } + Ok(ret) +} + +#[derive(Debug)] +pub enum EncoderError { + IoError(IoError) +} + +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) + } +} + +impl From for EncoderError { + fn from(err: IoError) -> EncoderError { EncoderError::IoError(err) } +} + +pub trait Encodable { + fn encode(&self, encoder: &mut E) -> Result<(), E::Error> where E: Encoder; + fn item_info(&self) -> ItemInfo; +} + +pub trait Encoder { + type Error; + + fn emit_value(&mut self, value: &V) -> Result<(), Self::Error> where V: Encodable + ToBytes; + fn emit_array(&mut self, array: &[V]) -> Result<(), Self::Error> where V: Encodable; +} + +impl Encodable for T where T: ToBytes { + fn encode(&self, encoder: &mut E) -> Result<(), E::Error> where E: Encoder { + encoder.emit_value(self) + } + + fn item_info(&self) -> ItemInfo { + match self.to_bytes_len() { + // just 0 + 0 => ItemInfo::new(0, 1), + // byte is its own encoding + 1 if self.first_byte().unwrap() < 0x80 => ItemInfo::new(0, 1), + // (prefix + length), followed by the stirng + len @ 1...55 => ItemInfo::new(1, len), + // (prefix + length of length), followed by the length, followed by the value + len => ItemInfo::new(1 + len.to_bytes_len(), len) + } + } +} + +impl <'a, T> Encodable for &'a [T] where T: Encodable + 'a { + fn encode(&self, encoder: &mut E) -> Result<(), E::Error> where E: Encoder { + encoder.emit_array(self) + } + + fn item_info(&self) -> ItemInfo { + let prefix_len = match self.len() { + 0...55 => 1, + len => len.to_bytes_len() + }; + + let value_len = self.iter().fold(0, |acc, ref enc| { + let item = enc.item_info(); + acc + item.prefix_len + item.value_len + }); + + ItemInfo::new(prefix_len, value_len) + } +} + +impl Encodable for Vec where T: Encodable { + fn encode(&self, encoder: &mut E) -> Result<(), E::Error> where E: Encoder { + let r: &[T] = self.as_ref(); + r.encode(encoder) + } + + fn item_info(&self) -> ItemInfo { + let r: &[T] = self.as_ref(); + r.item_info() + } +} + +struct BasicEncoder where W: Write { + writer: BufWriter +} + +impl BasicEncoder where W: Write { + pub fn new(writer: W) -> BasicEncoder { + BasicEncoder { writer: BufWriter::new(writer) } + } +} + +impl Encoder for BasicEncoder where W: Write { + type Error = EncoderError; + + fn emit_value(&mut self, value: &V) -> Result<(), Self::Error> where V: Encodable + ToBytes { + let v = value.to_bytes(); + let bytes: &[u8] = v.as_ref(); + + match bytes.len() { + // just 0 + 0 => { try!(self.writer.write(&[0x80u8])); }, + // byte is its own encoding + 1 if bytes[0] < 0x80 => { try!(self.writer.write(bytes)); }, + // (prefix + length), followed by the string + len @ 1 ... 55 => { + try!(self.writer.write(&[0x80u8 + len as u8])); + try!(self.writer.write(bytes)); + } + // (prefix + length of length), followed by the length, followd by the string + len => { + try!(self.writer.write(&[0xb7 + len.to_bytes_len() as u8])); + try!(self.writer.write(&len.to_bytes())); + try!(self.writer.write(bytes)); + } + } + Ok(()) + } + + fn emit_array(&mut self, array: &[V]) -> Result<(), Self::Error> where V: Encodable { + let item = array.item_info(); + + match item.value_len { + len @ 0...55 => { try!(self.writer.write(&[0xc0u8 + len as u8])); } + len => { + try!(self.writer.write(&[0x7fu8 + len.to_bytes_len() as u8])); + try!(self.writer.write(&len.to_bytes())); + } + }; + + for el in array.iter() { + try!(el.encode(self)); + } + + Ok(()) + } +} + #[cfg(test)] mod tests { use rlp; From 6006f7cc38546b9e568f425fc71e5b01144e03ea Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 25 Nov 2015 13:13:26 +0100 Subject: [PATCH 02/13] rlp encoding tests --- src/rlp.rs | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/src/rlp.rs b/src/rlp.rs index f8422ed7e..c2e5c6ff4 100644 --- a/src/rlp.rs +++ b/src/rlp.rs @@ -403,5 +403,113 @@ mod tests { assert_eq!(cat_again.bytes, &[0x83, b'c', b'a', b't']); } } + + struct ETestPair(T, Vec) where T: rlp::Encodable; + + fn run_encode_tests(tests: Vec>) where T: rlp::Encodable { + for t in &tests { + let res = rlp::encode(&t.0).unwrap(); + assert_eq!(res, &t.1[..]); + } + } + + #[test] + fn encode_u8() { + let tests = vec![ + ETestPair(0u8, vec![0x80u8]), + ETestPair(15, vec![15]), + ETestPair(55, vec![55]), + ETestPair(56, vec![56]), + ETestPair(0x7f, vec![0x7f]), + ETestPair(0x80, vec![0x81, 0x80]), + ETestPair(0xff, vec![0x81, 0xff]), + ]; + run_encode_tests(tests); + } + + #[test] + fn encode_u16() { + let tests = vec![ + ETestPair(0u16, vec![0x80u8]), + ETestPair(0x100, vec![0x82, 0x01, 0x00]), + ETestPair(0xffff, vec![0x82, 0xff, 0xff]), + ]; + run_encode_tests(tests); + } + + #[test] + fn encode_u32() { + let tests = vec![ + ETestPair(0u32, vec![0x80u8]), + ETestPair(0x10000, vec![0x83, 0x01, 0x00, 0x00]), + ETestPair(0xffffff, vec![0x83, 0xff, 0xff, 0xff]), + ]; + run_encode_tests(tests); + } + + #[test] + fn encode_u64() { + let tests = vec![ + ETestPair(0u64, vec![0x80u8]), + ETestPair(0x1000000, vec![0x84, 0x01, 0x00, 0x00, 0x00]), + ETestPair(0xFFFFFFFF, vec![0x84, 0xff, 0xff, 0xff, 0xff]), + ]; + run_encode_tests(tests); + } + + #[test] + fn encode_str() { + let tests = vec![ + ETestPair("cat", vec![0x83, b'c', b'a', b't']), + ETestPair("dog", vec![0x83, b'd', b'o', b'g']), + ETestPair("Marek", vec![0x85, b'M', b'a', b'r', b'e', b'k']), + ETestPair("", vec![0x80]), + ETestPair("Lorem ipsum dolor sit amet, consectetur adipisicing elit", + vec![0xb8, 0x38, b'L', b'o', b'r', b'e', b'm', b' ', b'i', + b'p', b's', b'u', b'm', b' ', b'd', b'o', b'l', b'o', b'r', + b' ', b's', b'i', b't', b' ', b'a', b'm', b'e', b't', b',', + b' ', b'c', b'o', b'n', b's', b'e', b'c', b't', b'e', b't', + b'u', b'r', b' ', b'a', b'd', b'i', b'p', b'i', b's', b'i', + b'c', b'i', b'n', b'g', b' ', b'e', b'l', b'i', b't']) + ]; + run_encode_tests(tests); + } + + #[test] + fn encode_vector_u8() { + let tests = vec![ + ETestPair(vec![], vec![0xc0]), + ETestPair(vec![15u8], vec![0xc1, 0x0f]), + ETestPair(vec![1, 2, 3, 7, 0xff], vec![0xc6, 1, 2, 3, 7, 0x81, 0xff]), + ]; + run_encode_tests(tests); + } + + #[test] + fn encode_vector_u64() { + let tests = vec![ + ETestPair(vec![], vec![0xc0]), + ETestPair(vec![15u64], vec![0xc1, 0x0f]), + ETestPair(vec![1, 2, 3, 7, 0xff], vec![0xc6, 1, 2, 3, 7, 0x81, 0xff]), + ETestPair(vec![0xffffffff, 1, 2, 3, 7, 0xff], vec![0xcb, 0x84, 0xff, 0xff, 0xff, 0xff, 1, 2, 3, 7, 0x81, 0xff]), + ]; + run_encode_tests(tests); + } + + #[test] + fn encode_vector_str() { + let tests = vec![ + ETestPair(vec!["cat", "dog"], vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']) + ]; + run_encode_tests(tests); + } + + #[test] + fn encode_vector_of_vectors_str() { + let tests = vec![ + ETestPair(vec![vec!["cat"]], vec![0xc5, 0xc4, 0x83, b'c', b'a', b't']) + ]; + run_encode_tests(tests); + } } From 798b8b0fb884c4a94bd69fd614770da43470663a Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 25 Nov 2015 17:54:50 +0100 Subject: [PATCH 03/13] rlp stream --- src/rlp.rs | 103 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 95 insertions(+), 8 deletions(-) diff --git a/src/rlp.rs b/src/rlp.rs index c2e5c6ff4..2e8d52902 100644 --- a/src/rlp.rs +++ b/src/rlp.rs @@ -191,8 +191,86 @@ impl <'a> Iterator for RlpIterator<'a> { } } +/// container that should be used to encoding the rlp +pub struct RlpStream { + len: usize, + max_len: usize, + bytes: Vec, + last_err: Option +} + +impl RlpStream { + /// create new container of size `max_len` + pub fn new(max_len: usize) -> RlpStream { + RlpStream { + len: 0, + max_len: max_len, + bytes: vec![], + last_err: None + } + } + + /// apends value to the end of stream, chainable + pub fn append<'a, E>(&'a mut self, object: &E) -> &'a mut RlpStream where E: Encodable { + // if there was an error, stop appending + if !self.last_err.is_none() { + return self + } + + // encode given value and add it at the end of the stream + match encode(object) { + Err(e) => { + self.last_err = Some(e); + return self; + }, + Ok(ref mut v) => { + self.bytes.append(v); + self.len += 1; + }, + }; + + // if array is finished, prepend the length + if self.is_finished() { + self.prepend_the_length(); + } + + // allow chaining calls + self + } + + /// return try if stream is ready + pub fn is_finished(&self) -> bool { + self.len == self.max_len + } + + /// streams out encoded bytes + pub fn out(self) -> Result, EncoderError> { + match self.last_err { + None if self.is_finished() => Ok(self.bytes), + Some(e) => Err(e), + _ => Err(EncoderError::StreamIsUnfinished) + } + } + + /// prepend the length of the bytes to the beginning of the vector + fn prepend_the_length(&mut self) -> () { + let mut v = match self.bytes.len() { + len @ 0...55 => vec![0xc0u8 + len as u8], + len => { + let mut res = vec![0x7fu8 + len.to_bytes_len() as u8]; + let mut b = len.to_bytes(); + res.append(&mut b); + res + } + }; + + v.append(&mut self.bytes); + self.bytes = v; + } +} + /// shortcut function to encode a `T: Encodable` into a Rlp `Vec` -pub fn encode(object: &E) -> Result, EncoderError> where E: Encodable { +fn encode(object: &E) -> Result, EncoderError> where E: Encodable { let mut ret: Vec = vec![]; { let mut encoder = BasicEncoder::new(&mut ret); @@ -203,7 +281,8 @@ pub fn encode(object: &E) -> Result, EncoderError> where E: Encodable #[derive(Debug)] pub enum EncoderError { - IoError(IoError) + IoError(IoError), + StreamIsUnfinished } impl StdError for EncoderError { @@ -257,16 +336,16 @@ impl <'a, T> Encodable for &'a [T] where T: Encodable + 'a { } fn item_info(&self) -> ItemInfo { - let prefix_len = match self.len() { - 0...55 => 1, - len => len.to_bytes_len() - }; - let value_len = self.iter().fold(0, |acc, ref enc| { let item = enc.item_info(); acc + item.prefix_len + item.value_len }); + let prefix_len = match value_len { + 0...55 => 1, + len => len.to_bytes_len() + }; + ItemInfo::new(prefix_len, value_len) } } @@ -342,7 +421,7 @@ impl Encoder for BasicEncoder where W: Write { #[cfg(test)] mod tests { use rlp; - use rlp::Rlp; + use rlp::{Rlp, RlpStream}; #[test] fn rlp_at() { @@ -511,5 +590,13 @@ mod tests { ]; run_encode_tests(tests); } + + #[test] + fn rlp_stream() { + let mut stream = RlpStream::new(2); + stream.append(&"cat").append(&"dog"); + let out = stream.out().unwrap(); + assert_eq!(out, vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']); + } } From 9f938fbaab03163c9369c5ab3be52a845efe9d4f Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 25 Nov 2015 19:36:27 +0100 Subject: [PATCH 04/13] RlpStream array method --- src/rlp.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/rlp.rs b/src/rlp.rs index 2e8d52902..aa3d08fe4 100644 --- a/src/rlp.rs +++ b/src/rlp.rs @@ -191,7 +191,7 @@ impl <'a> Iterator for RlpIterator<'a> { } } -/// container that should be used to encoding the rlp +/// container that should be used to encode rlp pub struct RlpStream { len: usize, max_len: usize, @@ -200,8 +200,14 @@ pub struct RlpStream { } impl RlpStream { - /// create new container of size `max_len` - pub fn new(max_len: usize) -> RlpStream { + /// create new container for values appended one after another, + /// but not being part of the same array + pub fn new() -> RlpStream { + RlpStream::array(0) + } + + /// create new container for array of size `max_len` + pub fn array(max_len: usize) -> RlpStream { RlpStream { len: 0, max_len: max_len, @@ -238,7 +244,7 @@ impl RlpStream { self } - /// return try if stream is ready + /// return true if stream is ready pub fn is_finished(&self) -> bool { self.len == self.max_len } @@ -593,7 +599,7 @@ mod tests { #[test] fn rlp_stream() { - let mut stream = RlpStream::new(2); + let mut stream = RlpStream::array(2); stream.append(&"cat").append(&"dog"); let out = stream.out().unwrap(); assert_eq!(out, vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']); From c5163b796fd344e04900604facf761dcd197b903 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 25 Nov 2015 21:04:43 +0100 Subject: [PATCH 05/13] improved encoder --- src/rlp.rs | 125 +++++++++++++++++++++++++---------------------------- 1 file changed, 58 insertions(+), 67 deletions(-) diff --git a/src/rlp.rs b/src/rlp.rs index aa3d08fe4..26a300db8 100644 --- a/src/rlp.rs +++ b/src/rlp.rs @@ -2,7 +2,7 @@ use std::fmt; use std::cell::Cell; -use std::io::{Write, BufWriter}; +use std::io::{Write}; use std::io::Error as IoError; use std::error::Error as StdError; use bytes::{ToBytes, FromBytes, FromBytesError}; @@ -28,7 +28,7 @@ impl OffsetCache { } /// stores basic information about item -pub struct ItemInfo { +struct ItemInfo { prefix_len: usize, value_len: usize } @@ -277,12 +277,9 @@ impl RlpStream { /// shortcut function to encode a `T: Encodable` into a Rlp `Vec` fn encode(object: &E) -> Result, EncoderError> where E: Encodable { - let mut ret: Vec = vec![]; - { - let mut encoder = BasicEncoder::new(&mut ret); - try!(object.encode(&mut encoder)); - } - Ok(ret) + let mut encoder = BasicEncoder::new(); + try!(object.encode(&mut encoder)); + Ok(encoder.out()) } #[derive(Debug)] @@ -307,7 +304,6 @@ impl From for EncoderError { pub trait Encodable { fn encode(&self, encoder: &mut E) -> Result<(), E::Error> where E: Encoder; - fn item_info(&self) -> ItemInfo; } pub trait Encoder { @@ -321,39 +317,12 @@ impl Encodable for T where T: ToBytes { fn encode(&self, encoder: &mut E) -> Result<(), E::Error> where E: Encoder { encoder.emit_value(self) } - - fn item_info(&self) -> ItemInfo { - match self.to_bytes_len() { - // just 0 - 0 => ItemInfo::new(0, 1), - // byte is its own encoding - 1 if self.first_byte().unwrap() < 0x80 => ItemInfo::new(0, 1), - // (prefix + length), followed by the stirng - len @ 1...55 => ItemInfo::new(1, len), - // (prefix + length of length), followed by the length, followed by the value - len => ItemInfo::new(1 + len.to_bytes_len(), len) - } - } } impl <'a, T> Encodable for &'a [T] where T: Encodable + 'a { fn encode(&self, encoder: &mut E) -> Result<(), E::Error> where E: Encoder { encoder.emit_array(self) } - - fn item_info(&self) -> ItemInfo { - let value_len = self.iter().fold(0, |acc, ref enc| { - let item = enc.item_info(); - acc + item.prefix_len + item.value_len - }); - - let prefix_len = match value_len { - 0...55 => 1, - len => len.to_bytes_len() - }; - - ItemInfo::new(prefix_len, value_len) - } } impl Encodable for Vec where T: Encodable { @@ -361,24 +330,46 @@ impl Encodable for Vec where T: Encodable { let r: &[T] = self.as_ref(); r.encode(encoder) } +} - fn item_info(&self) -> ItemInfo { - let r: &[T] = self.as_ref(); - r.item_info() +struct BasicEncoder { + bytes: Vec +} + +impl BasicEncoder { + fn new() -> BasicEncoder { + BasicEncoder { bytes: vec![] } + } + + /// inserts array prefix at given position + fn insert_array_len_at_pos(&mut self, len: usize, pos: usize) -> Result<(), EncoderError> { + // new bytes + let mut res: Vec = vec![]; + { + let (before_slice, after_slice) = self.bytes.split_at(pos); + try!(res.write(before_slice)); + + match len { + 0...55 => { try!(res.write(&[0xc0u8 + len as u8])); } + _ => { + try!(res.write(&[0x7fu8 + len.to_bytes_len() as u8])); + try!(res.write(&len.to_bytes())); + } + }; + + try!(res.write(after_slice)); + } + self.bytes = res; + Ok(()) + } + + /// get encoded value + fn out(self) -> Vec { + self.bytes } } -struct BasicEncoder where W: Write { - writer: BufWriter -} - -impl BasicEncoder where W: Write { - pub fn new(writer: W) -> BasicEncoder { - BasicEncoder { writer: BufWriter::new(writer) } - } -} - -impl Encoder for BasicEncoder where W: Write { +impl Encoder for BasicEncoder { type Error = EncoderError; fn emit_value(&mut self, value: &V) -> Result<(), Self::Error> where V: Encodable + ToBytes { @@ -387,40 +378,40 @@ impl Encoder for BasicEncoder where W: Write { match bytes.len() { // just 0 - 0 => { try!(self.writer.write(&[0x80u8])); }, + 0 => { try!(self.bytes.write(&[0x80u8])); }, // byte is its own encoding - 1 if bytes[0] < 0x80 => { try!(self.writer.write(bytes)); }, + 1 if bytes[0] < 0x80 => { try!(self.bytes.write(bytes)); }, // (prefix + length), followed by the string len @ 1 ... 55 => { - try!(self.writer.write(&[0x80u8 + len as u8])); - try!(self.writer.write(bytes)); + try!(self.bytes.write(&[0x80u8 + len as u8])); + try!(self.bytes.write(bytes)); } // (prefix + length of length), followed by the length, followd by the string len => { - try!(self.writer.write(&[0xb7 + len.to_bytes_len() as u8])); - try!(self.writer.write(&len.to_bytes())); - try!(self.writer.write(bytes)); + try!(self.bytes.write(&[0xb7 + len.to_bytes_len() as u8])); + try!(self.bytes.write(&len.to_bytes())); + try!(self.bytes.write(bytes)); } } Ok(()) } fn emit_array(&mut self, array: &[V]) -> Result<(), Self::Error> where V: Encodable { - let item = array.item_info(); - - match item.value_len { - len @ 0...55 => { try!(self.writer.write(&[0xc0u8 + len as u8])); } - len => { - try!(self.writer.write(&[0x7fu8 + len.to_bytes_len() as u8])); - try!(self.writer.write(&len.to_bytes())); - } - }; + // get len before inserting an array + let before_len = self.bytes.len(); + + // insert all array elements for el in array.iter() { try!(el.encode(self)); } - Ok(()) + // get len after inserting an array + let after_len = self.bytes.len(); + + // diff is array len + let array_len = after_len - before_len; + self.insert_array_len_at_pos(array_len, before_len) } } From c47bf0ce5f9fdfee20fbc9ccf4751215381619df Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 25 Nov 2015 21:14:53 +0100 Subject: [PATCH 06/13] emit_value && emit_array do not have constrains regarding type --- src/rlp.rs | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/rlp.rs b/src/rlp.rs index 26a300db8..e751b9d56 100644 --- a/src/rlp.rs +++ b/src/rlp.rs @@ -309,19 +309,26 @@ pub trait Encodable { pub trait Encoder { type Error; - fn emit_value(&mut self, value: &V) -> Result<(), Self::Error> where V: Encodable + ToBytes; - fn emit_array(&mut self, array: &[V]) -> Result<(), Self::Error> where V: Encodable; + fn emit_value(&mut self, bytes: &[u8]) -> Result<(), Self::Error>; + fn emit_array(&mut self, f: F) -> Result<(), Self::Error> where + F: FnOnce(&mut Self) -> Result<(), Self::Error>; } impl Encodable for T where T: ToBytes { fn encode(&self, encoder: &mut E) -> Result<(), E::Error> where E: Encoder { - encoder.emit_value(self) + encoder.emit_value(&self.to_bytes()) } } impl <'a, T> Encodable for &'a [T] where T: Encodable + 'a { fn encode(&self, encoder: &mut E) -> Result<(), E::Error> where E: Encoder { - encoder.emit_array(self) + encoder.emit_array(|e| { + // insert all array elements + for el in self.iter() { + try!(el.encode(e)); + } + Ok(()) + }) } } @@ -372,10 +379,7 @@ impl BasicEncoder { impl Encoder for BasicEncoder { type Error = EncoderError; - fn emit_value(&mut self, value: &V) -> Result<(), Self::Error> where V: Encodable + ToBytes { - let v = value.to_bytes(); - let bytes: &[u8] = v.as_ref(); - + fn emit_value(&mut self, bytes: &[u8]) -> Result<(), Self::Error> { match bytes.len() { // just 0 0 => { try!(self.bytes.write(&[0x80u8])); }, @@ -396,15 +400,14 @@ impl Encoder for BasicEncoder { Ok(()) } - fn emit_array(&mut self, array: &[V]) -> Result<(), Self::Error> where V: Encodable { + fn emit_array(&mut self, f: F) -> Result<(), Self::Error> where + F: FnOnce(&mut Self) -> Result<(), Self::Error> { // get len before inserting an array let before_len = self.bytes.len(); // insert all array elements - for el in array.iter() { - try!(el.encode(self)); - } + try!(f(self)); // get len after inserting an array let after_len = self.bytes.len(); From 94ecd8c3dffdb173adbe87c431df2e57ce9dc455 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 25 Nov 2015 21:16:24 +0100 Subject: [PATCH 07/13] there is no need for item info new to be public --- src/rlp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rlp.rs b/src/rlp.rs index e751b9d56..452f71c57 100644 --- a/src/rlp.rs +++ b/src/rlp.rs @@ -34,7 +34,7 @@ struct ItemInfo { } impl ItemInfo { - pub fn new(prefix_len: usize, value_len: usize) -> ItemInfo { + fn new(prefix_len: usize, value_len: usize) -> ItemInfo { ItemInfo { prefix_len: prefix_len, value_len: value_len } } } From 93aeec19ec0694b0812581f2e3de543a3a4710fc Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 25 Nov 2015 21:58:15 +0100 Subject: [PATCH 08/13] array -> list, RlpStream::array -> RlpStream::new_list --- src/rlp.rs | 56 +++++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/rlp.rs b/src/rlp.rs index 452f71c57..be67e4ace 100644 --- a/src/rlp.rs +++ b/src/rlp.rs @@ -43,7 +43,7 @@ impl ItemInfo { pub enum DecoderError { FromBytesError(FromBytesError), RlpIsTooShort, - RlpExpectedToBeArray, + RlpExpectedToBeList, BadRlp, } impl StdError for DecoderError { @@ -73,16 +73,16 @@ impl <'a>Rlp<'a> { /// /// paren container caches searched position pub fn at(&self, index: usize) -> Result, DecoderError> { - if !self.is_array() { - return Err(DecoderError::RlpExpectedToBeArray); + if !self.is_list() { + return Err(DecoderError::RlpExpectedToBeList); } // move to cached position if it's index is less or equal to - // current search index, otherwise move to beginning of array + // current search index, otherwise move to beginning of list let c = self.cache.get(); let (mut bytes, to_skip) = match c.index <= index { true => (try!(Rlp::consume(self.bytes, c.offset)), index - c.index), - false => (try!(self.consume_array_prefix()), index) + false => (try!(self.consume_list_prefix()), index) }; // skip up to x items @@ -96,8 +96,8 @@ impl <'a>Rlp<'a> { Ok(Rlp::new(&bytes[0..found.prefix_len + found.value_len])) } - /// returns true if rlp is an array - pub fn is_array(&self) -> bool { + /// returns true if rlp is an list + pub fn is_list(&self) -> bool { self.bytes.len() > 0 && self.bytes[0] >= 0xc0 } @@ -112,7 +112,7 @@ impl <'a>Rlp<'a> { } /// consumes first found prefix - fn consume_array_prefix(&self) -> Result<&'a [u8], DecoderError> { + fn consume_list_prefix(&self) -> Result<&'a [u8], DecoderError> { let item = try!(Rlp::item_info(self.bytes)); let bytes = try!(Rlp::consume(self.bytes, item.prefix_len)); Ok(bytes) @@ -201,13 +201,13 @@ pub struct RlpStream { impl RlpStream { /// create new container for values appended one after another, - /// but not being part of the same array + /// but not being part of the same list pub fn new() -> RlpStream { - RlpStream::array(0) + RlpStream::new_list(0) } - /// create new container for array of size `max_len` - pub fn array(max_len: usize) -> RlpStream { + /// create new container for list of size `max_len` + pub fn new_list(max_len: usize) -> RlpStream { RlpStream { len: 0, max_len: max_len, @@ -235,7 +235,7 @@ impl RlpStream { }, }; - // if array is finished, prepend the length + // if list is finished, prepend the length if self.is_finished() { self.prepend_the_length(); } @@ -310,7 +310,7 @@ pub trait Encoder { type Error; fn emit_value(&mut self, bytes: &[u8]) -> Result<(), Self::Error>; - fn emit_array(&mut self, f: F) -> Result<(), Self::Error> where + fn emit_list(&mut self, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>; } @@ -322,8 +322,8 @@ impl Encodable for T where T: ToBytes { impl <'a, T> Encodable for &'a [T] where T: Encodable + 'a { fn encode(&self, encoder: &mut E) -> Result<(), E::Error> where E: Encoder { - encoder.emit_array(|e| { - // insert all array elements + encoder.emit_list(|e| { + // insert all list elements for el in self.iter() { try!(el.encode(e)); } @@ -348,8 +348,8 @@ impl BasicEncoder { BasicEncoder { bytes: vec![] } } - /// inserts array prefix at given position - fn insert_array_len_at_pos(&mut self, len: usize, pos: usize) -> Result<(), EncoderError> { + /// inserts list prefix at given position + fn insert_list_len_at_pos(&mut self, len: usize, pos: usize) -> Result<(), EncoderError> { // new bytes let mut res: Vec = vec![]; { @@ -400,21 +400,21 @@ impl Encoder for BasicEncoder { Ok(()) } - fn emit_array(&mut self, f: F) -> Result<(), Self::Error> where + fn emit_list(&mut self, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error> { - // get len before inserting an array + // get len before inserting an list let before_len = self.bytes.len(); - // insert all array elements + // insert all list elements try!(f(self)); - // get len after inserting an array + // get len after inserting an list let after_len = self.bytes.len(); - // diff is array len - let array_len = after_len - before_len; - self.insert_array_len_at_pos(array_len, before_len) + // diff is list len + let list_len = after_len - before_len; + self.insert_list_len_at_pos(list_len, before_len) } } @@ -428,7 +428,7 @@ mod tests { let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']; { let rlp = Rlp::new(&data); - assert!(rlp.is_array()); + assert!(rlp.is_list()); let cat = rlp.at(0).unwrap(); assert!(cat.is_value()); @@ -449,7 +449,7 @@ mod tests { let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o']; { let rlp = Rlp::new(&data); - assert!(rlp.is_array()); + assert!(rlp.is_list()); let cat_err = rlp.at(0).unwrap_err(); assert_eq!(cat_err, rlp::DecoderError::RlpIsTooShort); @@ -593,7 +593,7 @@ mod tests { #[test] fn rlp_stream() { - let mut stream = RlpStream::array(2); + let mut stream = RlpStream::new_list(2); stream.append(&"cat").append(&"dog"); let out = stream.out().unwrap(); assert_eq!(out, vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']); From 9dff89427240e268677f7f8df133d3a90edec3f8 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 25 Nov 2015 22:13:57 +0100 Subject: [PATCH 09/13] do not use io::Write --- src/rlp.rs | 95 +++++++++++++++++++++++------------------------------- 1 file changed, 40 insertions(+), 55 deletions(-) diff --git a/src/rlp.rs b/src/rlp.rs index be67e4ace..4d146a30d 100644 --- a/src/rlp.rs +++ b/src/rlp.rs @@ -2,8 +2,6 @@ use std::fmt; use std::cell::Cell; -use std::io::{Write}; -use std::io::Error as IoError; use std::error::Error as StdError; use bytes::{ToBytes, FromBytes, FromBytesError}; @@ -224,16 +222,18 @@ impl RlpStream { } // encode given value and add it at the end of the stream - match encode(object) { - Err(e) => { - self.last_err = Some(e); - return self; - }, - Ok(ref mut v) => { - self.bytes.append(v); - self.len += 1; - }, - }; + self.bytes.extend(encode(object)); + self.len += 1; + + //Err(e) => { + //self.last_err = Some(e); + //return self; + //}, + //Ok(ref mut v) => { + //self.bytes.append(v); + //self.len += 1; + //}, + //}; // if list is finished, prepend the length if self.is_finished() { @@ -276,15 +276,14 @@ impl RlpStream { } /// shortcut function to encode a `T: Encodable` into a Rlp `Vec` -fn encode(object: &E) -> Result, EncoderError> where E: Encodable { +fn encode(object: &E) -> Vec where E: Encodable { let mut encoder = BasicEncoder::new(); - try!(object.encode(&mut encoder)); - Ok(encoder.out()) + object.encode(&mut encoder); + encoder.out() } #[derive(Debug)] pub enum EncoderError { - IoError(IoError), StreamIsUnfinished } @@ -298,42 +297,34 @@ impl fmt::Display for EncoderError { } } -impl From for EncoderError { - fn from(err: IoError) -> EncoderError { EncoderError::IoError(err) } -} - pub trait Encodable { - fn encode(&self, encoder: &mut E) -> Result<(), E::Error> where E: Encoder; + fn encode(&self, encoder: &mut E) -> () where E: Encoder; } pub trait Encoder { - type Error; - - fn emit_value(&mut self, bytes: &[u8]) -> Result<(), Self::Error>; - fn emit_list(&mut self, f: F) -> Result<(), Self::Error> where - F: FnOnce(&mut Self) -> Result<(), Self::Error>; + fn emit_value(&mut self, bytes: &[u8]) -> (); + fn emit_list(&mut self, f: F) -> () where F: FnOnce(&mut Self) -> (); } impl Encodable for T where T: ToBytes { - fn encode(&self, encoder: &mut E) -> Result<(), E::Error> where E: Encoder { + fn encode(&self, encoder: &mut E) -> () where E: Encoder { encoder.emit_value(&self.to_bytes()) } } impl <'a, T> Encodable for &'a [T] where T: Encodable + 'a { - fn encode(&self, encoder: &mut E) -> Result<(), E::Error> where E: Encoder { + fn encode(&self, encoder: &mut E) -> () where E: Encoder { encoder.emit_list(|e| { // insert all list elements for el in self.iter() { - try!(el.encode(e)); + el.encode(e); } - Ok(()) }) } } impl Encodable for Vec where T: Encodable { - fn encode(&self, encoder: &mut E) -> Result<(), E::Error> where E: Encoder { + fn encode(&self, encoder: &mut E) -> () where E: Encoder { let r: &[T] = self.as_ref(); r.encode(encoder) } @@ -349,25 +340,24 @@ impl BasicEncoder { } /// inserts list prefix at given position - fn insert_list_len_at_pos(&mut self, len: usize, pos: usize) -> Result<(), EncoderError> { + fn insert_list_len_at_pos(&mut self, len: usize, pos: usize) -> () { // new bytes let mut res: Vec = vec![]; { let (before_slice, after_slice) = self.bytes.split_at(pos); - try!(res.write(before_slice)); + res.extend(before_slice); match len { - 0...55 => { try!(res.write(&[0xc0u8 + len as u8])); } + 0...55 => res.push(0xc0u8 + len as u8), _ => { - try!(res.write(&[0x7fu8 + len.to_bytes_len() as u8])); - try!(res.write(&len.to_bytes())); + res.push(0x7fu8 + len.to_bytes_len() as u8); + res.extend(len.to_bytes()); } }; - try!(res.write(after_slice)); + res.extend(after_slice); } self.bytes = res; - Ok(()) } /// get encoded value @@ -377,44 +367,39 @@ impl BasicEncoder { } impl Encoder for BasicEncoder { - type Error = EncoderError; - - fn emit_value(&mut self, bytes: &[u8]) -> Result<(), Self::Error> { + fn emit_value(&mut self, bytes: &[u8]) -> () { match bytes.len() { // just 0 - 0 => { try!(self.bytes.write(&[0x80u8])); }, + 0 => self.bytes.push(0x80u8), // byte is its own encoding - 1 if bytes[0] < 0x80 => { try!(self.bytes.write(bytes)); }, + 1 if bytes[0] < 0x80 => self.bytes.extend(bytes), // (prefix + length), followed by the string len @ 1 ... 55 => { - try!(self.bytes.write(&[0x80u8 + len as u8])); - try!(self.bytes.write(bytes)); + self.bytes.push(0x80u8 + len as u8); + self.bytes.extend(bytes); } // (prefix + length of length), followed by the length, followd by the string len => { - try!(self.bytes.write(&[0xb7 + len.to_bytes_len() as u8])); - try!(self.bytes.write(&len.to_bytes())); - try!(self.bytes.write(bytes)); + self.bytes.push(0xb7 + len.to_bytes_len() as u8); + self.bytes.extend(len.to_bytes()); + self.bytes.extend(bytes); } } - Ok(()) } - fn emit_list(&mut self, f: F) -> Result<(), Self::Error> where - F: FnOnce(&mut Self) -> Result<(), Self::Error> { - + fn emit_list(&mut self, f: F) -> () where F: FnOnce(&mut Self) -> () { // get len before inserting an list let before_len = self.bytes.len(); // insert all list elements - try!(f(self)); + f(self); // get len after inserting an list let after_len = self.bytes.len(); // diff is list len let list_len = after_len - before_len; - self.insert_list_len_at_pos(list_len, before_len) + self.insert_list_len_at_pos(list_len, before_len); } } @@ -487,7 +472,7 @@ mod tests { fn run_encode_tests(tests: Vec>) where T: rlp::Encodable { for t in &tests { - let res = rlp::encode(&t.0).unwrap(); + let res = rlp::encode(&t.0); assert_eq!(res, &t.1[..]); } } From ebe7c09210e24bda53c7bc560326d505dd33ae4d Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 25 Nov 2015 22:14:43 +0100 Subject: [PATCH 10/13] removed legacy comment --- src/rlp.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/rlp.rs b/src/rlp.rs index 4d146a30d..48dbccc55 100644 --- a/src/rlp.rs +++ b/src/rlp.rs @@ -225,16 +225,6 @@ impl RlpStream { self.bytes.extend(encode(object)); self.len += 1; - //Err(e) => { - //self.last_err = Some(e); - //return self; - //}, - //Ok(ref mut v) => { - //self.bytes.append(v); - //self.len += 1; - //}, - //}; - // if list is finished, prepend the length if self.is_finished() { self.prepend_the_length(); From 1c2c8c4eb5dba77d91c6029c2954e0bad67a253d Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 25 Nov 2015 22:16:50 +0100 Subject: [PATCH 11/13] removed last_err field from RlpStream --- src/rlp.rs | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/rlp.rs b/src/rlp.rs index 48dbccc55..bd5561635 100644 --- a/src/rlp.rs +++ b/src/rlp.rs @@ -193,8 +193,7 @@ impl <'a> Iterator for RlpIterator<'a> { pub struct RlpStream { len: usize, max_len: usize, - bytes: Vec, - last_err: Option + bytes: Vec } impl RlpStream { @@ -209,18 +208,12 @@ impl RlpStream { RlpStream { len: 0, max_len: max_len, - bytes: vec![], - last_err: None + bytes: vec![] } } /// apends value to the end of stream, chainable pub fn append<'a, E>(&'a mut self, object: &E) -> &'a mut RlpStream where E: Encodable { - // if there was an error, stop appending - if !self.last_err.is_none() { - return self - } - // encode given value and add it at the end of the stream self.bytes.extend(encode(object)); self.len += 1; @@ -241,10 +234,9 @@ impl RlpStream { /// streams out encoded bytes pub fn out(self) -> Result, EncoderError> { - match self.last_err { - None if self.is_finished() => Ok(self.bytes), - Some(e) => Err(e), - _ => Err(EncoderError::StreamIsUnfinished) + match self.is_finished() { + true => Ok(self.bytes), + false => Err(EncoderError::StreamIsUnfinished) } } From 20cadef4f085ec890f8758734298055887733063 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 25 Nov 2015 22:29:21 +0100 Subject: [PATCH 12/13] RlpStream uses BasicEncoder --- src/rlp.rs | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/src/rlp.rs b/src/rlp.rs index bd5561635..6161e5cca 100644 --- a/src/rlp.rs +++ b/src/rlp.rs @@ -193,7 +193,7 @@ impl <'a> Iterator for RlpIterator<'a> { pub struct RlpStream { len: usize, max_len: usize, - bytes: Vec + encoder: BasicEncoder } impl RlpStream { @@ -208,14 +208,14 @@ impl RlpStream { RlpStream { len: 0, max_len: max_len, - bytes: vec![] + encoder: BasicEncoder::new() } } /// apends value to the end of stream, chainable 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 - self.bytes.extend(encode(object)); + object.encode(&mut self.encoder); self.len += 1; // if list is finished, prepend the length @@ -235,30 +235,20 @@ impl RlpStream { /// streams out encoded bytes pub fn out(self) -> Result, EncoderError> { match self.is_finished() { - true => Ok(self.bytes), + true => Ok(self.encoder.out()), false => Err(EncoderError::StreamIsUnfinished) } } /// prepend the length of the bytes to the beginning of the vector fn prepend_the_length(&mut self) -> () { - let mut v = match self.bytes.len() { - len @ 0...55 => vec![0xc0u8 + len as u8], - len => { - let mut res = vec![0x7fu8 + len.to_bytes_len() as u8]; - let mut b = len.to_bytes(); - res.append(&mut b); - res - } - }; - - v.append(&mut self.bytes); - self.bytes = v; + let len = self.encoder.bytes.len(); + self.encoder.insert_list_len_at_pos(len, 0); } } /// shortcut function to encode a `T: Encodable` into a Rlp `Vec` -fn encode(object: &E) -> Vec where E: Encodable { +pub fn encode(object: &E) -> Vec where E: Encodable { let mut encoder = BasicEncoder::new(); object.encode(&mut encoder); encoder.out() From e40bb6d52c3e7e4324b87b2cc711271ccf9208f6 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 25 Nov 2015 23:40:01 +0100 Subject: [PATCH 13/13] rlp append_list --- src/rlp.rs | 90 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 72 insertions(+), 18 deletions(-) diff --git a/src/rlp.rs b/src/rlp.rs index 6161e5cca..a085e2fc2 100644 --- a/src/rlp.rs +++ b/src/rlp.rs @@ -2,6 +2,7 @@ use std::fmt; use std::cell::Cell; +use std::collections::LinkedList; use std::error::Error as StdError; use bytes::{ToBytes, FromBytes, FromBytesError}; @@ -189,10 +190,26 @@ impl <'a> Iterator for RlpIterator<'a> { } } +#[derive(Debug)] +struct ListInfo { + position: usize, + current: usize, + max: usize +} + +impl ListInfo { + fn new(position: usize, max: usize) -> ListInfo { + ListInfo { + position: position, + current: 0, + max: max + } + } +} + /// container that should be used to encode rlp pub struct RlpStream { - len: usize, - max_len: usize, + unfinished_lists: LinkedList, encoder: BasicEncoder } @@ -200,36 +217,51 @@ impl RlpStream { /// create new container for values appended one after another, /// but not being part of the same list pub fn new() -> RlpStream { - RlpStream::new_list(0) + RlpStream { + unfinished_lists: LinkedList::new(), + encoder: BasicEncoder::new() + } } /// create new container for list of size `max_len` - pub fn new_list(max_len: usize) -> RlpStream { - RlpStream { - len: 0, - max_len: max_len, - encoder: BasicEncoder::new() - } + pub fn new_list(len: usize) -> RlpStream { + let mut stream = RlpStream::new(); + stream.append_list(len); + stream } /// apends value to the end of stream, chainable 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); - self.len += 1; // if list is finished, prepend the length - if self.is_finished() { - self.prepend_the_length(); + self.try_to_finish(); + + // return chainable self + self + } + + /// declare appending the list of given size + pub fn append_list<'a>(&'a mut self, len: usize) -> &'a mut RlpStream { + // push new list + let position = self.encoder.bytes.len(); + match len { + 0 => { + // we may finish, if the appended list len is equal 0 + self.encoder.insert_list_len_at_pos(0, position); + self.try_to_finish(); + }, + _ => self.unfinished_lists.push_back(ListInfo::new(position, len)) } - // allow chaining calls + // return chainable self self } /// return true if stream is ready pub fn is_finished(&self) -> bool { - self.len == self.max_len + self.unfinished_lists.back().is_none() } /// streams out encoded bytes @@ -240,10 +272,22 @@ impl RlpStream { } } - /// prepend the length of the bytes to the beginning of the vector - fn prepend_the_length(&mut self) -> () { - let len = self.encoder.bytes.len(); - self.encoder.insert_list_len_at_pos(len, 0); + /// try to finish lists + fn try_to_finish(&mut self) -> () { + let should_finish = match self.unfinished_lists.back_mut() { + None => false, + Some(ref mut x) => { + x.current += 1; + x.current == x.max + } + }; + + if should_finish { + 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(); + } } } @@ -555,5 +599,15 @@ mod tests { let out = stream.out().unwrap(); assert_eq!(out, vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']); } + + #[test] + fn rlp_stream_list() { + let mut stream = RlpStream::new_list(3); + stream.append_list(0); + stream.append_list(1).append(&vec![] as &Vec); + stream.append_list(2).append_list(0).append_list(1).append_list(0); + let out = stream.out().unwrap(); + assert_eq!(out, vec![0xc7, 0xc0, 0xc1, 0xc0, 0xc3, 0xc0, 0xc1, 0xc0]); + } }