1use keccak::State1600;
2use sponge_cursor::SpongeCursor;
3
4#[inline(always)]
5pub(crate) fn pad<const PAD: u8, const RATE: usize>(
6 state: &mut State1600,
7 cursor: &SpongeCursor<RATE>,
8) {
9 let pos = cursor.pos();
10 let word_offset = pos / 8;
11 let byte_offset = pos % 8;
12
13 let pad = u64::from(PAD) << (8 * byte_offset);
14 state[word_offset] ^= pad;
15 state[RATE / 8 - 1] ^= 1 << 63;
16}
17
18#[inline(always)]
19pub(crate) fn read_state(state: &State1600, dst: &mut [u8]) {
20 assert!(size_of_val(dst) <= size_of_val(state));
21
22 let chunks = dst.chunks_mut(size_of::<u64>());
23 for (src, dst) in state.iter().zip(chunks) {
24 dst.copy_from_slice(&src.to_le_bytes()[..dst.len()]);
25 }
26}
27
28#[inline(always)]
29pub(crate) fn serialize<const RATE: usize>(
30 state: &State1600,
31 cursor: &SpongeCursor<RATE>,
32) -> [u8; 201] {
33 let mut ser_state = [0u8; 201];
34 let [state_dst @ .., cursor_dst] = &mut ser_state;
36
37 let state_dst_chunks = state_dst.chunks_exact_mut(size_of::<u64>());
38 for (src, dst) in state.iter().zip(state_dst_chunks) {
39 dst.copy_from_slice(&src.to_le_bytes());
40 }
41
42 *cursor_dst = cursor.raw_pos();
43 ser_state
44}
45
46#[inline(always)]
47pub(crate) fn deserialize<const RATE: usize>(
48 ser_state: &[u8; 201],
49) -> Option<(State1600, SpongeCursor<RATE>)> {
50 let [state_src @ .., cursor_src] = ser_state;
52
53 let n = size_of::<u64>();
54 let state = core::array::from_fn(|i| {
55 let chunk = state_src[n * i..][..n]
56 .try_into()
57 .expect("chunk has correct length");
58 u64::from_le_bytes(chunk)
59 });
60
61 let cursor = SpongeCursor::new(*cursor_src)?;
62 Some((state, cursor))
63}