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() {
|
if decoder.as_raw().len() != try!(decoder.as_rlp().payload_info()).total() {
|
||||||
return Err(DecoderError::RlpIsTooBig);
|
return Err(DecoderError::RlpIsTooBig);
|
||||||
}
|
}
|
||||||
let d = try!(decoder.as_list());
|
let d = decoder.as_rlp();
|
||||||
if d.len() != 3 {
|
if d.item_count() != 3 {
|
||||||
return Err(DecoderError::RlpIncorrectListLen);
|
return Err(DecoderError::RlpIncorrectListLen);
|
||||||
}
|
}
|
||||||
Ok(Block {
|
Ok(Block {
|
||||||
header: try!(Decodable::decode(&d[0])),
|
header: try!(d.val_at(0)),
|
||||||
transactions: try!(Decodable::decode(&d[1])),
|
transactions: try!(d.val_at(1)),
|
||||||
uncles: try!(Decodable::decode(&d[2])),
|
uncles: try!(d.val_at(2)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,12 +133,12 @@ impl HeapSizeOf for BlockDetails {
|
|||||||
|
|
||||||
impl Decodable for BlockDetails {
|
impl Decodable for BlockDetails {
|
||||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
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 {
|
let details = BlockDetails {
|
||||||
number: try!(Decodable::decode(&d[0])),
|
number: try!(d.val_at(0)),
|
||||||
total_difficulty: try!(Decodable::decode(&d[1])),
|
total_difficulty: try!(d.val_at(1)),
|
||||||
parent: try!(Decodable::decode(&d[2])),
|
parent: try!(d.val_at(2)),
|
||||||
children: try!(Decodable::decode(&d[3]))
|
children: try!(d.val_at(3)),
|
||||||
};
|
};
|
||||||
Ok(details)
|
Ok(details)
|
||||||
}
|
}
|
||||||
@ -257,10 +257,10 @@ impl HeapSizeOf for TransactionAddress {
|
|||||||
|
|
||||||
impl Decodable for TransactionAddress {
|
impl Decodable for TransactionAddress {
|
||||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
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 {
|
let tx_address = TransactionAddress {
|
||||||
block_hash: try!(Decodable::decode(&d[0])),
|
block_hash: try!(d.val_at(0)),
|
||||||
index: try!(Decodable::decode(&d[1]))
|
index: try!(d.val_at(1)),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(tx_address)
|
Ok(tx_address)
|
||||||
|
@ -267,20 +267,20 @@ impl Decodable for Action {
|
|||||||
|
|
||||||
impl Decodable for Transaction {
|
impl Decodable for Transaction {
|
||||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||||
let d = try!(decoder.as_list());
|
let d = decoder.as_rlp();
|
||||||
if d.len() != 9 {
|
if d.item_count() != 9 {
|
||||||
return Err(DecoderError::RlpIncorrectListLen);
|
return Err(DecoderError::RlpIncorrectListLen);
|
||||||
}
|
}
|
||||||
Ok(Transaction {
|
Ok(Transaction {
|
||||||
nonce: try!(Decodable::decode(&d[0])),
|
nonce: try!(d.val_at(0)),
|
||||||
gas_price: try!(Decodable::decode(&d[1])),
|
gas_price: try!(d.val_at(1)),
|
||||||
gas: try!(Decodable::decode(&d[2])),
|
gas: try!(d.val_at(2)),
|
||||||
action: try!(Decodable::decode(&d[3])),
|
action: try!(d.val_at(3)),
|
||||||
value: try!(Decodable::decode(&d[4])),
|
value: try!(d.val_at(4)),
|
||||||
data: try!(Decodable::decode(&d[5])),
|
data: try!(d.val_at(5)),
|
||||||
v: try!(u16::decode(&d[6])) as u8,
|
v: try!(d.val_at(6)),
|
||||||
r: try!(Decodable::decode(&d[7])),
|
r: try!(d.val_at(7)),
|
||||||
s: try!(Decodable::decode(&d[8])),
|
s: try!(d.val_at(8)),
|
||||||
hash: RefCell::new(None),
|
hash: RefCell::new(None),
|
||||||
sender: RefCell::new(None),
|
sender: RefCell::new(None),
|
||||||
})
|
})
|
||||||
|
@ -11,37 +11,14 @@
|
|||||||
//! let slice: &[u8] = arr.bytes();
|
//! 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() {
|
//! fn main() {
|
||||||
//! bytes_convertable();
|
//! bytes_convertable();
|
||||||
//! to_bytes();
|
|
||||||
//! from_bytes();
|
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use std::mem;
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use std::cmp::Ordering;
|
|
||||||
use std::error::Error as StdError;
|
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use uint::{Uint, U128, U256};
|
|
||||||
use hash::FixedHash;
|
use hash::FixedHash;
|
||||||
use elastic_array::*;
|
use elastic_array::*;
|
||||||
|
|
||||||
@ -205,213 +182,6 @@ fn bytes_convertable() {
|
|||||||
assert_eq!([0u8; 0].bytes(), &[]);
|
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.
|
/// Simple trait to allow for raw population of a Sized object from a byte slice.
|
||||||
pub trait Populatable {
|
pub trait Populatable {
|
||||||
/// Copies a bunch of bytes `d` to `self`, overwriting as necessary.
|
/// Copies a bunch of bytes `d` to `self`, overwriting as necessary.
|
||||||
|
@ -57,11 +57,10 @@ pub struct PeerCapabilityInfo {
|
|||||||
|
|
||||||
impl Decodable for PeerCapabilityInfo {
|
impl Decodable for PeerCapabilityInfo {
|
||||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||||
let c = try!(decoder.as_list());
|
let c = decoder.as_rlp();
|
||||||
let v: u32 = try!(Decodable::decode(&c[1]));
|
|
||||||
Ok(PeerCapabilityInfo {
|
Ok(PeerCapabilityInfo {
|
||||||
protocol: try!(Decodable::decode(&c[0])),
|
protocol: try!(c.val_at(0)),
|
||||||
version: v as u8,
|
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 want to get view onto rlp-slice.
|
||||||
//! * You don't want to decode whole rlp at once.
|
//! * You don't want to decode whole rlp at once.
|
||||||
|
|
||||||
/// TODO [Gav Wood] Please document me
|
|
||||||
pub mod rlptraits;
|
pub mod rlptraits;
|
||||||
/// TODO [Gav Wood] Please document me
|
mod rlperrors;
|
||||||
pub mod rlperrors;
|
mod rlpin;
|
||||||
/// TODO [debris] Please document me
|
mod untrusted_rlp;
|
||||||
pub mod rlpin;
|
mod rlpstream;
|
||||||
/// TODO [debris] Please document me
|
mod bytes;
|
||||||
pub mod untrusted_rlp;
|
|
||||||
/// TODO [debris] Please document me
|
|
||||||
pub mod rlpstream;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
pub use self::rlperrors::DecoderError;
|
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::untrusted_rlp::{UntrustedRlp, UntrustedRlpIterator, PayloadInfo, Prototype};
|
||||||
pub use self::rlpin::{Rlp, RlpIterator};
|
pub use self::rlpin::{Rlp, RlpIterator};
|
||||||
pub use self::rlpstream::{RlpStream};
|
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()]);
|
/// 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);
|
let rlp = Rlp::new(bytes);
|
||||||
rlp.as_val()
|
rlp.as_val()
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::error::Error as StdError;
|
use std::error::Error as StdError;
|
||||||
use bytes::FromBytesError;
|
use rlp::bytes::FromBytesError;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
/// TODO [debris] Please document me
|
/// TODO [debris] Please document me
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use std::fmt;
|
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> {
|
impl<'a> From<UntrustedRlp<'a>> for Rlp<'a> {
|
||||||
fn from(rlp: UntrustedRlp<'a>) -> 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()
|
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()
|
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()
|
self.at(index).rlp.as_val()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'a, 'view> Rlp<'a> where 'a: 'view {
|
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();
|
let res: Result<T, DecoderError> = r.as_val();
|
||||||
res.unwrap_or_else(|_| panic!())
|
res.unwrap_or_else(|_| panic!())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO [debris] Please document me
|
/// 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)
|
Self::view_as_val(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO [debris] Please document me
|
/// 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))
|
Self::view_as_val(&self.at(index))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use elastic_array::*;
|
use elastic_array::*;
|
||||||
use bytes::{ToBytes, VecLike};
|
use rlp::bytes::{ToBytes, VecLike};
|
||||||
use rlp::{Stream, Encoder, Encodable};
|
use rlp::{Stream, Encoder, Encodable};
|
||||||
use rlp::rlptraits::{ByteEncodable, RlpEncodable};
|
use rlp::rlptraits::{ByteEncodable, RlpEncodable};
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
|
//! Common RLP traits
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use bytes::VecLike;
|
use rlp::bytes::VecLike;
|
||||||
use rlp::{DecoderError, UntrustedRlp};
|
use rlp::{DecoderError, UntrustedRlp};
|
||||||
use rlpstream::RlpStream;
|
use rlp::rlpstream::RlpStream;
|
||||||
use elastic_array::ElasticArray1024;
|
use elastic_array::ElasticArray1024;
|
||||||
use hash::H256;
|
use hash::H256;
|
||||||
use sha3::*;
|
use sha3::*;
|
||||||
@ -12,17 +13,21 @@ pub trait Decoder: Sized {
|
|||||||
fn read_value<T, F>(&self, f: F) -> Result<T, DecoderError>
|
fn read_value<T, F>(&self, f: F) -> Result<T, DecoderError>
|
||||||
where F: FnOnce(&[u8]) -> 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
|
/// TODO [Gav Wood] Please document me
|
||||||
fn as_rlp(&self) -> &UntrustedRlp;
|
fn as_rlp(&self) -> &UntrustedRlp;
|
||||||
/// TODO [debris] Please document me
|
/// TODO [debris] Please document me
|
||||||
fn as_raw(&self) -> &[u8];
|
fn as_raw(&self) -> &[u8];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO [debris] Please document me
|
/// RLP decodable trait
|
||||||
pub trait Decodable: Sized {
|
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;
|
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;
|
fn iter(&'view self) -> Self::Iter;
|
||||||
|
|
||||||
/// TODO [debris] Please document me
|
/// 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
|
/// 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
|
/// TODO [debris] Please document me
|
||||||
|
@ -13,7 +13,7 @@ fn rlp_at() {
|
|||||||
{
|
{
|
||||||
let rlp = UntrustedRlp::new(&data);
|
let rlp = UntrustedRlp::new(&data);
|
||||||
assert!(rlp.is_list());
|
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();
|
let animals: Vec<String> = rlp.as_val().unwrap();
|
||||||
assert_eq!(animals, vec!["cat".to_owned(), "dog".to_owned()]);
|
assert_eq!(animals, vec!["cat".to_owned(), "dog".to_owned()]);
|
||||||
|
|
||||||
@ -193,9 +193,9 @@ fn encode_vector_str() {
|
|||||||
run_encode_tests(tests);
|
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 {
|
for t in &tests {
|
||||||
let res: T = rlp::decode(&t.1);
|
let res: T = rlp::decode(&t.1);
|
||||||
assert_eq!(res, t.0);
|
assert_eq!(res, t.0);
|
||||||
@ -214,6 +214,16 @@ fn decode_vector_u8() {
|
|||||||
run_decode_tests(tests);
|
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]
|
#[test]
|
||||||
fn decode_untrusted_u16() {
|
fn decode_untrusted_u16() {
|
||||||
let tests = vec![
|
let tests = vec![
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use rustc_serialize::hex::ToHex;
|
use rustc_serialize::hex::ToHex;
|
||||||
use bytes::{FromBytes};
|
use rlp::bytes::{FromBytes, FromBytesResult, FromBytesError};
|
||||||
use rlp::{View, Decoder, Decodable, DecoderError};
|
use rlp::{View, Decoder, Decodable, DecoderError, RlpDecodable};
|
||||||
|
|
||||||
/// rlp offset
|
/// rlp offset
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
@ -211,12 +211,12 @@ impl<'a, 'view> View<'a, 'view> for UntrustedRlp<'a> where 'a: 'view {
|
|||||||
self.into_iter()
|
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)
|
// optimize, so it doesn't use clone (although This clone is cheap)
|
||||||
T::decode(&BasicDecoder::new(self.clone()))
|
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()
|
try!(self.at(index)).as_val()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -369,13 +369,6 @@ impl<'a> Decoder for BasicDecoder<'a> {
|
|||||||
self.rlp.as_raw()
|
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 {
|
fn as_rlp(&self) -> &UntrustedRlp {
|
||||||
&self.rlp
|
&self.rlp
|
||||||
}
|
}
|
||||||
@ -391,8 +384,7 @@ impl<T> Decodable for T where T: FromBytes {
|
|||||||
|
|
||||||
impl<T> Decodable for Vec<T> where T: Decodable {
|
impl<T> Decodable for Vec<T> where T: Decodable {
|
||||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||||
let decoders = try!(decoder.as_list());
|
decoder.as_rlp().iter().map(|d| T::decode(&BasicDecoder::new(d))).collect()
|
||||||
decoders.iter().map(|d| T::decode(d)).collect()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -423,15 +415,15 @@ macro_rules! impl_array_decodable {
|
|||||||
impl<T> Decodable for [T; $len] where T: Decodable {
|
impl<T> Decodable for [T; $len] where T: Decodable {
|
||||||
#[allow(len_zero)]
|
#[allow(len_zero)]
|
||||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
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() };
|
let mut result: [T; $len] = unsafe { ::std::mem::uninitialized() };
|
||||||
if decoders.len() != $len {
|
if decoders.item_count() != $len {
|
||||||
return Err(DecoderError::RlpIncorrectListLen);
|
return Err(DecoderError::RlpIncorrectListLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in 0..decoders.len() {
|
for i in 0..decoders.item_count() {
|
||||||
result[i] = try!(T::decode(&decoders[i]));
|
result[i] = try!(T::decode(&BasicDecoder::new(try!(decoders.at(i)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
@ -454,6 +446,36 @@ impl_array_decodable_recursive!(
|
|||||||
32, 40, 48, 56, 64, 72, 96, 128, 160, 192, 224,
|
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]
|
#[test]
|
||||||
fn test_rlp_display() {
|
fn test_rlp_display() {
|
||||||
use rustc_serialize::hex::FromHex;
|
use rustc_serialize::hex::FromHex;
|
||||||
|
Loading…
Reference in New Issue
Block a user