rlp encoding and decoding of fixed sized hashes

This commit is contained in:
debris 2015-11-28 11:25:00 +01:00
parent 07f3e6d5a5
commit 90c66a8079
3 changed files with 69 additions and 1 deletions

View File

@ -35,8 +35,10 @@
//! ``` //! ```
use std::fmt; use std::fmt;
use std::cmp::Ordering;
use std::error::Error as StdError; use std::error::Error as StdError;
use uint::{U128, U256}; use uint::{U128, U256};
use hash::FixedHash;
/// Vector of bytes /// Vector of bytes
pub type Bytes = Vec<u8>; pub type Bytes = Vec<u8>;
@ -173,10 +175,26 @@ macro_rules! impl_uint_to_bytes {
impl_uint_to_bytes!(U256); impl_uint_to_bytes!(U256);
impl_uint_to_bytes!(U128); impl_uint_to_bytes!(U128);
impl <T>ToBytes for T where T: FixedHash {
fn to_bytes(&self) -> Vec<u8> {
let mut res: Vec<u8> = 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 /// Error returned when FromBytes conversation goes wrong
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub enum FromBytesError { pub enum FromBytesError {
UnexpectedEnd DataIsTooShort,
DataIsTooLong
} }
impl StdError for FromBytesError { impl StdError for FromBytesError {
@ -256,3 +274,22 @@ macro_rules! impl_uint_from_bytes {
impl_uint_from_bytes!(U256); impl_uint_from_bytes!(U256);
impl_uint_from_bytes!(U128); 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.mut_bytes().as_mut_ptr(), T::size());
Ok(res)
}
}
}

View File

@ -14,6 +14,7 @@ pub trait FixedHash: Sized + BytesConvertable {
fn new() -> Self; fn new() -> Self;
fn random() -> Self; fn random() -> Self;
fn randomize(&mut self); fn randomize(&mut self);
fn size() -> usize;
fn mut_bytes(&mut self) -> &mut [u8]; fn mut_bytes(&mut self) -> &mut [u8];
fn shift_bloom<'a, T>(&'a mut self, b: &T) -> &'a mut Self where T: FixedHash; fn shift_bloom<'a, T>(&'a mut self, b: &T) -> &'a mut Self where T: FixedHash;
fn bloom_part<T>(&self, m: usize) -> T where T: FixedHash; fn bloom_part<T>(&self, m: usize) -> T where T: FixedHash;
@ -47,6 +48,10 @@ macro_rules! impl_hash {
rng.fill_bytes(&mut self.0); rng.fill_bytes(&mut self.0);
} }
fn size() -> usize {
$size
}
fn mut_bytes(&mut self) -> &mut [u8] { fn mut_bytes(&mut self) -> &mut [u8] {
&mut self.0 &mut self.0
} }

View File

@ -748,6 +748,19 @@ mod tests {
run_encode_tests(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] #[test]
fn encode_vector_u8() { fn encode_vector_u8() {
let tests = vec![ let tests = vec![
@ -891,6 +904,19 @@ mod tests {
run_decode_tests(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] #[test]
fn decode_vector_u8() { fn decode_vector_u8() {
let tests = vec![ let tests = vec![