use rand::distr::{Distribution, StandardUniform, uniform::SampleUniform};
use rand::prelude::*;
use std::cell::RefCell;
use std::ops::Range;
pub trait RandomProvider: Clone {
fn random<T>(&self) -> T
where
StandardUniform: Distribution<T>;
fn random_range<T>(&self, range: Range<T>) -> T
where
T: SampleUniform + PartialOrd;
fn random_ratio(&self) -> f64;
fn random_bool(&self, probability: f64) -> bool;
}
#[derive(Clone, Default)]
pub struct TokioRandomProvider;
impl TokioRandomProvider {
pub fn new() -> Self {
Self
}
}
thread_local! {
static RNG: RefCell<rand::rngs::ThreadRng> = RefCell::new(rand::rng());
}
impl RandomProvider for TokioRandomProvider {
fn random<T>(&self) -> T
where
StandardUniform: Distribution<T>,
{
RNG.with(|rng| rng.borrow_mut().random())
}
fn random_range<T>(&self, range: Range<T>) -> T
where
T: SampleUniform + PartialOrd,
{
RNG.with(|rng| rng.borrow_mut().random_range(range))
}
fn random_ratio(&self) -> f64 {
RNG.with(|rng| rng.borrow_mut().random())
}
fn random_bool(&self, probability: f64) -> bool {
self.random_ratio() < probability
}
}