rlp view interface + refactor
This commit is contained in:
parent
36bea4692e
commit
7e287755ca
179
src/rlp/faces.rs
179
src/rlp/faces.rs
@ -1,23 +1,198 @@
|
||||
pub trait Reader<'a, 'view>: Sized {
|
||||
pub trait Decoder {
|
||||
type Error;
|
||||
|
||||
fn read_value<T, F>(&self, f: F) -> Result<T, Self::Error>
|
||||
where F: FnOnce(&[u8]) -> Result<T, Self::Error>;
|
||||
|
||||
fn read_list<T, F>(&self, f: F) -> Result<T, Self::Error>
|
||||
where F: FnOnce(&[Self]) -> Result<T, Self::Error>;
|
||||
}
|
||||
|
||||
pub trait Decodable: Sized {
|
||||
fn decode<T, D>(decoder: &D) -> Result<T, D::Error> where D: Decoder;
|
||||
}
|
||||
|
||||
pub trait View<'a, 'view>: Sized {
|
||||
type Prototype;
|
||||
type PayloadInfo;
|
||||
type Data;
|
||||
type Item;
|
||||
type Iter;
|
||||
type Error;
|
||||
|
||||
/// Creates a new instance of `Rlp` reader
|
||||
fn new(bytes: &'a [u8]) -> Self;
|
||||
|
||||
/// The raw data of the RLP.
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate ethcore_util as util;
|
||||
/// use util::rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// let dog = rlp.at(1).raw();
|
||||
/// assert_eq!(dog, &[0x83, b'd', b'o', b'g']);
|
||||
/// }
|
||||
/// ```
|
||||
fn raw(&'view self) -> &'a [u8];
|
||||
|
||||
/// Get the prototype of the RLP.
|
||||
fn prototype(&self) -> Self::Prototype;
|
||||
|
||||
fn payload_info(&self) -> Self::PayloadInfo;
|
||||
|
||||
fn data(&'view self) -> Self::Data;
|
||||
|
||||
/// Returns number of RLP items.
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate ethcore_util as util;
|
||||
/// use util::rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// assert_eq!(rlp.item_count(), 2);
|
||||
/// let view = rlp.at(1);
|
||||
/// assert_eq!(view.item_count(), 0);
|
||||
/// }
|
||||
/// ```
|
||||
fn item_count(&self) -> usize;
|
||||
|
||||
/// Returns the number of bytes in the data, or zero if it isn't data.
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate ethcore_util as util;
|
||||
/// use util::rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// assert_eq!(rlp.size(), 0);
|
||||
/// let view = rlp.at(1);
|
||||
/// assert_eq!(view.size(), 3);
|
||||
/// }
|
||||
/// ```
|
||||
fn size(&self) -> usize;
|
||||
|
||||
/// Get view onto RLP-slice at index.
|
||||
///
|
||||
/// Caches offset to given index, so access to successive
|
||||
/// slices is faster.
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate ethcore_util as util;
|
||||
/// use util::rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// let dog = String::decode(&rlp.at(1));
|
||||
/// assert_eq!(dog, "dog".to_string());
|
||||
/// }
|
||||
fn at(&'view self, index: usize) -> Self::Item;
|
||||
|
||||
/// No value
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate ethcore_util as util;
|
||||
/// use util::rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// assert!(rlp.is_null());
|
||||
/// }
|
||||
/// ```
|
||||
fn is_null(&self) -> bool;
|
||||
|
||||
/// Contains a zero-length string or zero-length list.
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate ethcore_util as util;
|
||||
/// use util::rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![0xc0];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// assert!(rlp.is_empty());
|
||||
/// }
|
||||
/// ```
|
||||
fn is_empty(&self) -> bool;
|
||||
|
||||
/// List value
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate ethcore_util as util;
|
||||
/// use util::rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// 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_list());
|
||||
/// }
|
||||
/// ```
|
||||
fn is_list(&self) -> bool;
|
||||
|
||||
/// String value
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate ethcore_util as util;
|
||||
/// use util::rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// 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.at(1).is_data());
|
||||
/// }
|
||||
/// ```
|
||||
fn is_data(&self) -> bool;
|
||||
|
||||
/// Int value
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate ethcore_util as util;
|
||||
/// use util::rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![0xc1, 0x10];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// assert_eq!(rlp.is_int(), false);
|
||||
/// assert_eq!(rlp.at(0).is_int(), true);
|
||||
/// }
|
||||
/// ```
|
||||
fn is_int(&self) -> bool;
|
||||
|
||||
/// Get iterator over rlp-slices
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate ethcore_util as util;
|
||||
/// use util::rlp::*;
|
||||
///
|
||||
/// fn main () {
|
||||
/// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'];
|
||||
/// let rlp = Rlp::new(&data);
|
||||
/// let strings: Vec<String> = rlp.iter().map(| i | String::decode(&i)).collect();
|
||||
/// }
|
||||
/// ```
|
||||
fn iter(&'view self) -> Self::Iter;
|
||||
|
||||
fn as_val<T>(&self) -> Result<T, Self::Error> where T: Decodable;
|
||||
}
|
||||
|
||||
pub trait Stream {
|
||||
pub trait Encoder {
|
||||
fn emit_value(&mut self, bytes: &[u8]) -> ();
|
||||
fn emit_list<F>(&mut self, f: F) -> () where F: FnOnce(&mut Self) -> ();
|
||||
}
|
||||
|
||||
pub trait Encodable {
|
||||
fn encode<E>(&self, encoder: &mut E) -> () where E: Encoder;
|
||||
}
|
||||
|
||||
pub trait Stream: Sized {
|
||||
fn new() -> Self;
|
||||
fn new_list(len: usize) -> Self;
|
||||
fn append<'a, E>(&'a mut self, object: &E) -> &'a mut Self;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
pub mod old;
|
||||
|
||||
pub mod faces;
|
||||
pub mod coders;
|
||||
pub mod rlp;
|
||||
pub mod untrusted_rlp;
|
||||
|
||||
|
@ -1,19 +1,28 @@
|
||||
use super::faces::Reader;
|
||||
use super::faces::{View, Decodable};
|
||||
use super::untrusted_rlp::*;
|
||||
|
||||
impl<'a> From<UntrustedRlp<'a>> for Rlp<'a> {
|
||||
fn from(rlp: UntrustedRlp<'a>) -> Rlp<'a> {
|
||||
Rlp { rlp: 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.
|
||||
#[derive(Debug)]
|
||||
pub struct Rlp<'a> {
|
||||
rlp: UntrustedRlp<'a>
|
||||
}
|
||||
|
||||
impl<'a, 'view> Reader<'a, 'view> for Rlp<'a> where 'a: 'view {
|
||||
impl<'a, 'view> View<'a, 'view> for Rlp<'a> where 'a: 'view {
|
||||
type Prototype = Prototype;
|
||||
type PayloadInfo = PayloadInfo;
|
||||
type Data = &'a [u8];
|
||||
type Item = Rlp<'a>;
|
||||
type Iter = RlpIterator<'a, 'view>;
|
||||
type Error = DecoderError;
|
||||
|
||||
/// Create a new instance of `Rlp`
|
||||
fn new(bytes: &'a [u8]) -> Rlp<'a> {
|
||||
@ -27,46 +36,94 @@ impl<'a, 'view> Reader<'a, 'view> for Rlp<'a> where 'a: 'view {
|
||||
}
|
||||
|
||||
fn prototype(&self) -> Self::Prototype {
|
||||
unimplemented!()
|
||||
self.rlp.prototype().unwrap()
|
||||
}
|
||||
|
||||
fn payload_info(&self) -> Self::PayloadInfo {
|
||||
unimplemented!()
|
||||
self.rlp.payload_info().unwrap()
|
||||
}
|
||||
|
||||
fn data(&'view self) -> Self::Data {
|
||||
unimplemented!()
|
||||
self.rlp.data().unwrap()
|
||||
}
|
||||
|
||||
fn item_count(&self) -> usize {
|
||||
unimplemented!()
|
||||
self.rlp.item_count()
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
unimplemented!()
|
||||
self.rlp.size()
|
||||
}
|
||||
|
||||
fn at(&'view self, index: usize) -> Self::Item {
|
||||
unimplemented!()
|
||||
From::from(self.rlp.at(index).unwrap())
|
||||
}
|
||||
|
||||
fn is_null(&self) -> bool {
|
||||
unimplemented!()
|
||||
self.rlp.is_null()
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
unimplemented!()
|
||||
self.rlp.is_empty()
|
||||
}
|
||||
|
||||
fn is_list(&self) -> bool {
|
||||
unimplemented!()
|
||||
self.rlp.is_list()
|
||||
}
|
||||
|
||||
fn is_data(&self) -> bool {
|
||||
unimplemented!()
|
||||
self.rlp.is_data()
|
||||
}
|
||||
|
||||
fn is_int(&self) -> bool {
|
||||
unimplemented!()
|
||||
self.rlp.is_int()
|
||||
}
|
||||
|
||||
fn iter(&'view self) -> Self::Iter {
|
||||
self.into_iter()
|
||||
}
|
||||
|
||||
fn as_val<T>(&self) -> Result<T, Self::Error> where T: Decodable {
|
||||
self.rlp.as_val()
|
||||
}
|
||||
}
|
||||
|
||||
impl <'a, 'view> Rlp<'a> where 'a: 'view {
|
||||
fn reader_as_val<T, R>(r: &R) -> T where R: View<'a, 'view>, T: Decodable {
|
||||
let res: Result<T, R::Error> = r.as_val();
|
||||
res.unwrap_or_else(|_| panic!())
|
||||
}
|
||||
|
||||
pub fn as_val<T>(&self) -> T where T: Decodable {
|
||||
Self::reader_as_val(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterator over trusted rlp-slice list elements.
|
||||
pub struct RlpIterator<'a, 'view> where 'a: 'view {
|
||||
rlp: &'view Rlp<'a>,
|
||||
index: usize
|
||||
}
|
||||
|
||||
impl<'a, 'view> IntoIterator for &'view Rlp<'a> where 'a: 'view {
|
||||
type Item = Rlp<'a>;
|
||||
type IntoIter = RlpIterator<'a, 'view>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
RlpIterator {
|
||||
rlp: self,
|
||||
index: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'view> Iterator for RlpIterator<'a, 'view> {
|
||||
type Item = Rlp<'a>;
|
||||
|
||||
fn next(&mut self) -> Option<Rlp<'a>> {
|
||||
let index = self.index;
|
||||
let result = self.rlp.rlp.at(index).ok().map(| iter | { From::from(iter) });
|
||||
self.index += 1;
|
||||
result
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
use std::fmt;
|
||||
use std::cell::Cell;
|
||||
use std::error::Error as StdError;
|
||||
use bytes::{FromBytesError};
|
||||
use super::faces::Reader;
|
||||
use bytes::{FromBytes, FromBytesError};
|
||||
use super::faces::{View, Decoder, Decodable};
|
||||
|
||||
/// rlp offset
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
@ -79,11 +79,22 @@ pub struct UntrustedRlp<'a> {
|
||||
cache: Cell<OffsetCache>,
|
||||
}
|
||||
|
||||
impl<'a, 'view> Reader<'a, 'view> for UntrustedRlp<'a> where 'a: 'view {
|
||||
impl<'a> Clone for UntrustedRlp<'a> {
|
||||
fn clone(&self) -> UntrustedRlp<'a> {
|
||||
UntrustedRlp {
|
||||
bytes: self.bytes,
|
||||
cache: Cell::new(OffsetCache::new(usize::max_value(), 0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'view> View<'a, 'view> for UntrustedRlp<'a> where 'a: 'view {
|
||||
type Prototype = Result<Prototype, DecoderError>;
|
||||
type PayloadInfo = Result<PayloadInfo, DecoderError>;
|
||||
type Data = Result<&'a [u8], DecoderError>;
|
||||
type Item = Result<UntrustedRlp<'a>, DecoderError>;
|
||||
type Iter = UntrustedRlpIterator<'a, 'view>;
|
||||
type Error = DecoderError;
|
||||
|
||||
//returns new instance of `UntrustedRlp`
|
||||
fn new(bytes: &'a [u8]) -> UntrustedRlp<'a> {
|
||||
@ -98,46 +109,235 @@ impl<'a, 'view> Reader<'a, 'view> for UntrustedRlp<'a> where 'a: 'view {
|
||||
}
|
||||
|
||||
fn prototype(&self) -> Self::Prototype {
|
||||
unimplemented!()
|
||||
// optimize? && return appropriate errors
|
||||
if self.is_data() {
|
||||
Ok(Prototype::Data(self.size()))
|
||||
} else if self.is_list() {
|
||||
Ok(Prototype::List(self.item_count()))
|
||||
} else {
|
||||
Ok(Prototype::Null)
|
||||
}
|
||||
}
|
||||
|
||||
fn payload_info(&self) -> Self::PayloadInfo {
|
||||
unimplemented!()
|
||||
BasicDecoder::payload_info(self.bytes)
|
||||
}
|
||||
|
||||
fn data(&'view self) -> Self::Data {
|
||||
unimplemented!()
|
||||
let pi = try!(BasicDecoder::payload_info(self.bytes));
|
||||
Ok(&self.bytes[pi.header_len..(pi.header_len + pi.value_len)])
|
||||
}
|
||||
|
||||
fn item_count(&self) -> usize {
|
||||
unimplemented!()
|
||||
match self.is_list() {
|
||||
true => self.iter().count(),
|
||||
false => 0
|
||||
}
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
unimplemented!()
|
||||
match self.is_data() {
|
||||
// we can safely unwrap (?) cause its data
|
||||
true => BasicDecoder::payload_info(self.bytes).unwrap().value_len,
|
||||
false => 0
|
||||
}
|
||||
}
|
||||
|
||||
fn at(&'view self, index: usize) -> Self::Item {
|
||||
unimplemented!()
|
||||
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 list
|
||||
let c = self.cache.get();
|
||||
let (mut bytes, to_skip) = match c.index <= index {
|
||||
true => (try!(UntrustedRlp::consume(self.bytes, c.offset)), index - c.index),
|
||||
false => (try!(self.consume_list_prefix()), index),
|
||||
};
|
||||
|
||||
// skip up to x items
|
||||
bytes = try!(UntrustedRlp::consume_items(bytes, to_skip));
|
||||
|
||||
// update the cache
|
||||
self.cache.set(OffsetCache::new(index, self.bytes.len() - bytes.len()));
|
||||
|
||||
// construct new rlp
|
||||
let found = try!(BasicDecoder::payload_info(bytes));
|
||||
Ok(UntrustedRlp::new(&bytes[0..found.header_len + found.value_len]))
|
||||
}
|
||||
|
||||
fn is_null(&self) -> bool {
|
||||
unimplemented!()
|
||||
self.bytes.len() == 0
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
unimplemented!()
|
||||
!self.is_null() && (self.bytes[0] == 0xc0 || self.bytes[0] == 0x80)
|
||||
}
|
||||
|
||||
fn is_list(&self) -> bool {
|
||||
unimplemented!()
|
||||
!self.is_null() && self.bytes[0] >= 0xc0
|
||||
}
|
||||
|
||||
fn is_data(&self) -> bool {
|
||||
unimplemented!()
|
||||
!self.is_null() && self.bytes[0] < 0xc0
|
||||
}
|
||||
|
||||
fn is_int(&self) -> bool {
|
||||
unimplemented!()
|
||||
if self.is_null() {
|
||||
return false;
|
||||
}
|
||||
|
||||
match self.bytes[0] {
|
||||
0...0x80 => true,
|
||||
0x81...0xb7 => self.bytes[1] != 0,
|
||||
b @ 0xb8...0xbf => self.bytes[1 + b as usize - 0xb7] != 0,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
fn iter(&'view self) -> Self::Iter {
|
||||
self.into_iter()
|
||||
}
|
||||
|
||||
fn as_val<T>(&self) -> Result<T, Self::Error> where T: Decodable {
|
||||
// optimize, so it doesn't use clone (although This clone is cheap)
|
||||
T::decode(&BasicDecoder::new(self.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> UntrustedRlp<'a> {
|
||||
/// consumes first found prefix
|
||||
fn consume_list_prefix(&self) -> Result<&'a [u8], DecoderError> {
|
||||
let item = try!(BasicDecoder::payload_info(self.bytes));
|
||||
let bytes = try!(UntrustedRlp::consume(self.bytes, item.header_len));
|
||||
Ok(bytes)
|
||||
}
|
||||
|
||||
/// consumes fixed number of items
|
||||
fn consume_items(bytes: &'a [u8], items: usize) -> Result<&'a [u8], DecoderError> {
|
||||
let mut result = bytes;
|
||||
for _ in 0..items {
|
||||
let i = try!(BasicDecoder::payload_info(result));
|
||||
result = try!(UntrustedRlp::consume(result, (i.header_len + i.value_len)));
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
|
||||
/// consumes slice prefix of length `len`
|
||||
fn consume(bytes: &'a [u8], len: usize) -> Result<&'a [u8], DecoderError> {
|
||||
match bytes.len() >= len {
|
||||
true => Ok(&bytes[len..]),
|
||||
false => Err(DecoderError::RlpIsTooShort),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterator over rlp-slice list elements.
|
||||
pub struct UntrustedRlpIterator<'a, 'view> where 'a: 'view {
|
||||
rlp: &'view UntrustedRlp<'a>,
|
||||
index: usize,
|
||||
}
|
||||
|
||||
impl<'a, 'view> IntoIterator for &'view UntrustedRlp<'a> where 'a: 'view {
|
||||
type Item = UntrustedRlp<'a>;
|
||||
type IntoIter = UntrustedRlpIterator<'a, 'view>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
UntrustedRlpIterator {
|
||||
rlp: self,
|
||||
index: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'view> Iterator for UntrustedRlpIterator<'a, 'view> {
|
||||
type Item = UntrustedRlp<'a>;
|
||||
|
||||
fn next(&mut self) -> Option<UntrustedRlp<'a>> {
|
||||
let index = self.index;
|
||||
let result = self.rlp.at(index).ok();
|
||||
self.index += 1;
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
struct BasicDecoder<'a> {
|
||||
rlp: UntrustedRlp<'a>
|
||||
}
|
||||
|
||||
impl<'a> BasicDecoder<'a> {
|
||||
pub fn new(rlp: UntrustedRlp<'a>) -> BasicDecoder<'a> {
|
||||
BasicDecoder {
|
||||
rlp: rlp
|
||||
}
|
||||
}
|
||||
|
||||
/// Return first item info
|
||||
fn payload_info(bytes: &[u8]) -> Result<PayloadInfo, DecoderError> {
|
||||
let item = match bytes.first().map(|&x| x) {
|
||||
None => return Err(DecoderError::RlpIsTooShort),
|
||||
Some(0...0x7f) => PayloadInfo::new(0, 1),
|
||||
Some(l @ 0x80...0xb7) => PayloadInfo::new(1, l as usize - 0x80),
|
||||
Some(l @ 0xb8...0xbf) => {
|
||||
let len_of_len = l as usize - 0xb7;
|
||||
let header_len = 1 + len_of_len;
|
||||
let value_len = try!(usize::from_bytes(&bytes[1..header_len]));
|
||||
PayloadInfo::new(header_len, value_len)
|
||||
}
|
||||
Some(l @ 0xc0...0xf7) => PayloadInfo::new(1, l as usize - 0xc0),
|
||||
Some(l @ 0xf8...0xff) => {
|
||||
let len_of_len = l as usize - 0xf7;
|
||||
let header_len = 1 + len_of_len;
|
||||
let value_len = try!(usize::from_bytes(&bytes[1..header_len]));
|
||||
PayloadInfo::new(header_len, value_len)
|
||||
},
|
||||
// we cant reach this place, but rust requires _ to be implemented
|
||||
_ => { panic!(); }
|
||||
};
|
||||
|
||||
match item.header_len + item.value_len <= bytes.len() {
|
||||
true => Ok(item),
|
||||
false => Err(DecoderError::RlpIsTooShort),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Decoder for BasicDecoder<'a> {
|
||||
type Error = DecoderError;
|
||||
|
||||
fn read_value<T, F>(&self, f: F) -> Result<T, Self::Error>
|
||||
where F: FnOnce(&[u8]) -> Result<T, Self::Error> {
|
||||
|
||||
let bytes = self.rlp.raw();
|
||||
|
||||
match bytes.first().map(|&x| x) {
|
||||
// rlp is too short
|
||||
None => Err(DecoderError::RlpIsTooShort),
|
||||
// single byt value
|
||||
Some(l @ 0...0x7f) => Ok(try!(f(&[l]))),
|
||||
// 0-55 bytes
|
||||
Some(l @ 0x80...0xb7) => Ok(try!(f(&bytes[1..(1 + l as usize - 0x80)]))),
|
||||
// longer than 55 bytes
|
||||
Some(l @ 0xb8...0xbf) => {
|
||||
let len_of_len = l as usize - 0xb7;
|
||||
let begin_of_value = 1 as usize + len_of_len;
|
||||
let len = try!(usize::from_bytes(&bytes[1..begin_of_value]));
|
||||
Ok(try!(f(&bytes[begin_of_value..begin_of_value + len])))
|
||||
}
|
||||
// we are reading value, not a list!
|
||||
_ => { unreachable!(); }
|
||||
}
|
||||
}
|
||||
|
||||
fn read_list<T, F>(&self, f: F) -> Result<T, Self::Error>
|
||||
where F: FnOnce(&[Self]) -> Result<T, Self::Error> {
|
||||
|
||||
let v: Vec<BasicDecoder<'a>> = self.rlp.iter()
|
||||
.map(| i | BasicDecoder::new(i))
|
||||
.collect();
|
||||
f(&v)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user