use std::cell::RefCell;
use std::rc::Rc;
use std::sync::Mutex;
use log::trace;
use malloc_size_of_derive::MallocSizeOf;
use rand::distributions::{Distribution, Standard};
use rand::rngs::adapter::ReseedingRng;
use rand::rngs::OsRng;
pub use rand::seq::SliceRandom;
pub use rand::{Rng, RngCore, SeedableRng};
use rand_isaac::isaac::IsaacCore;
use uuid::{Builder, Uuid};
static OS_RNG: Mutex<OsRng> = Mutex::new(OsRng);
const RESEED_THRESHOLD: u64 = 32_768;
#[derive(MallocSizeOf)]
pub struct ServoRng {
#[ignore_malloc_size_of = "Defined in rand"]
rng: ReseedingRng<IsaacCore, ServoReseeder>,
}
impl RngCore for ServoRng {
#[inline]
fn next_u32(&mut self) -> u32 {
self.rng.next_u32()
}
#[inline]
fn next_u64(&mut self) -> u64 {
self.rng.next_u64()
}
#[inline]
fn fill_bytes(&mut self, bytes: &mut [u8]) {
self.rng.fill_bytes(bytes)
}
fn try_fill_bytes(&mut self, bytes: &mut [u8]) -> std::result::Result<(), rand_core::Error> {
self.rng.try_fill_bytes(bytes)
}
}
#[derive(Default)]
pub struct Seed([u8; 32]);
impl AsMut<[u8]> for Seed {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0
}
}
impl SeedableRng for ServoRng {
type Seed = Seed;
fn from_seed(seed: Seed) -> ServoRng {
trace!("Creating a new ServoRng.");
let isaac_rng = IsaacCore::from_seed(seed.0);
let reseeding_rng = ReseedingRng::new(isaac_rng, RESEED_THRESHOLD, ServoReseeder);
ServoRng { rng: reseeding_rng }
}
}
impl ServoRng {
pub fn new_manually_reseeded(seed: u64) -> ServoRng {
trace!("Creating a new manually-reseeded ServoRng.");
let isaac_rng = IsaacCore::seed_from_u64(seed);
let reseeding_rng = ReseedingRng::new(isaac_rng, 0, ServoReseeder);
ServoRng { rng: reseeding_rng }
}
}
impl Default for ServoRng {
fn default() -> Self {
trace!("Creating new ServoRng.");
let mut os_rng = OS_RNG.lock().expect("Poisoned lock.");
let isaac_rng = IsaacCore::from_rng(&mut *os_rng).unwrap();
let reseeding_rng = ReseedingRng::new(isaac_rng, RESEED_THRESHOLD, ServoReseeder);
ServoRng { rng: reseeding_rng }
}
}
struct ServoReseeder;
impl RngCore for ServoReseeder {
#[inline]
fn next_u32(&mut self) -> u32 {
let mut os_rng = OS_RNG.lock().expect("Poisoned lock.");
os_rng.next_u32()
}
#[inline]
fn next_u64(&mut self) -> u64 {
let mut os_rng = OS_RNG.lock().expect("Poisoned lock.");
os_rng.next_u64()
}
#[inline]
fn fill_bytes(&mut self, bytes: &mut [u8]) {
let mut os_rng = OS_RNG.lock().expect("Poisoned lock.");
os_rng.fill_bytes(bytes)
}
#[inline]
fn try_fill_bytes(&mut self, bytes: &mut [u8]) -> std::result::Result<(), rand_core::Error> {
let mut os_rng = OS_RNG.lock().expect("Poisoned lock.");
os_rng.try_fill_bytes(bytes)
}
}
impl Default for ServoReseeder {
fn default() -> ServoReseeder {
ServoReseeder
}
}
#[derive(Clone)]
pub struct ServoThreadRng {
rng: Rc<RefCell<ServoRng>>,
}
pub fn thread_rng() -> ServoThreadRng {
SERVO_THREAD_RNG.with(|t| t.clone())
}
thread_local! {
static SERVO_THREAD_RNG: ServoThreadRng = ServoThreadRng { rng: Rc::new(RefCell::new(ServoRng::default())) };
}
impl RngCore for ServoThreadRng {
fn next_u32(&mut self) -> u32 {
self.rng.borrow_mut().next_u32()
}
fn next_u64(&mut self) -> u64 {
self.rng.borrow_mut().next_u64()
}
#[inline]
fn fill_bytes(&mut self, bytes: &mut [u8]) {
self.rng.borrow_mut().fill_bytes(bytes)
}
#[inline]
fn try_fill_bytes(&mut self, bytes: &mut [u8]) -> std::result::Result<(), rand_core::Error> {
(self.rng.borrow_mut()).try_fill_bytes(bytes)
}
}
#[inline]
pub fn random<T>() -> T
where
Standard: Distribution<T>,
{
thread_rng().gen()
}
#[inline]
pub fn random_uuid() -> Uuid {
let mut bytes = [0; 16];
thread_rng().fill_bytes(&mut bytes);
Builder::from_random_bytes(bytes).into_uuid()
}