From fdd6f4f196a117a93aae9938f6af5111faec27ca Mon Sep 17 00:00:00 2001 From: Elichai Turkel Date: Mon, 2 Dec 2019 13:00:09 +0200 Subject: [PATCH] Derive macros instead of implementing via macro_rules --- src/internal_macros.rs | 86 +++++----------------------------------- src/network/constants.rs | 2 +- src/util/bip32.rs | 2 + src/util/uint.rs | 37 +++++++++++------ 4 files changed, 37 insertions(+), 90 deletions(-) diff --git a/src/internal_macros.rs b/src/internal_macros.rs index 873ae88f..f6029c9e 100644 --- a/src/internal_macros.rs +++ b/src/internal_macros.rs @@ -91,75 +91,7 @@ macro_rules! impl_array_newtype { } } - impl ::std::ops::Index for $thing { - type Output = $ty; - - #[inline] - fn index(&self, index: usize) -> &$ty { - let &$thing(ref dat) = self; - &dat[index] - } - } - impl_index_newtype!($thing, $ty); - - impl ::std::cmp::PartialEq for $thing { - #[inline] - fn eq(&self, other: &$thing) -> bool { - &self[..] == &other[..] - } - } - - impl ::std::cmp::Eq for $thing {} - - impl ::std::cmp::PartialOrd for $thing { - #[inline] - fn partial_cmp(&self, other: &$thing) -> Option<::std::cmp::Ordering> { - Some(self.cmp(&other)) - } - } - - impl ::std::cmp::Ord for $thing { - #[inline] - fn cmp(&self, other: &$thing) -> ::std::cmp::Ordering { - // manually implement comparison to get little-endian ordering - // (we need this for our numeric types; non-numeric ones shouldn't - // be ordered anyway except to put them in BTrees or whatever, and - // they don't care how we order as long as we're consistent). - for i in 0..$len { - if self[$len - 1 - i] < other[$len - 1 - i] { return ::std::cmp::Ordering::Less; } - if self[$len - 1 - i] > other[$len - 1 - i] { return ::std::cmp::Ordering::Greater; } - } - ::std::cmp::Ordering::Equal - } - } - - #[cfg_attr(feature = "clippy", allow(expl_impl_clone_on_copy))] // we don't define the `struct`, we have to explicitly impl - impl ::std::clone::Clone for $thing { - #[inline] - fn clone(&self) -> $thing { - $thing::from(&self[..]) - } - } - - impl ::std::marker::Copy for $thing {} - - impl ::std::hash::Hash for $thing { - #[inline] - fn hash(&self, state: &mut H) - where H: ::std::hash::Hasher - { - (&self[..]).hash(state); - } - - fn hash_slice(data: &[$thing], state: &mut H) - where H: ::std::hash::Hasher - { - for d in data.iter() { - (&d[..]).hash(state); - } - } - } } } @@ -177,6 +109,16 @@ macro_rules! impl_array_newtype_show { /// Implements standard indexing methods for a given wrapper type macro_rules! impl_index_newtype { ($thing:ident, $ty:ty) => { + + impl ::std::ops::Index for $thing { + type Output = $ty; + + #[inline] + fn index(&self, index: usize) -> &$ty { + &self.0[index] + } + } + impl ::std::ops::Index<::std::ops::Range> for $thing { type Output = [$ty]; @@ -754,14 +696,6 @@ macro_rules! user_enum { $(#[$doc] $elem),* } - impl ::std::fmt::Debug for $name { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - f.pad(match *self { - $($name::$elem => $txt),* - }) - } - } - impl ::std::fmt::Display for $name { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { f.pad(match *self { diff --git a/src/network/constants.rs b/src/network/constants.rs index 0540981a..71341e14 100644 --- a/src/network/constants.rs +++ b/src/network/constants.rs @@ -46,7 +46,7 @@ pub const PROTOCOL_VERSION: u32 = 70001; user_enum! { /// The cryptocurrency to act on - #[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)] + #[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Debug)] pub enum Network { /// Classic Bitcoin Bitcoin <-> "bitcoin", diff --git a/src/util/bip32.rs b/src/util/bip32.rs index 3fd8fc2b..bf19d548 100644 --- a/src/util/bip32.rs +++ b/src/util/bip32.rs @@ -30,12 +30,14 @@ use util::{base58, endian}; use util::key::{PublicKey, PrivateKey}; /// A chain code +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct ChainCode([u8; 32]); impl_array_newtype!(ChainCode, u8, 32); impl_array_newtype_show!(ChainCode); impl_bytes_newtype!(ChainCode, 32); /// A fingerprint +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Fingerprint([u8; 4]); impl_array_newtype!(Fingerprint, u8, 4); impl_array_newtype_show!(Fingerprint); diff --git a/src/util/uint.rs b/src/util/uint.rs index b721263a..5aba6129 100644 --- a/src/util/uint.rs +++ b/src/util/uint.rs @@ -21,7 +21,7 @@ macro_rules! construct_uint { ($name:ident, $n_words:expr) => ( /// Little-endian large integer type - #[repr(C)] + #[derive(Copy, Clone, PartialEq, Eq, Hash, Default)] pub struct $name(pub [u64; $n_words]); impl_array_newtype!($name, u64, $n_words); @@ -136,6 +136,27 @@ macro_rules! construct_uint { } } + impl PartialOrd for $name { + #[inline] + fn partial_cmp(&self, other: &$name) -> Option<::std::cmp::Ordering> { + Some(self.cmp(&other)) + } + } + + impl Ord for $name { + #[inline] + fn cmp(&self, other: &$name) -> ::std::cmp::Ordering { + // We need to manually implement ordering because we use little-endian + // and the auto derive is a lexicographic ordering(i.e. memcmp) + // which with numbers is equivilant to big-endian + for i in 0..$n_words { + if self[$n_words - 1 - i] < other[$n_words - 1 - i] { return ::std::cmp::Ordering::Less; } + if self[$n_words - 1 - i] > other[$n_words - 1 - i] { return ::std::cmp::Ordering::Greater; } + } + ::std::cmp::Ordering::Equal + } + } + impl ::std::ops::Add<$name> for $name { type Output = $name; @@ -232,18 +253,12 @@ macro_rules! construct_uint { (0x40 * ($n_words - 1)) + arr[$n_words - 1].trailing_zeros() as usize } - fn zero() -> $name { $name([0; $n_words]) } + fn zero() -> $name { Default::default() } fn one() -> $name { $name({ let mut ret = [0; $n_words]; ret[0] = 1; ret }) } } - impl ::std::default::Default for $name { - fn default() -> $name { - $crate::util::BitArray::zero() - } - } - impl ::std::ops::BitAnd<$name> for $name { type Output = $name; @@ -356,11 +371,7 @@ macro_rules! construct_uint { } } - impl ::std::fmt::Display for $name { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - <::std::fmt::Debug>::fmt(self, f) - } - } + display_from_debug!($name); impl $crate::consensus::Encodable for $name { #[inline]