1use crate::consts::ROUNDS;
2use core::fmt;
3use digest::XofReader;
4use keccak::{Keccak, State1600};
5use sponge_cursor::SpongeCursor;
6
7#[derive(Clone)]
9pub struct KtReader<const RATE: usize> {
10 state: State1600,
11 cursor: SpongeCursor<RATE>,
12 keccak: Keccak,
13}
14
15impl<const RATE: usize> KtReader<RATE> {
16 pub(crate) fn new(state: &State1600, keccak: Keccak) -> Self {
17 Self {
18 state: *state,
19 cursor: Default::default(),
20 keccak,
21 }
22 }
23}
24
25impl<const RATE: usize> XofReader for KtReader<RATE> {
26 #[inline]
27 fn read(&mut self, buf: &mut [u8]) {
28 self.keccak.with_p1600::<ROUNDS>(|p1600| {
29 self.cursor.squeeze_read_u64_le(&mut self.state, p1600, buf);
30 });
31 }
32}
33
34impl<const RATE: usize> fmt::Debug for KtReader<RATE> {
35 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36 let debug_str = match RATE {
37 168 => "Kt128Reader { ... }",
38 136 => "Kt256Reader { ... }",
39 _ => unreachable!(),
40 };
41 f.write_str(debug_str)
42 }
43}
44
45impl<const RATE: usize> Drop for KtReader<RATE> {
46 fn drop(&mut self) {
47 #[cfg(feature = "zeroize")]
48 {
49 use digest::zeroize::Zeroize;
50 self.state.zeroize();
51 }
53 }
54}
55
56#[cfg(feature = "zeroize")]
57impl<const RATE: usize> digest::zeroize::ZeroizeOnDrop for KtReader<RATE> {}