• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
11 use rand_core::{impls, Error, RngCore};
12 
13 #[cfg(feature = "serde1")]
14 use 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))]
32 pub struct StepRng {
33     v: u64,
34     a: u64,
35 }
36 
37 impl StepRng {
38     /// Create a `StepRng`, yielding an arithmetic sequence starting with
39     /// `initial` and incremented by `increment` each time.
new(initial: u64, increment: u64) -> Self40     pub fn new(initial: u64, increment: u64) -> Self {
41         StepRng {
42             v: initial,
43             a: increment,
44         }
45     }
46 }
47 
48 impl RngCore for StepRng {
49     #[inline]
next_u32(&mut self) -> u3250     fn next_u32(&mut self) -> u32 {
51         self.next_u64() as u32
52     }
53 
54     #[inline]
next_u64(&mut self) -> u6455     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]
fill_bytes(&mut self, dest: &mut [u8])62     fn fill_bytes(&mut self, dest: &mut [u8]) {
63         impls::fill_bytes_via_next(self, dest);
64     }
65 
66     #[inline]
try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error>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)]
74 mod tests {
75     #[test]
76     #[cfg(feature = "serde1")]
test_serialization_step_rng()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