• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 Developers of the Rand project.
2 //
3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5 // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6 // option. This file may not be copied, modified, or distributed
7 // except according to those terms.
8 
9 //! The `BlockRngCore` trait and implementation helpers
10 //!
11 //! The [`BlockRngCore`] trait exists to assist in the implementation of RNGs
12 //! which generate a block of data in a cache instead of returning generated
13 //! values directly.
14 //!
15 //! Usage of this trait is optional, but provides two advantages:
16 //! implementations only need to concern themselves with generation of the
17 //! block, not the various [`RngCore`] methods (especially [`fill_bytes`], where
18 //! the optimal implementations are not trivial), and this allows
19 //! `ReseedingRng` (see [`rand`](https://docs.rs/rand) crate) perform periodic
20 //! reseeding with very low overhead.
21 //!
22 //! # Example
23 //!
24 //! ```no_run
25 //! use rand_core::{RngCore, SeedableRng};
26 //! use rand_core::block::{BlockRngCore, BlockRng};
27 //!
28 //! struct MyRngCore;
29 //!
30 //! impl BlockRngCore for MyRngCore {
31 //!     type Item = u32;
32 //!     type Results = [u32; 16];
33 //!
34 //!     fn generate(&mut self, results: &mut Self::Results) {
35 //!         unimplemented!()
36 //!     }
37 //! }
38 //!
39 //! impl SeedableRng for MyRngCore {
40 //!     type Seed = [u8; 32];
41 //!     fn from_seed(seed: Self::Seed) -> Self {
42 //!         unimplemented!()
43 //!     }
44 //! }
45 //!
46 //! // optionally, also implement CryptoRng for MyRngCore
47 //!
48 //! // Final RNG.
49 //! let mut rng = BlockRng::<MyRngCore>::seed_from_u64(0);
50 //! println!("First value: {}", rng.next_u32());
51 //! ```
52 //!
53 //! [`BlockRngCore`]: crate::block::BlockRngCore
54 //! [`fill_bytes`]: RngCore::fill_bytes
55 
56 use crate::impls::{fill_via_u32_chunks, fill_via_u64_chunks};
57 use crate::{CryptoRng, Error, RngCore, SeedableRng};
58 use core::convert::AsRef;
59 use core::fmt;
60 #[cfg(feature = "serde1")]
61 use serde::{Deserialize, Serialize};
62 
63 /// A trait for RNGs which do not generate random numbers individually, but in
64 /// blocks (typically `[u32; N]`). This technique is commonly used by
65 /// cryptographic RNGs to improve performance.
66 ///
67 /// See the [module][crate::block] documentation for details.
68 pub trait BlockRngCore {
69     /// Results element type, e.g. `u32`.
70     type Item;
71 
72     /// Results type. This is the 'block' an RNG implementing `BlockRngCore`
73     /// generates, which will usually be an array like `[u32; 16]`.
74     type Results: AsRef<[Self::Item]> + AsMut<[Self::Item]> + Default;
75 
76     /// Generate a new block of results.
generate(&mut self, results: &mut Self::Results)77     fn generate(&mut self, results: &mut Self::Results);
78 }
79 
80 /// A wrapper type implementing [`RngCore`] for some type implementing
81 /// [`BlockRngCore`] with `u32` array buffer; i.e. this can be used to implement
82 /// a full RNG from just a `generate` function.
83 ///
84 /// The `core` field may be accessed directly but the results buffer may not.
85 /// PRNG implementations can simply use a type alias
86 /// (`pub type MyRng = BlockRng<MyRngCore>;`) but might prefer to use a
87 /// wrapper type (`pub struct MyRng(BlockRng<MyRngCore>);`); the latter must
88 /// re-implement `RngCore` but hides the implementation details and allows
89 /// extra functionality to be defined on the RNG
90 /// (e.g. `impl MyRng { fn set_stream(...){...} }`).
91 ///
92 /// `BlockRng` has heavily optimized implementations of the [`RngCore`] methods
93 /// reading values from the results buffer, as well as
94 /// calling [`BlockRngCore::generate`] directly on the output array when
95 /// [`fill_bytes`] / [`try_fill_bytes`] is called on a large array. These methods
96 /// also handle the bookkeeping of when to generate a new batch of values.
97 ///
98 /// No whole generated `u32` values are thrown away and all values are consumed
99 /// in-order. [`next_u32`] simply takes the next available `u32` value.
100 /// [`next_u64`] is implemented by combining two `u32` values, least
101 /// significant first. [`fill_bytes`] and [`try_fill_bytes`] consume a whole
102 /// number of `u32` values, converting each `u32` to a byte slice in
103 /// little-endian order. If the requested byte length is not a multiple of 4,
104 /// some bytes will be discarded.
105 ///
106 /// See also [`BlockRng64`] which uses `u64` array buffers. Currently there is
107 /// no direct support for other buffer types.
108 ///
109 /// For easy initialization `BlockRng` also implements [`SeedableRng`].
110 ///
111 /// [`next_u32`]: RngCore::next_u32
112 /// [`next_u64`]: RngCore::next_u64
113 /// [`fill_bytes`]: RngCore::fill_bytes
114 /// [`try_fill_bytes`]: RngCore::try_fill_bytes
115 #[derive(Clone)]
116 #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
117 #[cfg_attr(
118     feature = "serde1",
119     serde(
120         bound = "for<'x> R: Serialize + Deserialize<'x> + Sized, for<'x> R::Results: Serialize + Deserialize<'x>"
121     )
122 )]
123 pub struct BlockRng<R: BlockRngCore + ?Sized> {
124     results: R::Results,
125     index: usize,
126     /// The *core* part of the RNG, implementing the `generate` function.
127     pub core: R,
128 }
129 
130 // Custom Debug implementation that does not expose the contents of `results`.
131 impl<R: BlockRngCore + fmt::Debug> fmt::Debug for BlockRng<R> {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result132     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
133         fmt.debug_struct("BlockRng")
134             .field("core", &self.core)
135             .field("result_len", &self.results.as_ref().len())
136             .field("index", &self.index)
137             .finish()
138     }
139 }
140 
141 impl<R: BlockRngCore> BlockRng<R> {
142     /// Create a new `BlockRng` from an existing RNG implementing
143     /// `BlockRngCore`. Results will be generated on first use.
144     #[inline]
new(core: R) -> BlockRng<R>145     pub fn new(core: R) -> BlockRng<R> {
146         let results_empty = R::Results::default();
147         BlockRng {
148             core,
149             index: results_empty.as_ref().len(),
150             results: results_empty,
151         }
152     }
153 
154     /// Get the index into the result buffer.
155     ///
156     /// If this is equal to or larger than the size of the result buffer then
157     /// the buffer is "empty" and `generate()` must be called to produce new
158     /// results.
159     #[inline(always)]
index(&self) -> usize160     pub fn index(&self) -> usize {
161         self.index
162     }
163 
164     /// Reset the number of available results.
165     /// This will force a new set of results to be generated on next use.
166     #[inline]
reset(&mut self)167     pub fn reset(&mut self) {
168         self.index = self.results.as_ref().len();
169     }
170 
171     /// Generate a new set of results immediately, setting the index to the
172     /// given value.
173     #[inline]
generate_and_set(&mut self, index: usize)174     pub fn generate_and_set(&mut self, index: usize) {
175         assert!(index < self.results.as_ref().len());
176         self.core.generate(&mut self.results);
177         self.index = index;
178     }
179 }
180 
181 impl<R: BlockRngCore<Item = u32>> RngCore for BlockRng<R>
182 where
183     <R as BlockRngCore>::Results: AsRef<[u32]> + AsMut<[u32]>,
184 {
185     #[inline]
next_u32(&mut self) -> u32186     fn next_u32(&mut self) -> u32 {
187         if self.index >= self.results.as_ref().len() {
188             self.generate_and_set(0);
189         }
190 
191         let value = self.results.as_ref()[self.index];
192         self.index += 1;
193         value
194     }
195 
196     #[inline]
next_u64(&mut self) -> u64197     fn next_u64(&mut self) -> u64 {
198         let read_u64 = |results: &[u32], index| {
199             let data = &results[index..=index + 1];
200             u64::from(data[1]) << 32 | u64::from(data[0])
201         };
202 
203         let len = self.results.as_ref().len();
204 
205         let index = self.index;
206         if index < len - 1 {
207             self.index += 2;
208             // Read an u64 from the current index
209             read_u64(self.results.as_ref(), index)
210         } else if index >= len {
211             self.generate_and_set(2);
212             read_u64(self.results.as_ref(), 0)
213         } else {
214             let x = u64::from(self.results.as_ref()[len - 1]);
215             self.generate_and_set(1);
216             let y = u64::from(self.results.as_ref()[0]);
217             (y << 32) | x
218         }
219     }
220 
221     #[inline]
fill_bytes(&mut self, dest: &mut [u8])222     fn fill_bytes(&mut self, dest: &mut [u8]) {
223         let mut read_len = 0;
224         while read_len < dest.len() {
225             if self.index >= self.results.as_ref().len() {
226                 self.generate_and_set(0);
227             }
228             let (consumed_u32, filled_u8) =
229                 fill_via_u32_chunks(&self.results.as_ref()[self.index..], &mut dest[read_len..]);
230 
231             self.index += consumed_u32;
232             read_len += filled_u8;
233         }
234     }
235 
236     #[inline(always)]
try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error>237     fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
238         self.fill_bytes(dest);
239         Ok(())
240     }
241 }
242 
243 impl<R: BlockRngCore + SeedableRng> SeedableRng for BlockRng<R> {
244     type Seed = R::Seed;
245 
246     #[inline(always)]
from_seed(seed: Self::Seed) -> Self247     fn from_seed(seed: Self::Seed) -> Self {
248         Self::new(R::from_seed(seed))
249     }
250 
251     #[inline(always)]
seed_from_u64(seed: u64) -> Self252     fn seed_from_u64(seed: u64) -> Self {
253         Self::new(R::seed_from_u64(seed))
254     }
255 
256     #[inline(always)]
from_rng<S: RngCore>(rng: S) -> Result<Self, Error>257     fn from_rng<S: RngCore>(rng: S) -> Result<Self, Error> {
258         Ok(Self::new(R::from_rng(rng)?))
259     }
260 }
261 
262 /// A wrapper type implementing [`RngCore`] for some type implementing
263 /// [`BlockRngCore`] with `u64` array buffer; i.e. this can be used to implement
264 /// a full RNG from just a `generate` function.
265 ///
266 /// This is similar to [`BlockRng`], but specialized for algorithms that operate
267 /// on `u64` values.
268 ///
269 /// No whole generated `u64` values are thrown away and all values are consumed
270 /// in-order. [`next_u64`] simply takes the next available `u64` value.
271 /// [`next_u32`] is however a bit special: half of a `u64` is consumed, leaving
272 /// the other half in the buffer. If the next function called is [`next_u32`]
273 /// then the other half is then consumed, however both [`next_u64`] and
274 /// [`fill_bytes`] discard the rest of any half-consumed `u64`s when called.
275 ///
276 /// [`fill_bytes`] and [`try_fill_bytes`] consume a whole number of `u64`
277 /// values. If the requested length is not a multiple of 8, some bytes will be
278 /// discarded.
279 ///
280 /// [`next_u32`]: RngCore::next_u32
281 /// [`next_u64`]: RngCore::next_u64
282 /// [`fill_bytes`]: RngCore::fill_bytes
283 /// [`try_fill_bytes`]: RngCore::try_fill_bytes
284 #[derive(Clone)]
285 #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
286 pub struct BlockRng64<R: BlockRngCore + ?Sized> {
287     results: R::Results,
288     index: usize,
289     half_used: bool, // true if only half of the previous result is used
290     /// The *core* part of the RNG, implementing the `generate` function.
291     pub core: R,
292 }
293 
294 // Custom Debug implementation that does not expose the contents of `results`.
295 impl<R: BlockRngCore + fmt::Debug> fmt::Debug for BlockRng64<R> {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result296     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
297         fmt.debug_struct("BlockRng64")
298             .field("core", &self.core)
299             .field("result_len", &self.results.as_ref().len())
300             .field("index", &self.index)
301             .field("half_used", &self.half_used)
302             .finish()
303     }
304 }
305 
306 impl<R: BlockRngCore> BlockRng64<R> {
307     /// Create a new `BlockRng` from an existing RNG implementing
308     /// `BlockRngCore`. Results will be generated on first use.
309     #[inline]
new(core: R) -> BlockRng64<R>310     pub fn new(core: R) -> BlockRng64<R> {
311         let results_empty = R::Results::default();
312         BlockRng64 {
313             core,
314             index: results_empty.as_ref().len(),
315             half_used: false,
316             results: results_empty,
317         }
318     }
319 
320     /// Get the index into the result buffer.
321     ///
322     /// If this is equal to or larger than the size of the result buffer then
323     /// the buffer is "empty" and `generate()` must be called to produce new
324     /// results.
325     #[inline(always)]
index(&self) -> usize326     pub fn index(&self) -> usize {
327         self.index
328     }
329 
330     /// Reset the number of available results.
331     /// This will force a new set of results to be generated on next use.
332     #[inline]
reset(&mut self)333     pub fn reset(&mut self) {
334         self.index = self.results.as_ref().len();
335         self.half_used = false;
336     }
337 
338     /// Generate a new set of results immediately, setting the index to the
339     /// given value.
340     #[inline]
generate_and_set(&mut self, index: usize)341     pub fn generate_and_set(&mut self, index: usize) {
342         assert!(index < self.results.as_ref().len());
343         self.core.generate(&mut self.results);
344         self.index = index;
345         self.half_used = false;
346     }
347 }
348 
349 impl<R: BlockRngCore<Item = u64>> RngCore for BlockRng64<R>
350 where
351     <R as BlockRngCore>::Results: AsRef<[u64]> + AsMut<[u64]>,
352 {
353     #[inline]
next_u32(&mut self) -> u32354     fn next_u32(&mut self) -> u32 {
355         let mut index = self.index - self.half_used as usize;
356         if index >= self.results.as_ref().len() {
357             self.core.generate(&mut self.results);
358             self.index = 0;
359             index = 0;
360             // `self.half_used` is by definition `false`
361             self.half_used = false;
362         }
363 
364         let shift = 32 * (self.half_used as usize);
365 
366         self.half_used = !self.half_used;
367         self.index += self.half_used as usize;
368 
369         (self.results.as_ref()[index] >> shift) as u32
370     }
371 
372     #[inline]
next_u64(&mut self) -> u64373     fn next_u64(&mut self) -> u64 {
374         if self.index >= self.results.as_ref().len() {
375             self.core.generate(&mut self.results);
376             self.index = 0;
377         }
378 
379         let value = self.results.as_ref()[self.index];
380         self.index += 1;
381         self.half_used = false;
382         value
383     }
384 
385     #[inline]
fill_bytes(&mut self, dest: &mut [u8])386     fn fill_bytes(&mut self, dest: &mut [u8]) {
387         let mut read_len = 0;
388         self.half_used = false;
389         while read_len < dest.len() {
390             if self.index as usize >= self.results.as_ref().len() {
391                 self.core.generate(&mut self.results);
392                 self.index = 0;
393             }
394 
395             let (consumed_u64, filled_u8) = fill_via_u64_chunks(
396                 &self.results.as_ref()[self.index as usize..],
397                 &mut dest[read_len..],
398             );
399 
400             self.index += consumed_u64;
401             read_len += filled_u8;
402         }
403     }
404 
405     #[inline(always)]
try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error>406     fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
407         self.fill_bytes(dest);
408         Ok(())
409     }
410 }
411 
412 impl<R: BlockRngCore + SeedableRng> SeedableRng for BlockRng64<R> {
413     type Seed = R::Seed;
414 
415     #[inline(always)]
from_seed(seed: Self::Seed) -> Self416     fn from_seed(seed: Self::Seed) -> Self {
417         Self::new(R::from_seed(seed))
418     }
419 
420     #[inline(always)]
seed_from_u64(seed: u64) -> Self421     fn seed_from_u64(seed: u64) -> Self {
422         Self::new(R::seed_from_u64(seed))
423     }
424 
425     #[inline(always)]
from_rng<S: RngCore>(rng: S) -> Result<Self, Error>426     fn from_rng<S: RngCore>(rng: S) -> Result<Self, Error> {
427         Ok(Self::new(R::from_rng(rng)?))
428     }
429 }
430 
431 impl<R: BlockRngCore + CryptoRng> CryptoRng for BlockRng<R> {}
432 
433 #[cfg(test)]
434 mod test {
435     use crate::{SeedableRng, RngCore};
436     use crate::block::{BlockRng, BlockRng64, BlockRngCore};
437 
438     #[derive(Debug, Clone)]
439     struct DummyRng {
440         counter: u32,
441     }
442 
443     impl BlockRngCore for DummyRng {
444         type Item = u32;
445 
446         type Results = [u32; 16];
447 
generate(&mut self, results: &mut Self::Results)448         fn generate(&mut self, results: &mut Self::Results) {
449             for r in results {
450                 *r = self.counter;
451                 self.counter = self.counter.wrapping_add(3511615421);
452             }
453         }
454     }
455 
456     impl SeedableRng for DummyRng {
457         type Seed = [u8; 4];
458 
from_seed(seed: Self::Seed) -> Self459         fn from_seed(seed: Self::Seed) -> Self {
460             DummyRng { counter: u32::from_le_bytes(seed) }
461         }
462     }
463 
464     #[test]
blockrng_next_u32_vs_next_u64()465     fn blockrng_next_u32_vs_next_u64() {
466         let mut rng1 = BlockRng::<DummyRng>::from_seed([1, 2, 3, 4]);
467         let mut rng2 = rng1.clone();
468         let mut rng3 = rng1.clone();
469 
470         let mut a = [0; 16];
471         (&mut a[..4]).copy_from_slice(&rng1.next_u32().to_le_bytes());
472         (&mut a[4..12]).copy_from_slice(&rng1.next_u64().to_le_bytes());
473         (&mut a[12..]).copy_from_slice(&rng1.next_u32().to_le_bytes());
474 
475         let mut b = [0; 16];
476         (&mut b[..4]).copy_from_slice(&rng2.next_u32().to_le_bytes());
477         (&mut b[4..8]).copy_from_slice(&rng2.next_u32().to_le_bytes());
478         (&mut b[8..]).copy_from_slice(&rng2.next_u64().to_le_bytes());
479         assert_eq!(a, b);
480 
481         let mut c = [0; 16];
482         (&mut c[..8]).copy_from_slice(&rng3.next_u64().to_le_bytes());
483         (&mut c[8..12]).copy_from_slice(&rng3.next_u32().to_le_bytes());
484         (&mut c[12..]).copy_from_slice(&rng3.next_u32().to_le_bytes());
485         assert_eq!(a, c);
486     }
487 
488     #[derive(Debug, Clone)]
489     struct DummyRng64 {
490         counter: u64,
491     }
492 
493     impl BlockRngCore for DummyRng64 {
494         type Item = u64;
495 
496         type Results = [u64; 8];
497 
generate(&mut self, results: &mut Self::Results)498         fn generate(&mut self, results: &mut Self::Results) {
499             for r in results {
500                 *r = self.counter;
501                 self.counter = self.counter.wrapping_add(2781463553396133981);
502             }
503         }
504     }
505 
506     impl SeedableRng for DummyRng64 {
507         type Seed = [u8; 8];
508 
from_seed(seed: Self::Seed) -> Self509         fn from_seed(seed: Self::Seed) -> Self {
510             DummyRng64 { counter: u64::from_le_bytes(seed) }
511         }
512     }
513 
514     #[test]
blockrng64_next_u32_vs_next_u64()515     fn blockrng64_next_u32_vs_next_u64() {
516         let mut rng1 = BlockRng64::<DummyRng64>::from_seed([1, 2, 3, 4, 5, 6, 7, 8]);
517         let mut rng2 = rng1.clone();
518         let mut rng3 = rng1.clone();
519 
520         let mut a = [0; 16];
521         (&mut a[..4]).copy_from_slice(&rng1.next_u32().to_le_bytes());
522         (&mut a[4..12]).copy_from_slice(&rng1.next_u64().to_le_bytes());
523         (&mut a[12..]).copy_from_slice(&rng1.next_u32().to_le_bytes());
524 
525         let mut b = [0; 16];
526         (&mut b[..4]).copy_from_slice(&rng2.next_u32().to_le_bytes());
527         (&mut b[4..8]).copy_from_slice(&rng2.next_u32().to_le_bytes());
528         (&mut b[8..]).copy_from_slice(&rng2.next_u64().to_le_bytes());
529         assert_ne!(a, b);
530         assert_eq!(&a[..4], &b[..4]);
531         assert_eq!(&a[4..12], &b[8..]);
532 
533         let mut c = [0; 16];
534         (&mut c[..8]).copy_from_slice(&rng3.next_u64().to_le_bytes());
535         (&mut c[8..12]).copy_from_slice(&rng3.next_u32().to_le_bytes());
536         (&mut c[12..]).copy_from_slice(&rng3.next_u32().to_le_bytes());
537         assert_eq!(b, c);
538     }
539 }
540