use core::cell::RefCell;
use crate::unix::DevRandom;
#[cfg(unix)]
pub mod unix;
pub trait RandomSource {
fn fill_bytes(&mut self, bytes: &mut [u8]);
}
pub trait Random: Sized {
fn random<S>(source: &mut S) -> Self
where
S: RandomSource + ?Sized;
}
impl Random for bool {
fn random<S>(source: &mut S) -> Self
where
S: RandomSource + ?Sized
{
u8::random(source) & 1 == 1
}
}
macro_rules! numerics {
($($t:ty),* $(,)?) => {
$(
impl Random for $t {
fn random<S>(source: &mut S) -> Self
where
S: RandomSource + ?Sized
{
let mut bytes = (0 as Self).to_ne_bytes();
source.fill_bytes(&mut bytes);
Self::from_ne_bytes(bytes)
}
}
)*
};
}
numerics!(u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize);
#[cfg(unix)]
thread_local! {
static GLOBAL_RAND: RefCell<DevRandom> = RefCell::new(DevRandom::new().unwrap());
}
pub fn random<T: Random>() -> T {
GLOBAL_RAND.with(|r| {
let mut source = r.borrow_mut();
T::random(&mut *source)
})
}