pub fn splitmix64(state: &mut u64) -> u64 {
*state = state.wrapping_add(0x9e37_79b9_7f4a_7c15);
let mut z = *state;
z = (z ^ (z >> 30)).wrapping_mul(0xbf58_476d_1ce4_e5b9);
z = (z ^ (z >> 27)).wrapping_mul(0x94d0_49bb_1331_11eb);
z ^ (z >> 31)
}
pub fn seed_material<const N: usize>(seed: u64) -> [u8; N] {
let mut state = seed ^ 0xa076_1d64_78bd_642f;
let mut out = [0u8; N];
let mut pos = 0usize;
while pos < N {
let word = splitmix64(&mut state).to_be_bytes();
let take = (N - pos).min(8);
out[pos..pos + take].copy_from_slice(&word[..take]);
pos += take;
}
out
}
pub const fn sequential_bytes<const N: usize>() -> [u8; N] {
let mut out = [0u8; N];
let mut i = 0;
while i < N {
out[i] = i as u8;
i += 1;
}
out
}
pub const K16: [u8; 16] = sequential_bytes();
pub const K32: [u8; 32] = sequential_bytes();
pub const IV8: [u8; 8] = sequential_bytes();
pub const IV16: [u8; 16] = sequential_bytes();
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn splitmix64_nonzero_seed_zero() {
let out: [u8; 8] = seed_material(0);
assert!(out.iter().any(|&b| b != 0));
}
#[test]
fn splitmix64_deterministic() {
let mut s1 = 42u64;
let mut s2 = 42u64;
assert_eq!(splitmix64(&mut s1), splitmix64(&mut s2));
}
#[test]
fn seed_material_nonzero_for_seed_zero() {
let out: [u8; 32] = seed_material(0);
assert!(out.iter().any(|&b| b != 0));
}
#[test]
fn seed_material_deterministic() {
let a: [u8; 16] = seed_material(99);
let b: [u8; 16] = seed_material(99);
assert_eq!(a, b);
}
#[test]
fn sequential_bytes_correct() {
let b: [u8; 4] = sequential_bytes();
assert_eq!(b, [0x00, 0x01, 0x02, 0x03]);
let b16: [u8; 16] = sequential_bytes();
assert_eq!(b16[0], 0x00);
assert_eq!(b16[15], 0x0f);
let b257: [u8; 257] = sequential_bytes();
assert_eq!(b257[255], 0xff);
assert_eq!(b257[256], 0x00);
}
}