1use parking_lot::Mutex;
22use rand::Rng as _;
23
24pub trait Rng: Send + Sync {
29 fn gen_usize(&self, max: usize) -> usize;
31
32 fn gen_i32(&self) -> i32;
34
35 fn gen_u32(&self) -> u32;
37
38 fn gen_u64(&self) -> u64;
40
41 fn gen_bytes(&self, len: usize) -> Vec<u8>;
43}
44
45#[derive(Debug, Clone, Copy, Default)]
49pub struct ThreadRng;
50
51impl Rng for ThreadRng {
52 fn gen_usize(&self, max: usize) -> usize {
53 if max == 0 {
54 return 0;
55 }
56 rand::rng().random_range(0..max)
57 }
58
59 fn gen_i32(&self) -> i32 {
60 rand::rng().random::<i32>()
61 }
62
63 fn gen_u32(&self) -> u32 {
64 rand::rng().random::<u32>()
65 }
66
67 fn gen_u64(&self) -> u64 {
68 rand::rng().random::<u64>()
69 }
70
71 fn gen_bytes(&self, len: usize) -> Vec<u8> {
72 let mut bytes = vec![0u8; len];
73 rand::RngCore::fill_bytes(&mut rand::rng(), &mut bytes[..]);
74 bytes
75 }
76}
77
78impl steam_cm_provider::CmRng for ThreadRng {
79 fn gen_u32(&self) -> u32 {
80 rand::rng().random::<u32>()
81 }
82
83 fn gen_usize(&self, max: usize) -> usize {
84 if max == 0 {
85 return 0;
86 }
87 rand::rng().random_range(0..max)
88 }
89}
90
91#[derive(Debug)]
111pub struct MockRng {
112 usize_value: Mutex<usize>,
113 i32_value: Mutex<i32>,
114 u32_value: Mutex<u32>,
115 u64_value: Mutex<u64>,
116 bytes_value: Mutex<Vec<u8>>,
117}
118
119impl MockRng {
120 pub fn new() -> Self {
122 Self {
123 usize_value: Mutex::new(0),
124 i32_value: Mutex::new(0),
125 u32_value: Mutex::new(0),
126 u64_value: Mutex::new(0),
127 bytes_value: Mutex::new(Vec::new()),
128 }
129 }
130
131 pub fn with_values(usize_val: usize, i32_val: i32, u32_val: u32) -> Self {
133 Self::with_all_values(usize_val, i32_val, u32_val, 0, Vec::new())
134 }
135
136 pub fn with_all_values(usize_val: usize, i32_val: i32, u32_val: u32, u64_val: u64, bytes_val: Vec<u8>) -> Self {
138 Self {
139 usize_value: Mutex::new(usize_val),
140 i32_value: Mutex::new(i32_val),
141 u32_value: Mutex::new(u32_val),
142 u64_value: Mutex::new(u64_val),
143 bytes_value: Mutex::new(bytes_val),
144 }
145 }
146
147 pub fn set_usize(&self, value: usize) {
149 *self.usize_value.lock() = value;
150 }
151
152 pub fn set_i32(&self, value: i32) {
154 *self.i32_value.lock() = value;
155 }
156
157 pub fn set_u32(&self, value: u32) {
159 *self.u32_value.lock() = value;
160 }
161
162 pub fn set_u64(&self, value: u64) {
164 *self.u64_value.lock() = value;
165 }
166
167 pub fn set_bytes(&self, value: Vec<u8>) {
169 *self.bytes_value.lock() = value;
170 }
171
172 pub fn current_usize(&self) -> usize {
174 *self.usize_value.lock()
175 }
176
177 pub fn current_i32(&self) -> i32 {
179 *self.i32_value.lock()
180 }
181
182 pub fn current_u32(&self) -> u32 {
184 *self.u32_value.lock()
185 }
186
187 pub fn current_u64(&self) -> u64 {
189 *self.u64_value.lock()
190 }
191
192 pub fn current_bytes(&self) -> Vec<u8> {
194 self.bytes_value.lock().clone()
195 }
196}
197
198impl Default for MockRng {
199 fn default() -> Self {
200 Self::new()
201 }
202}
203
204impl Rng for MockRng {
205 fn gen_usize(&self, _max: usize) -> usize {
206 *self.usize_value.lock()
207 }
208
209 fn gen_i32(&self) -> i32 {
210 *self.i32_value.lock()
211 }
212
213 fn gen_u32(&self) -> u32 {
214 *self.u32_value.lock()
215 }
216
217 fn gen_u64(&self) -> u64 {
218 *self.u64_value.lock()
219 }
220
221 fn gen_bytes(&self, len: usize) -> Vec<u8> {
222 let val = self.bytes_value.lock();
223 if val.is_empty() {
224 vec![0; len]
225 } else {
226 let mut result = val.clone();
228 result.resize(len, 0);
229 result
230 }
231 }
232}
233
234impl steam_cm_provider::CmRng for MockRng {
235 fn gen_u32(&self) -> u32 {
236 *self.u32_value.lock()
237 }
238
239 fn gen_usize(&self, _max: usize) -> usize {
240 *self.usize_value.lock()
241 }
242}
243
244#[cfg(test)]
245mod tests {
246 use super::*;
247
248 #[test]
249 fn test_thread_rng_gen_usize() {
250 let rng = ThreadRng;
251 for _ in 0..100 {
253 let value = rng.gen_usize(10);
254 assert!(value < 10);
255 }
256 }
257
258 #[test]
259 fn test_thread_rng_gen_usize_zero_max() {
260 let rng = ThreadRng;
261 assert_eq!(rng.gen_usize(0), 0);
262 }
263
264 #[test]
265 fn test_mock_rng_default_values() {
266 let mock = MockRng::new();
267 assert_eq!(mock.gen_usize(100), 0);
268 assert_eq!(mock.gen_i32(), 0);
269 assert_eq!(mock.gen_u32(), 0);
270 }
271
272 #[test]
273 fn test_mock_rng_with_values() {
274 let mock = MockRng::with_values(42, -123, 456);
275 assert_eq!(mock.gen_usize(100), 42);
276 assert_eq!(mock.gen_i32(), -123);
277 assert_eq!(mock.gen_u32(), 456);
278 }
279
280 #[test]
281 fn test_mock_rng_set_values() {
282 let mock = MockRng::new();
283
284 mock.set_usize(100);
285 assert_eq!(mock.gen_usize(1000), 100);
286
287 mock.set_i32(-999);
288 assert_eq!(mock.gen_i32(), -999);
289
290 mock.set_u32(12345);
291 assert_eq!(mock.gen_u32(), 12345);
292 }
293
294 #[test]
295 fn test_mock_rng_ignores_max() {
296 let mock = MockRng::new();
297 mock.set_usize(50);
298
299 assert_eq!(mock.gen_usize(10), 50);
302 assert_eq!(mock.gen_usize(100), 50);
303 assert_eq!(mock.gen_usize(1000), 50);
304 }
305
306 #[test]
307 fn test_mock_rng_current_values() {
308 let mock = MockRng::with_values(1, 2, 3);
309
310 assert_eq!(mock.current_usize(), 1);
311 assert_eq!(mock.current_i32(), 2);
312 assert_eq!(mock.current_u32(), 3);
313
314 mock.set_usize(10);
315 assert_eq!(mock.current_usize(), 10);
316 }
317
318 #[test]
319 fn test_thread_rng_gen_bytes() {
320 let rng = ThreadRng;
321 let bytes = rng.gen_bytes(10);
322 assert_eq!(bytes.len(), 10);
323 }
324
325 #[test]
326 fn test_mock_rng_bytes() {
327 let mock = MockRng::new();
328
329 let bytes = mock.gen_bytes(5);
331 assert_eq!(bytes, vec![0, 0, 0, 0, 0]);
332
333 let test_bytes = vec![1, 2, 3, 4, 5];
335 mock.set_bytes(test_bytes.clone());
336 assert_eq!(mock.gen_bytes(5), test_bytes);
337 assert_eq!(mock.current_bytes(), test_bytes);
338
339 assert_eq!(mock.gen_bytes(3), vec![1, 2, 3]);
341 assert_eq!(mock.gen_bytes(7), vec![1, 2, 3, 4, 5, 0, 0]);
342 }
343}