diff --git a/src/hash.rs b/src/hash.rs index 5eb76a05e..73ffdd538 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -35,6 +35,14 @@ pub trait FixedHash: Sized + BytesConvertable + Populatable { fn is_zero(&self) -> bool; } +fn clean_0x(s: &str) -> &str { + if s.len() >= 2 && &s[0..2] == "0x" { + &s[2..] + } else { + s + } +} + macro_rules! impl_hash { ($from: ident, $size: expr) => { #[derive(Eq)] @@ -377,6 +385,30 @@ macro_rules! impl_hash { pub fn from_bloomed(b: &T) -> Self where T: FixedHash { b.bloom_part($size) } } + + impl From for $from { + fn from(mut value: u64) -> $from { + let mut ret = $from::new(); + for i in 0..8 { + if i < $size { + ret.0[$size - i - 1] = (value & 0xff) as u8; + value >>= 8; + } + } + ret + } + } + + impl<'_> From<&'_ str> for $from { + fn from(s: &'_ str) -> $from { + use std::str::FromStr; + if s.len() % 2 == 1 { + $from::from_str(&("0".to_string() + &(clean_0x(s).to_string()))[..]).unwrap_or($from::new()) + } else { + $from::from_str(clean_0x(s)).unwrap_or($from::new()) + } + } + } } } @@ -387,7 +419,7 @@ impl<'a> From<&'a U256> for H256 { value.to_bytes(&mut ret); ret } - } + } } impl From for Address { @@ -505,5 +537,21 @@ mod tests { let a = Address::from(h); assert_eq!(address, a); } + + #[test] + fn from_u64() { + 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")); + // too short. + assert_eq!(H64::from(0), H64::from("0x34567890abcdef")); + } }