1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
use core::convert::TryInto; const PLEN: usize = 25; #[derive(Clone, Default)] pub(crate) struct Sha3State { pub state: [u64; PLEN], } impl Sha3State { #[inline(always)] pub(crate) fn absorb_block(&mut self, block: &[u8]) { debug_assert_eq!(block.len() % 8, 0); if cfg!(target_endian = "little") { #[allow(unsafe_code)] let state = unsafe { &mut *(self.state.as_mut_ptr() as *mut [u8; 8 * PLEN]) }; for (d, i) in state.iter_mut().zip(block) { *d ^= *i; } } else if cfg!(target_endian = "big") { let n = block.len() / 8; let mut buf = [0u64; 21]; let buf = &mut buf[..n]; for (o, chunk) in buf.iter_mut().zip(block.chunks_exact(8)) { *o = u64::from_le_bytes(chunk.try_into().unwrap()); } for (d, i) in self.state[..n].iter_mut().zip(buf) { *d ^= *i; } } keccak::f1600(&mut self.state); } #[inline(always)] pub(crate) fn as_bytes<F: FnOnce(&[u8; 8 * PLEN])>(&self, f: F) { let mut data_copy; let data_ref: &[u8; 8 * PLEN] = if cfg!(target_endian = "little") { #[allow(unsafe_code)] unsafe { &*(self.state.as_ptr() as *const [u8; 8 * PLEN]) } } else { data_copy = [0u8; 8 * PLEN]; for (chunk, v) in data_copy.chunks_exact_mut(8).zip(self.state.iter()) { chunk.copy_from_slice(&v.to_le_bytes()); } &data_copy }; f(data_ref); } #[inline(always)] pub(crate) fn apply_f(&mut self) { keccak::f1600(&mut self.state); } }