|
1 | 1 | //! Random value generation.
|
2 |
| -//! |
3 |
| -//! The [`Random`] trait allows generating a random value for a type using a |
4 |
| -//! given [`RandomSource`]. |
| 2 | +
|
| 3 | +use crate::range::RangeFull; |
5 | 4 |
|
6 | 5 | /// A source of randomness.
|
7 | 6 | #[unstable(feature = "random", issue = "130703")]
|
8 | 7 | pub trait RandomSource {
|
9 | 8 | /// Fills `bytes` with random bytes.
|
| 9 | + /// |
| 10 | + /// Note that calling `fill_bytes` multiple times is not equivalent to calling `fill_bytes` once |
| 11 | + /// with a larger buffer. A `RandomSource` is allowed to return different bytes for those two |
| 12 | + /// cases. For instance, this allows a `RandomSource` to generate a word at a time and throw |
| 13 | + /// part of it away if not needed. |
10 | 14 | fn fill_bytes(&mut self, bytes: &mut [u8]);
|
11 | 15 | }
|
12 | 16 |
|
13 |
| -/// A trait for getting a random value for a type. |
14 |
| -/// |
15 |
| -/// **Warning:** Be careful when manipulating random values! The |
16 |
| -/// [`random`](Random::random) method on integers samples them with a uniform |
17 |
| -/// distribution, so a value of 1 is just as likely as [`i32::MAX`]. By using |
18 |
| -/// modulo operations, some of the resulting values can become more likely than |
19 |
| -/// others. Use audited crates when in doubt. |
| 17 | +/// A trait representing a distribution of random values for a type. |
20 | 18 | #[unstable(feature = "random", issue = "130703")]
|
21 |
| -pub trait Random: Sized { |
22 |
| - /// Generates a random value. |
23 |
| - fn random(source: &mut (impl RandomSource + ?Sized)) -> Self; |
| 19 | +pub trait Distribution<T> { |
| 20 | + /// Samples a random value from the distribution, using the specified random source. |
| 21 | + fn sample(&self, source: &mut (impl RandomSource + ?Sized)) -> T; |
| 22 | +} |
| 23 | + |
| 24 | +impl<T, DT: Distribution<T>> Distribution<T> for &DT { |
| 25 | + fn sample(&self, source: &mut (impl RandomSource + ?Sized)) -> T { |
| 26 | + (*self).sample(source) |
| 27 | + } |
24 | 28 | }
|
25 | 29 |
|
26 |
| -impl Random for bool { |
27 |
| - fn random(source: &mut (impl RandomSource + ?Sized)) -> Self { |
28 |
| - u8::random(source) & 1 == 1 |
| 30 | +impl Distribution<bool> for RangeFull { |
| 31 | + fn sample(&self, source: &mut (impl RandomSource + ?Sized)) -> bool { |
| 32 | + let byte: u8 = RangeFull.sample(source); |
| 33 | + byte & 1 == 1 |
29 | 34 | }
|
30 | 35 | }
|
31 | 36 |
|
32 | 37 | macro_rules! impl_primitive {
|
33 | 38 | ($t:ty) => {
|
34 |
| - impl Random for $t { |
35 |
| - /// Generates a random value. |
36 |
| - /// |
37 |
| - /// **Warning:** Be careful when manipulating the resulting value! This |
38 |
| - /// method samples according to a uniform distribution, so a value of 1 is |
39 |
| - /// just as likely as [`MAX`](Self::MAX). By using modulo operations, some |
40 |
| - /// values can become more likely than others. Use audited crates when in |
41 |
| - /// doubt. |
42 |
| - fn random(source: &mut (impl RandomSource + ?Sized)) -> Self { |
43 |
| - let mut bytes = (0 as Self).to_ne_bytes(); |
| 39 | + impl Distribution<$t> for RangeFull { |
| 40 | + fn sample(&self, source: &mut (impl RandomSource + ?Sized)) -> $t { |
| 41 | + let mut bytes = (0 as $t).to_ne_bytes(); |
44 | 42 | source.fill_bytes(&mut bytes);
|
45 |
| - Self::from_ne_bytes(bytes) |
| 43 | + <$t>::from_ne_bytes(bytes) |
46 | 44 | }
|
47 | 45 | }
|
48 | 46 | };
|
|
0 commit comments