#![doc(
html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
html_favicon_url = "https://www.rust-lang.org/favicon.ico",
html_root_url = "https://rust-random.github.io/rand/"
)]
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![doc(test(attr(allow(unused_variables), deny(warnings))))]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![no_std]
#[cfg(feature = "std")]
extern crate std;
use core::{fmt, ops::DerefMut};
pub mod block;
pub mod impls;
pub mod le;
#[cfg(feature = "os_rng")]
mod os;
#[cfg(feature = "os_rng")]
pub use os::{OsError, OsRng};
pub trait RngCore {
fn next_u32(&mut self) -> u32;
fn next_u64(&mut self) -> u64;
fn fill_bytes(&mut self, dst: &mut [u8]);
}
impl<T: DerefMut> RngCore for T
where
T::Target: RngCore,
{
#[inline]
fn next_u32(&mut self) -> u32 {
self.deref_mut().next_u32()
}
#[inline]
fn next_u64(&mut self) -> u64 {
self.deref_mut().next_u64()
}
#[inline]
fn fill_bytes(&mut self, dst: &mut [u8]) {
self.deref_mut().fill_bytes(dst);
}
}
pub trait CryptoRng: RngCore {}
impl<T: DerefMut> CryptoRng for T where T::Target: CryptoRng {}
pub trait TryRngCore {
type Error: fmt::Debug + fmt::Display;
fn try_next_u32(&mut self) -> Result<u32, Self::Error>;
fn try_next_u64(&mut self) -> Result<u64, Self::Error>;
fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Self::Error>;
fn unwrap_err(self) -> UnwrapErr<Self>
where
Self: Sized,
{
UnwrapErr(self)
}
fn unwrap_mut(&mut self) -> UnwrapMut<'_, Self> {
UnwrapMut(self)
}
#[cfg(feature = "std")]
fn read_adapter(&mut self) -> RngReadAdapter<'_, Self>
where
Self: Sized,
{
RngReadAdapter { inner: self }
}
}
impl<R: RngCore + ?Sized> TryRngCore for R {
type Error = core::convert::Infallible;
#[inline]
fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
Ok(self.next_u32())
}
#[inline]
fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
Ok(self.next_u64())
}
#[inline]
fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Self::Error> {
self.fill_bytes(dst);
Ok(())
}
}
pub trait TryCryptoRng: TryRngCore {}
impl<R: CryptoRng + ?Sized> TryCryptoRng for R {}
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash)]
pub struct UnwrapErr<R: TryRngCore>(pub R);
impl<R: TryRngCore> RngCore for UnwrapErr<R> {
#[inline]
fn next_u32(&mut self) -> u32 {
self.0.try_next_u32().unwrap()
}
#[inline]
fn next_u64(&mut self) -> u64 {
self.0.try_next_u64().unwrap()
}
#[inline]
fn fill_bytes(&mut self, dst: &mut [u8]) {
self.0.try_fill_bytes(dst).unwrap()
}
}
impl<R: TryCryptoRng> CryptoRng for UnwrapErr<R> {}
#[derive(Debug, Eq, PartialEq, Hash)]
pub struct UnwrapMut<'r, R: TryRngCore + ?Sized>(pub &'r mut R);
impl<'r, R: TryRngCore + ?Sized> UnwrapMut<'r, R> {
#[inline(always)]
pub fn re<'b>(&'b mut self) -> UnwrapMut<'b, R>
where
'r: 'b,
{
UnwrapMut(self.0)
}
}
impl<R: TryRngCore + ?Sized> RngCore for UnwrapMut<'_, R> {
#[inline]
fn next_u32(&mut self) -> u32 {
self.0.try_next_u32().unwrap()
}
#[inline]
fn next_u64(&mut self) -> u64 {
self.0.try_next_u64().unwrap()
}
#[inline]
fn fill_bytes(&mut self, dst: &mut [u8]) {
self.0.try_fill_bytes(dst).unwrap()
}
}
impl<R: TryCryptoRng + ?Sized> CryptoRng for UnwrapMut<'_, R> {}
pub trait SeedableRng: Sized {
type Seed: Clone + Default + AsRef<[u8]> + AsMut<[u8]>;
fn from_seed(seed: Self::Seed) -> Self;
fn seed_from_u64(mut state: u64) -> Self {
fn pcg32(state: &mut u64) -> [u8; 4] {
const MUL: u64 = 6364136223846793005;
const INC: u64 = 11634580027462260723;
*state = state.wrapping_mul(MUL).wrapping_add(INC);
let state = *state;
let xorshifted = (((state >> 18) ^ state) >> 27) as u32;
let rot = (state >> 59) as u32;
let x = xorshifted.rotate_right(rot);
x.to_le_bytes()
}
let mut seed = Self::Seed::default();
let mut iter = seed.as_mut().chunks_exact_mut(4);
for chunk in &mut iter {
chunk.copy_from_slice(&pcg32(&mut state));
}
let rem = iter.into_remainder();
if !rem.is_empty() {
rem.copy_from_slice(&pcg32(&mut state)[..rem.len()]);
}
Self::from_seed(seed)
}
fn from_rng(rng: &mut impl RngCore) -> Self {
let mut seed = Self::Seed::default();
rng.fill_bytes(seed.as_mut());
Self::from_seed(seed)
}
fn try_from_rng<R: TryRngCore>(rng: &mut R) -> Result<Self, R::Error> {
let mut seed = Self::Seed::default();
rng.try_fill_bytes(seed.as_mut())?;
Ok(Self::from_seed(seed))
}
#[cfg(feature = "os_rng")]
fn from_os_rng() -> Self {
match Self::try_from_os_rng() {
Ok(res) => res,
Err(err) => panic!("from_os_rng failed: {}", err),
}
}
#[cfg(feature = "os_rng")]
fn try_from_os_rng() -> Result<Self, getrandom::Error> {
let mut seed = Self::Seed::default();
getrandom::fill(seed.as_mut())?;
let res = Self::from_seed(seed);
Ok(res)
}
}
#[cfg(feature = "std")]
pub struct RngReadAdapter<'a, R: TryRngCore + ?Sized> {
inner: &'a mut R,
}
#[cfg(feature = "std")]
impl<R: TryRngCore + ?Sized> std::io::Read for RngReadAdapter<'_, R> {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
self.inner.try_fill_bytes(buf).map_err(|err| {
std::io::Error::new(std::io::ErrorKind::Other, std::format!("RNG error: {err}"))
})?;
Ok(buf.len())
}
}
#[cfg(feature = "std")]
impl<R: TryRngCore + ?Sized> std::fmt::Debug for RngReadAdapter<'_, R> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ReadAdapter").finish()
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_seed_from_u64() {
struct SeedableNum(u64);
impl SeedableRng for SeedableNum {
type Seed = [u8; 8];
fn from_seed(seed: Self::Seed) -> Self {
let mut x = [0u64; 1];
le::read_u64_into(&seed, &mut x);
SeedableNum(x[0])
}
}
const N: usize = 8;
const SEEDS: [u64; N] = [0u64, 1, 2, 3, 4, 8, 16, -1i64 as u64];
let mut results = [0u64; N];
for (i, seed) in SEEDS.iter().enumerate() {
let SeedableNum(x) = SeedableNum::seed_from_u64(*seed);
results[i] = x;
}
for (i1, r1) in results.iter().enumerate() {
let weight = r1.count_ones();
assert!((20..=44).contains(&weight));
for (i2, r2) in results.iter().enumerate() {
if i1 == i2 {
continue;
}
let diff_weight = (r1 ^ r2).count_ones();
assert!(diff_weight >= 20);
}
}
assert_eq!(results[0], 5029875928683246316);
}
struct SomeRng;
impl RngCore for SomeRng {
fn next_u32(&mut self) -> u32 {
unimplemented!()
}
fn next_u64(&mut self) -> u64 {
unimplemented!()
}
fn fill_bytes(&mut self, _: &mut [u8]) {
unimplemented!()
}
}
impl CryptoRng for SomeRng {}
#[test]
fn dyn_rngcore_to_tryrngcore() {
fn third_party_api(_rng: &mut (impl TryRngCore + ?Sized)) -> bool {
true
}
fn my_api(rng: &mut dyn RngCore) -> bool {
third_party_api(rng)
}
assert!(my_api(&mut SomeRng));
}
#[test]
fn dyn_cryptorng_to_trycryptorng() {
fn third_party_api(_rng: &mut (impl TryCryptoRng + ?Sized)) -> bool {
true
}
fn my_api(rng: &mut dyn CryptoRng) -> bool {
third_party_api(rng)
}
assert!(my_api(&mut SomeRng));
}
#[test]
fn dyn_unwrap_mut_tryrngcore() {
fn third_party_api(_rng: &mut impl RngCore) -> bool {
true
}
fn my_api(rng: &mut (impl TryRngCore + ?Sized)) -> bool {
let mut infallible_rng = rng.unwrap_mut();
third_party_api(&mut infallible_rng)
}
assert!(my_api(&mut SomeRng));
}
#[test]
fn dyn_unwrap_mut_trycryptorng() {
fn third_party_api(_rng: &mut impl CryptoRng) -> bool {
true
}
fn my_api(rng: &mut (impl TryCryptoRng + ?Sized)) -> bool {
let mut infallible_rng = rng.unwrap_mut();
third_party_api(&mut infallible_rng)
}
assert!(my_api(&mut SomeRng));
}
#[test]
fn reborrow_unwrap_mut() {
struct FourRng;
impl TryRngCore for FourRng {
type Error = core::convert::Infallible;
fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
Ok(4)
}
fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
unimplemented!()
}
fn try_fill_bytes(&mut self, _: &mut [u8]) -> Result<(), Self::Error> {
unimplemented!()
}
}
let mut rng = FourRng;
let mut rng = rng.unwrap_mut();
assert_eq!(rng.next_u32(), 4);
let mut rng2 = rng.re();
assert_eq!(rng2.next_u32(), 4);
drop(rng2);
assert_eq!(rng.next_u32(), 4);
}
}