use crate::error::Error;
use core::fmt::Debug;
use generic_array::typenum::marker_traits::Unsigned;
use generic_array::{ArrayLength, GenericArray};
pub trait Size:
ArrayLength<u8> + Debug + Default + Eq + core::hash::Hash + Send + Sync + 'static
{
}
impl<T: ArrayLength<u8> + Debug + Default + Eq + core::hash::Hash + Send + Sync + 'static> Size
for T
{
}
pub trait Digest<S: Size>:
AsRef<[u8]>
+ AsMut<[u8]>
+ From<GenericArray<u8, S>>
+ Into<GenericArray<u8, S>>
+ Clone
+ core::hash::Hash
+ Debug
+ Default
+ Eq
+ Send
+ Sync
+ 'static
{
fn size(&self) -> u8 {
S::to_u8()
}
fn wrap(digest: &[u8]) -> Result<Self, Error> {
if digest.len() != S::to_u8() as _ {
return Err(Error::InvalidSize(digest.len() as _));
}
Ok(Self::fit(digest))
}
fn extend(digest: &[u8]) -> Result<Self, Error> {
if digest.len() > S::to_u8() as _ {
return Err(Error::InvalidSize(digest.len() as _));
}
Ok(Self::fit(digest))
}
fn truncate(digest: &[u8]) -> Result<Self, Error> {
if digest.len() < S::to_u8() as _ {
return Err(Error::InvalidSize(digest.len() as _));
}
Ok(Self::fit(digest))
}
fn fit(digest: &[u8]) -> Self {
let mut array = GenericArray::default();
let len = digest.len().min(array.len());
array[..len].copy_from_slice(&digest[..len]);
array.into()
}
}
pub trait StatefulHasher: Default + Send + Sync {
type Size: Size;
type Digest: Digest<Self::Size>;
fn update(&mut self, input: &[u8]);
fn finalize(&self) -> Self::Digest;
fn reset(&mut self);
}
pub trait Hasher: Default + Send + Sync {
type Size: Size;
type Digest: Digest<Self::Size>;
fn size() -> u8 {
Self::Size::to_u8()
}
fn digest(input: &[u8]) -> Self::Digest
where
Self: Sized;
}
impl<T: StatefulHasher> Hasher for T {
type Size = T::Size;
type Digest = T::Digest;
fn digest(input: &[u8]) -> Self::Digest {
let mut hasher = Self::default();
hasher.update(input);
hasher.finalize()
}
}
#[cfg(feature = "std")]
pub struct WriteHasher<H: Hasher>(H);
#[cfg(feature = "std")]
impl<H: StatefulHasher> std::io::Write for WriteHasher<H> {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.0.update(buf);
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}