macro_rules! as_ref_impl(
($ty:ident) => (
$crate::internal_macros::as_ref_impl!($ty, );
);
($ty:ident, $($gen:ident: $gent:ident),*) => (
impl<$($gen: $gent),*> $crate::_export::_core::convert::AsRef<[u8]> for $ty<$($gen),*> {
fn as_ref(&self) -> &[u8] { &self[..] }
}
)
);
pub(crate) use as_ref_impl;
macro_rules! engine_input_impl(
($n:literal) => (
#[cfg(not(hashes_fuzz))]
fn input(&mut self, mut inp: &[u8]) {
while !inp.is_empty() {
let buf_idx = self.length % <Self as $crate::HashEngine>::BLOCK_SIZE;
let rem_len = <Self as $crate::HashEngine>::BLOCK_SIZE - buf_idx;
let write_len = $crate::_export::_core::cmp::min(rem_len, inp.len());
self.buffer[buf_idx..buf_idx + write_len]
.copy_from_slice(&inp[..write_len]);
self.length += write_len;
if self.length % <Self as $crate::HashEngine>::BLOCK_SIZE == 0 {
self.process_block();
}
inp = &inp[write_len..];
}
}
#[cfg(hashes_fuzz)]
fn input(&mut self, inp: &[u8]) {
for c in inp {
self.buffer[0] ^= *c;
}
self.length += inp.len();
}
)
);
pub(crate) use engine_input_impl;
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 {
$crate::hex::fmt_hex_exact!(f, $bytes, self.0.iter(), $crate::hex::Case::Lower)
}
}
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 {
$crate::hex::fmt_hex_exact!(f, $bytes, self.0.iter(), $crate::hex::Case::Upper)
}
}
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;
macro_rules! hash_trait_impls {
($bits:expr $(, $gen:ident: $gent:ident)*) => {
impl<$($gen: $gent),*> $crate::_export::_core::str::FromStr for Hash<$($gen),*> {
type Err = $crate::hex::HexToArrayError;
fn from_str(s: &str) -> $crate::_export::_core::result::Result<Self, Self::Err> {
use $crate::hex::FromHex;
let bytes = <[u8; $bits / 8]>::from_hex(s)?;
Ok(Self::from_byte_array(bytes))
}
}
$crate::internal_macros::arr_newtype_fmt_impl!(Hash, $bits / 8 $(, $gen: $gent)*);
serde_impl!(Hash, $bits / 8 $(, $gen: $gent)*);
$crate::internal_macros::as_ref_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: $crate::_export::_core::slice::SliceIndex<[u8]> $(, $gen: $gent)*> $crate::_export::_core::ops::Index<I> for Hash<$($gen),*> {
type Output = I::Output;
#[inline]
fn index(&self, index: I) -> &Self::Output { &self.0[index] }
}
};
}
pub(crate) use hash_trait_impls;
macro_rules! hash_type {
($bits:expr, $doc:literal) => {
#[doc = $doc]
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct Hash([u8; $bits / 8]);
impl Hash {
pub const LEN: usize = $bits / 8;
#[allow(clippy::self_named_constructors)] pub fn hash(bytes: &[u8]) -> Self {
let mut engine = Self::engine();
engine.input(bytes);
Self(engine.finalize())
}
pub fn engine() -> Engine { Engine::new() }
pub fn from_engine(engine: Engine) -> Self {
let digest = engine.finalize();
Self(digest)
}
pub fn from_bytes_ref(bytes: &[u8; $bits / 8]) -> &Self {
unsafe { &*(bytes as *const _ as *const Self) }
}
pub fn from_bytes_mut(bytes: &mut [u8; $bits / 8]) -> &mut Self {
unsafe { &mut *(bytes as *mut _ as *mut Self) }
}
pub fn from_slice(sl: &[u8]) -> Result<Self, $crate::FromSliceError> {
if sl.len() != $bits / 8 {
Err(crate::FromSliceError { expected: $bits / 8, got: sl.len() })
} else {
let mut ret = [0; $bits / 8];
ret.copy_from_slice(sl);
Ok(Self::from_byte_array(ret))
}
}
pub fn from_byte_array(bytes: [u8; $bits / 8]) -> Self { Self(bytes) }
pub fn to_byte_array(self) -> [u8; $bits / 8] { self.0 }
pub fn as_byte_array(&self) -> &[u8; $bits / 8] { &self.0 }
#[inline]
pub fn as_bytes(&self) -> &[u8] { &self.0 }
#[cfg(feature = "alloc")]
#[inline]
pub fn to_bytes(&self) -> Vec<u8> { self.0.to_vec() }
pub fn all_zeros() -> Self { Self([0x00; $bits / 8]) }
}
#[cfg(feature = "schemars")]
impl schemars::JsonSchema for Hash {
fn schema_name() -> String { "Hash".to_owned() }
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
let len = $bits / 8;
let mut schema: schemars::schema::SchemaObject = <String>::json_schema(gen).into();
schema.string = Some(Box::new(schemars::schema::StringValidation {
max_length: Some(len * 2),
min_length: Some(len * 2),
pattern: Some("[0-9a-fA-F]+".to_owned()),
}));
schema.into()
}
}
$crate::internal_macros::hash_trait_impls!($bits);
};
}
pub(crate) use hash_type;