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;
}