1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
// SPDX-License-Identifier: CC0-1.0
//! 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 {
#[allow(unused)]
use crate::Hash as _;
let case = $crate::hex::Case::Lower;
if <$ty<$($gen),*>>::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 {
#[allow(unused)]
use crate::Hash as _;
let case = $crate::hex::Case::Upper;
if <$ty<$($gen),*>>::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.
///
/// Implpements various conversion traits as well as the [`crate::Hash`] trait.
/// Arguments:
///
/// * `$bits` - number of bits this hash type has
/// * `$reverse` - `bool` - `true` if the hash type should be displayed backwards, `false`
/// otherwise.
/// * `$gen: $gent` - generic type(s) and trait bound(s)
///
/// Restrictions on usage:
///
/// * There must be a free-standing `fn from_engine(HashEngine) -> Hash` in the scope
/// * `fn internal_new([u8; $bits / 8]) -> Self` must exist on `Hash`
/// * `fn internal_engine() -> HashEngine` must exist on `Hash`
///
/// `from_engine` obviously implements the finalization algorithm.
/// `internal_new` is required so that types with more than one field are constructible.
/// `internal_engine` is required to initialize the engine for given hash type.
macro_rules! hash_trait_impls {
($bits:expr, $reverse:expr $(, $gen:ident: $gent:ident)*) => {
impl<$($gen: $gent),*> Hash<$($gen),*> {
/// Displays hex forwards, regardless of how this type would display it naturally.
///
/// This is mainly intended as an internal method and you shouldn't need it unless
/// you're doing something special.
pub fn forward_hex(&self) -> impl '_ + core::fmt::LowerHex + core::fmt::UpperHex {
$crate::hex::DisplayHex::as_hex(&self.0)
}
/// Displays hex backwards, regardless of how this type would display it naturally.
///
/// This is mainly intended as an internal method and you shouldn't need it unless
/// you're doing something special.
pub fn backward_hex(&self) -> impl '_ + core::fmt::LowerHex + core::fmt::UpperHex {
$crate::hex::display::DisplayArray::<_, [u8; $bits / 8 * 2]>::new(self.0.iter().rev())
}
/// Zero cost conversion between a fixed length byte array shared reference and
/// a shared reference to this Hash type.
pub fn from_bytes_ref(bytes: &[u8; $bits / 8]) -> &Self {
// Safety: Sound because Self is #[repr(transparent)] containing [u8; $bits / 8]
unsafe { &*(bytes as *const _ as *const Self) }
}
/// Zero cost conversion between a fixed length byte array exclusive reference and
/// an exclusive reference to this Hash type.
pub fn from_bytes_mut(bytes: &mut [u8; $bits / 8]) -> &mut Self {
// Safety: Sound because Self is #[repr(transparent)] containing [u8; $bits / 8]
unsafe { &mut *(bytes as *mut _ as *mut Self) }
}
}
impl<$($gen: $gent),*> str::FromStr for Hash<$($gen),*> {
type Err = $crate::hex::HexToArrayError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
use $crate::hex::{FromHex, HexToBytesIter};
use $crate::Hash;
let inner: [u8; $bits / 8] = if $reverse {
FromHex::from_byte_iter(HexToBytesIter::new(s)?.rev())?
} else {
FromHex::from_byte_iter(HexToBytesIter::new(s)?)?
};
Ok(Self::from_byte_array(inner))
}
}
$crate::internal_macros::arr_newtype_fmt_impl!(Hash, $bits / 8 $(, $gen: $gent)*);
serde_impl!(Hash, $bits / 8 $(, $gen: $gent)*);
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<I: SliceIndex<[u8]> $(, $gen: $gent)*> Index<I> for Hash<$($gen),*> {
type Output = I::Output;
#[inline]
fn index(&self, index: I) -> &Self::Output {
&self.0[index]
}
}
impl<$($gen: $gent),*> crate::Hash for Hash<$($gen),*> {
type Engine = HashEngine;
type Bytes = [u8; $bits / 8];
const LEN: usize = $bits / 8;
const DISPLAY_BACKWARD: bool = $reverse;
fn engine() -> Self::Engine {
Self::internal_engine()
}
fn from_engine(e: HashEngine) -> Hash<$($gen),*> {
from_engine(e)
}
fn from_slice(sl: &[u8]) -> Result<Hash<$($gen),*>, FromSliceError> {
if sl.len() != $bits / 8 {
Err(FromSliceError{expected: Self::LEN, got: sl.len()})
} else {
let mut ret = [0; $bits / 8];
ret.copy_from_slice(sl);
Ok(Self::internal_new(ret))
}
}
fn to_byte_array(self) -> Self::Bytes {
self.0
}
fn as_byte_array(&self) -> &Self::Bytes {
&self.0
}
fn from_byte_array(bytes: Self::Bytes) -> Self {
Self::internal_new(bytes)
}
fn all_zeros() -> Self {
Hash::internal_new([0x00; $bits / 8])
}
}
}
}
pub(crate) use hash_trait_impls;
/// Creates a type called `Hash` and implements standard interface for it.
///
/// The created type will have all standard derives, `Hash` impl and implementation of
/// `internal_engine` returning default. The created type has a single field.
///
/// Arguments:
///
/// * `$bits` - the number of bits of the hash type
/// * `$reverse` - `true` if the hash should be displayed backwards, `false` otherwise
/// * `$doc` - doc string to put on the type
/// * `$schemars` - a literal that goes into `schema_with`.
///
/// The `from_engine` free-standing function is still required with this macro. See the doc of
/// [`hash_trait_impls`].
macro_rules! hash_type {
($bits:expr, $reverse:expr, $doc:literal, $schemars:literal) => {
#[doc = $doc]
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "schemars", derive(crate::schemars::JsonSchema))]
#[repr(transparent)]
pub struct Hash(
#[cfg_attr(feature = "schemars", schemars(schema_with = $schemars))] [u8; $bits / 8],
);
impl Hash {
fn internal_new(arr: [u8; $bits / 8]) -> Self { Hash(arr) }
fn internal_engine() -> HashEngine { Default::default() }
}
crate::internal_macros::hash_trait_impls!($bits, $reverse);
};
}
pub(crate) use hash_type;