diff --git a/src/rlp/errors.rs b/src/rlp/errors.rs index ada3c2a47..4ee41a2ce 100644 --- a/src/rlp/errors.rs +++ b/src/rlp/errors.rs @@ -8,6 +8,7 @@ pub enum DecoderError { RlpIsTooShort, RlpExpectedToBeList, RlpExpectedToBeData, + RlpIncorrectListLen } impl StdError for DecoderError { diff --git a/src/rlp/tests.rs b/src/rlp/tests.rs index e44953e07..b4a60a3de 100644 --- a/src/rlp/tests.rs +++ b/src/rlp/tests.rs @@ -343,3 +343,11 @@ fn test_rlp_json() { }); } +#[test] +fn test_decoding_array() { + let v = vec![5u16, 2u16]; + let res = rlp::encode(&v); + let arr: [u16; 2] = rlp::decode(&res); + assert_eq!(arr[0], 5); + assert_eq!(arr[1], 2); +} diff --git a/src/rlp/traits.rs b/src/rlp/traits.rs index 4f9ad09e5..067c438bf 100644 --- a/src/rlp/traits.rs +++ b/src/rlp/traits.rs @@ -1,11 +1,10 @@ use rlp::DecoderError; -pub trait Decoder { +pub trait Decoder: Sized { fn read_value(&self, f: F) -> Result where F: FnOnce(&[u8]) -> Result; - fn read_list(&self, f: F) -> Result - where F: FnOnce(&[Self]) -> Result; + fn as_list(&self) -> Result, DecoderError>; } pub trait Decodable: Sized { diff --git a/src/rlp/untrusted_rlp.rs b/src/rlp/untrusted_rlp.rs index ec68fce99..a8cecf09f 100644 --- a/src/rlp/untrusted_rlp.rs +++ b/src/rlp/untrusted_rlp.rs @@ -305,13 +305,11 @@ impl<'a> Decoder for BasicDecoder<'a> { } } - fn read_list(&self, f: F) -> Result - where F: FnOnce(&[Self]) -> Result { - + fn as_list(&self) -> Result, DecoderError> { let v: Vec> = self.rlp.iter() .map(| i | BasicDecoder::new(i)) .collect(); - f(&v) + Ok(v) } } @@ -325,9 +323,8 @@ impl Decodable for T where T: FromBytes { impl Decodable for Vec where T: Decodable { fn decode(decoder: &D) -> Result where D: Decoder { - decoder.read_list(| decoders | { - decoders.iter().map(|d| T::decode(d)).collect() - }) + let decoders = try!(decoder.as_list()); + decoders.iter().map(|d| T::decode(d)).collect() } } @@ -352,3 +349,38 @@ impl Decodable for Option where T: Decodable { }) } } + +macro_rules! impl_array_decodable { + ($index_type:ty, $len:expr ) => ( + impl Decodable for [T; $len] where T: Decodable { + fn decode(decoder: &D) -> Result where D: Decoder { + let decoders = try!(decoder.as_list()); + + let mut result: [T; $len] = unsafe { ::std::mem::uninitialized() }; + if decoders.len() != $len { + return Err(DecoderError::RlpIncorrectListLen); + } + + for i in 0..decoders.len() { + result[i] = try!(T::decode(&decoders[i])); + } + + Ok(result) + } + } + ) +} + +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, +);