openethereum/util/src/rlp/untrusted_rlp.rs

462 lines
12 KiB
Rust
Raw Normal View History

2015-12-07 16:32:06 +01:00
use std::cell::Cell;
2016-01-15 21:03:38 +01:00
use std::fmt;
use rustc_serialize::hex::ToHex;
2015-12-08 00:07:07 +01:00
use bytes::{FromBytes};
2015-12-08 12:59:19 +01:00
use rlp::{View, Decoder, Decodable, DecoderError};
2015-12-07 16:32:06 +01:00
/// 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)]
2016-01-19 17:02:01 +01:00
/// TODO [debris] Please document me
2015-12-07 16:32:06 +01:00
pub enum Prototype {
2016-01-19 17:02:01 +01:00
/// TODO [debris] Please document me
2015-12-07 16:32:06 +01:00
Null,
2016-01-19 17:02:01 +01:00
/// TODO [debris] Please document me
2015-12-07 16:32:06 +01:00
Data(usize),
2016-01-19 17:02:01 +01:00
/// TODO [debris] Please document me
2015-12-07 16:32:06 +01:00
List(usize),
}
/// Stores basic information about item
pub struct PayloadInfo {
2016-01-19 17:02:01 +01:00
/// TODO [debris] Please document me
2015-12-07 16:32:06 +01:00
pub header_len: usize,
2016-01-19 17:02:01 +01:00
/// TODO [debris] Please document me
2015-12-07 16:32:06 +01:00
pub value_len: usize,
}
impl PayloadInfo {
fn new(header_len: usize, value_len: usize) -> PayloadInfo {
PayloadInfo {
header_len: header_len,
value_len: value_len,
}
}
}
/// Data-oriented view onto rlp-slice.
2015-12-22 22:23:01 +01:00
///
2015-12-07 16:32:06 +01:00
/// This is immutable structere. No operations change it.
2015-12-22 22:23:01 +01:00
///
2015-12-07 16:32:06 +01:00
/// Should be used in places where, error handling is required,
/// eg. on input
#[derive(Debug)]
pub struct UntrustedRlp<'a> {
bytes: &'a [u8],
2015-12-22 22:23:01 +01:00
offset_cache: Cell<OffsetCache>,
count_cache: Cell<Option<usize>>,
2015-12-07 16:32:06 +01:00
}
2015-12-07 23:47:26 +01:00
impl<'a> Clone for UntrustedRlp<'a> {
fn clone(&self) -> UntrustedRlp<'a> {
UntrustedRlp {
bytes: self.bytes,
2015-12-22 22:23:01 +01:00
offset_cache: self.offset_cache.clone(),
count_cache: self.count_cache.clone(),
2015-12-07 23:47:26 +01:00
}
}
}
2016-01-15 21:03:38 +01:00
impl<'a> fmt::Display for UntrustedRlp<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match self.prototype() {
Ok(Prototype::Null) => write!(f, "null"),
Ok(Prototype::Data(_)) => write!(f, "\"0x{}\"", self.data().unwrap().to_hex()),
Ok(Prototype::List(len)) => {
try!(write!(f, "["));
for i in 0..len-1 {
try!(write!(f, "{}, ", self.at(i).unwrap()));
}
try!(write!(f, "{}", self.at(len - 1).unwrap()));
write!(f, "]")
},
Err(err) => write!(f, "{:?}", err)
}
}
}
2015-12-07 23:47:26 +01:00
impl<'a, 'view> View<'a, 'view> for UntrustedRlp<'a> where 'a: 'view {
2015-12-07 16:32:06 +01:00
type Prototype = Result<Prototype, DecoderError>;
type PayloadInfo = Result<PayloadInfo, DecoderError>;
type Data = Result<&'a [u8], DecoderError>;
type Item = Result<UntrustedRlp<'a>, DecoderError>;
2015-12-07 23:47:26 +01:00
type Iter = UntrustedRlpIterator<'a, 'view>;
2015-12-07 16:32:06 +01:00
//returns new instance of `UntrustedRlp`
fn new(bytes: &'a [u8]) -> UntrustedRlp<'a> {
UntrustedRlp {
bytes: bytes,
2015-12-22 22:23:01 +01:00
offset_cache: Cell::new(OffsetCache::new(usize::max_value(), 0)),
count_cache: Cell::new(None)
2015-12-07 16:32:06 +01:00
}
}
2015-12-22 22:23:01 +01:00
2016-01-08 15:52:43 +01:00
fn as_raw(&'view self) -> &'a [u8] {
2015-12-07 16:32:06 +01:00
self.bytes
}
fn prototype(&self) -> Self::Prototype {
2015-12-07 23:47:26 +01:00
// 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)
}
2015-12-07 16:32:06 +01:00
}
fn payload_info(&self) -> Self::PayloadInfo {
2015-12-07 23:47:26 +01:00
BasicDecoder::payload_info(self.bytes)
2015-12-07 16:32:06 +01:00
}
fn data(&'view self) -> Self::Data {
2015-12-07 23:47:26 +01:00
let pi = try!(BasicDecoder::payload_info(self.bytes));
Ok(&self.bytes[pi.header_len..(pi.header_len + pi.value_len)])
2015-12-07 16:32:06 +01:00
}
fn item_count(&self) -> usize {
2015-12-07 23:47:26 +01:00
match self.is_list() {
2015-12-22 22:23:01 +01:00
true => match self.count_cache.get() {
Some(c) => c,
None => {
let c = self.iter().count();
self.count_cache.set(Some(c));
c
}
},
2015-12-07 23:47:26 +01:00
false => 0
}
2015-12-07 16:32:06 +01:00
}
fn size(&self) -> usize {
2015-12-07 23:47:26 +01:00
match self.is_data() {
// we can safely unwrap (?) cause its data
true => BasicDecoder::payload_info(self.bytes).unwrap().value_len,
false => 0
}
2015-12-07 16:32:06 +01:00
}
fn at(&'view self, index: usize) -> Self::Item {
2015-12-07 23:47:26 +01:00
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
2015-12-22 22:23:01 +01:00
let c = self.offset_cache.get();
2015-12-07 23:47:26 +01:00
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
2015-12-22 22:23:01 +01:00
self.offset_cache.set(OffsetCache::new(index, self.bytes.len() - bytes.len()));
2015-12-07 23:47:26 +01:00
// construct new rlp
let found = try!(BasicDecoder::payload_info(bytes));
Ok(UntrustedRlp::new(&bytes[0..found.header_len + found.value_len]))
2015-12-07 16:32:06 +01:00
}
fn is_null(&self) -> bool {
2015-12-07 23:47:26 +01:00
self.bytes.len() == 0
2015-12-07 16:32:06 +01:00
}
fn is_empty(&self) -> bool {
2015-12-07 23:47:26 +01:00
!self.is_null() && (self.bytes[0] == 0xc0 || self.bytes[0] == 0x80)
2015-12-07 16:32:06 +01:00
}
fn is_list(&self) -> bool {
2015-12-07 23:47:26 +01:00
!self.is_null() && self.bytes[0] >= 0xc0
2015-12-07 16:32:06 +01:00
}
fn is_data(&self) -> bool {
2015-12-07 23:47:26 +01:00
!self.is_null() && self.bytes[0] < 0xc0
2015-12-07 16:32:06 +01:00
}
fn is_int(&self) -> bool {
2015-12-07 23:47:26 +01:00
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()
}
2015-12-08 00:07:07 +01:00
fn as_val<T>(&self) -> Result<T, DecoderError> where T: Decodable {
2015-12-07 23:47:26 +01:00
// optimize, so it doesn't use clone (although This clone is cheap)
T::decode(&BasicDecoder::new(self.clone()))
}
2015-12-08 14:44:22 +01:00
fn val_at<T>(&self, index: usize) -> Result<T, DecoderError> where T: Decodable {
2016-01-10 14:02:01 +01:00
try!(self.at(index)).as_val()
2015-12-08 14:44:22 +01:00
}
2015-12-07 23:47:26 +01:00
}
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),
}
2015-12-07 16:32:06 +01:00
}
}
2015-12-07 23:47:26 +01:00
/// 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> {
2016-01-19 12:14:29 +01:00
let item = match bytes.first().cloned() {
2015-12-07 23:47:26 +01:00
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;
if bytes[1] == 0 { return Err(DecoderError::RlpDataLenWithZeroPrefix); }
2015-12-07 23:47:26 +01:00
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]));
if bytes[1] == 0 { return Err(DecoderError::RlpListLenWithZeroPrefix); }
2015-12-07 23:47:26 +01:00
PayloadInfo::new(header_len, value_len)
},
// we cant reach this place, but rust requires _ to be implemented
_ => { unreachable!(); }
2015-12-07 23:47:26 +01:00
};
match item.header_len + item.value_len <= bytes.len() {
true => Ok(item),
false => Err(DecoderError::RlpIsTooShort),
}
}
}
impl<'a> Decoder for BasicDecoder<'a> {
2015-12-08 00:07:07 +01:00
fn read_value<T, F>(&self, f: F) -> Result<T, DecoderError>
where F: FnOnce(&[u8]) -> Result<T, DecoderError> {
2015-12-07 23:47:26 +01:00
2016-01-08 15:52:43 +01:00
let bytes = self.rlp.as_raw();
2015-12-07 23:47:26 +01:00
2016-01-19 12:14:29 +01:00
match bytes.first().cloned() {
2015-12-07 23:47:26 +01:00
// 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) => {
2016-01-25 13:23:05 +01:00
let last_index_of = 1 + l as usize - 0x80;
if bytes.len() < last_index_of {
2016-01-25 14:27:11 +01:00
return Err(DecoderError::RlpInconsistentLengthAndData);
2016-01-25 13:23:05 +01:00
}
let d = &bytes[1..last_index_of];
if l == 0x81 && d[0] < 0x80 {
return Err(DecoderError::RlpInvalidIndirection);
}
2016-01-25 13:23:05 +01:00
Ok(try!(f(d)))
},
2015-12-07 23:47:26 +01:00
// 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;
2016-01-25 14:27:11 +01:00
if bytes.len() < begin_of_value {
return Err(DecoderError::RlpInconsistentLengthAndData);
}
2015-12-07 23:47:26 +01:00
let len = try!(usize::from_bytes(&bytes[1..begin_of_value]));
2016-01-25 14:27:11 +01:00
let last_index_of_value = begin_of_value + len;
if bytes.len() < last_index_of_value {
return Err(DecoderError::RlpInconsistentLengthAndData);
}
Ok(try!(f(&bytes[begin_of_value..last_index_of_value])))
2015-12-07 23:47:26 +01:00
}
// we are reading value, not a list!
_ => Err(DecoderError::RlpExpectedToBeData)
2015-12-07 23:47:26 +01:00
}
}
fn as_raw(&self) -> &[u8] {
2016-01-08 15:52:43 +01:00
self.rlp.as_raw()
}
2015-12-14 12:03:48 +01:00
fn as_list(&self) -> Result<Vec<Self>, DecoderError> {
2015-12-07 23:47:26 +01:00
let v: Vec<BasicDecoder<'a>> = self.rlp.iter()
2016-01-19 12:14:29 +01:00
.map(BasicDecoder::new)
2015-12-07 23:47:26 +01:00
.collect();
2015-12-14 12:03:48 +01:00
Ok(v)
2015-12-07 23:47:26 +01:00
}
2015-12-26 15:48:41 +01:00
2016-01-19 12:14:29 +01:00
fn as_rlp(&self) -> &UntrustedRlp {
2015-12-26 15:48:41 +01:00
&self.rlp
}
2015-12-07 23:47:26 +01:00
}
2015-12-08 00:07:07 +01:00
impl<T> Decodable for T where T: FromBytes {
2015-12-08 00:27:12 +01:00
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
decoder.read_value(| bytes | {
Ok(try!(T::from_bytes(bytes)))
})
2015-12-08 00:07:07 +01:00
}
}
impl<T> Decodable for Vec<T> where T: Decodable {
2015-12-08 00:27:12 +01:00
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
2015-12-14 12:03:48 +01:00
let decoders = try!(decoder.as_list());
decoders.iter().map(|d| T::decode(d)).collect()
2015-12-08 00:07:07 +01:00
}
}
impl Decodable for Vec<u8> {
2015-12-08 00:27:12 +01:00
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
decoder.read_value(| bytes | {
let mut res = vec![];
res.extend(bytes);
Ok(res)
})
2015-12-08 00:07:07 +01:00
}
}
impl<T> Decodable for Option<T> where T: Decodable {
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
decoder.read_value(| bytes | {
let res = match bytes.len() {
0 => None,
_ => Some(try!(T::decode(decoder)))
};
Ok(res)
})
}
}
2015-12-14 11:56:11 +01:00
macro_rules! impl_array_decodable {
($index_type:ty, $len:expr ) => (
impl<T> Decodable for [T; $len] where T: Decodable {
2016-01-19 12:14:29 +01:00
#[allow(len_zero)]
2015-12-14 11:56:11 +01:00
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
2015-12-14 12:03:48 +01:00
let decoders = try!(decoder.as_list());
let mut result: [T; $len] = unsafe { ::std::mem::uninitialized() };
if decoders.len() != $len {
return Err(DecoderError::RlpIncorrectListLen);
}
2015-12-22 22:23:01 +01:00
2015-12-14 12:03:48 +01:00
for i in 0..decoders.len() {
result[i] = try!(T::decode(&decoders[i]));
}
Ok(result)
2015-12-14 11:56:11 +01:00
}
}
)
}
macro_rules! impl_array_decodable_recursive {
($index_type:ty, ) => ();
($index_type:ty, $len:expr, $($more:expr,)*) => (
impl_array_decodable!($index_type, $len);
impl_array_decodable_recursive!($index_type, $($more,)*);
);
}
impl_array_decodable_recursive!(
u8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 40, 48, 56, 64, 72, 96, 128, 160, 192, 224,
);
2016-01-15 21:03:38 +01:00
#[test]
fn test_rlp_display() {
use rustc_serialize::hex::FromHex;
let data = "f84d0589010efbef67941f79b2a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470".from_hex().unwrap();
let rlp = UntrustedRlp::new(&data);
2016-01-16 00:42:02 +01:00
assert_eq!(format!("{}", rlp), "[\"0x05\", \"0x010efbef67941f79b2\", \"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\", \"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470\"]");
2016-01-15 21:03:38 +01:00
}