blob: 051fe26086389282eb3970323bf15eec4e69f756 [file] [log] [blame] [edit]
//! Random value generation.
//!
//! The [`Random`] trait allows generating a random value for a type using a
//! given [`RandomSource`].
/// A source of randomness.
#[unstable(feature = "random", issue = "130703")]
pub trait RandomSource {
/// Fills `bytes` with random bytes.
fn fill_bytes(&mut self, bytes: &mut [u8]);
}
/// A trait for getting a random value for a type.
///
/// **Warning:** Be careful when manipulating random values! The
/// [`random`](Random::random) method on integers samples them with a uniform
/// distribution, so a value of 1 is just as likely as [`i32::MAX`]. By using
/// modulo operations, some of the resulting values can become more likely than
/// others. Use audited crates when in doubt.
#[unstable(feature = "random", issue = "130703")]
pub trait Random: Sized {
/// Generates a random value.
fn random(source: &mut (impl RandomSource + ?Sized)) -> Self;
}
impl Random for bool {
fn random(source: &mut (impl RandomSource + ?Sized)) -> Self {
u8::random(source) & 1 == 1
}
}
macro_rules! impl_primitive {
($t:ty) => {
impl Random for $t {
/// Generates a random value.
///
/// **Warning:** Be careful when manipulating the resulting value! This
/// method samples according to a uniform distribution, so a value of 1 is
/// just as likely as [`MAX`](Self::MAX). By using modulo operations, some
/// values can become more likely than others. Use audited crates when in
/// doubt.
fn random(source: &mut (impl RandomSource + ?Sized)) -> Self {
let mut bytes = (0 as Self).to_ne_bytes();
source.fill_bytes(&mut bytes);
Self::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);