Port over relevant tests and code from parity-hash
This commit is contained in:
parent
6a04131111
commit
9252603e3a
|
@ -8,7 +8,7 @@ matrix:
|
|||
script:
|
||||
- cargo build
|
||||
- cargo test --all --exclude uint --exclude fixed-hash
|
||||
- cd fixed-hash/ && cargo test --features=std,heapsizeof && cd ..
|
||||
- cd fixed-hash/ && cargo test --features=std,heapsizeof,uint_conversions && cd ..
|
||||
- cd uint/ && cargo test --features=std,impl_quickcheck_arbitrary --release && cd ..
|
||||
- cd hashdb/ && cargo test --no-default-features && cd ..
|
||||
- cd plain_hasher/ && cargo test --no-default-features && cd ..
|
||||
|
|
|
@ -11,6 +11,9 @@ heapsize = { version = "0.4", optional = true }
|
|||
rand = { version = "0.4", optional = true }
|
||||
rustc-hex = { version = "2.0", optional = true }
|
||||
quickcheck = { version = "0.6", optional = true }
|
||||
uint = { path = "../uint", optional = true, default-features = false }
|
||||
serde = { version = "1.0", optional = true }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
|
||||
[target.'cfg(not(target_os = "unknown"))'.dependencies]
|
||||
libc = { version = "0.2", optional = true, default-features = false }
|
||||
|
@ -20,3 +23,5 @@ default = ["libc"]
|
|||
std = ["rustc-hex", "rand"]
|
||||
heapsizeof = ["heapsize"]
|
||||
impl_quickcheck_arbitrary = ["quickcheck"]
|
||||
serialize = ["serde", "serde_derive"]
|
||||
uint_conversions = ["uint"]
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
Macros to construct fixed-size hash types. Does not export any types.
|
||||
|
||||
Examples:
|
||||
|
||||
```rust
|
||||
construct_hash!(H256, 32);
|
||||
```
|
||||
|
||||
Add conversions between differently sized hashes:
|
||||
|
||||
```rust
|
||||
construct_hash!(H256, 32);
|
||||
construct_hash!(H160, 20);
|
||||
impl_hash_conversions!(H256, 32, H160, 20);
|
||||
```
|
||||
|
||||
Add conversions between a hash type and the equivalently sized unsigned int:
|
||||
|
||||
```rust
|
||||
extern crate uint;
|
||||
construct_hash!(H256, 32);
|
||||
use uint::U256;
|
||||
impl_hash_uint_conversions!(H256, U256);
|
||||
```
|
||||
|
||||
Build a serde serializable hash type:
|
||||
|
||||
```rust
|
||||
construct_hash!(H160, 20, cfg_attr(feature = "serialize", derive(Serialize, Deserialize)));
|
||||
```
|
|
@ -15,10 +15,15 @@ pub fn clean_0x(s: &str) -> &str {
|
|||
}
|
||||
}
|
||||
|
||||
/// Construct a fixed-size hash type.
|
||||
/// Takes the name of the type and the size in bytes and an optional third argument for meta data
|
||||
/// Example: `construct_hash!(H256, 32);`
|
||||
/// Example: `construct_hash!(H160, 20, cfg_attr(feature = "serialize", derive(Serialize, Deserialize)));`
|
||||
#[macro_export]
|
||||
macro_rules! construct_hash {
|
||||
($from: ident, $size: expr) => {
|
||||
($from: ident, $size: expr $(, $m:meta)*) => {
|
||||
#[repr(C)]
|
||||
$(#[$m])*
|
||||
/// Unformatted binary data of fixed length.
|
||||
pub struct $from (pub [u8; $size]);
|
||||
|
||||
|
@ -88,6 +93,15 @@ macro_rules! construct_hash {
|
|||
$size
|
||||
}
|
||||
|
||||
/// Returns a constant raw pointer to the value
|
||||
pub fn as_ptr(&self) -> *const u8 {
|
||||
self.0.as_ptr()
|
||||
}
|
||||
|
||||
pub fn as_mut_ptr(&mut self) -> *mut u8 {
|
||||
(&mut self.0).as_mut_ptr()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Assign self to be of the same value as a slice of bytes of length `len()`.
|
||||
pub fn clone_from_slice(&mut self, src: &[u8]) -> usize {
|
||||
|
@ -321,6 +335,80 @@ macro_rules! construct_hash {
|
|||
}
|
||||
}
|
||||
|
||||
/// Implements conversion to and from hash types of different sizes. Uses the
|
||||
/// last bytes, e.g. `From<H256> for H160` uses bytes 12..32
|
||||
/// CAUTION: make sure to call with correct sizes and the bigger type first or
|
||||
/// bad things will happen!
|
||||
#[macro_export]
|
||||
macro_rules! impl_hash_conversions {
|
||||
($a: ident, $a_size: expr, $b: ident, $b_size: expr) => {
|
||||
impl From<$b> for $a {
|
||||
fn from(value: $b) -> $a {
|
||||
// REVIEW: better way of ensuring the macro params are ok?
|
||||
assert!($a_size > $b_size && $a_size % 2 == 0 && $b_size %2 == 0);
|
||||
let mut ret = $a::new();
|
||||
ret.0[($a_size - $b_size)..$a_size].copy_from_slice(&value);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$a> for $b {
|
||||
fn from(value: $a) -> $b {
|
||||
// REVIEW: better way of ensuring the macro params are ok?
|
||||
assert!($a_size > $b_size && $a_size % 2 == 0 && $b_size %2 == 0);
|
||||
let mut ret = $b::new();
|
||||
ret.0.copy_from_slice(&value[($a_size - $b_size)..$a_size]);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a $b> for $a {
|
||||
fn from(value: &'a $b) -> $a {
|
||||
let mut ret = $a::new();
|
||||
ret.0[($a_size - $b_size)..$a_size].copy_from_slice(value);
|
||||
ret
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Implements conversion to and from a hash type and the equally sized unsigned int.
|
||||
/// CAUTION: Bad things will happen if the two types are not of the same size!
|
||||
#[cfg(feature="uint_conversions")]
|
||||
#[macro_export]
|
||||
macro_rules! impl_hash_uint_conversions {
|
||||
($hash: ident, $uint: ident) => {
|
||||
impl From<$uint> for $hash {
|
||||
fn from(value: $uint) -> $hash {
|
||||
let mut ret = $hash::new();
|
||||
value.to_big_endian(&mut ret);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a $uint> for $hash {
|
||||
fn from(value: &'a $uint) -> $hash {
|
||||
let mut ret: $hash = $hash::new();
|
||||
value.to_big_endian(&mut ret);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$hash> for $uint {
|
||||
fn from(value: $hash) -> $uint {
|
||||
$uint::from(&value as &[u8])
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a $hash> for $uint {
|
||||
fn from(value: &'a $hash) -> $uint {
|
||||
$uint::from(value.as_ref() as &[u8])
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature="heapsizeof", feature="libc", not(target_os = "unknown")))]
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
|
@ -492,7 +580,13 @@ macro_rules! impl_quickcheck_arbitrary_for_hash {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
construct_hash!(H256, 32);
|
||||
construct_hash!(H160, 20);
|
||||
construct_hash!(H128, 16);
|
||||
construct_hash!(H64, 8);
|
||||
construct_hash!(H32, 4);
|
||||
|
||||
impl_hash_conversions!(H256, 32, H160, 20);
|
||||
|
||||
#[test]
|
||||
fn test_construct_hash() {
|
||||
|
@ -528,4 +622,59 @@ mod tests {
|
|||
test(0xfff, "00000000000000000000000000000fff", "0000…0fff");
|
||||
test(0x1000, "00000000000000000000000000001000", "0000…1000");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hash_bitor() {
|
||||
let a = H64([1; 8]);
|
||||
let b = H64([2; 8]);
|
||||
let c = H64([3; 8]);
|
||||
|
||||
// borrow
|
||||
assert_eq!(&a | &b, c);
|
||||
|
||||
// move
|
||||
assert_eq!(a | b, c);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_and_to_address() {
|
||||
let address: H160 = "ef2d6d194084c2de36e0dabfce45d046b37d1106".into();
|
||||
let h = H256::from(address.clone());
|
||||
let a = H160::from(h);
|
||||
assert_eq!(address, a);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_u64() {
|
||||
use core::str::FromStr;
|
||||
|
||||
assert_eq!(H128::from(0x1234567890abcdef), H128::from_str("00000000000000001234567890abcdef").unwrap());
|
||||
assert_eq!(H64::from(0x1234567890abcdef), H64::from_str("1234567890abcdef").unwrap());
|
||||
assert_eq!(H32::from(0x1234567890abcdef), H32::from_str("90abcdef").unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str() {
|
||||
assert_eq!(H64::from(0x1234567890abcdef), H64::from("0x1234567890abcdef"));
|
||||
assert_eq!(H64::from(0x1234567890abcdef), H64::from("1234567890abcdef"));
|
||||
assert_eq!(H64::from(0x234567890abcdef), H64::from("0x234567890abcdef"));
|
||||
}
|
||||
|
||||
#[cfg(feature = "uint_conversions")]
|
||||
#[test]
|
||||
fn from_and_to_u256() {
|
||||
use uint::U256;
|
||||
|
||||
impl_hash_uint_conversions!(H256, U256);
|
||||
|
||||
let u: U256 = 0x123456789abcdef0u64.into();
|
||||
let h = H256::from(u);
|
||||
assert_eq!(H256::from(u), H256::from("000000000000000000000000000000000000000000000000123456789abcdef0"));
|
||||
let h_ref = H256::from(&u);
|
||||
assert_eq!(h, h_ref);
|
||||
let r_ref: U256 = From::from(&h);
|
||||
assert!(r_ref == u);
|
||||
let r: U256 = From::from(h);
|
||||
assert!(r == u)
|
||||
}
|
||||
}
|
|
@ -36,5 +36,15 @@ pub extern crate rand;
|
|||
#[doc(hidden)]
|
||||
pub extern crate quickcheck;
|
||||
|
||||
#[cfg(feature="uint_conversions")]
|
||||
extern crate uint;
|
||||
|
||||
#[cfg(feature="serialize")]
|
||||
extern crate serde;
|
||||
|
||||
#[cfg(feature="serialize")]
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
mod hash;
|
||||
pub use hash::*;
|
||||
|
|
Loading…
Reference in New Issue