xref: /aosp_15_r20/external/cronet/third_party/rust/chromium_crates_io/vendor/rand-0.8.5/src/rngs/small.rs (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 //! A small fast RNG
10 
11 use rand_core::{Error, RngCore, SeedableRng};
12 
13 #[cfg(target_pointer_width = "64")]
14 type Rng = super::xoshiro256plusplus::Xoshiro256PlusPlus;
15 #[cfg(not(target_pointer_width = "64"))]
16 type Rng = super::xoshiro128plusplus::Xoshiro128PlusPlus;
17 
18 /// A small-state, fast non-crypto PRNG
19 ///
20 /// `SmallRng` may be a good choice when a PRNG with small state, cheap
21 /// initialization, good statistical quality and good performance are required.
22 /// Note that depending on the application, [`StdRng`] may be faster on many
23 /// modern platforms while providing higher-quality randomness. Furthermore,
24 /// `SmallRng` is **not** a good choice when:
25 /// - Security against prediction is important. Use [`StdRng`] instead.
26 /// - Seeds with many zeros are provided. In such cases, it takes `SmallRng`
27 ///   about 10 samples to produce 0 and 1 bits with equal probability. Either
28 ///   provide seeds with an approximately equal number of 0 and 1 (for example
29 ///   by using [`SeedableRng::from_entropy`] or [`SeedableRng::seed_from_u64`]),
30 ///   or use [`StdRng`] instead.
31 ///
32 /// The algorithm is deterministic but should not be considered reproducible
33 /// due to dependence on platform and possible replacement in future
34 /// library versions. For a reproducible generator, use a named PRNG from an
35 /// external crate, e.g. [rand_xoshiro] or [rand_chacha].
36 /// Refer also to [The Book](https://rust-random.github.io/book/guide-rngs.html).
37 ///
38 /// The PRNG algorithm in `SmallRng` is chosen to be efficient on the current
39 /// platform, without consideration for cryptography or security. The size of
40 /// its state is much smaller than [`StdRng`]. The current algorithm is
41 /// `Xoshiro256PlusPlus` on 64-bit platforms and `Xoshiro128PlusPlus` on 32-bit
42 /// platforms. Both are also implemented by the [rand_xoshiro] crate.
43 ///
44 /// # Examples
45 ///
46 /// Initializing `SmallRng` with a random seed can be done using [`SeedableRng::from_entropy`]:
47 ///
48 /// ```
49 /// use rand::{Rng, SeedableRng};
50 /// use rand::rngs::SmallRng;
51 ///
52 /// // Create small, cheap to initialize and fast RNG with a random seed.
53 /// // The randomness is supplied by the operating system.
54 /// let mut small_rng = SmallRng::from_entropy();
55 /// # let v: u32 = small_rng.gen();
56 /// ```
57 ///
58 /// When initializing a lot of `SmallRng`'s, using [`thread_rng`] can be more
59 /// efficient:
60 ///
61 /// ```
62 /// use rand::{SeedableRng, thread_rng};
63 /// use rand::rngs::SmallRng;
64 ///
65 /// // Create a big, expensive to initialize and slower, but unpredictable RNG.
66 /// // This is cached and done only once per thread.
67 /// let mut thread_rng = thread_rng();
68 /// // Create small, cheap to initialize and fast RNGs with random seeds.
69 /// // One can generally assume this won't fail.
70 /// let rngs: Vec<SmallRng> = (0..10)
71 ///     .map(|_| SmallRng::from_rng(&mut thread_rng).unwrap())
72 ///     .collect();
73 /// ```
74 ///
75 /// [`StdRng`]: crate::rngs::StdRng
76 /// [`thread_rng`]: crate::thread_rng
77 /// [rand_chacha]: https://crates.io/crates/rand_chacha
78 /// [rand_xoshiro]: https://crates.io/crates/rand_xoshiro
79 #[cfg_attr(doc_cfg, doc(cfg(feature = "small_rng")))]
80 #[derive(Clone, Debug, PartialEq, Eq)]
81 pub struct SmallRng(Rng);
82 
83 impl RngCore for SmallRng {
84     #[inline(always)]
next_u32(&mut self) -> u3285     fn next_u32(&mut self) -> u32 {
86         self.0.next_u32()
87     }
88 
89     #[inline(always)]
next_u64(&mut self) -> u6490     fn next_u64(&mut self) -> u64 {
91         self.0.next_u64()
92     }
93 
94     #[inline(always)]
fill_bytes(&mut self, dest: &mut [u8])95     fn fill_bytes(&mut self, dest: &mut [u8]) {
96         self.0.fill_bytes(dest);
97     }
98 
99     #[inline(always)]
try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error>100     fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
101         self.0.try_fill_bytes(dest)
102     }
103 }
104 
105 impl SeedableRng for SmallRng {
106     type Seed = <Rng as SeedableRng>::Seed;
107 
108     #[inline(always)]
from_seed(seed: Self::Seed) -> Self109     fn from_seed(seed: Self::Seed) -> Self {
110         SmallRng(Rng::from_seed(seed))
111     }
112 
113     #[inline(always)]
from_rng<R: RngCore>(rng: R) -> Result<Self, Error>114     fn from_rng<R: RngCore>(rng: R) -> Result<Self, Error> {
115         Rng::from_rng(rng).map(SmallRng)
116     }
117 }
118