(index<- )        ./librand/reseeding.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Wed Apr  9 17:27:02 2014
   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 std::default::Default;
  15  use {Rng, SeedableRng};
  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      rng: R,
  25      generation_threshold: uint,
  26      bytes_generated: uint,
  27      /// Controls the behaviour when reseeding the RNG.
  28      pub 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(rngR, generation_thresholduint, reseederRsdr) -> 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.rng.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 rand::{Rng, SeedableRng, StdRng};
 104  /// use rand::reseeding::{Reseeder, ReseedingRng};
 105  ///
 106  /// struct TickTockReseeder { tick: bool }
 107  /// impl Reseeder<StdRng> for TickTockReseeder {
 108  ///     fn reseed(&mut self, rng: &mut StdRng) {
 109  ///         let val = if self.tick {0} else {1};
 110  ///         rng.reseed(&[val]);
 111  ///         self.tick = !self.tick;
 112  ///     }
 113  /// }
 114  /// fn main() {
 115  ///     let rsdr = TickTockReseeder { tick: true };
 116  ///
 117  ///     let inner = StdRng::new().unwrap();
 118  ///     let mut rng = ReseedingRng::new(inner, 10, rsdr);
 119  ///
 120  ///     // this will repeat, because it gets reseeded very regularly.
 121  ///     println!("{}", rng.gen_ascii_str(100));
 122  /// }
 123  ///
 124  /// ```
 125  pub trait Reseeder<R> {
 126      /// Reseed the given RNG.
 127      fn reseed(&mut self, rng: &mut R);
 128  }
 129  
 130  /// Reseed an RNG using a `Default` instance. This reseeds by
 131  /// replacing the RNG with the result of a `Default::default` call.
 132  pub struct ReseedWithDefault;
 133  
 134  impl<R: Rng + Default> Reseeder<R> for ReseedWithDefault {
 135      fn reseed(&mut self, rng&mut R) {
 136          *rng = Default::default();
 137      }
 138  }
 139  impl Default for ReseedWithDefault {
 140      fn default() -> ReseedWithDefault { ReseedWithDefault }
 141  }
 142  
 143  #[cfg(test)]
 144  mod test {
 145      use super::{ReseedingRng, ReseedWithDefault};
 146      use std::default::Default;
 147      use {SeedableRng, Rng};
 148  
 149      struct Counter {
 150          i: u32
 151      }
 152  
 153      impl Rng for Counter {
 154          fn next_u32(&mut self) -> u32 {
 155              self.i += 1;
 156              // very random
 157              self.i - 1
 158          }
 159      }
 160      impl Default for Counter {
 161          fn default() -> Counter {
 162              Counter { i: 0 }
 163          }
 164      }
 165      impl SeedableRng<u32> for Counter {
 166          fn reseed(&mut self, seed: u32) {
 167              self.i = seed;
 168          }
 169          fn from_seed(seed: u32) -> Counter {
 170              Counter { i: seed }
 171          }
 172      }
 173      type MyRng = ReseedingRng<Counter, ReseedWithDefault>;
 174  
 175      #[test]
 176      fn test_reseeding() {
 177          let mut rs = ReseedingRng::new(Counter {i:0}, 400, ReseedWithDefault);
 178  
 179          let mut i = 0;
 180          for _ in range(0, 1000) {
 181              assert_eq!(rs.next_u32(), i % 100);
 182              i += 1;
 183          }
 184      }
 185  
 186      #[test]
 187      fn test_rng_seeded() {
 188          let mut ra: MyRng = SeedableRng::from_seed((ReseedWithDefault, 2));
 189          let mut rb: MyRng = SeedableRng::from_seed((ReseedWithDefault, 2));
 190          assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
 191      }
 192  
 193      #[test]
 194      fn test_rng_reseed() {
 195          let mut r: MyRng = SeedableRng::from_seed((ReseedWithDefault, 3));
 196          let string1 = r.gen_ascii_str(100);
 197  
 198          r.reseed((ReseedWithDefault, 3));
 199  
 200          let string2 = r.gen_ascii_str(100);
 201          assert_eq!(string1, string2);
 202      }
 203  
 204      static fill_bytes_v_len: uint = 13579;
 205      #[test]
 206      fn test_rng_fill_bytes() {
 207          use task_rng;
 208          let mut v = Vec::from_elem(fill_bytes_v_len, 0u8);
 209          task_rng().fill_bytes(v.as_mut_slice());
 210  
 211          // Sanity test: if we've gotten here, `fill_bytes` has not infinitely
 212          // recursed.
 213          assert_eq!(v.len(), fill_bytes_v_len);
 214  
 215          // To test that `fill_bytes` actually did something, check that the
 216          // average of `v` is not 0.
 217          let mut sum = 0.0;
 218          for &x in v.iter() {
 219              sum += x as f64;
 220          }
 221          assert!(sum / v.len() as f64 != 0.0);
 222      }
 223  }


librand/reseeding.rs:22:52-22:52 -struct- definition:
/// has generated a certain number of random bytes.
pub struct ReseedingRng<R, Rsdr> {
    rng: R,
references:- 8
39:     pub fn new(rng: R, generation_threshold: uint, reseeder: Rsdr) -> ReseedingRng<R,Rsdr> {
40:         ReseedingRng {
41:             rng: rng,
--
88:     fn from_seed((rsdr, seed): (Rsdr, S)) -> ReseedingRng<R, Rsdr> {
89:         ReseedingRng {
90:             rng: SeedableRng::from_seed(seed),
librand/lib.rs:
566: static TASK_RNG_RESEED_THRESHOLD: uint = 32_768;
567: type TaskRngInner = reseeding::ReseedingRng<StdRng, TaskRngReseeder>;
568: /// The task-local RNG.
librand/reseeding.rs:
38:     /// * `reseeder`: the reseeding object to use.
39:     pub fn new(rng: R, generation_threshold: uint, reseeder: Rsdr) -> ReseedingRng<R,Rsdr> {
40:         ReseedingRng {


librand/reseeding.rs:124:8-124:8 -trait- definition:
/// ```
pub trait Reseeder<R> {
    /// Reseed the given RNG.
references:- 5
31: impl<R: Rng, Rsdr: Reseeder<R>> ReseedingRng<R, Rsdr> {
32:     /// Create a new `ReseedingRng` with the given parameters.
--
134: impl<R: Rng + Default> Reseeder<R> for ReseedWithDefault {
135:     fn reseed(&mut self, rng: &mut R) {
librand/lib.rs:
558: impl reseeding::Reseeder<StdRng> for TaskRngReseeder {
559:     fn reseed(&mut self, rng: &mut StdRng) {
librand/reseeding.rs:
59: impl<R: Rng, Rsdr: Reseeder<R>> Rng for ReseedingRng<R, Rsdr> {
60:     fn next_u32(&mut self) -> u32 {


librand/reseeding.rs:131:68-131:68 -struct- definition:
/// replacing the RNG with the result of a `Default::default` call.
pub struct ReseedWithDefault;
impl<R: Rng + Default> Reseeder<R> for ReseedWithDefault {
references:- 3
138: }
139: impl Default for ReseedWithDefault {
140:     fn default() -> ReseedWithDefault { ReseedWithDefault }
141: }