RLP decoder refactoring
This commit is contained in:
parent
cfa2776e75
commit
772de24cae
10
src/block.rs
10
src/block.rs
@ -45,14 +45,14 @@ impl Decodable for Block {
|
||||
if decoder.as_raw().len() != try!(decoder.as_rlp().payload_info()).total() {
|
||||
return Err(DecoderError::RlpIsTooBig);
|
||||
}
|
||||
let d = try!(decoder.as_list());
|
||||
if d.len() != 3 {
|
||||
let d = decoder.as_rlp();
|
||||
if d.item_count() != 3 {
|
||||
return Err(DecoderError::RlpIncorrectListLen);
|
||||
}
|
||||
Ok(Block {
|
||||
header: try!(Decodable::decode(&d[0])),
|
||||
transactions: try!(Decodable::decode(&d[1])),
|
||||
uncles: try!(Decodable::decode(&d[2])),
|
||||
header: try!(d.val_at(0)),
|
||||
transactions: try!(d.val_at(1)),
|
||||
uncles: try!(d.val_at(2)),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -133,12 +133,12 @@ impl HeapSizeOf for BlockDetails {
|
||||
|
||||
impl Decodable for BlockDetails {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let d = try!(decoder.as_list());
|
||||
let d = decoder.as_rlp();
|
||||
let details = BlockDetails {
|
||||
number: try!(Decodable::decode(&d[0])),
|
||||
total_difficulty: try!(Decodable::decode(&d[1])),
|
||||
parent: try!(Decodable::decode(&d[2])),
|
||||
children: try!(Decodable::decode(&d[3]))
|
||||
number: try!(d.val_at(0)),
|
||||
total_difficulty: try!(d.val_at(1)),
|
||||
parent: try!(d.val_at(2)),
|
||||
children: try!(d.val_at(3)),
|
||||
};
|
||||
Ok(details)
|
||||
}
|
||||
@ -257,10 +257,10 @@ impl HeapSizeOf for TransactionAddress {
|
||||
|
||||
impl Decodable for TransactionAddress {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let d = try!(decoder.as_list());
|
||||
let d = decoder.as_rlp();
|
||||
let tx_address = TransactionAddress {
|
||||
block_hash: try!(Decodable::decode(&d[0])),
|
||||
index: try!(Decodable::decode(&d[1]))
|
||||
block_hash: try!(d.val_at(0)),
|
||||
index: try!(d.val_at(1)),
|
||||
};
|
||||
|
||||
Ok(tx_address)
|
||||
|
@ -267,20 +267,20 @@ impl Decodable for Action {
|
||||
|
||||
impl Decodable for Transaction {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let d = try!(decoder.as_list());
|
||||
if d.len() != 9 {
|
||||
let d = decoder.as_rlp();
|
||||
if d.item_count() != 9 {
|
||||
return Err(DecoderError::RlpIncorrectListLen);
|
||||
}
|
||||
Ok(Transaction {
|
||||
nonce: try!(Decodable::decode(&d[0])),
|
||||
gas_price: try!(Decodable::decode(&d[1])),
|
||||
gas: try!(Decodable::decode(&d[2])),
|
||||
action: try!(Decodable::decode(&d[3])),
|
||||
value: try!(Decodable::decode(&d[4])),
|
||||
data: try!(Decodable::decode(&d[5])),
|
||||
v: try!(u16::decode(&d[6])) as u8,
|
||||
r: try!(Decodable::decode(&d[7])),
|
||||
s: try!(Decodable::decode(&d[8])),
|
||||
nonce: try!(d.val_at(0)),
|
||||
gas_price: try!(d.val_at(1)),
|
||||
gas: try!(d.val_at(2)),
|
||||
action: try!(d.val_at(3)),
|
||||
value: try!(d.val_at(4)),
|
||||
data: try!(d.val_at(5)),
|
||||
v: try!(d.val_at(6)),
|
||||
r: try!(d.val_at(7)),
|
||||
s: try!(d.val_at(8)),
|
||||
hash: RefCell::new(None),
|
||||
sender: RefCell::new(None),
|
||||
})
|
||||
|
@ -11,37 +11,14 @@
|
||||
//! let slice: &[u8] = arr.bytes();
|
||||
//! }
|
||||
//!
|
||||
//! fn to_bytes() {
|
||||
//! use util::bytes::ToBytes;
|
||||
//!
|
||||
//! let mut out: Vec<u8> = Vec::new();
|
||||
//! "hello_world".to_bytes(&mut out);
|
||||
//! 400u32.to_bytes(&mut out);
|
||||
//! 0xffffffffffffffffu64.to_bytes(&mut out);
|
||||
//! }
|
||||
//!
|
||||
//! fn from_bytes() {
|
||||
//! use util::bytes::FromBytes;
|
||||
//!
|
||||
//! let a = String::from_bytes(&[b'd', b'o', b'g']);
|
||||
//! let b = u16::from_bytes(&[0xfa]);
|
||||
//! let c = u64::from_bytes(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);
|
||||
//! }
|
||||
//!
|
||||
//! fn main() {
|
||||
//! bytes_convertable();
|
||||
//! to_bytes();
|
||||
//! from_bytes();
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use std::mem;
|
||||
use std::fmt;
|
||||
use std::slice;
|
||||
use std::cmp::Ordering;
|
||||
use std::error::Error as StdError;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use uint::{Uint, U128, U256};
|
||||
use hash::FixedHash;
|
||||
use elastic_array::*;
|
||||
|
||||
@ -205,213 +182,6 @@ fn bytes_convertable() {
|
||||
assert_eq!([0u8; 0].bytes(), &[]);
|
||||
}
|
||||
|
||||
/// Converts given type to its shortest representation in bytes
|
||||
///
|
||||
/// TODO: optimise some conversations
|
||||
pub trait ToBytes {
|
||||
/// Serialize self to byte array
|
||||
fn to_bytes<V: VecLike<u8>>(&self, out: &mut V);
|
||||
/// Get length of serialized data in bytes
|
||||
fn to_bytes_len(&self) -> usize;
|
||||
}
|
||||
|
||||
impl <'a> ToBytes for &'a str {
|
||||
fn to_bytes<V: VecLike<u8>>(&self, out: &mut V) {
|
||||
out.vec_extend(self.as_bytes());
|
||||
}
|
||||
|
||||
fn to_bytes_len(&self) -> usize {
|
||||
self.as_bytes().len()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToBytes for String {
|
||||
fn to_bytes<V: VecLike<u8>>(&self, out: &mut V) {
|
||||
out.vec_extend(self.as_bytes());
|
||||
}
|
||||
|
||||
fn to_bytes_len(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToBytes for u64 {
|
||||
fn to_bytes<V: VecLike<u8>>(&self, out: &mut V) {
|
||||
let count = self.to_bytes_len();
|
||||
for i in 0..count {
|
||||
let j = count - 1 - i;
|
||||
out.vec_push((*self >> (j * 8)) as u8);
|
||||
}
|
||||
}
|
||||
|
||||
fn to_bytes_len(&self) -> usize { 8 - self.leading_zeros() as usize / 8 }
|
||||
}
|
||||
|
||||
impl ToBytes for bool {
|
||||
fn to_bytes<V: VecLike<u8>>(&self, out: &mut V) {
|
||||
out.vec_push(if *self { 1u8 } else { 0u8 })
|
||||
}
|
||||
|
||||
fn to_bytes_len(&self) -> usize { 1 }
|
||||
}
|
||||
|
||||
macro_rules! impl_map_to_bytes {
|
||||
($from: ident, $to: ty) => {
|
||||
impl ToBytes for $from {
|
||||
fn to_bytes<V: VecLike<u8>>(&self, out: &mut V) {
|
||||
(*self as $to).to_bytes(out)
|
||||
}
|
||||
|
||||
fn to_bytes_len(&self) -> usize { (*self as $to).to_bytes_len() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_map_to_bytes!(usize, u64);
|
||||
impl_map_to_bytes!(u16, u64);
|
||||
impl_map_to_bytes!(u32, u64);
|
||||
|
||||
macro_rules! impl_uint_to_bytes {
|
||||
($name: ident) => {
|
||||
impl ToBytes for $name {
|
||||
fn to_bytes<V: VecLike<u8>>(&self, out: &mut V) {
|
||||
let count = self.to_bytes_len();
|
||||
for i in 0..count {
|
||||
let j = count - 1 - i;
|
||||
out.vec_push(self.byte(j));
|
||||
}
|
||||
}
|
||||
fn to_bytes_len(&self) -> usize { (self.bits() + 7) / 8 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_uint_to_bytes!(U256);
|
||||
impl_uint_to_bytes!(U128);
|
||||
|
||||
impl <T>ToBytes for T where T: FixedHash {
|
||||
fn to_bytes<V: VecLike<u8>>(&self, out: &mut V) {
|
||||
out.vec_extend(self.bytes());
|
||||
}
|
||||
fn to_bytes_len(&self) -> usize { self.bytes().len() }
|
||||
}
|
||||
|
||||
/// Error returned when FromBytes conversation goes wrong
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum FromBytesError {
|
||||
/// TODO [debris] Please document me
|
||||
DataIsTooShort,
|
||||
/// TODO [debris] Please document me
|
||||
DataIsTooLong,
|
||||
/// Integer-representation is non-canonically prefixed with zero byte(s).
|
||||
ZeroPrefixedInt,
|
||||
}
|
||||
|
||||
impl StdError for FromBytesError {
|
||||
fn description(&self) -> &str { "from_bytes error" }
|
||||
}
|
||||
|
||||
impl fmt::Display for FromBytesError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Debug::fmt(&self, f)
|
||||
}
|
||||
}
|
||||
|
||||
/// Alias for the result of FromBytes trait
|
||||
pub type FromBytesResult<T> = Result<T, FromBytesError>;
|
||||
|
||||
/// Converts to given type from its bytes representation
|
||||
///
|
||||
/// TODO: check size of bytes before conversation and return appropriate error
|
||||
pub trait FromBytes: Sized {
|
||||
/// TODO [debris] Please document me
|
||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<Self>;
|
||||
}
|
||||
|
||||
impl FromBytes for String {
|
||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<String> {
|
||||
Ok(::std::str::from_utf8(bytes).unwrap().to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_uint_from_bytes {
|
||||
($to: ident) => {
|
||||
impl FromBytes for $to {
|
||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<$to> {
|
||||
match bytes.len() {
|
||||
0 => Ok(0),
|
||||
l if l <= mem::size_of::<$to>() => {
|
||||
if bytes[0] == 0 {
|
||||
return Err(FromBytesError::ZeroPrefixedInt)
|
||||
}
|
||||
let mut res = 0 as $to;
|
||||
for i in 0..l {
|
||||
let shift = (l - 1 - i) * 8;
|
||||
res = res + ((bytes[i] as $to) << shift);
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
_ => Err(FromBytesError::DataIsTooLong)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromBytes for bool {
|
||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<bool> {
|
||||
match bytes.len() {
|
||||
0 => Ok(false),
|
||||
1 => Ok(bytes[0] != 0),
|
||||
_ => Err(FromBytesError::DataIsTooLong),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//impl_uint_from_bytes!(u8);
|
||||
impl_uint_from_bytes!(u16);
|
||||
impl_uint_from_bytes!(u32);
|
||||
impl_uint_from_bytes!(u64);
|
||||
impl_uint_from_bytes!(usize);
|
||||
|
||||
macro_rules! impl_uint_from_bytes {
|
||||
($name: ident) => {
|
||||
impl FromBytes for $name {
|
||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<$name> {
|
||||
if !bytes.is_empty() && bytes[0] == 0 {
|
||||
Err(FromBytesError::ZeroPrefixedInt)
|
||||
} else if bytes.len() <= $name::SIZE {
|
||||
Ok($name::from(bytes))
|
||||
} else {
|
||||
Err(FromBytesError::DataIsTooLong)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_uint_from_bytes!(U256);
|
||||
impl_uint_from_bytes!(U128);
|
||||
|
||||
impl <T>FromBytes for T where T: FixedHash {
|
||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<T> {
|
||||
match bytes.len().cmp(&T::size()) {
|
||||
Ordering::Less => return Err(FromBytesError::DataIsTooShort),
|
||||
Ordering::Greater => return Err(FromBytesError::DataIsTooLong),
|
||||
Ordering::Equal => ()
|
||||
};
|
||||
|
||||
unsafe {
|
||||
use std::{mem, ptr};
|
||||
|
||||
let mut res: T = mem::uninitialized();
|
||||
ptr::copy(bytes.as_ptr(), res.as_slice_mut().as_mut_ptr(), T::size());
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Simple trait to allow for raw population of a Sized object from a byte slice.
|
||||
pub trait Populatable {
|
||||
/// Copies a bunch of bytes `d` to `self`, overwriting as necessary.
|
||||
|
@ -57,11 +57,10 @@ pub struct PeerCapabilityInfo {
|
||||
|
||||
impl Decodable for PeerCapabilityInfo {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let c = try!(decoder.as_list());
|
||||
let v: u32 = try!(Decodable::decode(&c[1]));
|
||||
let c = decoder.as_rlp();
|
||||
Ok(PeerCapabilityInfo {
|
||||
protocol: try!(Decodable::decode(&c[0])),
|
||||
version: v as u8,
|
||||
protocol: try!(c.val_at(0)),
|
||||
version: try!(c.val_at(1))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
255
util/src/rlp/bytes.rs
Normal file
255
util/src/rlp/bytes.rs
Normal file
@ -0,0 +1,255 @@
|
||||
//! Unified interfaces for RLP bytes operations on basic types
|
||||
//!
|
||||
|
||||
use std::mem;
|
||||
use std::fmt;
|
||||
use std::cmp::Ordering;
|
||||
use std::error::Error as StdError;
|
||||
use uint::{Uint, U128, U256};
|
||||
use hash::FixedHash;
|
||||
use elastic_array::*;
|
||||
|
||||
/// Vector like object
|
||||
pub trait VecLike<T> {
|
||||
/// Add an element to the collection
|
||||
fn vec_push(&mut self, value: T);
|
||||
|
||||
/// Add a slice to the collection
|
||||
fn vec_extend(&mut self, slice: &[T]);
|
||||
}
|
||||
|
||||
impl<T> VecLike<T> for Vec<T> where T: Copy {
|
||||
fn vec_push(&mut self, value: T) {
|
||||
Vec::<T>::push(self, value)
|
||||
}
|
||||
|
||||
fn vec_extend(&mut self, slice: &[T]) {
|
||||
Vec::<T>::extend_from_slice(self, slice)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_veclike_for_elastic_array {
|
||||
($from: ident) => {
|
||||
impl<T> VecLike<T> for $from<T> where T: Copy {
|
||||
fn vec_push(&mut self, value: T) {
|
||||
$from::<T>::push(self, value)
|
||||
}
|
||||
fn vec_extend(&mut self, slice: &[T]) {
|
||||
$from::<T>::append_slice(self, slice)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_veclike_for_elastic_array!(ElasticArray16);
|
||||
impl_veclike_for_elastic_array!(ElasticArray32);
|
||||
impl_veclike_for_elastic_array!(ElasticArray1024);
|
||||
|
||||
/// Converts given type to its shortest representation in bytes
|
||||
///
|
||||
/// TODO: optimise some conversations
|
||||
pub trait ToBytes {
|
||||
/// Serialize self to byte array
|
||||
fn to_bytes<V: VecLike<u8>>(&self, out: &mut V);
|
||||
/// Get length of serialized data in bytes
|
||||
fn to_bytes_len(&self) -> usize;
|
||||
}
|
||||
|
||||
impl <'a> ToBytes for &'a str {
|
||||
fn to_bytes<V: VecLike<u8>>(&self, out: &mut V) {
|
||||
out.vec_extend(self.as_bytes());
|
||||
}
|
||||
|
||||
fn to_bytes_len(&self) -> usize {
|
||||
self.as_bytes().len()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToBytes for String {
|
||||
fn to_bytes<V: VecLike<u8>>(&self, out: &mut V) {
|
||||
out.vec_extend(self.as_bytes());
|
||||
}
|
||||
|
||||
fn to_bytes_len(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToBytes for u64 {
|
||||
fn to_bytes<V: VecLike<u8>>(&self, out: &mut V) {
|
||||
let count = self.to_bytes_len();
|
||||
for i in 0..count {
|
||||
let j = count - 1 - i;
|
||||
out.vec_push((*self >> (j * 8)) as u8);
|
||||
}
|
||||
}
|
||||
|
||||
fn to_bytes_len(&self) -> usize { 8 - self.leading_zeros() as usize / 8 }
|
||||
}
|
||||
|
||||
impl ToBytes for bool {
|
||||
fn to_bytes<V: VecLike<u8>>(&self, out: &mut V) {
|
||||
out.vec_push(if *self { 1u8 } else { 0u8 })
|
||||
}
|
||||
|
||||
fn to_bytes_len(&self) -> usize { 1 }
|
||||
}
|
||||
|
||||
macro_rules! impl_map_to_bytes {
|
||||
($from: ident, $to: ty) => {
|
||||
impl ToBytes for $from {
|
||||
fn to_bytes<V: VecLike<u8>>(&self, out: &mut V) {
|
||||
(*self as $to).to_bytes(out)
|
||||
}
|
||||
|
||||
fn to_bytes_len(&self) -> usize { (*self as $to).to_bytes_len() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_map_to_bytes!(usize, u64);
|
||||
impl_map_to_bytes!(u16, u64);
|
||||
impl_map_to_bytes!(u32, u64);
|
||||
|
||||
macro_rules! impl_uint_to_bytes {
|
||||
($name: ident) => {
|
||||
impl ToBytes for $name {
|
||||
fn to_bytes<V: VecLike<u8>>(&self, out: &mut V) {
|
||||
let count = self.to_bytes_len();
|
||||
for i in 0..count {
|
||||
let j = count - 1 - i;
|
||||
out.vec_push(self.byte(j));
|
||||
}
|
||||
}
|
||||
fn to_bytes_len(&self) -> usize { (self.bits() + 7) / 8 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_uint_to_bytes!(U256);
|
||||
impl_uint_to_bytes!(U128);
|
||||
|
||||
impl <T>ToBytes for T where T: FixedHash {
|
||||
fn to_bytes<V: VecLike<u8>>(&self, out: &mut V) {
|
||||
out.vec_extend(self.bytes());
|
||||
}
|
||||
fn to_bytes_len(&self) -> usize { self.bytes().len() }
|
||||
}
|
||||
|
||||
/// Error returned when FromBytes conversation goes wrong
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum FromBytesError {
|
||||
/// TODO [debris] Please document me
|
||||
DataIsTooShort,
|
||||
/// TODO [debris] Please document me
|
||||
DataIsTooLong,
|
||||
/// Integer-representation is non-canonically prefixed with zero byte(s).
|
||||
ZeroPrefixedInt,
|
||||
}
|
||||
|
||||
impl StdError for FromBytesError {
|
||||
fn description(&self) -> &str { "from_bytes error" }
|
||||
}
|
||||
|
||||
impl fmt::Display for FromBytesError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Debug::fmt(&self, f)
|
||||
}
|
||||
}
|
||||
|
||||
/// Alias for the result of FromBytes trait
|
||||
pub type FromBytesResult<T> = Result<T, FromBytesError>;
|
||||
|
||||
/// Converts to given type from its bytes representation
|
||||
///
|
||||
/// TODO: check size of bytes before conversation and return appropriate error
|
||||
pub trait FromBytes: Sized {
|
||||
/// TODO [debris] Please document me
|
||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<Self>;
|
||||
}
|
||||
|
||||
impl FromBytes for String {
|
||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<String> {
|
||||
Ok(::std::str::from_utf8(bytes).unwrap().to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_uint_from_bytes {
|
||||
($to: ident) => {
|
||||
impl FromBytes for $to {
|
||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<$to> {
|
||||
match bytes.len() {
|
||||
0 => Ok(0),
|
||||
l if l <= mem::size_of::<$to>() => {
|
||||
if bytes[0] == 0 {
|
||||
return Err(FromBytesError::ZeroPrefixedInt)
|
||||
}
|
||||
let mut res = 0 as $to;
|
||||
for i in 0..l {
|
||||
let shift = (l - 1 - i) * 8;
|
||||
res = res + ((bytes[i] as $to) << shift);
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
_ => Err(FromBytesError::DataIsTooLong)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromBytes for bool {
|
||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<bool> {
|
||||
match bytes.len() {
|
||||
0 => Ok(false),
|
||||
1 => Ok(bytes[0] != 0),
|
||||
_ => Err(FromBytesError::DataIsTooLong),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//impl_uint_from_bytes!(u8);
|
||||
impl_uint_from_bytes!(u16);
|
||||
impl_uint_from_bytes!(u32);
|
||||
impl_uint_from_bytes!(u64);
|
||||
impl_uint_from_bytes!(usize);
|
||||
|
||||
macro_rules! impl_uint_from_bytes {
|
||||
($name: ident) => {
|
||||
impl FromBytes for $name {
|
||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<$name> {
|
||||
if !bytes.is_empty() && bytes[0] == 0 {
|
||||
Err(FromBytesError::ZeroPrefixedInt)
|
||||
} else if bytes.len() <= $name::SIZE {
|
||||
Ok($name::from(bytes))
|
||||
} else {
|
||||
Err(FromBytesError::DataIsTooLong)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_uint_from_bytes!(U256);
|
||||
impl_uint_from_bytes!(U128);
|
||||
|
||||
impl <T>FromBytes for T where T: FixedHash {
|
||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<T> {
|
||||
match bytes.len().cmp(&T::size()) {
|
||||
Ordering::Less => return Err(FromBytesError::DataIsTooShort),
|
||||
Ordering::Greater => return Err(FromBytesError::DataIsTooLong),
|
||||
Ordering::Equal => ()
|
||||
};
|
||||
|
||||
unsafe {
|
||||
use std::{mem, ptr};
|
||||
|
||||
let mut res: T = mem::uninitialized();
|
||||
ptr::copy(bytes.as_ptr(), res.as_slice_mut().as_mut_ptr(), T::size());
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,22 +30,18 @@
|
||||
//! * You want to get view onto rlp-slice.
|
||||
//! * You don't want to decode whole rlp at once.
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub mod rlptraits;
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub mod rlperrors;
|
||||
/// TODO [debris] Please document me
|
||||
pub mod rlpin;
|
||||
/// TODO [debris] Please document me
|
||||
pub mod untrusted_rlp;
|
||||
/// TODO [debris] Please document me
|
||||
pub mod rlpstream;
|
||||
mod rlperrors;
|
||||
mod rlpin;
|
||||
mod untrusted_rlp;
|
||||
mod rlpstream;
|
||||
mod bytes;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub use self::rlperrors::DecoderError;
|
||||
pub use self::rlptraits::{Decoder, Decodable, View, Stream, Encodable, Encoder, RlpEncodable};
|
||||
pub use self::rlptraits::{Decoder, Decodable, View, Stream, Encodable, Encoder, RlpEncodable, RlpDecodable};
|
||||
pub use self::untrusted_rlp::{UntrustedRlp, UntrustedRlpIterator, PayloadInfo, Prototype};
|
||||
pub use self::rlpin::{Rlp, RlpIterator};
|
||||
pub use self::rlpstream::{RlpStream};
|
||||
@ -73,7 +69,7 @@ pub const SHA3_EMPTY_LIST_RLP: H256 = H256( [0x1d, 0xcc, 0x4d, 0xe8, 0xde, 0xc7,
|
||||
/// assert_eq!(animals, vec!["cat".to_string(), "dog".to_string()]);
|
||||
/// }
|
||||
/// ```
|
||||
pub fn decode<T>(bytes: &[u8]) -> T where T: Decodable {
|
||||
pub fn decode<T>(bytes: &[u8]) -> T where T: RlpDecodable {
|
||||
let rlp = Rlp::new(bytes);
|
||||
rlp.as_val()
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::fmt;
|
||||
use std::error::Error as StdError;
|
||||
use bytes::FromBytesError;
|
||||
use rlp::bytes::FromBytesError;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
/// TODO [debris] Please document me
|
||||
|
@ -1,5 +1,5 @@
|
||||
use std::fmt;
|
||||
use rlp::{View, Decodable, DecoderError, UntrustedRlp, PayloadInfo, Prototype};
|
||||
use rlp::{View, DecoderError, UntrustedRlp, PayloadInfo, Prototype, RlpDecodable};
|
||||
|
||||
impl<'a> From<UntrustedRlp<'a>> for Rlp<'a> {
|
||||
fn from(rlp: UntrustedRlp<'a>) -> Rlp<'a> {
|
||||
@ -88,28 +88,28 @@ impl<'a, 'view> View<'a, 'view> for Rlp<'a> where 'a: 'view {
|
||||
self.into_iter()
|
||||
}
|
||||
|
||||
fn as_val<T>(&self) -> Result<T, DecoderError> where T: Decodable {
|
||||
fn as_val<T>(&self) -> Result<T, DecoderError> where T: RlpDecodable {
|
||||
self.rlp.as_val()
|
||||
}
|
||||
|
||||
fn val_at<T>(&self, index: usize) -> Result<T, DecoderError> where T: Decodable {
|
||||
fn val_at<T>(&self, index: usize) -> Result<T, DecoderError> where T: RlpDecodable {
|
||||
self.at(index).rlp.as_val()
|
||||
}
|
||||
}
|
||||
|
||||
impl <'a, 'view> Rlp<'a> where 'a: 'view {
|
||||
fn view_as_val<T, R>(r: &R) -> T where R: View<'a, 'view>, T: Decodable {
|
||||
fn view_as_val<T, R>(r: &R) -> T where R: View<'a, 'view>, T: RlpDecodable {
|
||||
let res: Result<T, DecoderError> = r.as_val();
|
||||
res.unwrap_or_else(|_| panic!())
|
||||
}
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
pub fn as_val<T>(&self) -> T where T: Decodable {
|
||||
pub fn as_val<T>(&self) -> T where T: RlpDecodable {
|
||||
Self::view_as_val(self)
|
||||
}
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
pub fn val_at<T>(&self, index: usize) -> T where T: Decodable {
|
||||
pub fn val_at<T>(&self, index: usize) -> T where T: RlpDecodable {
|
||||
Self::view_as_val(&self.at(index))
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::ops::Deref;
|
||||
use elastic_array::*;
|
||||
use bytes::{ToBytes, VecLike};
|
||||
use rlp::bytes::{ToBytes, VecLike};
|
||||
use rlp::{Stream, Encoder, Encodable};
|
||||
use rlp::rlptraits::{ByteEncodable, RlpEncodable};
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
//! Common RLP traits
|
||||
use std::ops::Deref;
|
||||
use bytes::VecLike;
|
||||
use rlp::bytes::VecLike;
|
||||
use rlp::{DecoderError, UntrustedRlp};
|
||||
use rlpstream::RlpStream;
|
||||
use rlp::rlpstream::RlpStream;
|
||||
use elastic_array::ElasticArray1024;
|
||||
use hash::H256;
|
||||
use sha3::*;
|
||||
@ -12,17 +13,21 @@ pub trait Decoder: Sized {
|
||||
fn read_value<T, F>(&self, f: F) -> Result<T, DecoderError>
|
||||
where F: FnOnce(&[u8]) -> Result<T, DecoderError>;
|
||||
|
||||
/// TODO [arkpar] Please document me
|
||||
fn as_list(&self) -> Result<Vec<Self>, DecoderError>;
|
||||
/// TODO [Gav Wood] Please document me
|
||||
fn as_rlp(&self) -> &UntrustedRlp;
|
||||
/// TODO [debris] Please document me
|
||||
fn as_raw(&self) -> &[u8];
|
||||
}
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
/// RLP decodable trait
|
||||
pub trait Decodable: Sized {
|
||||
/// TODO [debris] Please document me
|
||||
/// Decode a value from RLP bytes
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder;
|
||||
}
|
||||
|
||||
/// Internal helper trait. Implement `Decodable` for custom types.
|
||||
pub trait RlpDecodable: Sized {
|
||||
/// Decode a value from RLP bytes
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder;
|
||||
}
|
||||
|
||||
@ -201,10 +206,10 @@ pub trait View<'a, 'view>: Sized {
|
||||
fn iter(&'view self) -> Self::Iter;
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
fn as_val<T>(&self) -> Result<T, DecoderError> where T: Decodable;
|
||||
fn as_val<T>(&self) -> Result<T, DecoderError> where T: RlpDecodable;
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
fn val_at<T>(&self, index: usize) -> Result<T, DecoderError> where T: Decodable;
|
||||
fn val_at<T>(&self, index: usize) -> Result<T, DecoderError> where T: RlpDecodable;
|
||||
}
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
|
@ -13,7 +13,7 @@ fn rlp_at() {
|
||||
{
|
||||
let rlp = UntrustedRlp::new(&data);
|
||||
assert!(rlp.is_list());
|
||||
//let animals = <Vec<String> as rlp::Decodable>::decode_untrusted(&rlp).unwrap();
|
||||
//let animals = <Vec<String> as rlp::RlpDecodable>::decode_untrusted(&rlp).unwrap();
|
||||
let animals: Vec<String> = rlp.as_val().unwrap();
|
||||
assert_eq!(animals, vec!["cat".to_owned(), "dog".to_owned()]);
|
||||
|
||||
@ -193,9 +193,9 @@ fn encode_vector_str() {
|
||||
run_encode_tests(tests);
|
||||
}
|
||||
|
||||
struct DTestPair<T>(T, Vec<u8>) where T: rlp::Decodable + fmt::Debug + cmp::Eq;
|
||||
struct DTestPair<T>(T, Vec<u8>) where T: rlp::RlpDecodable + fmt::Debug + cmp::Eq;
|
||||
|
||||
fn run_decode_tests<T>(tests: Vec<DTestPair<T>>) where T: rlp::Decodable + fmt::Debug + cmp::Eq {
|
||||
fn run_decode_tests<T>(tests: Vec<DTestPair<T>>) where T: rlp::RlpDecodable + fmt::Debug + cmp::Eq {
|
||||
for t in &tests {
|
||||
let res: T = rlp::decode(&t.1);
|
||||
assert_eq!(res, t.0);
|
||||
@ -214,6 +214,16 @@ fn decode_vector_u8() {
|
||||
run_decode_tests(tests);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decode_untrusted_u8() {
|
||||
let tests = vec![
|
||||
DTestPair(0x0u8, vec![0x80]),
|
||||
DTestPair(0x77u8, vec![0x77]),
|
||||
DTestPair(0xccu8, vec![0x81, 0xcc]),
|
||||
];
|
||||
run_decode_tests(tests);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decode_untrusted_u16() {
|
||||
let tests = vec![
|
||||
|
@ -1,8 +1,8 @@
|
||||
use std::cell::Cell;
|
||||
use std::fmt;
|
||||
use rustc_serialize::hex::ToHex;
|
||||
use bytes::{FromBytes};
|
||||
use rlp::{View, Decoder, Decodable, DecoderError};
|
||||
use rlp::bytes::{FromBytes, FromBytesResult, FromBytesError};
|
||||
use rlp::{View, Decoder, Decodable, DecoderError, RlpDecodable};
|
||||
|
||||
/// rlp offset
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
@ -211,12 +211,12 @@ impl<'a, 'view> View<'a, 'view> for UntrustedRlp<'a> where 'a: 'view {
|
||||
self.into_iter()
|
||||
}
|
||||
|
||||
fn as_val<T>(&self) -> Result<T, DecoderError> where T: Decodable {
|
||||
fn as_val<T>(&self) -> Result<T, DecoderError> where T: RlpDecodable {
|
||||
// optimize, so it doesn't use clone (although This clone is cheap)
|
||||
T::decode(&BasicDecoder::new(self.clone()))
|
||||
}
|
||||
|
||||
fn val_at<T>(&self, index: usize) -> Result<T, DecoderError> where T: Decodable {
|
||||
fn val_at<T>(&self, index: usize) -> Result<T, DecoderError> where T: RlpDecodable {
|
||||
try!(self.at(index)).as_val()
|
||||
}
|
||||
}
|
||||
@ -369,13 +369,6 @@ impl<'a> Decoder for BasicDecoder<'a> {
|
||||
self.rlp.as_raw()
|
||||
}
|
||||
|
||||
fn as_list(&self) -> Result<Vec<Self>, DecoderError> {
|
||||
let v: Vec<BasicDecoder<'a>> = self.rlp.iter()
|
||||
.map(BasicDecoder::new)
|
||||
.collect();
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
fn as_rlp(&self) -> &UntrustedRlp {
|
||||
&self.rlp
|
||||
}
|
||||
@ -391,8 +384,7 @@ impl<T> Decodable for T where T: FromBytes {
|
||||
|
||||
impl<T> Decodable for Vec<T> where T: Decodable {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let decoders = try!(decoder.as_list());
|
||||
decoders.iter().map(|d| T::decode(d)).collect()
|
||||
decoder.as_rlp().iter().map(|d| T::decode(&BasicDecoder::new(d))).collect()
|
||||
}
|
||||
}
|
||||
|
||||
@ -423,15 +415,15 @@ macro_rules! impl_array_decodable {
|
||||
impl<T> Decodable for [T; $len] where T: Decodable {
|
||||
#[allow(len_zero)]
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let decoders = try!(decoder.as_list());
|
||||
let decoders = decoder.as_rlp();
|
||||
|
||||
let mut result: [T; $len] = unsafe { ::std::mem::uninitialized() };
|
||||
if decoders.len() != $len {
|
||||
if decoders.item_count() != $len {
|
||||
return Err(DecoderError::RlpIncorrectListLen);
|
||||
}
|
||||
|
||||
for i in 0..decoders.len() {
|
||||
result[i] = try!(T::decode(&decoders[i]));
|
||||
for i in 0..decoders.item_count() {
|
||||
result[i] = try!(T::decode(&BasicDecoder::new(try!(decoders.at(i)))));
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
@ -454,6 +446,36 @@ impl_array_decodable_recursive!(
|
||||
32, 40, 48, 56, 64, 72, 96, 128, 160, 192, 224,
|
||||
);
|
||||
|
||||
impl<T> RlpDecodable for T where T: Decodable {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
Decodable::decode(decoder)
|
||||
}
|
||||
}
|
||||
|
||||
struct DecodableU8 (u8);
|
||||
|
||||
impl FromBytes for DecodableU8 {
|
||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<DecodableU8> {
|
||||
match bytes.len() {
|
||||
0 => Ok(DecodableU8(0u8)),
|
||||
1 => {
|
||||
if bytes[0] == 0 {
|
||||
return Err(FromBytesError::ZeroPrefixedInt)
|
||||
}
|
||||
Ok(DecodableU8(bytes[0]))
|
||||
}
|
||||
_ => Err(FromBytesError::DataIsTooLong)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RlpDecodable for u8 {
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||
let u: DecodableU8 = try!(Decodable::decode(decoder));
|
||||
Ok(u.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rlp_display() {
|
||||
use rustc_serialize::hex::FromHex;
|
||||
|
Loading…
Reference in New Issue
Block a user