use std::marker::PhantomData;
#[allow(private_bounds)]
pub trait HashAlgo<const N: usize>: std::fmt::Debug + Send + Sync + Sized + Sealed {
fn hash(data: &[u8]) -> Digest<N, Self>;
}
pub(super) trait Sealed {}
#[derive(Debug)]
pub struct Digest<const N: usize, T>
where
T: HashAlgo<N>,
{
digest: [u8; N],
_algo: PhantomData<T>,
}
impl<const N: usize, T> Digest<N, T>
where
T: HashAlgo<N>,
{
pub(crate) fn from_raw(digest: [u8; N]) -> Self {
Self {
digest,
_algo: PhantomData,
}
}
pub fn as_bytes(&self) -> &[u8] {
&self.digest
}
pub fn as_array(&self) -> &[u8; N] {
&self.digest
}
}
impl<const N: usize, T> Clone for Digest<N, T>
where
T: HashAlgo<N>,
{
fn clone(&self) -> Self {
Self {
digest: self.digest,
_algo: self._algo,
}
}
}
impl<const N: usize, T> std::hash::Hash for Digest<N, T>
where
T: HashAlgo<N>,
{
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.digest.hash(state);
}
}
impl<const N: usize, T> Eq for Digest<N, T> where T: HashAlgo<N> {}
impl<const N: usize, T> PartialEq for Digest<N, T>
where
T: HashAlgo<N>,
{
fn eq(&self, other: &Self) -> bool {
self.digest == other.digest
}
}