use std::collections::VecDeque;
use typenum::{U2, U3};
use extra_safe::{
iopat,
traits::{Absorb, Squeeze},
Error, ExtraSponge, IOPattern, SpongeAPI, SpongeOp,
};
struct BasicSponge {
elements: Vec<u8>,
pattern: VecDeque<SpongeOp>,
}
impl BasicSponge {
fn permute(&mut self, other_elems: &Vec<u8>) {
self.elements
.iter_mut()
.zip(other_elems)
.for_each(|(a, b)| {
*a = *a ^ *b;
});
}
}
impl Default for BasicSponge {
fn default() -> Self {
BasicSponge {
elements: Vec::new(),
pattern: VecDeque::new(),
}
}
}
impl SpongeAPI for BasicSponge {
type Acc = Vec<u8>;
type Value = u8;
fn start(&mut self, p: IOPattern, _: Option<u32>, acc: &mut Vec<u8>) {
self.elements = acc.clone();
self.pattern = p.0.into_iter().collect();
}
fn absorb(&mut self, length: u32, elements: &[u8], acc: &mut Vec<u8>) {
assert_eq!(length as usize, elements.len());
let word = self.pattern.pop_front().unwrap();
assert_eq!(word, SpongeOp::Absorb(length));
self.permute(acc);
self.elements.extend_from_slice(elements);
}
fn squeeze(&mut self, length: u32, elements: &mut [u8], acc: &mut Vec<u8>) {
assert_eq!(length as usize, elements.len());
let word = self.pattern.pop_front().unwrap();
assert_eq!(word, SpongeOp::Squeeze(length));
self.permute(acc);
for i in 0..length as usize {
elements[i] = self.elements[i];
}
}
fn finish(&mut self) -> Result<(), Error> {
self.pattern
.is_empty()
.then(|| ())
.ok_or(Error::ParameterUsageMismatch)
}
}
fn main() {
let mut start_acc: Vec<u8> = vec![1, 2, 3];
let basic_sponge = BasicSponge::default();
let _extra_sponge: ExtraSponge<BasicSponge, iopat![Absorb<U2>, Absorb<U3>, Squeeze<U3>]> =
ExtraSponge::<BasicSponge, iopat![Absorb<U2>, Absorb<U3>, Squeeze<U3>]>::start(
None,
basic_sponge,
&mut start_acc,
);
}