1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
//! Interfaces for accessing a random number generator. //! //! A random number generator produces a stream of random numbers, either from //! hardware or based on an initial seed. The [RNG](trait.RNG.html) trait //! provides a simple, implementation agnostic interface for getting new random //! values. //! //! The interface is designed to work well with random number generators that //! may not have values ready immediately. This is important when generating //! numbers from a low-bandwidth hardware random number generator or when the //! RNG is virtualized among many consumers. //! //! Random numbers are yielded to the [Client](trait.Client.html) as an //! `Iterator` which only terminates when no more numbers are currently //! available. Clients can request more randmoness if needed and will be called //! again when more is available. //! //! # Example //! //! The following example is a simple capsule that prints out a random number //! once a second using the `Alarm` and `RNG` traits. //! //! ``` //! struct RngTest<'a, A: Alarm + 'a> { //! rng: &'a RNG, //! alarm: &'a A //! } //! //! impl<'a, A: Alarm> RngTest<'a, A> { //! pub fn initialize(&self) { //! let interval = 1 * <A::Frequency>::frequency(); //! let tics = self.alarm.now().wrapping_add(interval); //! self.alarm.set_alarm(tics); //! } //! } //! //! impl<'a, A: Alarm> time::Client for RngTest<'a, A> { //! fn fired(&self) { //! self.rng.get(); //! } //! } //! //! impl<'a, A: Alarm> rng::Client for RngTest<'a, A> { //! fn randomness_available(&self, randomness: &mut Iterator<Item = u32>) -> rng::Continue { //! match randomness.next() { //! Some(random) => { //! println!("Rand {}", random); //! let interval = 1 * <A::Frequency>::frequency(); //! let tics = self.alarm.now().wrapping_add(interval); //! self.alarm.set_alarm(tics); //! rng::Continue::Done //! }, //! None => rng::Continue::More //! } //! } //! } //! ``` /// Denotes whether the [Client](trait.Client.html) wants to be notified when /// `More` randomness is available or if they are `Done` #[derive(Debug, Eq, PartialEq)] pub enum Continue { /// More randomness is required. More, /// No more randomness required. Done, } /// Generic interface for a random number generator /// /// Implementors should assume the client implements the /// [Client](trait.Client.html) trait. pub trait RNG { /// Initiate the aquisition of new random number generation. /// /// The implementor may ignore this command if the generation proccess is /// already in progress. fn get(&self); } /// An [RNG](trait.RNG.html) client /// /// Clients of an [RNG](trait.RNG.html) must implement this trait. pub trait Client { /// Called by the (RNG)[trait.RNG.html] when there are one or more random /// numbers available /// /// `randomness` in an `Iterator` of available random numbers. The amount of /// randomness available may increase if `randomness` is not consumed /// quickly so clients should not rely on iterator termination to finish /// consuming randomn numbers. /// /// The client returns either `Continue::More` if the iterator did not have /// enough random values and the client would like to be called again when /// more is available, or `Continue::Done`. fn randomness_available(&self, randomness: &mut Iterator<Item = u32>) -> Continue; }