rand/rngs/
mock.rs

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}