Remove hex string trait bounds from GeneralHash

For the `hashes` crate we would like to make `hex` an optional
dependency. In preparation for doing so do the following:

- Remove the trait bounds from `GeneralHash`
- Split the hex/string stuff out of `impl_bytelike_traits` into a
  separate macro.
This commit is contained in:
Tobin C. Harding 2024-11-13 12:55:40 +11:00
parent 766f498b33
commit 9dce0b4b8c
No known key found for this signature in database
GPG Key ID: 40BF9E4C269D6607
14 changed files with 82 additions and 41 deletions

View File

@ -62,6 +62,7 @@ hashes::hash_newtype! {
pub struct FilterHeader(sha256d::Hash);
}
hashes::impl_hex_for_newtype!(FilterHash, FilterHeader);
#[cfg(feature = "serde")]
hashes::impl_serde_for_newtype!(FilterHash, FilterHeader);

View File

@ -58,6 +58,7 @@ hash_newtype! {
pub struct XKeyIdentifier(hash160::Hash);
}
hashes::impl_hex_for_newtype!(XKeyIdentifier);
#[cfg(feature = "serde")]
hashes::impl_serde_for_newtype!(XKeyIdentifier);

View File

@ -93,6 +93,7 @@ hashes::hash_newtype! {
pub struct WScriptHash(sha256::Hash);
}
hashes::impl_hex_for_newtype!(ScriptHash, WScriptHash);
#[cfg(feature = "serde")]
hashes::impl_serde_for_newtype!(ScriptHash, WScriptHash);

View File

@ -265,6 +265,7 @@ hashes::hash_newtype! {
pub struct WPubkeyHash(hash160::Hash);
}
hashes::impl_hex_for_newtype!(PubkeyHash, WPubkeyHash);
#[cfg(feature = "serde")]
hashes::impl_serde_for_newtype!(PubkeyHash, WPubkeyHash);

View File

@ -56,6 +56,7 @@ hash_newtype! {
pub struct SegwitV0Sighash(sha256d::Hash);
}
hashes::impl_hex_for_newtype!(LegacySighash, SegwitV0Sighash);
#[cfg(feature = "serde")]
hashes::impl_serde_for_newtype!(LegacySighash, SegwitV0Sighash);
@ -85,6 +86,7 @@ hash_newtype! {
pub struct TapSighash(sha256t::Hash<TapSighashTag>);
}
hashes::impl_hex_for_newtype!(TapSighash);
#[cfg(feature = "serde")]
hashes::impl_serde_for_newtype!(TapSighash);

View File

@ -96,15 +96,15 @@ impl<T: GeneralHash> HashEngine for HmacEngine<T> {
fn input(&mut self, buf: &[u8]) { self.iengine.input(buf) }
}
impl<T: GeneralHash> fmt::Debug for Hmac<T> {
impl<T: GeneralHash + fmt::Debug> fmt::Debug for Hmac<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&self.0, f) }
}
impl<T: GeneralHash> fmt::Display for Hmac<T> {
impl<T: GeneralHash + fmt::Display> fmt::Display for Hmac<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
}
impl<T: GeneralHash> fmt::LowerHex for Hmac<T> {
impl<T: GeneralHash + fmt::LowerHex> fmt::LowerHex for Hmac<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) }
}

View File

