diff --git a/util/src/bytes.rs b/util/src/bytes.rs index dfd21fd90..a3a546d7a 100644 --- a/util/src/bytes.rs +++ b/util/src/bytes.rs @@ -35,47 +35,6 @@ use std::fmt; use std::slice; use std::ops::{Deref, DerefMut}; -use hash::FixedHash; -use elastic_array::*; -use std::mem; -use std::cmp::Ordering; - -/// Vector like object -pub trait VecLike { - /// 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 VecLike for Vec where T: Copy { - fn vec_push(&mut self, value: T) { - Vec::::push(self, value) - } - - fn vec_extend(&mut self, slice: &[T]) { - Vec::::extend_from_slice(self, slice) - } -} - -macro_rules! impl_veclike_for_elastic_array { - ($from: ident) => { - impl VecLike for $from where T: Copy { - fn vec_push(&mut self, value: T) { - $from::::push(self, value) - } - fn vec_extend(&mut self, slice: &[T]) { - $from::::append_slice(self, slice) - - } - } - } -} - -impl_veclike_for_elastic_array!(ElasticArray16); -impl_veclike_for_elastic_array!(ElasticArray32); -impl_veclike_for_elastic_array!(ElasticArray1024); /// Slie pretty print helper pub struct PrettySlice<'a> (&'a [u8]); @@ -230,213 +189,6 @@ impl Populatable for [T] where T: Sized { } } -#[derive(Debug)] -/// Bytes array deserialization error -pub enum FromBytesError { - /// Not enough bytes for the requested type - NotLongEnough, - /// Too many bytes for the requested type - TooLong, - /// Invalid marker for (enums) - UnknownMarker, -} - -/// Value that can be serialized from bytes array -pub trait FromRawBytes: Sized { - /// function that will instantiate and initialize object from slice - fn from_bytes(d: &[u8]) -> Result; -} - -impl FromRawBytes for T where T: FixedHash { - fn from_bytes(bytes: &[u8]) -> Result { - match bytes.len().cmp(&mem::size_of::()) { - Ordering::Less => return Err(FromBytesError::NotLongEnough), - Ordering::Greater => return Err(FromBytesError::TooLong), - Ordering::Equal => () - }; - - let mut res = T::zero(); - res.copy_raw(bytes); - Ok(res) - } -} - -#[macro_export] -macro_rules! sized_binary_map { - ($target_ty: ident) => { - impl FromRawBytes for $target_ty { - fn from_bytes(bytes: &[u8]) -> Result { - match bytes.len().cmp(&::std::mem::size_of::<$target_ty>()) { - ::std::cmp::Ordering::Less => return Err(FromBytesError::NotLongEnough), - ::std::cmp::Ordering::Greater => return Err(FromBytesError::TooLong), - ::std::cmp::Ordering::Equal => () - }; - let mut res: Self = 0; - res.copy_raw(bytes); - Ok(res) - } - } - impl ToBytesWithMap for $target_ty { - fn to_bytes_map(&self) -> Vec { - let sz = ::std::mem::size_of::<$target_ty>(); - let mut res = Vec::::with_capacity(sz); - - let ip: *const $target_ty = self; - let ptr: *const u8 = ip as *const _; - unsafe { - res.set_len(sz); - ::std::ptr::copy(ptr, res.as_mut_ptr(), sz); - } - res - } - } - } -} - -sized_binary_map!(u16); -sized_binary_map!(u32); -sized_binary_map!(u64); - -/// Value that can be serialized from variable-length byte array -pub trait FromRawBytesVariable: Sized { - /// Create value from slice - fn from_bytes_variable(bytes: &[u8]) -> Result; -} - -impl FromRawBytesVariable for T where T: FromRawBytes { - fn from_bytes_variable(bytes: &[u8]) -> Result { - match bytes.len().cmp(&mem::size_of::()) { - Ordering::Less => return Err(FromBytesError::NotLongEnough), - Ordering::Greater => return Err(FromBytesError::TooLong), - Ordering::Equal => () - }; - - T::from_bytes(bytes) - } -} - -impl FromRawBytesVariable for String { - fn from_bytes_variable(bytes: &[u8]) -> Result { - Ok(::std::str::from_utf8(bytes).unwrap().to_owned()) - } -} - -impl FromRawBytesVariable for Vec where T: FromRawBytes { - fn from_bytes_variable(bytes: &[u8]) -> Result { - let size_of_t = mem::size_of::(); - let length_in_chunks = bytes.len() / size_of_t; - - let mut result = Vec::with_capacity(length_in_chunks); - unsafe { result.set_len(length_in_chunks) }; - for i in 0..length_in_chunks { - *result.get_mut(i).unwrap() = try!(T::from_bytes( - &bytes[size_of_t * i..size_of_t * (i+1)])) - } - Ok(result) - } -} - -impl FromRawBytes for (V1, T2) where V1: FromRawBytesVariable, T2: FromRawBytes { - fn from_bytes(bytes: &[u8]) -> Result { - let header = 8usize; - let mut map: (u64, ) = (0,); - - if bytes.len() < header { return Err(FromBytesError::NotLongEnough); } - map.copy_raw(&bytes[0..header]); - - Ok(( - try!(V1::from_bytes_variable(&bytes[header..header + (map.0 as usize)])), - try!(T2::from_bytes(&bytes[header + (map.0 as usize)..bytes.len()])), - )) - } -} - -impl FromRawBytes for (V1, V2, T3) - where V1: FromRawBytesVariable, - V2: FromRawBytesVariable, - T3: FromRawBytes -{ - fn from_bytes(bytes: &[u8]) -> Result { - let header = 16usize; - let mut map: (u64, u64, ) = (0, 0,); - - if bytes.len() < header { return Err(FromBytesError::NotLongEnough); } - map.copy_raw(&bytes[0..header]); - - let map_1 = (header, header + map.0 as usize); - let map_2 = (map_1.1 as usize, map_1.1 as usize + map.1 as usize); - Ok(( - try!(V1::from_bytes_variable(&bytes[map_1.0..map_1.1])), - try!(V2::from_bytes_variable(&bytes[map_2.0..map_2.1])), - try!(T3::from_bytes(&bytes[map_2.1..bytes.len()])), - )) - } -} - -impl<'a, V1, X1, T2> ToBytesWithMap for (X1, &'a T2) where V1: ToBytesWithMap, X1: Deref, T2: ToBytesWithMap { - fn to_bytes_map(&self) -> Vec { - let header = 8usize; - let v1_size = mem::size_of::(); - let mut result = Vec::with_capacity(header + self.0.len() * v1_size + mem::size_of::()); - result.extend(((self.0.len() * v1_size) as u64).to_bytes_map()); - - for i in 0..self.0.len() { - result.extend(self.0[i].to_bytes_map()); - } - result.extend(self.1.to_bytes_map()); - - result - } - -} - -impl<'a, V1, X1, V2, X2, T3> ToBytesWithMap for (X1, X2, &'a T3) - where V1: ToBytesWithMap, X1: Deref, - V2: ToBytesWithMap, X2: Deref, - T3: ToBytesWithMap -{ - fn to_bytes_map(&self) -> Vec { - let header = 16usize; - let v1_size = mem::size_of::(); - let v2_size = mem::size_of::(); - let mut result = Vec::with_capacity( - header + - self.0.len() * v1_size + - self.1.len() * v2_size + - mem::size_of::() - ); - result.extend(((self.0.len() * v1_size) as u64).to_bytes_map()); - result.extend(((self.1.len() * v2_size) as u64).to_bytes_map()); - for i in 0..self.0.len() { - result.extend(self.0[i].to_bytes_map()); - } - for i in 0..self.1.len() { - result.extend(self.1[i].to_bytes_map()); - } - result.extend(self.2.to_bytes_map()); - - result - } -} - -impl FromRawBytesVariable for Vec { - fn from_bytes_variable(bytes: &[u8]) -> Result, FromBytesError> { - Ok(bytes.to_vec()) - } -} - -/// Value that serializes directly to variable-sized byte array and stores map -pub trait ToBytesWithMap { - /// serialize to variable-sized byte array and store map - fn to_bytes_map(&self) -> Vec; -} - -impl ToBytesWithMap for T where T: FixedHash { - fn to_bytes_map(&self) -> Vec { - self.as_slice().to_owned() - } -} - #[test] fn fax_raw() { let mut x = [255u8; 4]; @@ -488,44 +240,3 @@ fn populate_big_types() { h.copy_raw_from(&a); assert_eq!(h, h256_from_hex("ffffffffffffffffffffffffffffffffffffffff000000000000000000000069")); } - -#[test] -fn raw_bytes_from_tuple() { - type Tup = (Vec, u16); - - let tup: (&[u16], u16) = (&[1; 4], 10); - let bytes = vec![ - // map - 8u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, - // four 1u16 - 1u8, 0u8, - 1u8, 0u8, - 1u8, 0u8, - 1u8, 0u8, - // 10u16 - 10u8, 0u8]; - - let (v, x) = Tup::from_bytes(&bytes).unwrap(); - assert_eq!(tup, (&v[..], x)); - let tup_from = (v, x); - - let tup_to = (tup_from.0, &tup_from.1); - let bytes_to = tup_to.to_bytes_map(); - assert_eq!(bytes_to, bytes); -} - -#[test] -fn bytes_map_from_triple() { - let data: (&[u16], &[u32], u64) = (&[2; 6], &[6; 3], 12u64); - let bytes_map = (data.0, data.1, &data.2).to_bytes_map(); - assert_eq!(bytes_map, vec![ - // data map 2 x u64 - 12, 0, 0, 0, 0, 0, 0, 0, - 12, 0, 0, 0, 0, 0, 0, 0, - // vec![2u16; 6] - 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, - // vec![6u32; 3] - 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, - // 12u64 - 12, 0, 0, 0, 0, 0, 0, 0]); -} diff --git a/util/src/rlp/bytes.rs b/util/src/rlp/bytes.rs index 479fc7261..8d33f390d 100644 --- a/util/src/rlp/bytes.rs +++ b/util/src/rlp/bytes.rs @@ -22,7 +22,7 @@ use std::fmt; use std::cmp::Ordering; use std::error::Error as StdError; use bigint::uint::{Uint, U128, U256}; -use hash::FixedHash; +use hash::{H64, H128, Address, H256, H512, H520, H2048}; use elastic_array::*; /// Vector like object @@ -146,13 +146,25 @@ 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, out: &mut V) { - out.vec_extend(self.as_slice()); +macro_rules! impl_hash_to_bytes { + ($name: ident) => { + impl ToBytes for $name { + fn to_bytes>(&self, out: &mut V) { + out.vec_extend(&self); + } + fn to_bytes_len(&self) -> usize { self.len() } + } } - fn to_bytes_len(&self) -> usize { self.as_slice().len() } } +impl_hash_to_bytes!(H64); +impl_hash_to_bytes!(H128); +impl_hash_to_bytes!(Address); +impl_hash_to_bytes!(H256); +impl_hash_to_bytes!(H512); +impl_hash_to_bytes!(H520); +impl_hash_to_bytes!(H2048); + /// Error returned when `FromBytes` conversation goes wrong #[derive(Debug, PartialEq, Eq)] pub enum FromBytesError { @@ -250,15 +262,29 @@ macro_rules! impl_uint_from_bytes { impl_uint_from_bytes!(U256, 32); impl_uint_from_bytes!(U128, 16); -impl FromBytes for T where T: FixedHash { - fn from_bytes(bytes: &[u8]) -> FromBytesResult { - match bytes.len().cmp(&T::len()) { - Ordering::Less => return Err(FromBytesError::DataIsTooShort), - Ordering::Greater => return Err(FromBytesError::DataIsTooLong), - Ordering::Equal => () - }; - - Ok(T::from_slice(bytes)) +macro_rules! impl_hash_from_bytes { + ($name: ident, $size: expr) => { + impl FromBytes for $name { + fn from_bytes(bytes: &[u8]) -> FromBytesResult<$name> { + match bytes.len().cmp(&$size) { + Ordering::Less => Err(FromBytesError::DataIsTooShort), + Ordering::Greater => Err(FromBytesError::DataIsTooLong), + Ordering::Equal => { + let mut t = [0u8; $size]; + t.copy_from_slice(bytes); + Ok($name(t)) + } + } + } + } } } +impl_hash_from_bytes!(H64, 8); +impl_hash_from_bytes!(H128, 16); +impl_hash_from_bytes!(Address, 20); +impl_hash_from_bytes!(H256, 32); +impl_hash_from_bytes!(H512, 64); +impl_hash_from_bytes!(H520, 65); +impl_hash_from_bytes!(H2048, 256); +