#![allow(clippy::indexing_slicing)]
use super::keccak::KeccakCore;
pub(crate) const RATE_256: usize = 136;
#[inline]
fn encode_u64_be(value: u64, out: &mut [u8; 9], right: bool) -> usize {
let bytes = value.to_be_bytes();
let first = bytes.iter().position(|&byte| byte != 0).unwrap_or(7);
let width = 8usize.strict_sub(first);
if right {
out[..width].copy_from_slice(&bytes[first..]);
out[width] = width as u8;
width.strict_add(1)
} else {
out[0] = width as u8;
out[1..=width].copy_from_slice(&bytes[first..]);
width.strict_add(1)
}
}
#[inline]
pub(crate) fn left_encode(value: u64) -> ([u8; 9], usize) {
let mut out = [0u8; 9];
let len = encode_u64_be(value, &mut out, false);
(out, len)
}
#[inline]
#[cfg(feature = "kmac")]
pub(crate) fn right_encode(value: u64) -> ([u8; 9], usize) {
let mut out = [0u8; 9];
let len = encode_u64_be(value, &mut out, true);
(out, len)
}
#[inline]
pub(crate) fn encoded_string_len(data: &[u8]) -> usize {
left_encode(crate::bytes_to_bits(data.len())).1.strict_add(data.len())
}
pub(crate) fn absorb_bytepad<const RATE: usize>(core: &mut KeccakCore<RATE>, segments: &[&[u8]], payload_len: usize) {
let (prefix, prefix_len) = left_encode(RATE as u64);
core.update(&prefix[..prefix_len]);
for segment in segments {
core.update(segment);
}
let total_len = prefix_len.strict_add(payload_len);
let rem = total_len % RATE;
let pad_len = if rem == 0 { RATE } else { RATE.strict_sub(rem) };
core.update(&[0u8; RATE][..pad_len]);
}