use rand_core::{
Infallible,
TryRng,
};
pub(crate) struct OsRngFill;
impl TryRng for OsRngFill {
type Error = Infallible;
fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
let mut b = [0u8; 4];
self.try_fill_bytes(&mut b)?;
Ok(u32::from_le_bytes(b))
}
fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
let mut b = [0u8; 8];
self.try_fill_bytes(&mut b)?;
Ok(u64::from_le_bytes(b))
}
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Self::Error> {
getrandom::fill(dest)
.expect("OS CSPRNG unavailable: hardened masking requires a live entropy source");
Ok(())
}
}
#[allow(clippy::needless_range_loop, clippy::integer_division_remainder_used)]
pub(crate) fn shuffle_indices<R: rand_core::Rng>(rng: &mut R, k: usize, perm: &mut [usize]) {
for i in 0..k {
perm[i] = i;
}
for i in (1..k).rev() {
let mut buf = [0u8; 8];
rng.fill_bytes(&mut buf);
let j = usize::try_from(u64::from_le_bytes(buf) % (i as u64 + 1))
.expect("shuffle index fits in usize (k <= 4)");
perm.swap(i, j);
}
}