use crate::{Error, Result, Word};
const USIZE_BYTES: usize = usize::BITS as usize / 8;
#[inline(always)]
pub const fn words_for(data: &[u8]) -> usize {
words_for_len(data.len())
}
#[inline(always)]
pub const fn words_for_len(len: usize) -> usize {
(len + 31) / 32
}
#[inline(always)]
pub(crate) const fn padded_len(data: &[u8]) -> usize {
next_multiple_of_32(data.len())
}
#[inline(always)]
pub const fn next_multiple_of_32(n: usize) -> usize {
match n % 32 {
0 => n,
r => n + (32 - r),
}
}
#[inline]
pub(crate) fn pad_usize(value: usize) -> Word {
let mut padded = Word::ZERO;
padded[32 - USIZE_BYTES..32].copy_from_slice(&value.to_be_bytes());
padded
}
#[doc(hidden)]
#[inline]
pub const fn just_ok<T>(_: &T) -> crate::Result<()> {
Ok(())
}
#[inline]
pub(crate) fn check_zeroes(data: &[u8]) -> bool {
data.iter().all(|b| *b == 0)
}
#[inline]
pub(crate) fn as_offset(word: &Word, validate: bool) -> Result<usize> {
let (before, data) = word.split_at(32 - USIZE_BYTES);
if validate && !check_zeroes(before) {
return Err(Error::type_check_fail(&word[..], "offset (usize)"));
}
Ok(usize::from_be_bytes(<[u8; USIZE_BYTES]>::try_from(data).unwrap()))
}
#[cfg(test)]
mod tests {
use super::*;
use alloy_primitives::b256;
#[test]
fn test_words_for() {
assert_eq!(words_for(&[]), 0);
assert_eq!(words_for(&[0; 31]), 1);
assert_eq!(words_for(&[0; 32]), 1);
assert_eq!(words_for(&[0; 33]), 2);
}
#[test]
fn test_pad_u32() {
assert_eq!(
pad_usize(0),
b256!("0000000000000000000000000000000000000000000000000000000000000000")
);
assert_eq!(
pad_usize(1),
b256!("0000000000000000000000000000000000000000000000000000000000000001")
);
assert_eq!(
pad_usize(0x100),
b256!("0000000000000000000000000000000000000000000000000000000000000100")
);
assert_eq!(
pad_usize(0xffffffff),
b256!("00000000000000000000000000000000000000000000000000000000ffffffff")
);
}
}