1use std::sync::Arc;
2
3use parking_lot::RwLock;
4use rand::distributions::{Alphanumeric, Standard};
5use rand::prelude::Distribution;
6use rand::{Rng, SeedableRng};
7use rand_chacha::ChaCha12Rng;
8
9use crate::Seed;
10
11#[derive(Debug)]
12#[must_use]
13pub struct Random {
15 rng: Arc<RwLock<ChaCha12Rng>>,
16}
17
18#[must_use]
19#[cfg(feature = "std")]
20pub(crate) fn new_seed() -> Seed {
21 let mut rng = rand::thread_rng();
22 Seed(rng.gen())
23}
24
25impl Random {
26 #[cfg(feature = "std")]
28 pub fn new() -> Self {
29 Self::from_seed(new_seed())
30 }
31
32 #[allow(clippy::needless_pass_by_value)]
35 pub fn from_seed(seed: Seed) -> Self {
37 let rng = ChaCha12Rng::seed_from_u64(seed.0);
38 Self {
39 rng: Arc::new(RwLock::new(rng)),
40 }
41 }
42
43 pub fn seed(&self) -> Seed {
45 Seed(self.gen())
46 }
47
48 #[must_use]
49 pub fn gen<T>(&self) -> T
51 where
52 Standard: Distribution<T>,
53 {
54 let mut rng = self.rng.write();
55 rng.gen()
56 }
57
58 pub fn u32(&self) -> u32 {
60 self.gen()
61 }
62
63 pub fn i32(&self) -> i32 {
65 self.gen()
66 }
67
68 pub fn bytes(&self, length: usize) -> Vec<u8> {
70 let mut bytes: Vec<u8> = Vec::with_capacity(length);
71 let mut rng = self.rng.write();
72 for _ in 0..length {
73 bytes.push(rng.gen());
74 }
75 bytes
76 }
77
78 pub fn string(&self, length: usize) -> String {
80 let mut string: String = String::with_capacity(length);
81 let mut rng = self.rng.write();
82
83 for _ in 0..length {
84 string.push(rng.gen());
85 }
86 string
87 }
88
89 pub fn alphanumeric(&self, length: usize) -> String {
91 let mut rng = self.rng.write();
92 let chars: String = std::iter::repeat(())
93 .map(|()| rng.sample(Alphanumeric))
94 .map(char::from)
95 .take(length)
96 .collect();
97 chars
98 }
99
100 #[cfg(feature = "uuid")]
102 pub fn uuid(&self) -> uuid::Uuid {
103 let mut raw_bytes: [u8; 16] = [0; 16];
104 let mut rng = self.rng.write();
105 rng.fill(&mut raw_bytes);
106 let bytes: uuid::Bytes = raw_bytes;
107 let builder = uuid::Builder::from_bytes(bytes);
108 builder.into_uuid()
109 }
110
111 pub fn range(&self, min: u32, max: u32) -> u32 {
113 let mut rng = self.rng.write();
114 rng.gen_range(min..max)
115 }
116}
117
118#[cfg(feature = "std")]
119impl Default for Random {
120 fn default() -> Self {
121 Self::new()
122 }
123}
124
125#[cfg(test)]
126mod tests {
127 use super::*;
128
129 #[test]
130 fn bytes() {
131 let rng = Random::from_seed(Seed(100000));
132 let bytes1 = rng.bytes(10);
133 let bytes2 = rng.bytes(10);
134 assert_ne!(bytes1, bytes2);
135 let rng = Random::from_seed(Seed(100000));
136 let bytes2 = rng.bytes(10);
137 assert_eq!(bytes1, bytes2);
138 }
139 #[test]
140 fn string() {
141 let rng = Random::from_seed(Seed(100000));
142 let v1 = rng.string(10);
143 let v2 = rng.string(10);
144 assert_ne!(v1, v2);
145 let rng = Random::from_seed(Seed(100000));
146 let v2 = rng.string(10);
147 assert_eq!(v1, v2);
148 }
149
150 #[test]
151 fn alphanum() {
152 let rng = Random::from_seed(Seed(100000));
153 let v1 = rng.alphanumeric(10);
154 let v2 = rng.alphanumeric(10);
155 assert_ne!(v1, v2);
156 let rng = Random::from_seed(Seed(100000));
157 let v2 = rng.alphanumeric(10);
158 assert_eq!(v1, v2);
159 }
160
161 #[test]
162 #[cfg(feature = "uuid")]
163 fn uuid() {
164 let rng = Random::from_seed(Seed(100000));
165 let v1 = rng.uuid();
166 let v2 = rng.uuid();
167 assert_ne!(v1, v2);
168 let rng = Random::from_seed(Seed(100000));
169 let v2 = rng.uuid();
170 assert_eq!(v1, v2);
171 }
172}