(index<- ) ./libstd/rand/reseeding.rs
1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! A wrapper around another RNG that reseeds it after it
12 //! generates a certain number of random bytes.
13
14 use rand::{Rng, SeedableRng};
15 use default::Default;
16
17 /// How many bytes of entropy the underling RNG is allowed to generate
18 /// before it is reseeded.
19 static DEFAULT_GENERATION_THRESHOLD: uint = 32 * 1024;
20
21 /// A wrapper around any RNG which reseeds the underlying RNG after it
22 /// has generated a certain number of random bytes.
23 pub struct ReseedingRng<R, Rsdr> {
24 priv rng: R,
25 priv generation_threshold: uint,
26 priv bytes_generated: uint,
27 /// Controls the behaviour when reseeding the RNG.
28 reseeder: Rsdr
29 }
30
31 impl<R: Rng, Rsdr: Reseeder<R>> ReseedingRng<R, Rsdr> {
32 /// Create a new `ReseedingRng` with the given parameters.
33 ///
34 /// # Arguments
35 ///
36 /// * `rng`: the random number generator to use.
37 /// * `generation_threshold`: the number of bytes of entropy at which to reseed the RNG.
38 /// * `reseeder`: the reseeding object to use.
39 pub fn new(rng: R, generation_threshold: uint, reseeder: Rsdr) -> ReseedingRng<R,Rsdr> {
40 ReseedingRng {
41 rng: rng,
42 generation_threshold: generation_threshold,
43 bytes_generated: 0,
44 reseeder: reseeder
45 }
46 }
47
48 /// Reseed the internal RNG if the number of bytes that have been
49 /// generated exceed the threshold.
50 pub fn reseed_if_necessary(&mut self) {
51 if self.bytes_generated >= self.generation_threshold {
52 self.reseeder.reseed(&mut self.rng);
53 self.bytes_generated = 0;
54 }
55 }
56 }
57
58
59 impl<R: Rng, Rsdr: Reseeder<R>> Rng for ReseedingRng<R, Rsdr> {
60 fn next_u32(&mut self) -> u32 {
61 self.reseed_if_necessary();
62 self.bytes_generated += 4;
63 self.rng.next_u32()
64 }
65
66 fn next_u64(&mut self) -> u64 {
67 self.reseed_if_necessary();
68 self.bytes_generated += 8;
69 self.rng.next_u64()
70 }
71
72 fn fill_bytes(&mut self, dest: &mut [u8]) {
73 self.reseed_if_necessary();
74 self.bytes_generated += dest.len();
75 self.fill_bytes(dest)
76 }
77 }
78
79 impl<S, R: SeedableRng<S>, Rsdr: Reseeder<R>>
80 SeedableRng<(Rsdr, S)> for ReseedingRng<R, Rsdr> {
81 fn reseed(&mut self, (rsdr, seed): (Rsdr, S)) {
82 self.rng.reseed(seed);
83 self.reseeder = rsdr;
84 self.bytes_generated = 0;
85 }
86 /// Create a new `ReseedingRng` from the given reseeder and
87 /// seed. This uses a default value for `generation_threshold`.
88 fn from_seed((rsdr, seed): (Rsdr, S)) -> ReseedingRng<R, Rsdr> {
89 ReseedingRng {
90 rng: SeedableRng::from_seed(seed),
91 generation_threshold: DEFAULT_GENERATION_THRESHOLD,
92 bytes_generated: 0,
93 reseeder: rsdr
94 }
95 }
96 }
97
98 /// Something that can be used to reseed an RNG via `ReseedingRng`.
99 ///
100 /// # Example
101 ///
102 /// ```rust
103 /// use std::rand;
104 /// use std::rand::{Rng, SeedableRng};
105 /// use std::rand::reseeding::{Reseeder, ReseedingRng};
106 ///
107 /// struct TickTockReseeder { tick: bool }
108 /// impl Reseeder<rand::StdRng> for TickTockReseeder {
109 /// fn reseed(&mut self, rng: &mut rand::StdRng) {
110 /// let val = if self.tick {0} else {1};
111 /// rng.reseed(&[val]);
112 /// self.tick = !self.tick;
113 /// }
114 /// }
115 /// fn main() {
116 /// let rsdr = TickTockReseeder { tick: true };
117 /// let mut rng = ReseedingRng::new(rand::StdRng::new(), 10, rsdr);
118 ///
119 /// // this will repeat, because it gets reseeded very regularly.
120 /// println(rng.gen_ascii_str(100));
121 /// }
122 ///
123 /// ```
124 pub trait Reseeder<R> {
125 /// Reseed the given RNG.
126 fn reseed(&mut self, rng: &mut R);
127 }
128
129 /// Reseed an RNG using a `Default` instance. This reseeds by
130 /// replacing the RNG with the result of a `Default::default` call.
131 pub struct ReseedWithDefault;
132
133 impl<R: Rng + Default> Reseeder<R> for ReseedWithDefault {
134 fn reseed(&mut self, rng: &mut R) {
135 *rng = Default::default();
136 }
137 }
138 impl Default for ReseedWithDefault {
139 fn default() -> ReseedWithDefault { ReseedWithDefault }
140 }
141
142 #[cfg(test)]
143 mod test {
144 use super::*;
145 use rand::{SeedableRng, Rng};
146 use default::Default;
147 use iter::range;
148 use option::{None, Some};
149
150 struct Counter {
151 i: u32
152 }
153
154 impl Rng for Counter {
155 fn next_u32(&mut self) -> u32 {
156 self.i += 1;
157 // very random
158 self.i - 1
159 }
160 }
161 impl Default for Counter {
162 fn default() -> Counter {
163 Counter { i: 0 }
164 }
165 }
166 impl SeedableRng<u32> for Counter {
167 fn reseed(&mut self, seed: u32) {
168 self.i = seed;
169 }
170 fn from_seed(seed: u32) -> Counter {
171 Counter { i: seed }
172 }
173 }
174 type MyRng = ReseedingRng<Counter, ReseedWithDefault>;
175
176 #[test]
177 fn test_reseeding() {
178 let mut rs = ReseedingRng::new(Counter {i:0}, 400, ReseedWithDefault);
179
180 let mut i = 0;
181 for _ in range(0, 1000) {
182 assert_eq!(rs.next_u32(), i % 100);
183 i += 1;
184 }
185 }
186
187 #[test]
188 fn test_rng_seeded() {
189 let mut ra: MyRng = SeedableRng::from_seed((ReseedWithDefault, 2));
190 let mut rb: MyRng = SeedableRng::from_seed((ReseedWithDefault, 2));
191 assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
192 }
193
194 #[test]
195 fn test_rng_reseed() {
196 let mut r: MyRng = SeedableRng::from_seed((ReseedWithDefault, 3));
197 let string1 = r.gen_ascii_str(100);
198
199 r.reseed((ReseedWithDefault, 3));
200
201 let string2 = r.gen_ascii_str(100);
202 assert_eq!(string1, string2);
203 }
204 }
libstd/rand/reseeding.rs:22:52-22:52 -struct- definition:
/// has generated a certain number of random bytes.
pub struct ReseedingRng<R, Rsdr> {
references:-88: fn from_seed((rsdr, seed): (Rsdr, S)) -> ReseedingRng<R, Rsdr> {
40: ReseedingRng {
39: pub fn new(rng: R, generation_threshold: uint, reseeder: Rsdr) -> ReseedingRng<R,Rsdr> {
59: impl<R: Rng, Rsdr: Reseeder<R>> Rng for ReseedingRng<R, Rsdr> {
31: impl<R: Rng, Rsdr: Reseeder<R>> ReseedingRng<R, Rsdr> {
89: ReseedingRng {
80: SeedableRng<(Rsdr, S)> for ReseedingRng<R, Rsdr> {
libstd/rand/mod.rs:
679: pub type TaskRng = reseeding::ReseedingRng<StdRng, TaskRngReseeder>;
libstd/rand/reseeding.rs:123:8-123:8 -trait- definition:
/// ```
pub trait Reseeder<R> {
references:-31: impl<R: Rng, Rsdr: Reseeder<R>> ReseedingRng<R, Rsdr> {
79: impl<S, R: SeedableRng<S>, Rsdr: Reseeder<R>>
59: impl<R: Rng, Rsdr: Reseeder<R>> Rng for ReseedingRng<R, Rsdr> {
133: impl<R: Rng + Default> Reseeder<R> for ReseedWithDefault {
libstd/rand/mod.rs:
672: impl reseeding::Reseeder<StdRng> for TaskRngReseeder {
libstd/rand/reseeding.rs:130:68-130:68 -struct- definition:
/// replacing the RNG with the result of a `Default::default` call.
pub struct ReseedWithDefault;
references:-139: fn default() -> ReseedWithDefault { ReseedWithDefault }
138: impl Default for ReseedWithDefault {
133: impl<R: Rng + Default> Reseeder<R> for ReseedWithDefault {