use digest::{ExtendableOutput, XofReader};
#[cfg(feature = "zeroize")]
use zeroize::{Zeroize, ZeroizeOnDrop};
use crate::duplex_sponge::DuplexSpongeInterface;
#[derive(Clone)]
pub struct XOF<H: ExtendableOutput> {
hasher: H,
xof_reader: Option<H::Reader>,
}
impl<H> DuplexSpongeInterface for XOF<H>
where
H: ExtendableOutput + Clone + Default,
H::Reader: Clone,
{
type U = u8;
fn absorb(&mut self, input: &[u8]) -> &mut Self {
self.xof_reader = None;
self.hasher.update(input);
self
}
fn squeeze(&mut self, output: &mut [u8]) -> &mut Self {
self.xof_reader
.get_or_insert_with(|| self.hasher.clone().finalize_xof())
.read(output);
self
}
fn ratchet(&mut self) -> &mut Self {
todo!()
}
}
#[cfg(feature = "zeroize")]
impl<H> Zeroize for XOF<H>
where
H: ExtendableOutput + Default + Zeroize,
{
fn zeroize(&mut self) {
self.hasher.zeroize();
self.xof_reader = None;
}
}
#[cfg(feature = "zeroize")]
impl<H> ZeroizeOnDrop for XOF<H> where H: ExtendableOutput + Default {}
impl<H: ExtendableOutput + Default> Default for XOF<H> {
fn default() -> Self {
Self {
hasher: H::default(),
xof_reader: None,
}
}
}