use std::sync::{Arc, Mutex};
use getrandom::fill as getrandom_fill;
use rand::{Rng as RandRng, SeedableRng, rngs::StdRng};
#[derive(Clone)]
pub enum Rng {
Os,
Seeded(SeededRng),
}
impl Default for Rng {
fn default() -> Self {
Rng::Os
}
}
impl Rng {
pub fn seeded(seed: u64) -> Self {
Rng::Seeded(SeededRng::new(seed))
}
pub fn bytes_16(&self) -> [u8; 16] {
match self {
Rng::Os => {
let mut buf = [0u8; 16];
getrandom_fill(&mut buf).expect("getrandom failed");
buf
}
Rng::Seeded(seeded) => {
let mut buf = [0u8; 16];
let mut rng = seeded.inner.lock().unwrap();
rng.fill_bytes(&mut buf);
buf
}
}
}
pub fn bytes_32(&self) -> [u8; 32] {
match self {
Rng::Os => {
let mut buf = [0u8; 32];
getrandom_fill(&mut buf).expect("getrandom failed");
buf
}
Rng::Seeded(seeded) => {
let mut buf = [0u8; 32];
let mut rng = seeded.inner.lock().unwrap();
rng.fill_bytes(&mut buf);
buf
}
}
}
pub fn bytes_10(&self) -> [u8; 10] {
match self {
Rng::Os => {
let mut buf = [0u8; 10];
getrandom_fill(&mut buf).expect("getrandom failed");
buf
}
Rng::Seeded(seeded) => {
let mut buf = [0u8; 10];
let mut rng = seeded.inner.lock().unwrap();
rng.fill_bytes(&mut buf);
buf
}
}
}
}
#[derive(Clone)]
pub struct SeededRng {
inner: Arc<Mutex<StdRng>>,
}
impl SeededRng {
pub fn new(seed: u64) -> Self {
Self {
inner: Arc::new(Mutex::new(StdRng::seed_from_u64(seed))),
}
}
}