nanorand/
rand.rs

1#[cfg(feature = "chacha")]
2pub use chacha::{ChaCha, ChaCha12, ChaCha20, ChaCha8};
3#[cfg(feature = "pcg64")]
4pub use pcg64::Pcg64;
5#[cfg(feature = "wyrand")]
6pub use wyrand::WyRand;
7
8use crate::gen::{RandomGen, RandomRange};
9use core::ops::RangeBounds;
10
11/// Implementation of the wyrand PRNG algorithm.
12/// More details can be seen at <https://github.com/wangyi-fudan/wyhash>
13#[cfg(feature = "wyrand")]
14pub mod wyrand;
15
16/// Implementation of the Pcg64 PRNG algorithm.
17/// More details can be seen at <https://www.pcg-random.org/index.html>
18#[cfg(feature = "pcg64")]
19pub mod pcg64;
20
21/// Implementation of the ChaCha CSPRNG algorithm.
22/// More details can be seen at <https://en.wikipedia.org/wiki/Salsa20>
23#[cfg(feature = "chacha")]
24pub mod chacha;
25
26/// A trait that represents a random number generator.
27pub trait Rng<const OUTPUT: usize>: Clone {
28	/// Generates a random sequence of bytes, seeding from the internal state.
29	fn rand(&mut self) -> [u8; OUTPUT];
30
31	/// Generates a random of the specified type, seeding from the internal state.
32	fn generate<Generated>(&mut self) -> Generated
33	where
34		Generated: RandomGen<Self, OUTPUT>,
35	{
36		Generated::random(self)
37	}
38
39	/// Fill an array of bytes with randomness.
40	fn fill_bytes<Bytes>(&mut self, mut buffer: Bytes)
41	where
42		Bytes: AsMut<[u8]>,
43	{
44		let mut buffer = buffer.as_mut();
45		let mut length = buffer.len();
46		while length > 0 {
47			let chunk = self.rand();
48			let generated = chunk.len().min(length);
49			buffer[..generated].copy_from_slice(&chunk[..generated]);
50			buffer = &mut buffer[generated..];
51			length -= generated;
52		}
53	}
54
55	/// Fill an array with the specified type.
56	fn fill<Contents, Array>(&mut self, mut target: Array)
57	where
58		Contents: RandomGen<Self, OUTPUT>,
59		Array: AsMut<[Contents]>,
60	{
61		let target = target.as_mut();
62		target.iter_mut().for_each(|entry| *entry = self.generate());
63	}
64
65	/// Generates a random of the specified type, seeding from the internal state.
66	fn generate_range<Number, Bounds>(&mut self, range: Bounds) -> Number
67	where
68		Number: RandomRange<Self, OUTPUT>,
69		Bounds: RangeBounds<Number>,
70	{
71		Number::random_range(self, range)
72	}
73
74	/// Shuffle a slice, using the RNG.
75	fn shuffle<Contents, Array>(&mut self, mut target: Array)
76	where
77		Array: AsMut<[Contents]>,
78	{
79		let target = target.as_mut();
80		let target_len = target.len();
81		for idx in (1..target_len).rev() {
82			let random_idx = self.generate_range(0..idx + 1);
83			target.swap(idx, random_idx);
84		}
85	}
86}
87
88/// A trait that represents an RNG that can be reseeded from arbitrary bytes.
89pub trait SeedableRng<const SEED_SIZE: usize, const OUTPUT: usize>: Rng<OUTPUT> {
90	/// Re-seed the RNG with the specified bytes.
91	fn reseed(&mut self, seed: [u8; SEED_SIZE]);
92}