use crate::prelude::*;
use rand::Rng;
use rand::SeedableRng;
use rand::distr::Distribution;
use rand::distr::StandardUniform;
use rand::distr::uniform::SampleRange;
use rand::distr::uniform::SampleUniform;
use rand_chacha::ChaCha8Rng;
#[derive(Deref, DerefMut, Resource)]
pub struct RandomSource(pub ChaCha8Rng);
impl RandomSource {
pub fn from_seed(seed: u64) -> Self {
let rng = ChaCha8Rng::seed_from_u64(seed);
Self(rng)
}
}
impl Default for RandomSource {
fn default() -> Self {
let rng = ChaCha8Rng::from_rng(&mut rand::rng());
Self(rng)
}
}
impl RandomSource {
pub fn random<T>(&mut self) -> T
where
StandardUniform: Distribution<T>,
{
self.0.random()
}
pub fn random_iter<T>(
self,
) -> rand::distr::Iter<StandardUniform, ChaCha8Rng, T>
where
Self: Sized,
StandardUniform: Distribution<T>,
{
self.0.random_iter()
}
pub fn random_range<T, R>(&mut self, range: R) -> T
where
T: SampleUniform,
R: SampleRange<T>,
{
self.0.random_range(range)
}
pub fn random_bool(&mut self, p: f64) -> bool { self.0.random_bool(p) }
pub fn random_ratio(&mut self, numerator: u32, denominator: u32) -> bool {
self.0.random_ratio(numerator, denominator)
}
pub fn sample<T, D: Distribution<T>>(&mut self, distr: D) -> T {
self.0.sample(distr)
}
pub fn sample_iter<T, D>(
self,
distr: D,
) -> rand::distr::Iter<D, ChaCha8Rng, T>
where
D: Distribution<T>,
Self: Sized,
{
self.0.sample_iter(distr)
}
pub fn fill<T: rand::Fill + ?Sized>(&mut self, dest: &mut T) {
self.0.fill(dest)
}
}
#[cfg(test)]
mod test {
use crate::prelude::*;
#[test]
fn seed() {
let mut source = RandomSource::from_seed(7);
let val = source.random_range(10..100);
val.xpect_eq(22);
}
#[test]
fn entropy() {
let mut source = RandomSource::default();
let val = source.random_range(10..100);
(val >= 10).xpect_true();
(val < 100).xpect_true();
}
}