hashes: Introduce impl_bytelike_traits macro
We have a couple of problems: 1. There are two macros currently for fmt stuff that do similar things, `arr_newtype_fmt_impl` and `hex_fmt_impl` - the difference is not immediately obvious, its the way that the byte array is iterated. 2. Our hash types are missing `AsRef<[u8; len]>` and `Borrow<[u8; len]>`. Introduce a new macro and remove a bunch of other macros. Include extensive docs but hide the macro from public docs because its not really for consumers of the library. The macro requires `$crate::hex` to point to `hex-conservative`. Note the macro is pretty generic (as in general purpose), `hashes` might not be the right home for it. Potentially a better place would be in `hex` itself?
This commit is contained in:
parent
515c0f584a
commit
90b2ac03e3
|
@ -1970,7 +1970,7 @@ mod tests {
|
||||||
let display = "0000000000000000000000000000000000000000000000000000000000000000:4294967295";
|
let display = "0000000000000000000000000000000000000000000000000000000000000000:4294967295";
|
||||||
assert_eq!(display, format!("{}", &outpoint));
|
assert_eq!(display, format!("{}", &outpoint));
|
||||||
|
|
||||||
let pretty_debug = "OutPoint {\n txid: 0000000000000000000000000000000000000000000000000000000000000000,\n vout: 4294967295,\n}";
|
let pretty_debug = "OutPoint {\n txid: 0x0000000000000000000000000000000000000000000000000000000000000000,\n vout: 4294967295,\n}";
|
||||||
assert_eq!(pretty_debug, format!("{:#?}", &outpoint));
|
assert_eq!(pretty_debug, format!("{:#?}", &outpoint));
|
||||||
|
|
||||||
let debug_txid = "0000000000000000000000000000000000000000000000000000000000000000";
|
let debug_txid = "0000000000000000000000000000000000000000000000000000000000000000";
|
||||||
|
|
|
@ -2,49 +2,6 @@
|
||||||
|
|
||||||
//! Non-public macros
|
//! Non-public macros
|
||||||
|
|
||||||
macro_rules! arr_newtype_fmt_impl {
|
|
||||||
($ty:ident, $bytes:expr $(, $gen:ident: $gent:ident)*) => {
|
|
||||||
impl<$($gen: $gent),*> $crate::_export::_core::fmt::LowerHex for $ty<$($gen),*> {
|
|
||||||
#[inline]
|
|
||||||
fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result {
|
|
||||||
let case = $crate::hex::Case::Lower;
|
|
||||||
if <$ty<$($gen),*> as crate::Hash>::DISPLAY_BACKWARD {
|
|
||||||
$crate::hex::fmt_hex_exact!(f, $bytes, self.0.iter().rev(), case)
|
|
||||||
} else {
|
|
||||||
$crate::hex::fmt_hex_exact!(f, $bytes, self.0.iter(), case)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<$($gen: $gent),*> $crate::_export::_core::fmt::UpperHex for $ty<$($gen),*> {
|
|
||||||
#[inline]
|
|
||||||
fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result {
|
|
||||||
let case = $crate::hex::Case::Upper;
|
|
||||||
if <$ty<$($gen),*> as crate::Hash>::DISPLAY_BACKWARD {
|
|
||||||
$crate::hex::fmt_hex_exact!(f, $bytes, self.0.iter().rev(), case)
|
|
||||||
} else {
|
|
||||||
$crate::hex::fmt_hex_exact!(f, $bytes, self.0.iter(), case)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<$($gen: $gent),*> $crate::_export::_core::fmt::Display for $ty<$($gen),*> {
|
|
||||||
#[inline]
|
|
||||||
fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result {
|
|
||||||
$crate::_export::_core::fmt::LowerHex::fmt(self, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<$($gen: $gent),*> $crate::_export::_core::fmt::Debug for $ty<$($gen),*> {
|
|
||||||
#[inline]
|
|
||||||
fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result {
|
|
||||||
write!(f, "{:#}", self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub(crate) use arr_newtype_fmt_impl;
|
|
||||||
|
|
||||||
/// Adds trait impls to the type called `Hash` in the current scope.
|
/// Adds trait impls to the type called `Hash` in the current scope.
|
||||||
///
|
///
|
||||||
/// Implpements various conversion traits as well as the [`crate::Hash`] trait.
|
/// Implpements various conversion traits as well as the [`crate::Hash`] trait.
|
||||||
|
@ -63,28 +20,7 @@ pub(crate) use arr_newtype_fmt_impl;
|
||||||
/// `from_engine` obviously implements the finalization algorithm.
|
/// `from_engine` obviously implements the finalization algorithm.
|
||||||
macro_rules! hash_trait_impls {
|
macro_rules! hash_trait_impls {
|
||||||
($bits:expr, $reverse:expr $(, $gen:ident: $gent:ident)*) => {
|
($bits:expr, $reverse:expr $(, $gen:ident: $gent:ident)*) => {
|
||||||
impl<$($gen: $gent),*> $crate::_export::_core::str::FromStr for Hash<$($gen),*> {
|
$crate::impl_bytelike_traits!(Hash, { $bits / 8 }, $reverse $(, $gen: $gent)*);
|
||||||
type Err = $crate::hex::HexToArrayError;
|
|
||||||
fn from_str(s: &str) -> $crate::_export::_core::result::Result<Self, Self::Err> {
|
|
||||||
use $crate::{hex::{FromHex}};
|
|
||||||
|
|
||||||
let mut bytes = <[u8; $bits / 8]>::from_hex(s)?;
|
|
||||||
if $reverse {
|
|
||||||
bytes.reverse();
|
|
||||||
}
|
|
||||||
Ok(Self::from_byte_array(bytes))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$crate::internal_macros::arr_newtype_fmt_impl!(Hash, $bits / 8 $(, $gen: $gent)*);
|
|
||||||
$crate::serde_impl!(Hash, { $bits / 8 } $(, $gen: $gent)*);
|
|
||||||
$crate::borrow_slice_impl!(Hash $(, $gen: $gent)*);
|
|
||||||
|
|
||||||
impl<$($gen: $gent),*> $crate::_export::_core::convert::AsRef<[u8; $bits / 8]> for Hash<$($gen),*> {
|
|
||||||
fn as_ref(&self) -> &[u8; $bits / 8] {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<$($gen: $gent),*> $crate::GeneralHash for Hash<$($gen),*> {
|
impl<$($gen: $gent),*> $crate::GeneralHash for Hash<$($gen),*> {
|
||||||
type Engine = HashEngine;
|
type Engine = HashEngine;
|
||||||
|
|
|
@ -133,9 +133,7 @@ macro_rules! hash_newtype {
|
||||||
$({ $($type_attrs)* })*
|
$({ $($type_attrs)* })*
|
||||||
}
|
}
|
||||||
|
|
||||||
$crate::hex_fmt_impl!(<$newtype as $crate::Hash>::DISPLAY_BACKWARD, <$newtype as $crate::Hash>::LEN, $newtype);
|
$crate::impl_bytelike_traits!($newtype, { <$newtype as $crate::Hash>::LEN }, <$newtype as $crate::Hash>::DISPLAY_BACKWARD);
|
||||||
$crate::serde_impl!($newtype, { <$newtype as $crate::Hash>::LEN });
|
|
||||||
$crate::borrow_slice_impl!($newtype);
|
|
||||||
|
|
||||||
#[allow(unused)] // Private wrapper types may not need all functions.
|
#[allow(unused)] // Private wrapper types may not need all functions.
|
||||||
impl $newtype {
|
impl $newtype {
|
||||||
|
@ -192,96 +190,84 @@ macro_rules! hash_newtype {
|
||||||
|
|
||||||
fn as_byte_array(&self) -> &Self::Bytes { self.as_byte_array() }
|
fn as_byte_array(&self) -> &Self::Bytes { self.as_byte_array() }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl $crate::_export::_core::str::FromStr for $newtype {
|
|
||||||
type Err = $crate::hex::HexToArrayError;
|
|
||||||
fn from_str(s: &str) -> $crate::_export::_core::result::Result<$newtype, Self::Err> {
|
|
||||||
use $crate::{hex::FromHex};
|
|
||||||
|
|
||||||
let mut bytes = <[u8; <Self as $crate::Hash>::LEN]>::from_hex(s)?;
|
|
||||||
if <Self as $crate::Hash>::DISPLAY_BACKWARD {
|
|
||||||
bytes.reverse();
|
|
||||||
};
|
|
||||||
Ok($newtype(<$hash>::from_byte_array(bytes)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $crate::_export::_core::convert::AsRef<[u8; <$hash as $crate::Hash>::LEN]> for $newtype {
|
|
||||||
fn as_ref(&self) -> &[u8; <$hash as $crate::Hash>::LEN] {
|
|
||||||
AsRef::<[u8; <$hash as $crate::Hash>::LEN]>::as_ref(&self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)+
|
)+
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds hexadecimal formatting implementation of a trait `$imp` to a given type `$ty`.
|
/// Adds trait impls to a bytelike type.
|
||||||
|
///
|
||||||
|
/// Implements:
|
||||||
|
///
|
||||||
|
/// * `str::FromStr`
|
||||||
|
/// * `fmt::{LowerHex, UpperHex}` using `hex-conservative`.
|
||||||
|
/// * `fmt::{Display, Debug}` by calling `LowerHex`
|
||||||
|
/// * `serde::{Deserialize, Serialize}`
|
||||||
|
/// * `AsRef[u8; $len]`
|
||||||
|
/// * `AsRef[u8]`
|
||||||
|
/// * `Borrow<[u8; $len]>`
|
||||||
|
/// * `Borrow<[u8]>`
|
||||||
|
///
|
||||||
|
/// Requires:
|
||||||
|
///
|
||||||
|
/// * [`hex-conservative`] to publicly available as `$crate::hex`.
|
||||||
|
/// * `$ty` must implement `IntoIterator<Item=Borrow<u8>>`.
|
||||||
|
///
|
||||||
|
/// (See also [`hex-conservative::fmt_hex_exact`].)
|
||||||
|
///
|
||||||
|
/// ## Parameters
|
||||||
|
///
|
||||||
|
/// * `ty` - The bytelike type to implement the traits on.
|
||||||
|
/// * `$len` - The number of bytes this type has.
|
||||||
|
/// * `$reverse` - `true` if the type should be displayed backwards, `false` otherwise.
|
||||||
|
/// * `$gen: $gent` - generic type(s) and trait bound(s).
|
||||||
|
///
|
||||||
|
/// [`hex-conservative`]: <https://crates.io/crates/hex-conservative>
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! hex_fmt_impl(
|
macro_rules! impl_bytelike_traits {
|
||||||
($reverse:expr, $len:expr, $ty:ident) => (
|
($ty:ident, $len:expr, $reverse:expr $(, $gen:ident: $gent:ident)*) => {
|
||||||
$crate::hex_fmt_impl!($reverse, $len, $ty, );
|
impl<$($gen: $gent),*> $crate::_export::_core::str::FromStr for $ty<$($gen),*> {
|
||||||
);
|
type Err = $crate::hex::HexToArrayError;
|
||||||
($reverse:expr, $len:expr, $ty:ident, $($gen:ident: $gent:ident),*) => (
|
|
||||||
impl<$($gen: $gent),*> $crate::_export::_core::fmt::LowerHex for $ty<$($gen),*> {
|
fn from_str(s: &str) -> $crate::_export::_core::result::Result<Self, Self::Err> {
|
||||||
#[inline]
|
use $crate::hex::FromHex;
|
||||||
fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result {
|
|
||||||
|
let mut bytes = <[u8; { $len }]>::from_hex(s)?;
|
||||||
if $reverse {
|
if $reverse {
|
||||||
$crate::hex::fmt_hex_exact!(f, $len, <Self as $crate::Hash>::as_byte_array(&self).iter().rev(), $crate::hex::Case::Lower)
|
bytes.reverse();
|
||||||
} else {
|
|
||||||
$crate::hex::fmt_hex_exact!(f, $len, <Self as $crate::Hash>::as_byte_array(&self), $crate::hex::Case::Lower)
|
|
||||||
}
|
}
|
||||||
|
Ok(Self::from_byte_array(bytes))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<$($gen: $gent),*> $crate::_export::_core::fmt::UpperHex for $ty<$($gen),*> {
|
$crate::hex::impl_fmt_traits! {
|
||||||
|
#[display_backward($reverse)]
|
||||||
|
impl<$($gen: $gent),*> fmt_traits for $ty<$($gen),*> {
|
||||||
|
const LENGTH: usize = ($len); // parens required due to rustc parser weirdness
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$crate::serde_impl!($ty, $len $(, $gen: $gent)*);
|
||||||
|
|
||||||
|
impl<$($gen: $gent),*> $crate::_export::_core::convert::AsRef<[u8; { $len }]> for $ty<$($gen),*> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result {
|
fn as_ref(&self) -> &[u8; { $len }] { self.as_byte_array() }
|
||||||
if $reverse {
|
|
||||||
$crate::hex::fmt_hex_exact!(f, $len, <Self as $crate::Hash>::as_byte_array(&self).iter().rev(), $crate::hex::Case::Upper)
|
|
||||||
} else {
|
|
||||||
$crate::hex::fmt_hex_exact!(f, $len, <Self as $crate::Hash>::as_byte_array(&self), $crate::hex::Case::Upper)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<$($gen: $gent),*> $crate::_export::_core::fmt::Display for $ty<$($gen),*> {
|
impl<$($gen: $gent),*> $crate::_export::_core::convert::AsRef<[u8]> for $ty<$($gen),*> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result {
|
fn as_ref(&self) -> &[u8] { self.as_byte_array() }
|
||||||
$crate::_export::_core::fmt::LowerHex::fmt(&self, f)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<$($gen: $gent),*> $crate::_export::_core::fmt::Debug for $ty<$($gen),*> {
|
impl<$($gen: $gent),*> $crate::_export::_core::borrow::Borrow<[u8; { $len }]> for $ty<$($gen),*> {
|
||||||
#[inline]
|
fn borrow(&self) -> &[u8; { $len }] { self.as_byte_array() }
|
||||||
fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result {
|
|
||||||
write!(f, "{}", self)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
);
|
|
||||||
|
|
||||||
/// Adds slicing traits implementations to a given type `$ty`
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! borrow_slice_impl(
|
|
||||||
($ty:ident) => (
|
|
||||||
$crate::borrow_slice_impl!($ty, );
|
|
||||||
);
|
|
||||||
($ty:ident, $($gen:ident: $gent:ident),*) => (
|
|
||||||
impl<$($gen: $gent),*> $crate::_export::_core::borrow::Borrow<[u8]> for $ty<$($gen),*> {
|
impl<$($gen: $gent),*> $crate::_export::_core::borrow::Borrow<[u8]> for $ty<$($gen),*> {
|
||||||
fn borrow(&self) -> &[u8] {
|
fn borrow(&self) -> &[u8] { self.as_byte_array() }
|
||||||
self.as_byte_array()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
impl<$($gen: $gent),*> $crate::_export::_core::convert::AsRef<[u8]> for $ty<$($gen),*> {
|
}
|
||||||
fn as_ref(&self) -> &[u8] {
|
|
||||||
self.as_byte_array()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Generates the struct only (no impls)
|
// Generates the struct only (no impls)
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in New Issue