use crate::error::Error;
use core::fmt::Debug;
pub trait Digest<const S: usize>:
AsRef<[u8]>
+ AsMut<[u8]>
+ From<[u8; S]>
+ Into<[u8; S]>
+ Clone
+ core::hash::Hash
+ Debug
+ Default
+ Eq
+ Send
+ Sync
+ 'static {
const SIZE: usize = S;
fn wrap(digest: &[u8]) -> Result<Self, Error> {
if digest.len() != S {
return Err(Error::InvalidSize(digest.len() as _));
}
let mut array = [0; S];
let len = digest.len().min(array.len());
array[..len].copy_from_slice(&digest[..len]);
Ok(array.into())
}
#[cfg(feature = "std")]
fn from_reader<R>(mut r: R) -> Result<Self, Error>
where R: std::io::Read {
use unsigned_varint::io::read_u64;
let size = read_u64(&mut r)?;
if size > S as u64 || size > u8::max_value() as u64 {
return Err(Error::InvalidSize(size));
}
let mut digest = [0; S];
r.read_exact(&mut digest[..size as usize])?;
Ok(Self::from(digest))
}
}
pub trait StatefulHasher<const S: usize>: Default + Send + Sync {
type Digest: Digest<S>;
fn update(&mut self, input: &[u8]);
fn finalize(&self) -> Self::Digest;
fn reset(&mut self);
}
pub trait Hasher<const S: usize>: Default + Send + Sync {
type Digest: Digest<S>;
const SIZE: usize = S;
fn digest(input: &[u8]) -> Self::Digest
where Self: Sized;
}
impl<T: StatefulHasher<S>, const S: usize> Hasher<S> for T {
type Digest = T::Digest;
fn digest(input: &[u8]) -> Self::Digest {
let mut hasher = Self::default();
hasher.update(input);
hasher.finalize()
}
}