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_usize() {
return Err(Error::InvalidSize(digest.len() as _));
}
let mut array = GenericArray::default();
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::to_u64() || size > u8::max_value() as u64 {
return Err(Error::InvalidSize(size));
}
let mut digest = GenericArray::default();
r.read_exact(&mut digest[..size as usize])?;
Ok(Self::from(digest))
}
}
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(())
}
}