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)
57 }
58 #[cfg(not(feature = "std"))]
59 {
60 use rand::SeedableRng;
61 Self(StdRng::from_seed(seed))
62 }
63 }
64}
65
66impl Default for BlueprintRng {
67 fn default() -> Self {
68 Self::new()
69 }
70}
71
72impl CryptoRng for BlueprintRng {}
73
74#[cfg(feature = "std")]
75impl RngCore for BlueprintRng {
76 fn next_u32(&mut self) -> u32 {
77 self.0.next_u32()
78 }
79 fn next_u64(&mut self) -> u64 {
80 self.0.next_u64()
81 }
82 fn fill_bytes(&mut self, dest: &mut [u8]) {
83 self.0.fill_bytes(dest);
84 }
85 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> {
86 self.0.try_fill_bytes(dest)
87 }
88}
89
90#[cfg(not(feature = "std"))]
91impl RngCore for BlueprintRng {
92 fn next_u32(&mut self) -> u32 {
93 self.0.r#gen()
94 }
95 fn next_u64(&mut self) -> u64 {
96 self.0.r#gen()
97 }
98 fn fill_bytes(&mut self, dest: &mut [u8]) {
99 self.0.fill_bytes(dest);
100 }
101 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> {
102 self.0.fill_bytes(dest);
103 Ok(())
104 }
105}
106
107#[must_use]
109pub fn test_rng() -> BlueprintRng {
110 const TEST_SEED: [u8; 32] = [
111 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,
112 0, 0, 0, 0,
113 ];
114 BlueprintRng::from_seed(TEST_SEED)
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120
121 #[test]
122 fn test_rng_generates_different_values() {
123 let mut rng = BlueprintRng::new();
124 assert_ne!(rng.next_u64(), rng.next_u64());
125 }
126
127 #[test]
128 fn test_deterministic_rng() {
129 #[cfg(not(feature = "std"))]
130 {
131 let mut rng1 = BlueprintRng::from_seed([1u8; 32]);
132 let mut rng2 = BlueprintRng::from_seed([1u8; 32]);
133 assert_eq!(rng1.next_u64(), rng2.next_u64());
134 }
135 }
136}