Merge branch 'master' of github.com:gavofyork/ethcore-util into network

This commit is contained in:
arkpar 2016-01-09 10:20:11 +01:00
commit 6183ba5cb5
5 changed files with 103 additions and 22 deletions

View File

@ -35,6 +35,7 @@
//! ``` //! ```
use std::fmt; use std::fmt;
use std::slice;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::error::Error as StdError; use std::error::Error as StdError;
use uint::{U128, U256}; use uint::{U128, U256};
@ -332,21 +333,106 @@ impl <T>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. /// Simple trait to allow for raw population of a Sized object from a byte slice.
pub trait Populatable { pub trait Populatable {
/// Populate self from byte slice `d` in a raw fashion. /// Copies a bunch of bytes `d` to `self`, overwriting as necessary.
fn populate_raw(&mut self, d: &[u8]); ///
/// 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<T> Populatable for T where T: Sized { impl<T> 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::mem;
use std::slice;
use std::io::Write;
unsafe { unsafe {
slice::from_raw_parts_mut(self as *mut T as *mut u8, mem::size_of::<T>()) slice::from_raw_parts_mut(self as *mut T as *mut u8, mem::size_of::<T>())
}.write(&d).unwrap();
} }
} }
}
impl<T> 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::<T>() * 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"));
}

View File

@ -10,19 +10,18 @@ use rustc_serialize::hex::*;
use error::EthcoreError; use error::EthcoreError;
use rand::Rng; use rand::Rng;
use rand::os::OsRng; use rand::os::OsRng;
use bytes::BytesConvertable; use bytes::{BytesConvertable,Populatable};
use math::log2; use math::log2;
use uint::U256; use uint::U256;
/// Trait for a fixed-size byte array to be used as the output of hash functions. /// Trait for a fixed-size byte array to be used as the output of hash functions.
/// ///
/// Note: types implementing `FixedHash` must be also `BytesConvertable`. /// Note: types implementing `FixedHash` must be also `BytesConvertable`.
pub trait FixedHash: Sized + BytesConvertable { pub trait FixedHash: Sized + BytesConvertable + Populatable {
fn new() -> Self; fn new() -> Self;
fn random() -> Self; fn random() -> Self;
fn randomize(&mut self); fn randomize(&mut self);
fn size() -> usize; fn size() -> usize;
fn as_slice_mut(&mut self) -> &mut [u8];
fn from_slice(src: &[u8]) -> Self; fn from_slice(src: &[u8]) -> Self;
fn clone_from_slice(&mut self, src: &[u8]) -> usize; fn clone_from_slice(&mut self, src: &[u8]) -> usize;
fn copy_to(&self, dest: &mut [u8]); fn copy_to(&self, dest: &mut [u8]);
@ -80,10 +79,6 @@ macro_rules! impl_hash {
$size $size
} }
fn as_slice_mut(&mut self) -> &mut [u8] {
&mut self.0
}
// TODO: remove once slice::clone_from_slice is stable // TODO: remove once slice::clone_from_slice is stable
#[inline] #[inline]
fn clone_from_slice(&mut self, src: &[u8]) -> usize { fn clone_from_slice(&mut self, src: &[u8]) -> usize {

View File

@ -2,8 +2,8 @@
use std::mem::uninitialized; use std::mem::uninitialized;
use tiny_keccak::Keccak; use tiny_keccak::Keccak;
use bytes::BytesConvertable; use bytes::{BytesConvertable,Populatable};
use hash::{FixedHash, H256}; use hash::H256;
/// Types implementing this trait are sha3able. /// Types implementing this trait are sha3able.
/// ///

View File

@ -22,8 +22,8 @@ impl<'db> SecTrieDBMut<'db> {
/// Create a new trie with the backing database `db` and `root` /// Create a new trie with the backing database `db` and `root`
/// Panics, if `root` does not exist /// Panics, if `root` does not exist
pub fn new_existing(db: &'db mut HashDB, root: &'db mut H256) -> Self { pub fn from_existing(db: &'db mut HashDB, root: &'db mut H256) -> Self {
SecTrieDBMut { raw: TrieDBMut::new_existing(db, root) } SecTrieDBMut { raw: TrieDBMut::from_existing(db, root) }
} }
} }

View File

@ -70,7 +70,7 @@ impl<'db> TrieDBMut<'db> {
/// Create a new trie with the backing database `db` and `root` /// Create a new trie with the backing database `db` and `root`
/// Panics, if `root` does not exist /// Panics, if `root` does not exist
pub fn new_existing(db: &'db mut HashDB, root: &'db mut H256) -> Self { pub fn from_existing(db: &'db mut HashDB, root: &'db mut H256) -> Self {
assert!(db.exists(root)); assert!(db.exists(root));
TrieDBMut { TrieDBMut {
db: db, db: db,
@ -668,7 +668,7 @@ mod tests {
use env_logger; use env_logger;
use rand::random; use rand::random;
use std::collections::HashSet; use std::collections::HashSet;
use bytes::{ToPretty,Bytes}; use bytes::{ToPretty,Bytes,Populatable};
use super::super::node::*; use super::super::node::*;
use super::super::trietraits::*; use super::super::trietraits::*;
@ -1093,7 +1093,7 @@ mod tests {
} }
{ {
let _ = TrieDBMut::new_existing(&mut db, &mut root); let _ = TrieDBMut::from_existing(&mut db, &mut root);
} }
} }
} }