• 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 implementations of the `Standard` distribution for other built-in types.
10 
11 use core::char;
12 use core::num::Wrapping;
13 #[cfg(feature = "alloc")]
14 use alloc::string::String;
15 
16 use crate::distributions::{Distribution, Standard, Uniform};
17 #[cfg(feature = "alloc")]
18 use crate::distributions::DistString;
19 use crate::Rng;
20 
21 #[cfg(feature = "serde1")]
22 use serde::{Serialize, Deserialize};
23 #[cfg(feature = "min_const_gen")]
24 use core::mem::{self, MaybeUninit};
25 
26 
27 // ----- Sampling distributions -----
28 
29 /// Sample a `u8`, uniformly distributed over ASCII letters and numbers:
30 /// a-z, A-Z and 0-9.
31 ///
32 /// # Example
33 ///
34 /// ```
35 /// use rand::{Rng, thread_rng};
36 /// use rand::distributions::Alphanumeric;
37 ///
38 /// let mut rng = thread_rng();
39 /// let chars: String = (0..7).map(|_| rng.sample(Alphanumeric) as char).collect();
40 /// println!("Random chars: {}", chars);
41 /// ```
42 ///
43 /// The [`DistString`] trait provides an easier method of generating
44 /// a random `String`, and offers more efficient allocation:
45 /// ```
46 /// use rand::distributions::{Alphanumeric, DistString};
47 /// let string = Alphanumeric.sample_string(&mut rand::thread_rng(), 16);
48 /// println!("Random string: {}", string);
49 /// ```
50 ///
51 /// # Passwords
52 ///
53 /// Users sometimes ask whether it is safe to use a string of random characters
54 /// as a password. In principle, all RNGs in Rand implementing `CryptoRng` are
55 /// suitable as a source of randomness for generating passwords (if they are
56 /// properly seeded), but it is more conservative to only use randomness
57 /// directly from the operating system via the `getrandom` crate, or the
58 /// corresponding bindings of a crypto library.
59 ///
60 /// When generating passwords or keys, it is important to consider the threat
61 /// model and in some cases the memorability of the password. This is out of
62 /// scope of the Rand project, and therefore we defer to the following
63 /// references:
64 ///
65 /// - [Wikipedia article on Password Strength](https://en.wikipedia.org/wiki/Password_strength)
66 /// - [Diceware for generating memorable passwords](https://en.wikipedia.org/wiki/Diceware)
67 #[derive(Debug, Clone, Copy)]
68 #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
69 pub struct Alphanumeric;
70 
71 
72 // ----- Implementations of distributions -----
73 
74 impl Distribution<char> for Standard {
75     #[inline]
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> char76     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> char {
77         // A valid `char` is either in the interval `[0, 0xD800)` or
78         // `(0xDFFF, 0x11_0000)`. All `char`s must therefore be in
79         // `[0, 0x11_0000)` but not in the "gap" `[0xD800, 0xDFFF]` which is
80         // reserved for surrogates. This is the size of that gap.
81         const GAP_SIZE: u32 = 0xDFFF - 0xD800 + 1;
82 
83         // Uniform::new(0, 0x11_0000 - GAP_SIZE) can also be used but it
84         // seemed slower.
85         let range = Uniform::new(GAP_SIZE, 0x11_0000);
86 
87         let mut n = range.sample(rng);
88         if n <= 0xDFFF {
89             n -= GAP_SIZE;
90         }
91         unsafe { char::from_u32_unchecked(n) }
92     }
93 }
94 
95 /// Note: the `String` is potentially left with excess capacity; optionally the
96 /// user may call `string.shrink_to_fit()` afterwards.
97 #[cfg(feature = "alloc")]
98 impl DistString for Standard {
append_string<R: Rng + ?Sized>(&self, rng: &mut R, s: &mut String, len: usize)99     fn append_string<R: Rng + ?Sized>(&self, rng: &mut R, s: &mut String, len: usize) {
100         // A char is encoded with at most four bytes, thus this reservation is
101         // guaranteed to be sufficient. We do not shrink_to_fit afterwards so
102         // that repeated usage on the same `String` buffer does not reallocate.
103         s.reserve(4 * len);
104         s.extend(Distribution::<char>::sample_iter(self, rng).take(len));
105     }
106 }
107 
108 impl Distribution<u8> for Alphanumeric {
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u8109     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> u8 {
110         const RANGE: u32 = 26 + 26 + 10;
111         const GEN_ASCII_STR_CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
112                 abcdefghijklmnopqrstuvwxyz\
113                 0123456789";
114         // We can pick from 62 characters. This is so close to a power of 2, 64,
115         // that we can do better than `Uniform`. Use a simple bitshift and
116         // rejection sampling. We do not use a bitmask, because for small RNGs
117         // the most significant bits are usually of higher quality.
118         loop {
119             let var = rng.next_u32() >> (32 - 6);
120             if var < RANGE {
121                 return GEN_ASCII_STR_CHARSET[var as usize];
122             }
123         }
124     }
125 }
126 
127 #[cfg(feature = "alloc")]
128 impl DistString for Alphanumeric {
append_string<R: Rng + ?Sized>(&self, rng: &mut R, string: &mut String, len: usize)129     fn append_string<R: Rng + ?Sized>(&self, rng: &mut R, string: &mut String, len: usize) {
130         unsafe {
131             let v = string.as_mut_vec();
132             v.extend(self.sample_iter(rng).take(len));
133         }
134     }
135 }
136 
137 impl Distribution<bool> for Standard {
138     #[inline]
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> bool139     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> bool {
140         // We can compare against an arbitrary bit of an u32 to get a bool.
141         // Because the least significant bits of a lower quality RNG can have
142         // simple patterns, we compare against the most significant bit. This is
143         // easiest done using a sign test.
144         (rng.next_u32() as i32) < 0
145     }
146 }
147 
148 macro_rules! tuple_impl {
149     // use variables to indicate the arity of the tuple
150     ($($tyvar:ident),* ) => {
151         // the trailing commas are for the 1 tuple
152         impl< $( $tyvar ),* >
153             Distribution<( $( $tyvar ),* , )>
154             for Standard
155             where $( Standard: Distribution<$tyvar> ),*
156         {
157             #[inline]
158             fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> ( $( $tyvar ),* , ) {
159                 (
160                     // use the $tyvar's to get the appropriate number of
161                     // repeats (they're not actually needed)
162                     $(
163                         _rng.gen::<$tyvar>()
164                     ),*
165                     ,
166                 )
167             }
168         }
169     }
170 }
171 
172 impl Distribution<()> for Standard {
173     #[allow(clippy::unused_unit)]
174     #[inline]
sample<R: Rng + ?Sized>(&self, _: &mut R) -> ()175     fn sample<R: Rng + ?Sized>(&self, _: &mut R) -> () {
176         ()
177     }
178 }
179 tuple_impl! {A}
180 tuple_impl! {A, B}
181 tuple_impl! {A, B, C}
182 tuple_impl! {A, B, C, D}
183 tuple_impl! {A, B, C, D, E}
184 tuple_impl! {A, B, C, D, E, F}
185 tuple_impl! {A, B, C, D, E, F, G}
186 tuple_impl! {A, B, C, D, E, F, G, H}
187 tuple_impl! {A, B, C, D, E, F, G, H, I}
188 tuple_impl! {A, B, C, D, E, F, G, H, I, J}
189 tuple_impl! {A, B, C, D, E, F, G, H, I, J, K}
190 tuple_impl! {A, B, C, D, E, F, G, H, I, J, K, L}
191 
192 #[cfg(feature = "min_const_gen")]
193 #[cfg_attr(doc_cfg, doc(cfg(feature = "min_const_gen")))]
194 impl<T, const N: usize> Distribution<[T; N]> for Standard
195 where Standard: Distribution<T>
196 {
197     #[inline]
sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> [T; N]198     fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> [T; N] {
199         let mut buff: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
200 
201         for elem in &mut buff {
202             *elem = MaybeUninit::new(_rng.gen());
203         }
204 
205         unsafe { mem::transmute_copy::<_, _>(&buff) }
206     }
207 }
208 
209 #[cfg(not(feature = "min_const_gen"))]
210 macro_rules! array_impl {
211     // recursive, given at least one type parameter:
212     {$n:expr, $t:ident, $($ts:ident,)*} => {
213         array_impl!{($n - 1), $($ts,)*}
214 
215         impl<T> Distribution<[T; $n]> for Standard where Standard: Distribution<T> {
216             #[inline]
217             fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> [T; $n] {
218                 [_rng.gen::<$t>(), $(_rng.gen::<$ts>()),*]
219             }
220         }
221     };
222     // empty case:
223     {$n:expr,} => {
224         impl<T> Distribution<[T; $n]> for Standard {
225             fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> [T; $n] { [] }
226         }
227     };
228 }
229 
230 #[cfg(not(feature = "min_const_gen"))]
231 array_impl! {32, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T,}
232 
233 impl<T> Distribution<Option<T>> for Standard
234 where Standard: Distribution<T>
235 {
236     #[inline]
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Option<T>237     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Option<T> {
238         // UFCS is needed here: https://github.com/rust-lang/rust/issues/24066
239         if rng.gen::<bool>() {
240             Some(rng.gen())
241         } else {
242             None
243         }
244     }
245 }
246 
247 impl<T> Distribution<Wrapping<T>> for Standard
248 where Standard: Distribution<T>
249 {
250     #[inline]
sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Wrapping<T>251     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Wrapping<T> {
252         Wrapping(rng.gen())
253     }
254 }
255 
256 
257 #[cfg(test)]
258 mod tests {
259     use super::*;
260     use crate::RngCore;
261     #[cfg(feature = "alloc")] use alloc::string::String;
262 
263     #[test]
test_misc()264     fn test_misc() {
265         let rng: &mut dyn RngCore = &mut crate::test::rng(820);
266 
267         rng.sample::<char, _>(Standard);
268         rng.sample::<bool, _>(Standard);
269     }
270 
271     #[cfg(feature = "alloc")]
272     #[test]
test_chars()273     fn test_chars() {
274         use core::iter;
275         let mut rng = crate::test::rng(805);
276 
277         // Test by generating a relatively large number of chars, so we also
278         // take the rejection sampling path.
279         let word: String = iter::repeat(())
280             .map(|()| rng.gen::<char>())
281             .take(1000)
282             .collect();
283         assert!(!word.is_empty());
284     }
285 
286     #[test]
test_alphanumeric()287     fn test_alphanumeric() {
288         let mut rng = crate::test::rng(806);
289 
290         // Test by generating a relatively large number of chars, so we also
291         // take the rejection sampling path.
292         let mut incorrect = false;
293         for _ in 0..100 {
294             let c: char = rng.sample(Alphanumeric).into();
295             incorrect |= !(('0'..='9').contains(&c) ||
296                            ('A'..='Z').contains(&c) ||
297                            ('a'..='z').contains(&c) );
298         }
299         assert!(!incorrect);
300     }
301 
302     #[test]
value_stability()303     fn value_stability() {
304         fn test_samples<T: Copy + core::fmt::Debug + PartialEq, D: Distribution<T>>(
305             distr: &D, zero: T, expected: &[T],
306         ) {
307             let mut rng = crate::test::rng(807);
308             let mut buf = [zero; 5];
309             for x in &mut buf {
310                 *x = rng.sample(&distr);
311             }
312             assert_eq!(&buf, expected);
313         }
314 
315         test_samples(&Standard, 'a', &[
316             '\u{8cdac}',
317             '\u{a346a}',
318             '\u{80120}',
319             '\u{ed692}',
320             '\u{35888}',
321         ]);
322         test_samples(&Alphanumeric, 0, &[104, 109, 101, 51, 77]);
323         test_samples(&Standard, false, &[true, true, false, true, false]);
324         test_samples(&Standard, None as Option<bool>, &[
325             Some(true),
326             None,
327             Some(false),
328             None,
329             Some(false),
330         ]);
331         test_samples(&Standard, Wrapping(0i32), &[
332             Wrapping(-2074640887),
333             Wrapping(-1719949321),
334             Wrapping(2018088303),
335             Wrapping(-547181756),
336             Wrapping(838957336),
337         ]);
338 
339         // We test only sub-sets of tuple and array impls
340         test_samples(&Standard, (), &[(), (), (), (), ()]);
341         test_samples(&Standard, (false,), &[
342             (true,),
343             (true,),
344             (false,),
345             (true,),
346             (false,),
347         ]);
348         test_samples(&Standard, (false, false), &[
349             (true, true),
350             (false, true),
351             (false, false),
352             (true, false),
353             (false, false),
354         ]);
355 
356         test_samples(&Standard, [0u8; 0], &[[], [], [], [], []]);
357         test_samples(&Standard, [0u8; 3], &[
358             [9, 247, 111],
359             [68, 24, 13],
360             [174, 19, 194],
361             [172, 69, 213],
362             [149, 207, 29],
363         ]);
364     }
365 }
366