| // Copyright 2013 The Rust Project Developers. See the COPYRIGHT | 
 | // file at the top-level directory of this distribution and at | 
 | // http://rust-lang.org/COPYRIGHT. | 
 | // | 
 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | 
 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | 
 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | 
 | // option. This file may not be copied, modified, or distributed | 
 | // except according to those terms. | 
 |  | 
 | //! A wrapper around another RNG that reseeds it after it | 
 | //! generates a certain number of random bytes. | 
 |  | 
 | use core::default::Default; | 
 |  | 
 | use {Rng, SeedableRng}; | 
 |  | 
 | /// How many bytes of entropy the underling RNG is allowed to generate | 
 | /// before it is reseeded | 
 | const DEFAULT_GENERATION_THRESHOLD: u64 = 32 * 1024; | 
 |  | 
 | /// A wrapper around any RNG which reseeds the underlying RNG after it | 
 | /// has generated a certain number of random bytes. | 
 | #[derive(Debug)] | 
 | pub struct ReseedingRng<R, Rsdr> { | 
 |     rng: R, | 
 |     generation_threshold: u64, | 
 |     bytes_generated: u64, | 
 |     /// Controls the behaviour when reseeding the RNG. | 
 |     pub reseeder: Rsdr, | 
 | } | 
 |  | 
 | impl<R: Rng, Rsdr: Reseeder<R>> ReseedingRng<R, Rsdr> { | 
 |     /// Create a new `ReseedingRng` with the given parameters. | 
 |     /// | 
 |     /// # Arguments | 
 |     /// | 
 |     /// * `rng`: the random number generator to use. | 
 |     /// * `generation_threshold`: the number of bytes of entropy at which to reseed the RNG. | 
 |     /// * `reseeder`: the reseeding object to use. | 
 |     pub fn new(rng: R, generation_threshold: u64, reseeder: Rsdr) -> ReseedingRng<R,Rsdr> { | 
 |         ReseedingRng { | 
 |             rng: rng, | 
 |             generation_threshold: generation_threshold, | 
 |             bytes_generated: 0, | 
 |             reseeder: reseeder | 
 |         } | 
 |     } | 
 |  | 
 |     /// Reseed the internal RNG if the number of bytes that have been | 
 |     /// generated exceed the threshold. | 
 |     pub fn reseed_if_necessary(&mut self) { | 
 |         if self.bytes_generated >= self.generation_threshold { | 
 |             self.reseeder.reseed(&mut self.rng); | 
 |             self.bytes_generated = 0; | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 |  | 
 | impl<R: Rng, Rsdr: Reseeder<R>> Rng for ReseedingRng<R, Rsdr> { | 
 |     fn next_u32(&mut self) -> u32 { | 
 |         self.reseed_if_necessary(); | 
 |         self.bytes_generated += 4; | 
 |         self.rng.next_u32() | 
 |     } | 
 |  | 
 |     fn next_u64(&mut self) -> u64 { | 
 |         self.reseed_if_necessary(); | 
 |         self.bytes_generated += 8; | 
 |         self.rng.next_u64() | 
 |     } | 
 |  | 
 |     fn fill_bytes(&mut self, dest: &mut [u8]) { | 
 |         self.reseed_if_necessary(); | 
 |         self.bytes_generated += dest.len() as u64; | 
 |         self.rng.fill_bytes(dest) | 
 |     } | 
 | } | 
 |  | 
 | impl<S, R: SeedableRng<S>, Rsdr: Reseeder<R> + Default> | 
 |      SeedableRng<(Rsdr, S)> for ReseedingRng<R, Rsdr> { | 
 |     fn reseed(&mut self, (rsdr, seed): (Rsdr, S)) { | 
 |         self.rng.reseed(seed); | 
 |         self.reseeder = rsdr; | 
 |         self.bytes_generated = 0; | 
 |     } | 
 |  | 
 |     /// Create a new `ReseedingRng` from the given reseeder and | 
 |     /// seed. This uses a default value for `generation_threshold`. | 
 |     fn from_seed((rsdr, seed): (Rsdr, S)) -> ReseedingRng<R, Rsdr> { | 
 |         ReseedingRng { | 
 |             rng: SeedableRng::from_seed(seed), | 
 |             generation_threshold: DEFAULT_GENERATION_THRESHOLD, | 
 |             bytes_generated: 0, | 
 |             reseeder: rsdr | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | /// Something that can be used to reseed an RNG via `ReseedingRng`. | 
 | /// | 
 | /// # Example | 
 | /// | 
 | /// ```rust | 
 | /// use rand::{Rng, SeedableRng, StdRng}; | 
 | /// use rand::reseeding::{Reseeder, ReseedingRng}; | 
 | /// | 
 | /// struct TickTockReseeder { tick: bool } | 
 | /// impl Reseeder<StdRng> for TickTockReseeder { | 
 | ///     fn reseed(&mut self, rng: &mut StdRng) { | 
 | ///         let val = if self.tick {0} else {1}; | 
 | ///         rng.reseed(&[val]); | 
 | ///         self.tick = !self.tick; | 
 | ///     } | 
 | /// } | 
 | /// fn main() { | 
 | ///     let rsdr = TickTockReseeder { tick: true }; | 
 | /// | 
 | ///     let inner = StdRng::new().unwrap(); | 
 | ///     let mut rng = ReseedingRng::new(inner, 10, rsdr); | 
 | /// | 
 | ///     // this will repeat, because it gets reseeded very regularly. | 
 | ///     let s: String = rng.gen_ascii_chars().take(100).collect(); | 
 | ///     println!("{}", s); | 
 | /// } | 
 | /// | 
 | /// ``` | 
 | pub trait Reseeder<R> { | 
 |     /// Reseed the given RNG. | 
 |     fn reseed(&mut self, rng: &mut R); | 
 | } | 
 |  | 
 | /// Reseed an RNG using a `Default` instance. This reseeds by | 
 | /// replacing the RNG with the result of a `Default::default` call. | 
 | #[derive(Clone, Copy, Debug)] | 
 | pub struct ReseedWithDefault; | 
 |  | 
 | impl<R: Rng + Default> Reseeder<R> for ReseedWithDefault { | 
 |     fn reseed(&mut self, rng: &mut R) { | 
 |         *rng = Default::default(); | 
 |     } | 
 | } | 
 | impl Default for ReseedWithDefault { | 
 |     fn default() -> ReseedWithDefault { ReseedWithDefault } | 
 | } | 
 |  | 
 | #[cfg(test)] | 
 | mod test { | 
 |     use std::default::Default; | 
 |     use std::iter::repeat; | 
 |     use super::{ReseedingRng, ReseedWithDefault}; | 
 |     use {SeedableRng, Rng}; | 
 |  | 
 |     struct Counter { | 
 |         i: u32 | 
 |     } | 
 |  | 
 |     impl Rng for Counter { | 
 |         fn next_u32(&mut self) -> u32 { | 
 |             self.i += 1; | 
 |             // very random | 
 |             self.i - 1 | 
 |         } | 
 |     } | 
 |     impl Default for Counter { | 
 |         fn default() -> Counter { | 
 |             Counter { i: 0 } | 
 |         } | 
 |     } | 
 |     impl SeedableRng<u32> for Counter { | 
 |         fn reseed(&mut self, seed: u32) { | 
 |             self.i = seed; | 
 |         } | 
 |         fn from_seed(seed: u32) -> Counter { | 
 |             Counter { i: seed } | 
 |         } | 
 |     } | 
 |     type MyRng = ReseedingRng<Counter, ReseedWithDefault>; | 
 |  | 
 |     #[test] | 
 |     fn test_reseeding() { | 
 |         let mut rs = ReseedingRng::new(Counter {i:0}, 400, ReseedWithDefault); | 
 |  | 
 |         let mut i = 0; | 
 |         for _ in 0..1000 { | 
 |             assert_eq!(rs.next_u32(), i % 100); | 
 |             i += 1; | 
 |         } | 
 |     } | 
 |  | 
 |     #[test] | 
 |     fn test_rng_seeded() { | 
 |         let mut ra: MyRng = SeedableRng::from_seed((ReseedWithDefault, 2)); | 
 |         let mut rb: MyRng = SeedableRng::from_seed((ReseedWithDefault, 2)); | 
 |         assert!(::test::iter_eq(ra.gen_ascii_chars().take(100), | 
 |                                 rb.gen_ascii_chars().take(100))); | 
 |     } | 
 |  | 
 |     #[test] | 
 |     fn test_rng_reseed() { | 
 |         let mut r: MyRng = SeedableRng::from_seed((ReseedWithDefault, 3)); | 
 |         let string1: String = r.gen_ascii_chars().take(100).collect(); | 
 |  | 
 |         r.reseed((ReseedWithDefault, 3)); | 
 |  | 
 |         let string2: String = r.gen_ascii_chars().take(100).collect(); | 
 |         assert_eq!(string1, string2); | 
 |     } | 
 |  | 
 |     const FILL_BYTES_V_LEN: usize = 13579; | 
 |     #[test] | 
 |     fn test_rng_fill_bytes() { | 
 |         let mut v = repeat(0u8).take(FILL_BYTES_V_LEN).collect::<Vec<_>>(); | 
 |         ::test::rng().fill_bytes(&mut v); | 
 |  | 
 |         // Sanity test: if we've gotten here, `fill_bytes` has not infinitely | 
 |         // recursed. | 
 |         assert_eq!(v.len(), FILL_BYTES_V_LEN); | 
 |  | 
 |         // To test that `fill_bytes` actually did something, check that the | 
 |         // average of `v` is not 0. | 
 |         let mut sum = 0.0; | 
 |         for &x in v.iter() { | 
 |             sum += x as f64; | 
 |         } | 
 |         assert!(sum / v.len() as f64 != 0.0); | 
 |     } | 
 | } |