@ -20,7 +20,8 @@
/// `from_engine` obviously implements the finalization algorithm.
macro_rules! hash_trait_impls {
($bits:expr, $reverse:expr $(, $gen:ident: $gent:ident)*) => {
$crate::impl_bytelike_traits!(Hash, { $bits / 8 }, $reverse $(, $gen: $gent)*);
$crate::impl_bytelike_traits!(Hash, { $bits / 8 } $(, $gen: $gent)*);
$crate::impl_hex_string_traits!(Hash, { $bits / 8 }, $reverse $(, $gen: $gent)*);
impl<$($gen: $gent),*> $crate::GeneralHash for Hash<$($gen),*> {
type Engine = HashEngine;

View File

@ -126,7 +126,7 @@ pub mod serde_macros {
}
}
use core::{convert, fmt, hash};
use core::{convert, hash};
#[rustfmt::skip] // Keep public re-exports separate.
#[doc(inline)]
@ -261,20 +261,10 @@ pub trait GeneralHash: Hash {
/// Trait which applies to hashes of all types.
pub trait Hash:
Copy
+ Clone
+ PartialEq
+ Eq
+ PartialOrd
+ Ord
+ hash::Hash
+ fmt::Debug
+ fmt::Display
+ fmt::LowerHex
+ convert::AsRef<[u8]>
Copy + Clone + PartialEq + Eq + PartialOrd + Ord + hash::Hash + convert::AsRef<[u8]>
{
/// The byte array that represents the hash internally.
type Bytes: hex::FromHex + Copy + IsByteArray;
type Bytes: Copy + IsByteArray;
/// Length of the hash, in bytes.
const LEN: usize = Self::Bytes::LEN;
@ -335,6 +325,8 @@ mod tests {
struct TestNewtype2(sha256d::Hash);
}
crate::impl_hex_for_newtype!(TestNewtype, TestNewtype2);
#[test]
#[cfg(feature = "alloc")]
fn newtype_fmt_roundtrip() {

View File

@ -4,6 +4,7 @@
//!
//! - [`sha256t_tag`](crate::sha256t_tag)
//! - [`hash_newtype`](crate::hash_newtype)
//! - [`impl_hex_for_newtype`](crate::impl_hex_for_newtype)
//! - [`impl_serde_for_newtype`](crate::impl_serde_for_newtype)
/// Macro used to define a tag.
@ -133,7 +134,7 @@ macro_rules! hash_newtype {
$({ $($type_attrs)* })*
}
$crate::impl_bytelike_traits!($newtype, { <$newtype as $crate::Hash>::LEN }, <$newtype as $crate::Hash>::DISPLAY_BACKWARD);
$crate::impl_bytelike_traits!($newtype, { <$newtype as $crate::Hash>::LEN });
#[allow(unused)] // Private wrapper types may not need all functions.
impl $newtype {
@ -194,17 +195,67 @@ macro_rules! hash_newtype {
};
}
/// Implements string functions using hex for a new type crated with [`crate::hash_newtype`] macro.
///
/// Implements:
///
/// * `str::FromStr`
/// * `fmt::{LowerHex, UpperHex}` using `hex-conservative`
/// * `fmt::{Display, Debug}` by calling `LowerHex`
#[macro_export]
macro_rules! impl_hex_for_newtype {
($($newtype:ident),*) => {
$(
$crate::impl_hex_string_traits!($newtype, { <$newtype as $crate::Hash>::LEN }, { <$newtype as $crate::Hash>::DISPLAY_BACKWARD });
)*
}
}
/// Adds trait impls to a bytelike type.
///
/// Implements:
///
/// * `AsRef[u8; $len]`
/// * `AsRef[u8]`
/// * `Borrow<[u8; $len]>`
/// * `Borrow<[u8]>`
///
/// ## Parameters
///
/// * `ty` - The bytelike type to implement the traits on.
/// * `$len` - The number of bytes this type has.
/// * `$gen: $gent` - generic type(s) and trait bound(s).
#[doc(hidden)]
#[macro_export]
macro_rules! impl_bytelike_traits {
($ty:ident, $len:expr $(, $gen:ident: $gent:ident)*) => {
impl<$($gen: $gent),*> $crate::_export::_core::convert::AsRef<[u8; { $len }]> for $ty<$($gen),*> {
#[inline]
fn as_ref(&self) -> &[u8; { $len }] { self.as_byte_array() }
}
impl<$($gen: $gent),*> $crate::_export::_core::convert::AsRef<[u8]> for $ty<$($gen),*> {
#[inline]
fn as_ref(&self) -> &[u8] { self.as_byte_array() }
}
impl<$($gen: $gent),*> $crate::_export::_core::borrow::Borrow<[u8; { $len }]> for $ty<$($gen),*> {
fn borrow(&self) -> &[u8; { $len }] { self.as_byte_array() }
}
impl<$($gen: $gent),*> $crate::_export::_core::borrow::Borrow<[u8]> for $ty<$($gen),*> {
fn borrow(&self) -> &[u8] { self.as_byte_array() }
}
}
}
/// Adds hex string trait impls to a bytelike type using hex.
///
/// Implements:
///
/// * `str::FromStr`
/// * `fmt::{LowerHex, UpperHex}` using `hex-conservative`.
/// * `fmt::{Display, Debug}` by calling `LowerHex`
/// * `AsRef[u8; $len]`
/// * `AsRef[u8]`
/// * `Borrow<[u8; $len]>`
/// * `Borrow<[u8]>`
///
/// Requires:
///
@ -223,7 +274,7 @@ macro_rules! hash_newtype {
/// [`hex-conservative`]: <https://crates.io/crates/hex-conservative>
#[doc(hidden)]
#[macro_export]
macro_rules! impl_bytelike_traits {
macro_rules! impl_hex_string_traits {
($ty:ident, $len:expr, $reverse:expr $(, $gen:ident: $gent:ident)*) => {
impl<$($gen: $gent),*> $crate::_export::_core::str::FromStr for $ty<$($gen),*> {
type Err = $crate::hex::HexToArrayError;
@ -245,24 +296,6 @@ macro_rules! impl_bytelike_traits {
const LENGTH: usize = ($len); // parens required due to rustc parser weirdness
}
}
impl<$($gen: $gent),*> $crate::_export::_core::convert::AsRef<[u8; { $len }]> for $ty<$($gen),*> {
#[inline]
fn as_ref(&self) -> &[u8; { $len }] { self.as_byte_array() }
}
impl<$($gen: $gent),*> $crate::_export::_core::convert::AsRef<[u8]> for $ty<$($gen),*> {
#[inline]
fn as_ref(&self) -> &[u8] { self.as_byte_array() }
}
impl<$($gen: $gent),*> $crate::_export::_core::borrow::Borrow<[u8; { $len }]> for $ty<$($gen),*> {
fn borrow(&self) -> &[u8; { $len }] { self.as_byte_array() }
}
impl<$($gen: $gent),*> $crate::_export::_core::borrow::Borrow<[u8]> for $ty<$($gen),*> {
fn borrow(&self) -> &[u8] { self.as_byte_array() }
}
}
}
@ -509,6 +542,7 @@ mod test {
/// Test hash.
struct TestHash(crate::sha256d::Hash);
}
crate::impl_hex_for_newtype!(TestHash);
impl TestHash {
fn all_zeros() -> Self { Self::from_byte_array([0; 32]) }

View File

@ -321,6 +321,7 @@ mod tests {
#[hash_newtype(backward)]
struct NewTypeHashBackward(sha256t::Hash<NewTypeTagBackward>);
}
crate::impl_hex_for_newtype!(NewTypeHashBackward);
#[test]
#[cfg(feature = "alloc")]
@ -344,6 +345,7 @@ mod tests {
#[hash_newtype(forward)]
struct NewTypeHashForward(sha256t::Hash<NewTypeTagForward>);
}
crate::impl_hex_for_newtype!(NewTypeHashForward);
#[test]
#[cfg(feature = "alloc")]

View File

@ -162,6 +162,7 @@ hashes::hash_newtype! {
pub struct WitnessCommitment(sha256d::Hash);
}
hashes::impl_hex_for_newtype!(BlockHash, WitnessCommitment);
#[cfg(feature = "serde")]
hashes::impl_serde_for_newtype!(BlockHash, WitnessCommitment);

View File

@ -11,5 +11,6 @@ hashes::hash_newtype! {
pub struct WitnessMerkleNode(sha256d::Hash);
}
hashes::impl_hex_for_newtype!(TxMerkleNode, WitnessMerkleNode);
#[cfg(feature = "serde")]
hashes::impl_serde_for_newtype!(TxMerkleNode, WitnessMerkleNode);

View File

@ -18,6 +18,7 @@ hash_newtype! {
pub struct TapLeafHash(sha256t::Hash<TapLeafTag>);
}
hashes::impl_hex_for_newtype!(TapLeafHash);
#[cfg(feature = "serde")]
hashes::impl_serde_for_newtype!(TapLeafHash);
@ -32,6 +33,7 @@ hash_newtype! {
pub struct TapNodeHash(sha256t::Hash<TapBranchTag>);
}
hashes::impl_hex_for_newtype!(TapNodeHash);
#[cfg(feature = "serde")]
hashes::impl_serde_for_newtype!(TapNodeHash);
@ -46,6 +48,7 @@ hash_newtype! {
pub struct TapTweakHash(sha256t::Hash<TapTweakTag>);
}
hashes::impl_hex_for_newtype!(TapTweakHash);
#[cfg(feature = "serde")]
hashes::impl_serde_for_newtype!(TapTweakHash);

View File

@ -476,6 +476,7 @@ hashes::hash_newtype! {
pub struct Wtxid(sha256d::Hash);
}
hashes::impl_hex_for_newtype!(Txid, Wtxid);
#[cfg(feature = "serde")]
hashes::impl_serde_for_newtype!(Txid, Wtxid);