diff --git a/ethbloom/Cargo.toml b/ethbloom/Cargo.toml index 16de3c0..0aa6b8f 100644 --- a/ethbloom/Cargo.toml +++ b/ethbloom/Cargo.toml @@ -11,9 +11,8 @@ repository = "https://github.com/paritytech/primitives" [dependencies] tiny-keccak = "1.4" crunchy = { version = "0.2.1", default-features = false, features = ["limit_256"] } -fixed-hash = { version = "0.3", default_features = false } -ethereum-types-serialize = { version = "0.2.1", path = "../serialize", optional = true } -serde = { version = "1.0", optional = true } +fixed-hash = { version = "0.3", default-features = false } +impl-serde = { version = "0.1", default-features = false, optional = true } [dev-dependencies] rand = { version = "0.4" } @@ -23,4 +22,4 @@ hex-literal = "0.1.1" default = ["std", "heapsize", "serialize", "fixed-hash/libc", "fixed-hash/rustc-hex"] std = ["fixed-hash/std", "crunchy/std"] heapsize = ["fixed-hash/heapsize"] -serialize = ["std", "ethereum-types-serialize", "serde"] +serialize = ["std", "impl-serde"] diff --git a/ethbloom/src/lib.rs b/ethbloom/src/lib.rs index cfd5ab6..9734e07 100644 --- a/ethbloom/src/lib.rs +++ b/ethbloom/src/lib.rs @@ -1,4 +1,4 @@ -//! +//! //! ```rust //! extern crate ethbloom; //! #[macro_use] extern crate hex_literal; @@ -26,7 +26,7 @@ //! ).unwrap(); //! let address = hex!("ef2d6d194084c2de36e0dabfce45d046b37d1106"); //! let topic = hex!("02c69be41d0b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc"); -//! +//! //! let mut my_bloom = Bloom::default(); //! assert!(!my_bloom.contains_input(Input::Raw(&address))); //! assert!(!my_bloom.contains_input(Input::Raw(&topic))); @@ -34,7 +34,7 @@ //! my_bloom.accrue(Input::Raw(&address)); //! assert!(my_bloom.contains_input(Input::Raw(&address))); //! assert!(!my_bloom.contains_input(Input::Raw(&topic))); -//! +//! //! my_bloom.accrue(Input::Raw(&topic)); //! assert!(my_bloom.contains_input(Input::Raw(&address))); //! assert!(my_bloom.contains_input(Input::Raw(&topic))); @@ -56,18 +56,13 @@ extern crate crunchy; extern crate fixed_hash; #[cfg(feature="serialize")] -extern crate ethereum_types_serialize; - -#[cfg(feature="serialize")] -extern crate serde; +#[macro_use] +extern crate impl_serde; #[cfg(test)] #[macro_use] extern crate hex_literal; -#[cfg(feature="serialize")] -use serde::{Serialize, Serializer, Deserialize, Deserializer}; - use core::{ops, mem}; use tiny_keccak::keccak256; @@ -227,7 +222,7 @@ impl<'a> BloomRef<'a> { let bloom: Bloom = input.into(); self.contains_bloom(&bloom) } - + pub fn contains_bloom<'b, B>(&self, bloom: B) -> bool where BloomRef<'b>: From { let bloom_ref: BloomRef = bloom.into(); assert_eq!(self.0.len(), BLOOM_SIZE); @@ -259,22 +254,8 @@ impl<'a> From<&'a Bloom> for BloomRef<'a> { } } -#[cfg(feature="serialize")] -impl Serialize for Bloom { - fn serialize(&self, serializer: S) -> Result where S: Serializer { - let mut slice = [0u8; 2 + 2 * BLOOM_SIZE]; - ethereum_types_serialize::serialize(&mut slice, &self.0, serializer) - } -} - -#[cfg(feature="serialize")] -impl<'de> Deserialize<'de> for Bloom { - fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { - let mut bytes = [0; BLOOM_SIZE]; - ethereum_types_serialize::deserialize_check_len(deserializer, ethereum_types_serialize::ExpectedLen::Exact(&mut bytes))?; - Ok(Bloom(bytes)) - } -} +#[cfg(feature = "serialize")] +impl_fixed_hash_serde!(Bloom, BLOOM_SIZE); #[cfg(test)] mod tests { diff --git a/serialize/Cargo.toml b/serialize/Cargo.toml deleted file mode 100644 index cb160dd..0000000 --- a/serialize/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "ethereum-types-serialize" -version = "0.2.1" -authors = ["Parity Technologies "] -license = "MIT" -homepage = "https://github.com/paritytech/primitives" -description = "Ethereum types" - -[dependencies] -serde = "1.0" diff --git a/serialize/src/lib.rs b/serialize/src/lib.rs deleted file mode 100644 index 7691dd1..0000000 --- a/serialize/src/lib.rs +++ /dev/null @@ -1,144 +0,0 @@ -extern crate serde; - -use std::fmt; -use serde::{de, Serializer, Deserializer}; - -static CHARS: &'static[u8] = b"0123456789abcdef"; - -fn to_hex<'a>(v: &'a mut [u8], bytes: &[u8], skip_leading_zero: bool) -> &'a str { - assert!(v.len() > 1 + bytes.len() * 2); - - v[0] = b'0'; - v[1] = b'x'; - - let mut idx = 2; - let first_nibble = bytes[0] >> 4; - if first_nibble != 0 || !skip_leading_zero { - v[idx] = CHARS[first_nibble as usize]; - idx += 1; - } - v[idx] = CHARS[(bytes[0] & 0xf) as usize]; - idx += 1; - - for &byte in bytes.iter().skip(1) { - v[idx] = CHARS[(byte >> 4) as usize]; - v[idx + 1] = CHARS[(byte & 0xf) as usize]; - idx += 2; - } - - ::std::str::from_utf8(&v[0..idx]).expect("All characters are coming from CHARS") -} - -/// Serializes a slice of bytes. -pub fn serialize(slice: &mut [u8], bytes: &[u8], serializer: S) -> Result where - S: Serializer, -{ - serializer.serialize_str(to_hex(slice, bytes, false)) -} - -/// Serialize a slice of bytes as uint. -/// -/// The representation will have all leading zeros trimmed. -pub fn serialize_uint(slice: &mut [u8], bytes: &[u8], serializer: S) -> Result where - S: Serializer, -{ - let non_zero = bytes.iter().take_while(|b| **b == 0).count(); - let bytes = &bytes[non_zero..]; - if bytes.is_empty() { - return serializer.serialize_str("0x0"); - } - - serializer.serialize_str(to_hex(slice, bytes, true)) -} - -/// Expected length of bytes vector. -#[derive(Debug, PartialEq, Eq)] -pub enum ExpectedLen<'a> { - /// Exact length in bytes. - Exact(&'a mut [u8]), - /// A bytes length between (min; slice.len()]. - Between(usize, &'a mut [u8]), -} - -impl<'a> fmt::Display for ExpectedLen<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match *self { - ExpectedLen::Exact(ref v) => write!(fmt, "length of {}", v.len() * 2), - ExpectedLen::Between(min, ref v) => write!(fmt, "length between ({}; {}]", min * 2, v.len() * 2), - } - } -} - -/// Deserialize into vector of bytes with additional size check. -/// Returns number of bytes written. -pub fn deserialize_check_len<'a, 'de, D>(deserializer: D, len: ExpectedLen<'a>) -> Result where - D: Deserializer<'de>, -{ - struct Visitor<'a> { - len: ExpectedLen<'a>, - } - - impl<'a, 'b> de::Visitor<'b> for Visitor<'a> { - type Value = usize; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "a 0x-prefixed hex string with {}", self.len) - } - - fn visit_str(self, v: &str) -> Result { - if v.len() < 2 || &v[0..2] != "0x" { - return Err(E::custom("prefix is missing")) - } - - let is_len_valid = match self.len { - ExpectedLen::Exact(ref slice) => v.len() == 2 * slice.len() + 2, - ExpectedLen::Between(min, ref slice) => v.len() <= 2 * slice.len() + 2 && v.len() > 2 * min + 2, - }; - - if !is_len_valid { - return Err(E::invalid_length(v.len() - 2, &self)) - } - - let bytes = match self.len { - ExpectedLen::Exact(slice) => slice, - ExpectedLen::Between(_, slice) => slice, - }; - - let mut modulus = v.len() % 2; - let mut buf = 0; - let mut pos = 0; - for (idx, byte) in v.bytes().enumerate().skip(2) { - buf <<= 4; - - match byte { - b'A'...b'F' => buf |= byte - b'A' + 10, - b'a'...b'f' => buf |= byte - b'a' + 10, - b'0'...b'9' => buf |= byte - b'0', - b' '|b'\r'|b'\n'|b'\t' => { - buf >>= 4; - continue - } - _ => { - let ch = v[idx..].chars().next().unwrap(); - return Err(E::custom(&format!("invalid hex character: {}, at {}", ch, idx))) - } - } - - modulus += 1; - if modulus == 2 { - modulus = 0; - bytes[pos] = buf; - pos += 1; - } - } - - Ok(pos) - } - - fn visit_string(self, v: String) -> Result { - self.visit_str(&v) - } - } - - deserializer.deserialize_str(Visitor { len }) -}