1// Copyright 2018 Developers of the Rand project.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! Mock random number generator
10
11use rand_core::{impls, Error, RngCore};
12
13#[cfg(feature = "serde1")]
14use serde::{Serialize, Deserialize};
15
16/// A simple implementation of `RngCore` for testing purposes.
17///
18/// This generates an arithmetic sequence (i.e. adds a constant each step)
19/// over a `u64` number, using wrapping arithmetic. If the increment is 0
20/// the generator yields a constant.
21///
22/// ```
23/// use rand::Rng;
24/// use rand::rngs::mock::StepRng;
25///
26/// let mut my_rng = StepRng::new(2, 1);
27/// let sample: [u64; 3] = my_rng.gen();
28/// assert_eq!(sample, [2, 3, 4]);
29/// ```
30#[derive(Debug, Clone, PartialEq, Eq)]
31#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
32pub struct StepRng {
33 v: u64,
34 a: u64,
35}
36
37impl StepRng {
38 /// Create a `StepRng`, yielding an arithmetic sequence starting with
39 /// `initial` and incremented by `increment` each time.
40 pub fn new(initial: u64, increment: u64) -> Self {
41 StepRng {
42 v: initial,
43 a: increment,
44 }
45 }
46}
47
48impl RngCore for StepRng {
49 #[inline]
50 fn next_u32(&mut self) -> u32 {
51 self.next_u64() as u32
52 }
53
54 #[inline]
55 fn next_u64(&mut self) -> u64 {
56 let result = self.v;
57 self.v = self.v.wrapping_add(self.a);
58 result
59 }
60
61 #[inline]
62 fn fill_bytes(&mut self, dest: &mut [u8]) {
63 impls::fill_bytes_via_next(self, dest);
64 }
65
66 #[inline]
67 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
68 self.fill_bytes(dest);
69 Ok(())
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 #[test]
76 #[cfg(feature = "serde1")]
77 fn test_serialization_step_rng() {
78 use super::StepRng;
79
80 let some_rng = StepRng::new(42, 7);
81 let de_some_rng: StepRng =
82 bincode::deserialize(&bincode::serialize(&some_rng).unwrap()).unwrap();
83 assert_eq!(some_rng.v, de_some_rng.v);
84 assert_eq!(some_rng.a, de_some_rng.a);
85
86 }
87}
88