From 90c66a8079b553cfd5cbff58e5263eee431087ea Mon Sep 17 00:00:00 2001 From: debris Date: Sat, 28 Nov 2015 11:25:00 +0100 Subject: [PATCH] rlp encoding and decoding of fixed sized hashes --- src/bytes.rs | 39 ++++++++++++++++++++++++++++++++++++++- src/hash.rs | 5 +++++ src/rlp.rs | 26 ++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/src/bytes.rs b/src/bytes.rs index 0f82748a1..c08c4ee2a 100644 --- a/src/bytes.rs +++ b/src/bytes.rs @@ -35,8 +35,10 @@ //! ``` use std::fmt; +use std::cmp::Ordering; use std::error::Error as StdError; use uint::{U128, U256}; +use hash::FixedHash; /// Vector of bytes pub type Bytes = Vec; @@ -173,10 +175,26 @@ macro_rules! impl_uint_to_bytes { impl_uint_to_bytes!(U256); impl_uint_to_bytes!(U128); +impl ToBytes for T where T: FixedHash { + fn to_bytes(&self) -> Vec { + let mut res: Vec = vec![]; + res.reserve(T::size()); + + unsafe { + use std::ptr; + ptr::copy(self.bytes().as_ptr(), res.as_mut_ptr(), T::size()); + res.set_len(T::size()); + } + + res + } +} + /// Error returned when FromBytes conversation goes wrong #[derive(Debug, PartialEq, Eq)] pub enum FromBytesError { - UnexpectedEnd + DataIsTooShort, + DataIsTooLong } impl StdError for FromBytesError { @@ -256,3 +274,22 @@ macro_rules! impl_uint_from_bytes { impl_uint_from_bytes!(U256); impl_uint_from_bytes!(U128); + +impl FromBytes for T where T: FixedHash { + fn from_bytes(bytes: &[u8]) -> FromBytesResult { + 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.mut_bytes().as_mut_ptr(), T::size()); + + Ok(res) + } + } +} diff --git a/src/hash.rs b/src/hash.rs index 0dfd4f487..a0493f2bb 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -14,6 +14,7 @@ pub trait FixedHash: Sized + BytesConvertable { fn new() -> Self; fn random() -> Self; fn randomize(&mut self); + fn size() -> usize; fn mut_bytes(&mut self) -> &mut [u8]; fn shift_bloom<'a, T>(&'a mut self, b: &T) -> &'a mut Self where T: FixedHash; fn bloom_part(&self, m: usize) -> T where T: FixedHash; @@ -47,6 +48,10 @@ macro_rules! impl_hash { rng.fill_bytes(&mut self.0); } + fn size() -> usize { + $size + } + fn mut_bytes(&mut self) -> &mut [u8] { &mut self.0 } diff --git a/src/rlp.rs b/src/rlp.rs index 8fbe8cf8f..4b6df2c6e 100644 --- a/src/rlp.rs +++ b/src/rlp.rs @@ -748,6 +748,19 @@ mod tests { run_encode_tests(tests); } + #[test] + fn encode_address() { + use hash::*; + + let tests = vec![ + ETestPair(Address::from_str("ef2d6d194084c2de36e0dabfce45d046b37d1106").unwrap(), + vec![0x94, 0xef, 0x2d, 0x6d, 0x19, 0x40, 0x84, 0xc2, 0xde, + 0x36, 0xe0, 0xda, 0xbf, 0xce, 0x45, 0xd0, 0x46, + 0xb3, 0x7d, 0x11, 0x06]) + ]; + run_encode_tests(tests); + } + #[test] fn encode_vector_u8() { let tests = vec![ @@ -891,6 +904,19 @@ mod tests { run_decode_tests(tests); } + #[test] + fn decode_address() { + use hash::*; + + let tests = vec![ + DTestPair(Address::from_str("ef2d6d194084c2de36e0dabfce45d046b37d1106").unwrap(), + vec![0x94, 0xef, 0x2d, 0x6d, 0x19, 0x40, 0x84, 0xc2, 0xde, + 0x36, 0xe0, 0xda, 0xbf, 0xce, 0x45, 0xd0, 0x46, + 0xb3, 0x7d, 0x11, 0x06]) + ]; + run_decode_tests(tests); + } + #[test] fn decode_vector_u8() { let tests = vec![