#[cfg(feature = "curl-p")]
#[cfg_attr(docsrs, doc(cfg(feature = "curl-p")))]
pub mod curl_p;
#[cfg(feature = "kerl_deprecated_do_not_use")]
#[cfg_attr(docsrs, doc(cfg(feature = "kerl_deprecated_do_not_use")))]
#[cfg_attr(not(test), deprecated)]
pub mod kerl;
pub const HASH_LENGTH: usize = 243;
pub const HASH_LENGTH_TRYTES: usize = 243 / 3;
use core::ops::DerefMut;
use crate::encoding::ternary::{raw::RawEncoding, Btrit, TritBuf, Trits, T1B1};
pub trait Sponge {
type Error;
fn reset(&mut self);
fn absorb(&mut self, input: &Trits) -> Result<(), Self::Error>;
fn squeeze_into(&mut self, buf: &mut Trits) -> Result<(), Self::Error>;
fn squeeze(&mut self) -> Result<TritBuf, Self::Error> {
let mut output = TritBuf::zeros(HASH_LENGTH);
self.squeeze_into(&mut output)?;
Ok(output)
}
fn digest_into(&mut self, input: &Trits, buf: &mut Trits) -> Result<(), Self::Error> {
self.absorb(input)?;
self.squeeze_into(buf)?;
self.reset();
Ok(())
}
fn digest(&mut self, input: &Trits) -> Result<TritBuf, Self::Error> {
self.absorb(input)?;
let output = self.squeeze()?;
self.reset();
Ok(output)
}
}
impl<T: Sponge, U: DerefMut<Target = T>> Sponge for U {
type Error = T::Error;
fn reset(&mut self) {
T::reset(self)
}
fn absorb(&mut self, input: &Trits) -> Result<(), Self::Error> {
T::absorb(self, input)
}
fn squeeze_into(&mut self, buf: &mut Trits) -> Result<(), Self::Error> {
T::squeeze_into(self, buf)
}
}
#[derive(Debug)]
pub enum HashError {
WrongLength,
}
#[derive(Copy, Clone)]
pub struct Hash([Btrit; HASH_LENGTH]);
impl Hash {
pub fn zeros() -> Self {
Self([Btrit::Zero; HASH_LENGTH])
}
pub fn as_trits(&self) -> &Trits<T1B1> {
self
}
pub fn as_trits_mut(&mut self) -> &mut Trits<T1B1> {
&mut *self
}
#[allow(clippy::cast_possible_truncation)] pub fn weight(&self) -> u8 {
self.iter().rev().take_while(|t| *t == Btrit::Zero).count() as u8
}
}
impl<'a, T: RawEncoding<Trit = Btrit>> core::convert::TryFrom<&'a Trits<T>> for Hash {
type Error = HashError;
fn try_from(trits: &'a Trits<T>) -> Result<Self, Self::Error> {
if trits.len() == HASH_LENGTH {
let mut hash = Self([Btrit::Zero; HASH_LENGTH]);
hash.copy_from(trits);
Ok(hash)
} else {
Err(HashError::WrongLength)
}
}
}
impl core::ops::Deref for Hash {
type Target = Trits<T1B1>;
fn deref(&self) -> &Trits<T1B1> {
<&Trits>::from(&self.0 as &[_])
}
}
impl DerefMut for Hash {
fn deref_mut(&mut self) -> &mut Trits<T1B1> {
<&mut Trits>::from(&mut self.0 as &mut [_])
}
}
impl PartialEq for Hash {
fn eq(&self, other: &Self) -> bool {
self.as_trits() == other.as_trits()
}
}
impl Eq for Hash {}
impl core::fmt::Display for Hash {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::fmt::Debug::fmt(self, f)
}
}
impl core::fmt::Debug for Hash {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "{:?}", self.as_trits())
}
}
impl core::hash::Hash for Hash {
fn hash<H: core::hash::Hasher>(&self, hasher: &mut H) {
self.0.hash(hasher)
}
}