use crate::chacha::ChaCha12;
#[cfg(feature = "std")]
use crate::entropy::DefaultEntropy;
use crate::entropy::EntropySource;
use crate::ranges::GenerateRange;
use crate::rng::Rng;
use crate::rng::{RangeFromRng, ValueFromRng};
pub struct StdRng(Impl);
type Impl = ChaCha12;
impl Rng for StdRng {
#[inline]
fn random_u32(&mut self) -> u32 {
self.0.random_u32()
}
#[inline]
fn random_u64(&mut self) -> u64 {
self.0.random_u64()
}
}
impl StdRng {
#[cfg(feature = "std")]
#[must_use]
pub fn new() -> Self {
Self(Impl::from_entropy(&mut DefaultEntropy::new()))
}
#[must_use]
pub fn from_entropy<T>(entropy_source: &mut T) -> Self
where
T: EntropySource,
{
Self(Impl::from_entropy(entropy_source))
}
#[inline]
pub fn random<T>(&mut self) -> T
where
T: ValueFromRng,
Self: Sized,
{
self.0.random()
}
#[inline]
pub fn range<T>(&mut self, range: impl Into<GenerateRange<T>>) -> T
where
T: RangeFromRng,
Self: Sized,
{
self.0.range(range)
}
#[inline]
pub fn iter<'a, T>(&'a mut self) -> impl Iterator<Item = T> + 'a
where
T: ValueFromRng + 'a,
Self: Sized,
{
self.0.iter()
}
#[inline]
pub fn fill<T>(&mut self, destination: &mut [T])
where
T: ValueFromRng,
Self: Sized,
{
self.0.fill(destination);
}
#[inline]
pub fn fill_u8(&mut self, destination: &mut [u8])
where
Self: Sized,
{
self.0.fill_u8(destination);
}
#[inline]
pub fn shuffle<T>(&mut self, target: &mut [T])
where
Self: Sized,
{
self.0.shuffle(target);
}
#[cfg(test)]
fn from_entropy_and_nonce<T>(entropy_source: &mut T, nonce: [u8; 8]) -> Self
where
T: EntropySource,
{
Self(Impl::from_entropy_and_nonce(entropy_source, nonce))
}
}
#[cfg(feature = "std")]
impl Default for StdRng {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use crate::{Rng, SplitMix, StdRng};
#[test]
fn test_forwarding() {
let mut rng =
StdRng::from_entropy_and_nonce(&mut SplitMix::new(12345678), [1, 2, 3, 4, 5, 6, 7, 8]);
assert_ne!(rng.random_u32(), rng.random_u32());
assert_ne!(rng.random_u64(), rng.random_u64());
assert_ne!(rng.random::<u16>(), rng.random::<u16>());
assert_ne!(rng.random::<u32>(), rng.random::<u32>());
assert_ne!(rng.random::<u64>(), rng.random::<u64>());
assert_ne!(rng.range::<u32>(0..12452), rng.range::<u32>(0..12452));
{
let mut i = rng.iter::<u128>();
i.next();
assert_ne!(i.next(), i.next());
}
let mut a1 = [0_u8; 32];
let mut a2 = [0_u8; 32];
rng.fill(&mut a1);
rng.fill(&mut a2);
assert_ne!(a1, a2);
a2 = a1;
rng.fill_u8(&mut a1);
rng.fill_u8(&mut a2);
assert_ne!(a1, a2);
a2 = a1;
rng.shuffle(&mut a2);
assert_ne!(a1, a2);
}
#[test]
fn same_entropy_and_nonce_generates_same_values() {
let mut rng1 =
StdRng::from_entropy_and_nonce(&mut SplitMix::new(12345678), [1, 2, 3, 4, 5, 6, 7, 8]);
let mut rng2 =
StdRng::from_entropy_and_nonce(&mut SplitMix::new(12345678), [1, 2, 3, 4, 5, 6, 7, 8]);
assert_eq!(rng1.random_u64(), rng2.random_u64());
}
#[test]
fn same_entropy_and_different_nonce_produces_different_values() {
let mut rng1 = StdRng::from_entropy(&mut SplitMix::new(12345678));
let mut rng2 = StdRng::from_entropy(&mut SplitMix::new(12345678));
assert_ne!(rng1.random_u64(), rng2.random_u64());
}
#[test]
fn different_entropy_and_same_nonce_produces_different_values() {
let mut rng1 =
StdRng::from_entropy_and_nonce(&mut SplitMix::new(12345678), [1, 2, 3, 4, 5, 6, 7, 8]);
let mut rng2 =
StdRng::from_entropy_and_nonce(&mut SplitMix::new(87654321), [1, 2, 3, 4, 5, 6, 7, 8]);
assert_ne!(rng1.random_u64(), rng2.random_u64());
}
}