blueprint_std/
rand_helper.rs1use rand::RngCore;
2
3#[cfg(not(feature = "std"))]
4use rand::prelude::StdRng;
5
6pub use rand::{
7 self, CryptoRng, Rng,
8 distributions::{Distribution, Standard},
9};
10
11pub trait UniformRand: Sized {
13 fn rand<R: Rng + ?Sized>(rng: &mut R) -> Self;
14}
15
16impl<T> UniformRand for T
17where
18 Standard: Distribution<T>,
19{
20 #[inline]
21 fn rand<R: Rng + ?Sized>(rng: &mut R) -> Self {
22 rng.sample(Standard)
23 }
24}
25
26pub struct BlueprintRng(RngImpl);
28
29#[cfg(feature = "std")]
30type RngImpl = rand::rngs::OsRng;
31
32#[cfg(not(feature = "std"))]
33type RngImpl = StdRng;
34
35impl BlueprintRng {
36 #[must_use]
38 pub fn new() -> Self {
39 #[cfg(feature = "std")]
40 {
41 Self(rand::rngs::OsRng)
42 }
43 #[cfg(not(feature = "std"))]
44 {
45 test_rng()
46 }
47 }
48
49 #[must_use]
51 pub fn from_seed(seed: [u8; 32]) -> Self {
52 #[cfg(feature = "std")]
53 {
54 let _ = seed;
56 Self(rand::rngs::OsRng)
58 }
59 #[cfg(not(feature = "std"))]
60 {
61 use rand::SeedableRng;
62 Self(StdRng::from_seed(seed))
63 }
64 }
65}
66
67impl Default for BlueprintRng {
68 fn default() -> Self {
69 Self::new()
70 }
71}
72
73impl CryptoRng for BlueprintRng {}
74
75#[cfg(feature = "std")]
76impl RngCore for BlueprintRng {
77 fn next_u32(&mut self) -> u32 {
78 self.0.next_u32()
79 }
80 fn next_u64(&mut self) -> u64 {
81 self.0.next_u64()
82 }
83 fn fill_bytes(&mut self, dest: &mut [u8]) {
84 self.0.fill_bytes(dest);
85 }
86 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> {
87 self.0.try_fill_bytes(dest)
88 }
89}
90
91#[cfg(not(feature = "std"))]
92impl RngCore for BlueprintRng {
93 fn next_u32(&mut self) -> u32 {
94 self.0.r#gen()
95 }
96 fn next_u64(&mut self) -> u64 {
97 self.0.r#gen()
98 }
99 fn fill_bytes(&mut self, dest: &mut [u8]) {
100 self.0.fill_bytes(dest);
101 }
102 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> {
103 self.0.fill_bytes(dest);
104 Ok(())
105 }
106}
107
108#[must_use]
110pub fn test_rng() -> BlueprintRng {
111 const TEST_SEED: [u8; 32] = [
112 1, 0, 0, 0, 23, 0, 0, 0, 200, 1, 0, 0, 210, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
113 0, 0, 0, 0,
114 ];
115 BlueprintRng::from_seed(TEST_SEED)
116}
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121
122 #[test]
123 fn test_rng_generates_different_values() {
124 let mut rng = BlueprintRng::new();
125 assert_ne!(rng.next_u64(), rng.next_u64());
126 }
127
128 #[test]
129 fn test_deterministic_rng() {
130 #[cfg(not(feature = "std"))]
131 {
132 let mut rng1 = BlueprintRng::from_seed([1u8; 32]);
133 let mut rng2 = BlueprintRng::from_seed([1u8; 32]);
134 assert_eq!(rng1.next_u64(), rng2.next_u64());
135 }
136 }
137}