diff --git a/benches/rlp.rs b/benches/rlp.rs index 1160e311f..62f6c6112 100644 --- a/benches/rlp.rs +++ b/benches/rlp.rs @@ -91,6 +91,6 @@ fn bench_stream_1000_empty_lists(b: &mut Bencher) { for _ in 0..1000 { stream.append_list(0); } - let _ = stream.out(); + //let _ = stream.out(); }); } diff --git a/src/rlp/faces.rs b/src/rlp/faces.rs new file mode 100644 index 000000000..8ebe962c5 --- /dev/null +++ b/src/rlp/faces.rs @@ -0,0 +1,23 @@ +pub trait Reader<'a, 'view>: Sized { + type Prototype; + type PayloadInfo; + type Data; + type Item; + + fn new(bytes: &'a [u8]) -> Self; + fn raw(&'view self) -> &'a [u8]; + fn prototype(&self) -> Self::Prototype; + fn payload_info(&self) -> Self::PayloadInfo; + fn data(&'view self) -> Self::Data; + fn item_count(&self) -> usize; + fn size(&self) -> usize; + fn at(&'view self, index: usize) -> Self::Item; + fn is_null(&self) -> bool; + fn is_empty(&self) -> bool; + fn is_list(&self) -> bool; + fn is_data(&self) -> bool; + fn is_int(&self) -> bool; +} + +pub trait Stream { +} diff --git a/src/rlp/mod.rs b/src/rlp/mod.rs new file mode 100644 index 000000000..98e73665f --- /dev/null +++ b/src/rlp/mod.rs @@ -0,0 +1,7 @@ +pub mod old; + +pub mod faces; +pub mod rlp; +pub mod untrusted_rlp; + +pub use self::old::*; diff --git a/src/rlp.rs b/src/rlp/old.rs similarity index 99% rename from src/rlp.rs rename to src/rlp/old.rs index d0dece3ba..63c3040e0 100644 --- a/src/rlp.rs +++ b/src/rlp/old.rs @@ -32,10 +32,10 @@ use std::fmt; use std::cell::Cell; +use std::ops::Deref; use std::error::Error as StdError; use elastic_array::*; use bytes::{ToBytes, FromBytes, FromBytesError}; -use vector::InsertSlice; /// Data-oriented view onto rlp-slice. /// @@ -113,6 +113,14 @@ pub struct Rlp<'a> { rlp: UntrustedRlp<'a> } +//impl<'a> Deref for Rlp<'a> { + //type Target = UntrustedRlp<'a>; + + //fn deref(&self) -> &Self::Target { + //&self.rlp + //} +//} + impl<'a> From> for Rlp<'a> { fn from(rlp: UntrustedRlp<'a>) -> Rlp<'a> { Rlp { rlp: rlp } @@ -837,8 +845,6 @@ impl RlpStream { /// } /// ``` 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 @@ -846,8 +852,7 @@ impl RlpStream { self.note_appended(1); }, _ => { - // reserve at least double size of the len - //self.encoder.bytes.reserve(len * 2); + let position = self.encoder.bytes.len(); self.unfinished_lists.push(ListInfo::new(position, len)); }, } diff --git a/src/rlp/rlp.rs b/src/rlp/rlp.rs new file mode 100644 index 000000000..603ba425d --- /dev/null +++ b/src/rlp/rlp.rs @@ -0,0 +1,72 @@ +use super::faces::Reader; +use super::untrusted_rlp::*; + +/// Data-oriented view onto trusted rlp-slice. +/// +/// Unlikely to `UntrustedRlp` doesn't bother you with error +/// handling. It assumes that you know what you are doing. +pub struct Rlp<'a> { + rlp: UntrustedRlp<'a> +} + +impl<'a, 'view> Reader<'a, 'view> for Rlp<'a> where 'a: 'view { + type Prototype = Prototype; + type PayloadInfo = PayloadInfo; + type Data = &'a [u8]; + type Item = Rlp<'a>; + + /// Create a new instance of `Rlp` + fn new(bytes: &'a [u8]) -> Rlp<'a> { + Rlp { + rlp: UntrustedRlp::new(bytes) + } + } + + fn raw(&'view self) -> &'a [u8] { + self.rlp.raw() + } + + fn prototype(&self) -> Self::Prototype { + unimplemented!() + } + + fn payload_info(&self) -> Self::PayloadInfo { + unimplemented!() + } + + fn data(&'view self) -> Self::Data { + unimplemented!() + } + + fn item_count(&self) -> usize { + unimplemented!() + } + + fn size(&self) -> usize { + unimplemented!() + } + + fn at(&'view self, index: usize) -> Self::Item { + unimplemented!() + } + + fn is_null(&self) -> bool { + unimplemented!() + } + + fn is_empty(&self) -> bool { + unimplemented!() + } + + fn is_list(&self) -> bool { + unimplemented!() + } + + fn is_data(&self) -> bool { + unimplemented!() + } + + fn is_int(&self) -> bool { + unimplemented!() + } +} diff --git a/src/rlp/rlpstream.rs b/src/rlp/rlpstream.rs new file mode 100644 index 000000000..e69de29bb diff --git a/src/rlp/untrusted_rlp.rs b/src/rlp/untrusted_rlp.rs new file mode 100644 index 000000000..8d875324e --- /dev/null +++ b/src/rlp/untrusted_rlp.rs @@ -0,0 +1,143 @@ +use std::fmt; +use std::cell::Cell; +use std::error::Error as StdError; +use bytes::{FromBytesError}; +use super::faces::Reader; + +/// rlp offset +#[derive(Copy, Clone, Debug)] +struct OffsetCache { + index: usize, + offset: usize, +} + +impl OffsetCache { + fn new(index: usize, offset: usize) -> OffsetCache { + OffsetCache { + index: index, + offset: offset, + } + } +} + +#[derive(Debug)] +pub enum Prototype { + Null, + Data(usize), + List(usize), +} + +/// Stores basic information about item +pub struct PayloadInfo { + pub header_len: usize, + pub value_len: usize, +} + +impl PayloadInfo { + fn new(header_len: usize, value_len: usize) -> PayloadInfo { + PayloadInfo { + header_len: header_len, + value_len: value_len, + } + } +} + +#[derive(Debug, PartialEq, Eq)] +pub enum DecoderError { + FromBytesError(FromBytesError), + RlpIsTooShort, + RlpExpectedToBeList, + RlpExpectedToBeData, +} +impl StdError for DecoderError { + fn description(&self) -> &str { + "builder error" + } +} + +impl fmt::Display for DecoderError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self, f) + } +} + +impl From for DecoderError { + fn from(err: FromBytesError) -> DecoderError { + DecoderError::FromBytesError(err) + } +} + +/// Data-oriented view onto rlp-slice. +/// +/// This is immutable structere. No operations change it. +/// +/// Should be used in places where, error handling is required, +/// eg. on input +#[derive(Debug)] +pub struct UntrustedRlp<'a> { + bytes: &'a [u8], + cache: Cell, +} + +impl<'a, 'view> Reader<'a, 'view> for UntrustedRlp<'a> where 'a: 'view { + type Prototype = Result; + type PayloadInfo = Result; + type Data = Result<&'a [u8], DecoderError>; + type Item = Result, DecoderError>; + + //returns new instance of `UntrustedRlp` + fn new(bytes: &'a [u8]) -> UntrustedRlp<'a> { + UntrustedRlp { + bytes: bytes, + cache: Cell::new(OffsetCache::new(usize::max_value(), 0)), + } + } + + fn raw(&'view self) -> &'a [u8] { + self.bytes + } + + fn prototype(&self) -> Self::Prototype { + unimplemented!() + } + + fn payload_info(&self) -> Self::PayloadInfo { + unimplemented!() + } + + fn data(&'view self) -> Self::Data { + unimplemented!() + } + + fn item_count(&self) -> usize { + unimplemented!() + } + + fn size(&self) -> usize { + unimplemented!() + } + + fn at(&'view self, index: usize) -> Self::Item { + unimplemented!() + } + + fn is_null(&self) -> bool { + unimplemented!() + } + + fn is_empty(&self) -> bool { + unimplemented!() + } + + fn is_list(&self) -> bool { + unimplemented!() + } + + fn is_data(&self) -> bool { + unimplemented!() + } + + fn is_int(&self) -> bool { + unimplemented!() + } +}