cache item count in Rlp

This commit is contained in:
arkpar 2015-12-22 22:23:01 +01:00
parent 900fc833f0
commit f34b22c65b
2 changed files with 24 additions and 14 deletions

View File

@ -26,7 +26,7 @@ pub struct RlpStream {
} }
impl Stream for RlpStream { impl Stream for RlpStream {
fn new() -> Self { fn new() -> Self {
RlpStream { RlpStream {
unfinished_lists: ElasticArray16::new(), unfinished_lists: ElasticArray16::new(),
encoder: BasicEncoder::new(), encoder: BasicEncoder::new(),
@ -57,7 +57,7 @@ impl Stream for RlpStream {
self.encoder.bytes.push(0xc0u8); self.encoder.bytes.push(0xc0u8);
self.note_appended(1); self.note_appended(1);
}, },
_ => { _ => {
let position = self.encoder.bytes.len(); let position = self.encoder.bytes.len();
self.unfinished_lists.push(ListInfo::new(position, len)); self.unfinished_lists.push(ListInfo::new(position, len));
}, },
@ -66,7 +66,7 @@ impl Stream for RlpStream {
// return chainable self // return chainable self
self self
} }
fn append_empty_data<'a>(&'a mut self) -> &'a mut RlpStream { fn append_empty_data<'a>(&'a mut self) -> &'a mut RlpStream {
// self push raw item // self push raw item
self.encoder.bytes.push(0x80); self.encoder.bytes.push(0x80);
@ -80,7 +80,7 @@ impl Stream for RlpStream {
fn append_raw<'a>(&'a mut self, bytes: &[u8], item_count: usize) -> &'a mut RlpStream { fn append_raw<'a>(&'a mut self, bytes: &[u8], item_count: usize) -> &'a mut RlpStream {
// push raw items // push raw items
self.encoder.bytes.append_slice(bytes); self.encoder.bytes.append_slice(bytes);
// try to finish and prepend the length // try to finish and prepend the length
self.note_appended(item_count); self.note_appended(item_count);

View File

@ -41,22 +41,24 @@ impl PayloadInfo {
} }
/// Data-oriented view onto rlp-slice. /// Data-oriented view onto rlp-slice.
/// ///
/// This is immutable structere. No operations change it. /// This is immutable structere. No operations change it.
/// ///
/// Should be used in places where, error handling is required, /// Should be used in places where, error handling is required,
/// eg. on input /// eg. on input
#[derive(Debug)] #[derive(Debug)]
pub struct UntrustedRlp<'a> { pub struct UntrustedRlp<'a> {
bytes: &'a [u8], bytes: &'a [u8],
cache: Cell<OffsetCache>, offset_cache: Cell<OffsetCache>,
count_cache: Cell<Option<usize>>,
} }
impl<'a> Clone for UntrustedRlp<'a> { impl<'a> Clone for UntrustedRlp<'a> {
fn clone(&self) -> UntrustedRlp<'a> { fn clone(&self) -> UntrustedRlp<'a> {
UntrustedRlp { UntrustedRlp {
bytes: self.bytes, bytes: self.bytes,
cache: Cell::new(OffsetCache::new(usize::max_value(), 0)) offset_cache: self.offset_cache.clone(),
count_cache: self.count_cache.clone(),
} }
} }
} }
@ -72,10 +74,11 @@ impl<'a, 'view> View<'a, 'view> for UntrustedRlp<'a> where 'a: 'view {
fn new(bytes: &'a [u8]) -> UntrustedRlp<'a> { fn new(bytes: &'a [u8]) -> UntrustedRlp<'a> {
UntrustedRlp { UntrustedRlp {
bytes: bytes, bytes: bytes,
cache: Cell::new(OffsetCache::new(usize::max_value(), 0)), offset_cache: Cell::new(OffsetCache::new(usize::max_value(), 0)),
count_cache: Cell::new(None)
} }
} }
fn raw(&'view self) -> &'a [u8] { fn raw(&'view self) -> &'a [u8] {
self.bytes self.bytes
} }
@ -102,7 +105,14 @@ impl<'a, 'view> View<'a, 'view> for UntrustedRlp<'a> where 'a: 'view {
fn item_count(&self) -> usize { fn item_count(&self) -> usize {
match self.is_list() { match self.is_list() {
true => self.iter().count(), true => match self.count_cache.get() {
Some(c) => c,
None => {
let c = self.iter().count();
self.count_cache.set(Some(c));
c
}
},
false => 0 false => 0
} }
} }
@ -122,7 +132,7 @@ impl<'a, 'view> View<'a, 'view> for UntrustedRlp<'a> where 'a: 'view {
// move to cached position if it's index is less or equal to // move to cached position if it's index is less or equal to
// current search index, otherwise move to beginning of list // current search index, otherwise move to beginning of list
let c = self.cache.get(); let c = self.offset_cache.get();
let (mut bytes, to_skip) = match c.index <= index { let (mut bytes, to_skip) = match c.index <= index {
true => (try!(UntrustedRlp::consume(self.bytes, c.offset)), index - c.index), true => (try!(UntrustedRlp::consume(self.bytes, c.offset)), index - c.index),
false => (try!(self.consume_list_prefix()), index), false => (try!(self.consume_list_prefix()), index),
@ -132,7 +142,7 @@ impl<'a, 'view> View<'a, 'view> for UntrustedRlp<'a> where 'a: 'view {
bytes = try!(UntrustedRlp::consume_items(bytes, to_skip)); bytes = try!(UntrustedRlp::consume_items(bytes, to_skip));
// update the cache // update the cache
self.cache.set(OffsetCache::new(index, self.bytes.len() - bytes.len())); self.offset_cache.set(OffsetCache::new(index, self.bytes.len() - bytes.len()));
// construct new rlp // construct new rlp
let found = try!(BasicDecoder::payload_info(bytes)); let found = try!(BasicDecoder::payload_info(bytes));
@ -360,7 +370,7 @@ macro_rules! impl_array_decodable {
if decoders.len() != $len { if decoders.len() != $len {
return Err(DecoderError::RlpIncorrectListLen); return Err(DecoderError::RlpIncorrectListLen);
} }
for i in 0..decoders.len() { for i in 0..decoders.len() {
result[i] = try!(T::decode(&decoders[i])); result[i] = try!(T::decode(&decoders[i]));
} }