macro_rules! hash_trait_impls {
($bits:expr, $reverse:expr $(, $gen:ident: $gent:ident)*) => {
$crate::impl_bytelike_traits!(Hash, { $bits / 8 } $(, $gen: $gent)*);
#[cfg(feature = "hex")]
$crate::impl_hex_string_traits!(Hash, { $bits / 8 }, $reverse $(, $gen: $gent)*);
#[cfg(not(feature = "hex"))]
$crate::impl_debug_only!(Hash, { $bits / 8 }, $reverse $(, $gen: $gent)*);
#[cfg(feature = "serde")]
$crate::serde_impl!(Hash, { $bits / 8} $(, $gen: $gent)*);
impl<$($gen: $gent),*> $crate::Hash for Hash<$($gen),*> {
type Bytes = [u8; $bits / 8];
const DISPLAY_BACKWARD: bool = $reverse;
fn from_byte_array(bytes: Self::Bytes) -> Self { Self::from_byte_array(bytes) }
fn to_byte_array(self) -> Self::Bytes { self.to_byte_array() }
fn as_byte_array(&self) -> &Self::Bytes { self.as_byte_array() }
}
}
}
pub(crate) use hash_trait_impls;
macro_rules! general_hash_type {
(
$(#[$type_attrs:meta])*
pub struct Hash([u8; $len:expr]);
const DISPLAY_BACKWARD: bool = $reverse:expr;
) => {
pub fn hash(data: &[u8]) -> Hash {
use crate::HashEngine as _;
let mut engine = Hash::engine();
engine.input(data);
engine.finalize()
}
pub fn hash_byte_chunks<B, I>(byte_slices: I) -> Hash
where
B: AsRef<[u8]>,
I: IntoIterator<Item = B>,
{
use crate::HashEngine as _;
let mut engine = Hash::engine();
for slice in byte_slices {
engine.input(slice.as_ref());
}
engine.finalize()
}
$crate::internal_macros::hash_type_no_default! {
$(#[$type_attrs])*
pub struct Hash([u8; $len]);
const DISPLAY_BACKWARD: bool = $reverse;
}
impl Hash {
pub fn engine() -> HashEngine { Default::default() }
#[allow(clippy::self_named_constructors)] pub fn hash(data: &[u8]) -> Self { hash(data) }
pub fn hash_byte_chunks<B, I>(byte_slices: I) -> Self
where
B: AsRef<[u8]>,
I: IntoIterator<Item = B>,
{
hash_byte_chunks(byte_slices)
}
}
#[cfg(feature = "arbitrary")]
impl<'a> arbitrary::Arbitrary<'a> for Hash {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
Ok(Self(u.arbitrary()?))
}
}
};
}
pub(crate) use general_hash_type;
macro_rules! hash_type_no_default {
(
$(#[$type_attrs:meta])*
pub struct Hash([u8; $len:expr]);
const DISPLAY_BACKWARD: bool = $reverse:expr;
) => {
internals::transparent_newtype! {
$(#[$type_attrs])*
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Hash([u8; $len]);
impl Hash {
pub fn from_bytes_ref(bytes: &_) -> &Self;
pub fn from_bytes_mut(bytes: &mut _) -> &mut Self;
}
}
impl Hash {
pub const fn from_byte_array(bytes: [u8; $len]) -> Self { Hash(bytes) }
pub const fn to_byte_array(self) -> [u8; $len] { self.0 }
pub const fn as_byte_array(&self) -> &[u8; $len] { &self.0 }
}
$crate::internal_macros::hash_trait_impls!(($len) * 8, $reverse);
$crate::internal_macros::impl_write!(
HashEngine,
|us: &mut HashEngine, buf| {
crate::HashEngine::input(us, buf);
Ok(buf.len())
},
|_us| { Ok(()) }
);
};
}
pub(crate) use hash_type_no_default;
macro_rules! impl_write {
($ty: ty, $write_fn: expr, $flush_fn: expr $(, $bounded_ty: ident : $bounds: path),*) => {
#[cfg(feature = "std")]
impl<$($bounded_ty: $bounds),*> std::io::Write for $ty {
#[inline]
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
$write_fn(self, buf)
}
#[inline]
fn flush(&mut self) -> std::io::Result<()> {
$flush_fn(self)
}
}
}
}
pub(crate) use impl_write;
macro_rules! engine_input_impl(
() => (
#[cfg(not(hashes_fuzz))]
fn input(&mut self, mut inp: &[u8]) {
let buf_idx = $crate::incomplete_block_len(self);
let block_size = <Self as crate::HashEngine>::BLOCK_SIZE;
self.bytes_hashed += inp.len() as u64;
if buf_idx + inp.len() < block_size {
return self.buffer[buf_idx..buf_idx + inp.len()].copy_from_slice(&inp)
}
if buf_idx > 0 {
let needed = block_size - buf_idx;
self.buffer[buf_idx..buf_idx+needed].copy_from_slice(&inp[..needed]);
Self::process_blocks(&mut self.h, &self.buffer);
inp = &inp[needed..]
}
let full_blocks = inp.len() / block_size * block_size;
if full_blocks > 0 {
Self::process_blocks(&mut self.h, &inp[..full_blocks])
}
self.buffer[..inp.len() - full_blocks].copy_from_slice(&inp[full_blocks..])
}
#[cfg(hashes_fuzz)]
fn input(&mut self, inp: &[u8]) {
for c in inp {
self.buffer[0] ^= *c;
}
self.bytes_hashed += inp.len() as u64;
}
)
);
pub(crate) use engine_input_impl;