1#![doc = include_str!("../README.md")]
2
3#[cfg(feature = "rand-v09")]
4pub use rand;
5
6use rand_chacha::ChaCha8Rng;
7use rand_core::{CryptoRng, OsRng, RngCore, SeedableRng, TryRngCore};
8
9#[derive(Debug, Clone)]
11pub struct DevRng(ChaCha8Rng);
12
13impl DevRng {
14 const VAR_NAME: &'static str = "RUST_TESTS_SEED";
15
16 #[track_caller]
23 pub fn new() -> Self {
24 let mut seed = [0u8; 32];
25 match std::env::var(Self::VAR_NAME) {
26 Ok(provided_seed) => const_hex::decode_to_slice(provided_seed, &mut seed)
27 .expect("provided seed is not valid"),
28 Err(std::env::VarError::NotUnicode(_)) => {
29 panic!("provided seed is not a valid unicode")
30 }
31 Err(std::env::VarError::NotPresent) => OsRng
32 .try_fill_bytes(&mut seed)
33 .expect("system randomness unavailable"),
34 }
35 eprintln!("RUST_TESTS_SEED={}", const_hex::encode(seed));
36
37 DevRng(ChaCha8Rng::from_seed(seed))
38 }
39
40 pub fn fork(&mut self) -> Self {
47 let mut seed = [0u8; 32];
48 self.fill_bytes(&mut seed);
49 Self::from_seed(seed)
50 }
51
52 pub fn get_seed(&self) -> [u8; 32] {
54 self.0.get_seed()
55 }
56}
57
58impl Default for DevRng {
59 fn default() -> Self {
60 Self::new()
61 }
62}
63
64impl RngCore for DevRng {
65 fn next_u32(&mut self) -> u32 {
66 self.0.next_u32()
67 }
68
69 fn next_u64(&mut self) -> u64 {
70 self.0.next_u64()
71 }
72
73 fn fill_bytes(&mut self, dest: &mut [u8]) {
74 self.0.fill_bytes(dest)
75 }
76}
77
78impl SeedableRng for DevRng {
79 type Seed = <ChaCha8Rng as SeedableRng>::Seed;
80
81 fn from_seed(seed: Self::Seed) -> Self {
82 DevRng(ChaCha8Rng::from_seed(seed))
83 }
84
85 fn seed_from_u64(state: u64) -> Self {
86 DevRng(ChaCha8Rng::seed_from_u64(state))
87 }
88
89 fn from_rng(rng: &mut impl RngCore) -> Self {
90 Self(ChaCha8Rng::from_rng(rng))
91 }
92
93 fn try_from_rng<R: TryRngCore>(rng: &mut R) -> Result<Self, R::Error> {
94 ChaCha8Rng::try_from_rng(rng).map(Self)
95 }
96
97 fn from_os_rng() -> Self {
98 Self(ChaCha8Rng::from_os_rng())
99 }
100
101 fn try_from_os_rng() -> Result<Self, getrandom::Error> {
102 ChaCha8Rng::try_from_os_rng().map(Self)
103 }
104}
105
106impl CryptoRng for DevRng {}