use crate::{Hasher, HasherBuild, Infallible, RandQualities, RandTry, RandomState};
#[cfg(feature = "std")]
#[doc = crate::_tags!(rand)]
#[doc = crate::_doc_meta!{location("num/prob/rand")}]
#[derive(Clone, Copy, Debug, Default)]
pub struct StdRand;
#[cfg(feature = "std")]
impl StdRand {
const DOMAIN: &[u8] = b"devela::StdRand/v1";
#[inline(never)]
pub fn random_u64() -> u64 {
let h = RandomState::new();
let mut hasher = h.build_hasher();
hasher.write(Self::DOMAIN);
hasher.finish()
}
#[inline(never)]
pub fn random_bytes(buf: &mut [u8]) {
let h = RandomState::new();
let mut counter = 0u64;
let mut i = 0;
while i < buf.len() {
let mut hasher = h.build_hasher();
hasher.write(Self::DOMAIN);
hasher.write_u64(counter);
let bytes = hasher.finish().to_ne_bytes();
let n = usize::min(8, buf.len() - i);
buf[i..i + n].copy_from_slice(&bytes[..n]);
counter = counter.wrapping_add(1);
i += n;
}
}
}
#[cfg(feature = "std")]
impl RandTry for StdRand {
type Error = Infallible;
const RAND_OUTPUT_BITS: u32 = 64;
const RAND_STATE_BITS: u32 = 0;
const RAND_QUALITIES: RandQualities = RandQualities::EXTERNAL;
#[inline(always)]
fn rand_try_next_u64(&mut self) -> Result<u64, Self::Error> {
Ok(StdRand::random_u64())
}
#[inline(always)]
fn rand_try_fill_bytes(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
StdRand::random_bytes(buf);
Ok(())
}
}