From c5163b796fd344e04900604facf761dcd197b903 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 25 Nov 2015 21:04:43 +0100 Subject: [PATCH] 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) } }