Skip to main content

rand_core/
block.rs

1//! The [`Generator`] trait and [`BlockRng`]
2//!
3//! Trait [`Generator`] may be implemented by block-generators; that is PRNGs
4//! whose output is a *block* of words, such as `[u32; 16]`.
5//!
6//! The struct [`BlockRng`] wraps such a [`Generator`] together with an output
7//! buffer and implements several methods (e.g. [`BlockRng::next_word`]) to
8//! assist in the implementation of [`TryRng`]. Note that (unlike in earlier
9//! versions of `rand_core`) [`BlockRng`] itself does not implement [`TryRng`]
10//! since in practice we found it was always beneficial to use a wrapper type
11//! over [`BlockRng`].
12//!
13//! # Example
14//!
15//! ```
16//! use core::convert::Infallible;
17//! use rand_core::{Rng, SeedableRng, TryRng};
18//! use rand_core::block::{Generator, BlockRng};
19//!
20//! struct MyRngCore {
21//!     // Generator state ...
22//! #    state: [u32; 8],
23//! }
24//!
25//! impl Generator for MyRngCore {
26//!     type Output = [u32; 8];
27//!
28//!     fn generate(&mut self, output: &mut Self::Output) {
29//!         // Write a new block to output...
30//! #        *output = self.state;
31//!     }
32//! }
33//!
34//! // Our RNG is a wrapper over BlockRng
35//! pub struct MyRng(BlockRng<MyRngCore>);
36//!
37//! impl SeedableRng for MyRng {
38//!     type Seed = [u8; 32];
39//!     fn from_seed(seed: Self::Seed) -> Self {
40//!         let core = MyRngCore {
41//!             // ...
42//! #            state: rand_core::utils::read_words(&seed),
43//!         };
44//!         MyRng(BlockRng::new(core))
45//!     }
46//! }
47//!
48//! impl TryRng for MyRng {
49//!     type Error = Infallible;
50//!
51//!     #[inline]
52//!     fn try_next_u32(&mut self) -> Result<u32, Infallible> {
53//!         Ok(self.0.next_word())
54//!     }
55//!
56//!     #[inline]
57//!     fn try_next_u64(&mut self) -> Result<u64, Infallible> {
58//!         Ok(self.0.next_u64_from_u32())
59//!     }
60//!
61//!     #[inline]
62//!     fn try_fill_bytes(&mut self, bytes: &mut [u8]) -> Result<(), Infallible> {
63//!         Ok(self.0.fill_bytes(bytes))
64//!     }
65//! }
66//!
67//! // And if applicable: impl TryCryptoRng for MyRng {}
68//!
69//! let mut rng = MyRng::seed_from_u64(0);
70//! println!("First value: {}", rng.next_u32());
71//! # assert_eq!(rng.next_u32(), 1171109249);
72//! ```
73//!
74//! [`TryRng`]: crate::TryRng
75//! [`SeedableRng`]: crate::SeedableRng
76
77use crate::utils::Word;
78use core::fmt;
79
80/// A random (block) generator
81pub trait Generator {
82    /// The output type.
83    ///
84    /// For use with [`rand_core::block`](crate::block) code this must be `[u32; _]` or `[u64; _]`.
85    type Output;
86
87    /// Generate a new block of `output`.
88    ///
89    /// This must fill `output` with random data.
90    fn generate(&mut self, output: &mut Self::Output);
91
92    /// Destruct the output buffer
93    ///
94    /// This method is called on [`Drop`] of the [`Self::Output`] buffer.
95    /// The default implementation does nothing.
96    #[inline]
97    fn drop(&mut self, output: &mut Self::Output) {
98        let _ = output;
99    }
100}
101
102/// RNG functionality for a block [`Generator`]
103///
104/// This type encompasses a [`Generator`] [`core`](Self::core) and a buffer.
105/// It provides optimized implementations of methods required by an [`Rng`].
106///
107/// All values are consumed in-order of generation. No whole words (e.g. `u32`
108/// or `u64`) are discarded, though where a word is partially used (e.g. for a
109/// byte-fill whose length is not a multiple of the word size) the rest of the
110/// word is discarded.
111///
112/// [`Rng`]: crate::Rng
113#[derive(#[automatically_derived]
impl<G: ::core::clone::Clone + Generator> ::core::clone::Clone for BlockRng<G>
    where G::Output: ::core::clone::Clone {
    #[inline]
    fn clone(&self) -> BlockRng<G> {
        BlockRng {
            results: ::core::clone::Clone::clone(&self.results),
            core: ::core::clone::Clone::clone(&self.core),
        }
    }
}Clone)]
114pub struct BlockRng<G: Generator> {
115    results: G::Output,
116    /// The *core* part of the RNG, implementing the `generate` function.
117    pub core: G,
118}
119
120// Custom Debug implementation that does not expose the contents of `results`.
121impl<G> fmt::Debug for BlockRng<G>
122where
123    G: Generator + fmt::Debug,
124{
125    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
126        fmt.debug_struct("BlockRng")
127            .field("core", &self.core)
128            .finish_non_exhaustive()
129    }
130}
131
132impl<G: Generator> Drop for BlockRng<G> {
133    fn drop(&mut self) {
134        self.core.drop(&mut self.results);
135    }
136}
137
138impl<W: Word + Default, const N: usize, G: Generator<Output = [W; N]>> BlockRng<G> {
139    /// Create a new `BlockRng` from an existing RNG implementing
140    /// `Generator`. Results will be generated on first use.
141    #[inline]
142    pub fn new(core: G) -> BlockRng<G> {
143        let mut results = [W::default(); N];
144        results[0] = W::from_usize(N);
145        BlockRng { core, results }
146    }
147
148    /// Reconstruct from a core and a remaining-results buffer.
149    ///
150    /// This may be used to deserialize using a `core` and the output of
151    /// [`Self::remaining_results`].
152    ///
153    /// Returns `None` if `remaining_results` is too long.
154    pub fn reconstruct(core: G, remaining_results: &[W]) -> Option<Self> {
155        let mut results = [W::default(); N];
156        if remaining_results.len() < N {
157            let index = N - remaining_results.len();
158            results[index..].copy_from_slice(remaining_results);
159            results[0] = W::from_usize(index);
160            Some(BlockRng { results, core })
161        } else {
162            None
163        }
164    }
165}
166
167impl<W: Word, const N: usize, G: Generator<Output = [W; N]>> BlockRng<G> {
168    /// Get the index into the result buffer.
169    ///
170    /// If this is equal to or larger than the size of the result buffer then
171    /// the buffer is "empty" and `generate()` must be called to produce new
172    /// results.
173    #[inline(always)]
174    fn index(&self) -> usize {
175        self.results[0].into_usize()
176    }
177
178    #[inline(always)]
179    fn set_index(&mut self, index: usize) {
180        if true {
    if !(0 < index && index <= N) {
        ::core::panicking::panic("assertion failed: 0 < index && index <= N")
    };
};debug_assert!(0 < index && index <= N);
181        self.results[0] = W::from_usize(index);
182    }
183
184    /// Re-generate buffer contents, skipping the first `n` words
185    ///
186    /// Existing buffer contents are discarded. A new set of results is
187    /// generated (either immediately or when next required). The first `n`
188    /// words are skipped (this may be used to set a specific word position).
189    ///
190    /// # Panics
191    ///
192    /// This method will panic if `n >= N` where `N` is the buffer size (in
193    /// words).
194    #[inline]
195    pub fn reset_and_skip(&mut self, n: usize) {
196        if n == 0 {
197            self.set_index(N);
198            return;
199        }
200
201        if !(n < N) { ::core::panicking::panic("assertion failed: n < N") };assert!(n < N);
202        self.core.generate(&mut self.results);
203        self.set_index(n);
204    }
205
206    /// Get the number of words consumed since the start of the block
207    ///
208    /// The result is in the range `0..N` where `N` is the buffer size (in
209    /// words).
210    #[inline]
211    pub fn word_offset(&self) -> usize {
212        let index = self.index();
213        if index >= N { 0 } else { index }
214    }
215
216    /// Access the unused part of the results buffer
217    ///
218    /// The length of the returned slice is guaranteed to be less than the
219    /// length of `<Self as Generator>::Output` (i.e. less than `N` where
220    /// `Output = [W; N]`).
221    ///
222    /// This is a low-level interface intended for serialization.
223    /// Results are not marked as consumed.
224    #[inline]
225    pub fn remaining_results(&self) -> &[W] {
226        let index = self.index();
227        &self.results[index..]
228    }
229
230    /// Generate the next word (e.g. `u32`)
231    #[inline]
232    pub fn next_word(&mut self) -> W {
233        let mut index = self.index();
234        if index >= N {
235            self.core.generate(&mut self.results);
236            index = 0;
237        }
238
239        let value = self.results[index];
240        self.set_index(index + 1);
241        value
242    }
243}
244
245impl<const N: usize, G: Generator<Output = [u32; N]>> BlockRng<G> {
246    /// Generate a `u64` from two `u32` words
247    #[inline]
248    pub fn next_u64_from_u32(&mut self) -> u64 {
249        let index = self.index();
250        let mut new_index;
251        let (mut lo, mut hi);
252        if index < N - 1 {
253            lo = self.results[index];
254            hi = self.results[index + 1];
255            new_index = index + 2;
256        } else {
257            lo = self.results[N - 1];
258            self.core.generate(&mut self.results);
259            hi = self.results[0];
260            new_index = 1;
261            if index >= N {
262                lo = hi;
263                hi = self.results[1];
264                new_index = 2;
265            }
266        }
267        self.set_index(new_index);
268        (u64::from(hi) << 32) | u64::from(lo)
269    }
270}
271
272impl<W: Word, const N: usize, G: Generator<Output = [W; N]>> BlockRng<G> {
273    /// Fill `dest`
274    #[inline]
275    pub fn fill_bytes(&mut self, dest: &mut [u8]) {
276        let mut read_len = 0;
277        let mut index = self.index();
278        while read_len < dest.len() {
279            if index >= N {
280                self.core.generate(&mut self.results);
281                index = 0;
282            }
283
284            let size = core::mem::size_of::<W>();
285            let mut chunks = dest[read_len..].chunks_exact_mut(size);
286            let mut src = self.results[index..].iter();
287
288            let zipped = chunks.by_ref().zip(src.by_ref());
289            let num_chunks = zipped.len();
290            zipped.for_each(|(chunk, src)| chunk.copy_from_slice(src.to_le_bytes().as_ref()));
291            index += num_chunks;
292            read_len += num_chunks * size;
293
294            if let Some(src) = src.next() {
295                // We have consumed all full chunks of dest, but not src.
296                let dest_rem = chunks.into_remainder();
297                let n = dest_rem.len();
298                if n > 0 {
299                    dest_rem.copy_from_slice(&src.to_le_bytes().as_ref()[..n]);
300                    index += 1;
301                    if true {
    match (&(read_len + n), &dest.len()) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val, ::core::option::Option::None);
            }
        }
    };
};debug_assert_eq!(read_len + n, dest.len());
302                }
303                break;
304            }
305        }
306        self.set_index(index);
307    }
308}