This will let people make calls like random(1..=6), and allows for future expansion to non-uniform distributions, as well as floating-point. For now, this is only implemented for `RangeFull`, to get the interface in place. Subsequent commits will implement it for other range types.
60 lines
1.8 KiB
Rust
60 lines
1.8 KiB
Rust
//! Random value generation.
|
|
|
|
use crate::range::RangeFull;
|
|
|
|
/// A source of randomness.
|
|
#[unstable(feature = "random", issue = "130703")]
|
|
pub trait RandomSource {
|
|
/// Fills `bytes` with random bytes.
|
|
///
|
|
/// Note that calling `fill_bytes` multiple times is not equivalent to calling `fill_bytes` once
|
|
/// with a larger buffer. A `RandomSource` is allowed to return different bytes for those two
|
|
/// cases. For instance, this allows a `RandomSource` to generate a word at a time and throw
|
|
/// part of it away if not needed.
|
|
fn fill_bytes(&mut self, bytes: &mut [u8]);
|
|
}
|
|
|
|
/// A trait representing a distribution of random values for a type.
|
|
#[unstable(feature = "random", issue = "130703")]
|
|
pub trait Distribution<T> {
|
|
/// Samples a random value from the distribution, using the specified random source.
|
|
fn sample(&self, source: &mut (impl RandomSource + ?Sized)) -> T;
|
|
}
|
|
|
|
impl<T, DT: Distribution<T>> Distribution<T> for &DT {
|
|
fn sample(&self, source: &mut (impl RandomSource + ?Sized)) -> T {
|
|
(*self).sample(source)
|
|
}
|
|
}
|
|
|
|
impl Distribution<bool> for RangeFull {
|
|
fn sample(&self, source: &mut (impl RandomSource + ?Sized)) -> bool {
|
|
let byte: u8 = RangeFull.sample(source);
|
|
byte & 1 == 1
|
|
}
|
|
}
|
|
|
|
macro_rules! impl_primitive {
|
|
($t:ty) => {
|
|
impl Distribution<$t> for RangeFull {
|
|
fn sample(&self, source: &mut (impl RandomSource + ?Sized)) -> $t {
|
|
let mut bytes = (0 as $t).to_ne_bytes();
|
|
source.fill_bytes(&mut bytes);
|
|
<$t>::from_ne_bytes(bytes)
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
impl_primitive!(u8);
|
|
impl_primitive!(i8);
|
|
impl_primitive!(u16);
|
|
impl_primitive!(i16);
|
|
impl_primitive!(u32);
|
|
impl_primitive!(i32);
|
|
impl_primitive!(u64);
|
|
impl_primitive!(i64);
|
|
impl_primitive!(u128);
|
|
impl_primitive!(i128);
|
|
impl_primitive!(usize);
|
|
impl_primitive!(isize);
|