use rand::SeedableRng;
use rand_chacha::ChaCha8Rng;
pub type Rng = ChaCha8Rng;
#[must_use]
pub fn resolve_seed(seed: Option<u64>) -> (u64, Rng) {
let s = seed.unwrap_or_else(draw_os_seed);
(s, ChaCha8Rng::seed_from_u64(s))
}
#[must_use]
pub fn draw_os_seed() -> u64 {
let mut buf = [0u8; 8];
getrandom::fill(&mut buf).expect("getrandom failed");
u64::from_le_bytes(buf)
}
#[must_use]
pub fn child_seeds(parent: &mut Rng, n_iterations: usize) -> Vec<u64> {
use rand::Rng;
(0..n_iterations).map(|_| parent.next_u64()).collect()
}
#[must_use]
pub fn child_rng(seed: u64) -> Rng {
ChaCha8Rng::seed_from_u64(seed)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn child_seeds_are_deterministic_for_fixed_parent_seed() {
let (_, mut rng_a) = resolve_seed(Some(42));
let (_, mut rng_b) = resolve_seed(Some(42));
let a = child_seeds(&mut rng_a, 100);
let b = child_seeds(&mut rng_b, 100);
assert_eq!(a, b);
}
#[test]
fn resolve_seed_passes_through_caller_value() {
let (s, _) = resolve_seed(Some(12345));
assert_eq!(s, 12345);
}
#[test]
fn resolve_seed_none_returns_nonzero_seed() {
let (s, _) = resolve_seed(None);
assert_ne!(s, 0);
}
#[test]
fn child_rng_reproducible_from_seed() {
use rand::Rng;
let mut a = child_rng(7);
let mut b = child_rng(7);
let mut va = vec![0u64; 10];
let mut vb = vec![0u64; 10];
for i in 0..10 {
va[i] = a.next_u64();
vb[i] = b.next_u64();
}
assert_eq!(va, vb);
}
}