diff --git a/src/bytes.rs b/src/bytes.rs index 91b0e849c..5ffc72c08 100644 --- a/src/bytes.rs +++ b/src/bytes.rs @@ -35,6 +35,7 @@ //! ``` use std::fmt; +use std::slice; use std::cmp::Ordering; use std::error::Error as StdError; use uint::{U128, U256}; @@ -313,21 +314,106 @@ impl FromBytes for T where T: FixedHash { } } -// TODO: tests and additional docs for these two. - /// Simple trait to allow for raw population of a Sized object from a byte slice. pub trait Populatable { - /// Populate self from byte slice `d` in a raw fashion. - fn populate_raw(&mut self, d: &[u8]); + /// Copies a bunch of bytes `d` to `self`, overwriting as necessary. + /// + /// If `d` is smaller, zero-out the remaining bytes. + fn populate_raw(&mut self, d: &[u8]) { + let mut s = self.as_slice_mut(); + for i in 0..s.len() { + s[i] = if i < d.len() {d[i]} else {0}; + } + } + + /// Copies a bunch of bytes `d` to `self`, overwriting as necessary. + /// + /// If `d` is smaller, will leave some bytes untouched. + fn copy_raw(&mut self, d: &[u8]) { + use std::io::Write; + self.as_slice_mut().write(&d).unwrap(); + } + + /// Copies the raw representation of an object `d` to `self`, overwriting as necessary. + /// + /// If `d` is smaller, zero-out the remaining bytes. + fn populate_raw_from(&mut self, d: &BytesConvertable) { self.populate_raw(d.as_slice()); } + + /// Copies the raw representation of an object `d` to `self`, overwriting as necessary. + /// + /// If `d` is smaller, will leave some bytes untouched. + fn copy_raw_from(&mut self, d: &BytesConvertable) { self.copy_raw(d.as_slice()); } + + /// Get the raw slice for this object. + fn as_slice_mut(&mut self) -> &mut [u8]; } impl Populatable for T where T: Sized { - fn populate_raw(&mut self, d: &[u8]) { + fn as_slice_mut(&mut self) -> &mut [u8] { use std::mem; - use std::slice; - use std::io::Write; unsafe { slice::from_raw_parts_mut(self as *mut T as *mut u8, mem::size_of::()) - }.write(&d).unwrap(); + } } } + +impl Populatable for [T] where T: Sized { + fn as_slice_mut(&mut self) -> &mut [u8] { + use std::mem; + unsafe { + slice::from_raw_parts_mut(self.as_mut_ptr() as *mut u8, mem::size_of::() * self.len()) + } + } +} + +#[test] +fn fax_raw() { + let mut x = [255u8; 4]; + x.copy_raw(&[1u8; 2][..]); + assert_eq!(x, [1u8, 1, 255, 255]); + let mut x = [255u8; 4]; + x.copy_raw(&[1u8; 6][..]); + assert_eq!(x, [1u8, 1, 1, 1]); +} + +#[test] +fn populate_raw() { + let mut x = [255u8; 4]; + x.populate_raw(&[1u8; 2][..]); + assert_eq!(x, [1u8, 1, 0, 0]); + let mut x = [255u8; 4]; + x.populate_raw(&[1u8; 6][..]); + assert_eq!(x, [1u8, 1, 1, 1]); +} + +#[test] +fn populate_raw_dyn() { + let mut x = [255u8; 4]; + x.populate_raw(&[1u8; 2][..]); + assert_eq!(&x[..], [1u8, 1, 0, 0]); + let mut x = [255u8; 4]; + x.populate_raw(&[1u8; 6][..]); + assert_eq!(&x[..], [1u8, 1, 1, 1]); +} + +#[test] +fn fax_raw_dyn() { + let mut x = [255u8; 4]; + x.copy_raw(&[1u8; 2][..]); + assert_eq!(&x[..], [1u8, 1, 255, 255]); + let mut x = [255u8; 4]; + x.copy_raw(&[1u8; 6][..]); + assert_eq!(&x[..], [1u8, 1, 1, 1]); +} + +#[test] +fn populate_big_types() { + use hash::*; + let a = address_from_hex("ffffffffffffffffffffffffffffffffffffffff"); + let mut h = h256_from_u64(0x69); + h.populate_raw_from(&a); + assert_eq!(h, h256_from_hex("ffffffffffffffffffffffffffffffffffffffff000000000000000000000000")); + let mut h = h256_from_u64(0x69); + h.copy_raw_from(&a); + assert_eq!(h, h256_from_hex("ffffffffffffffffffffffffffffffffffffffff000000000000000000000069")); +} \ No newline at end of file diff --git a/src/crypto.rs b/src/crypto.rs index 9a1203921..70b3d0d0b 100644 --- a/src/crypto.rs +++ b/src/crypto.rs @@ -168,8 +168,6 @@ pub fn verify(public: &Public, signature: &Signature, message: &H256) -> Result< #[cfg(test)] mod tests { - - use std::str::FromStr; use hash::*; use crypto::*; diff --git a/src/hash.rs b/src/hash.rs index e6f9a61c7..2fb4b71e6 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -10,19 +10,18 @@ use rustc_serialize::hex::*; use error::EthcoreError; use rand::Rng; use rand::os::OsRng; -use bytes::BytesConvertable; +use bytes::{BytesConvertable,Populatable}; use math::log2; use uint::U256; /// Trait for a fixed-size byte array to be used as the output of hash functions. /// /// Note: types implementing `FixedHash` must be also `BytesConvertable`. -pub trait FixedHash: Sized + BytesConvertable { +pub trait FixedHash: Sized + BytesConvertable + Populatable { fn new() -> Self; fn random() -> Self; fn randomize(&mut self); fn size() -> usize; - fn as_slice_mut(&mut self) -> &mut [u8]; fn from_slice(src: &[u8]) -> Self; fn clone_from_slice(&mut self, src: &[u8]) -> usize; fn shift_bloom<'a, T>(&'a mut self, b: &T) -> &'a mut Self where T: FixedHash; @@ -78,10 +77,6 @@ macro_rules! impl_hash { $size } - fn as_slice_mut(&mut self) -> &mut [u8] { - &mut self.0 - } - // TODO: remove once slice::clone_from_slice is stable #[inline] fn clone_from_slice(&mut self, src: &[u8]) -> usize { diff --git a/src/sha3.rs b/src/sha3.rs index e1337c5f7..f3faa4e3b 100644 --- a/src/sha3.rs +++ b/src/sha3.rs @@ -2,8 +2,8 @@ use std::mem::uninitialized; use tiny_keccak::Keccak; -use bytes::BytesConvertable; -use hash::{FixedHash, H256}; +use bytes::{BytesConvertable,Populatable}; +use hash::H256; /// Types implementing this trait are sha3able. /// diff --git a/src/trie/triedbmut.rs b/src/trie/triedbmut.rs index e04b7c758..a51e56a83 100644 --- a/src/trie/triedbmut.rs +++ b/src/trie/triedbmut.rs @@ -668,7 +668,7 @@ mod tests { use env_logger; use rand::random; use std::collections::HashSet; - use bytes::{ToPretty,Bytes}; + use bytes::{ToPretty,Bytes,Populatable}; use super::super::node::*; use super::super::trietraits::*;