Doc: improve random, thread_rng, ThreadRng docs (#1257)
* Use a custom Debug impl for ThreadRng * Adjust documentation of random, thread_rng, ThreadRng * Fix no-std build * Compatibility with older rustc
This commit is contained in:
parent
2b4f00add7
commit
766c7eccd7
@ -19,8 +19,9 @@ use getrandom::getrandom;
|
||||
/// The implementation is provided by the [getrandom] crate. Refer to
|
||||
/// [getrandom] documentation for details.
|
||||
///
|
||||
/// This struct is only available when specifying the crate feature `getrandom`
|
||||
/// or `std`. When using the `rand` lib, it is also available as `rand::rngs::OsRng`.
|
||||
/// This struct is available as `rand_core::OsRng` and as `rand::rngs::OsRng`.
|
||||
/// In both cases, this requires the crate feature `getrandom` or `std`
|
||||
/// (enabled by default in `rand` but not in `rand_core`).
|
||||
///
|
||||
/// # Blocking and error handling
|
||||
///
|
||||
|
33
src/lib.rs
33
src/lib.rs
@ -110,36 +110,10 @@ use crate::distributions::{Distribution, Standard};
|
||||
|
||||
/// Generates a random value using the thread-local random number generator.
|
||||
///
|
||||
/// This is simply a shortcut for `thread_rng().gen()`. See [`thread_rng`] for
|
||||
/// documentation of the entropy source and [`Standard`] for documentation of
|
||||
/// distributions and type-specific generation.
|
||||
/// This function is simply a shortcut for `thread_rng().gen()`:
|
||||
///
|
||||
/// # Provided implementations
|
||||
///
|
||||
/// The following types have provided implementations that
|
||||
/// generate values with the following ranges and distributions:
|
||||
///
|
||||
/// * Integers (`i32`, `u32`, `isize`, `usize`, etc.): Uniformly distributed
|
||||
/// over all values of the type.
|
||||
/// * `char`: Uniformly distributed over all Unicode scalar values, i.e. all
|
||||
/// code points in the range `0...0x10_FFFF`, except for the range
|
||||
/// `0xD800...0xDFFF` (the surrogate code points). This includes
|
||||
/// unassigned/reserved code points.
|
||||
/// * `bool`: Generates `false` or `true`, each with probability 0.5.
|
||||
/// * Floating point types (`f32` and `f64`): Uniformly distributed in the
|
||||
/// half-open range `[0, 1)`. See notes below.
|
||||
/// * Wrapping integers (`Wrapping<T>`), besides the type identical to their
|
||||
/// normal integer variants.
|
||||
///
|
||||
/// Also supported is the generation of the following
|
||||
/// compound types where all component types are supported:
|
||||
///
|
||||
/// * Tuples (up to 12 elements): each element is generated sequentially.
|
||||
/// * Arrays (up to 32 elements): each element is generated sequentially;
|
||||
/// see also [`Rng::fill`] which supports arbitrary array length for integer
|
||||
/// types and tends to be faster for `u32` and smaller types.
|
||||
/// * `Option<T>` first generates a `bool`, and if true generates and returns
|
||||
/// `Some(value)` where `value: T`, otherwise returning `None`.
|
||||
/// - See [`ThreadRng`] for documentation of the generator and security
|
||||
/// - See [`Standard`] for documentation of supported types and distributions
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -177,6 +151,7 @@ use crate::distributions::{Distribution, Standard};
|
||||
/// ```
|
||||
///
|
||||
/// [`Standard`]: distributions::Standard
|
||||
/// [`ThreadRng`]: rngs::ThreadRng
|
||||
#[cfg(all(feature = "std", feature = "std_rng"))]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", feature = "std_rng"))))]
|
||||
#[inline]
|
||||
|
@ -53,7 +53,7 @@ use core::{mem, slice};
|
||||
/// # let v = foo(&mut thread_rng());
|
||||
/// ```
|
||||
pub trait Rng: RngCore {
|
||||
/// Return a random value supporting the [`Standard`] distribution.
|
||||
/// Return a random value via the [`Standard`] distribution.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
|
@ -11,6 +11,7 @@
|
||||
use core::cell::UnsafeCell;
|
||||
use std::rc::Rc;
|
||||
use std::thread_local;
|
||||
use std::fmt;
|
||||
|
||||
use super::std::Core;
|
||||
use crate::rngs::adapter::ReseedingRng;
|
||||
@ -39,31 +40,43 @@ const THREAD_RNG_RESEED_THRESHOLD: u64 = 1024 * 64;
|
||||
|
||||
/// A reference to the thread-local generator
|
||||
///
|
||||
/// This type is a reference to a lazily-initialized thread-local generator.
|
||||
/// An instance can be obtained via [`thread_rng`] or via `ThreadRng::default()`.
|
||||
/// This handle is safe to use everywhere (including thread-local destructors),
|
||||
/// though it is recommended not to use inside a fork handler.
|
||||
/// The handle cannot be passed between threads (is not `Send` or `Sync`).
|
||||
///
|
||||
/// `ThreadRng` uses the same PRNG as [`StdRng`] for security and performance
|
||||
/// and is automatically seeded from [`OsRng`].
|
||||
/// `ThreadRng` uses the same CSPRNG as [`StdRng`], ChaCha12. As with
|
||||
/// [`StdRng`], the algorithm may be changed, subject to reasonable expectations
|
||||
/// of security and performance.
|
||||
///
|
||||
/// Unlike `StdRng`, `ThreadRng` uses the [`ReseedingRng`] wrapper to reseed
|
||||
/// the PRNG from fresh entropy every 64 kiB of random data as well as after a
|
||||
/// fork on Unix (though not quite immediately; see documentation of
|
||||
/// [`ReseedingRng`]).
|
||||
/// Note that the reseeding is done as an extra precaution against side-channel
|
||||
/// attacks and mis-use (e.g. if somehow weak entropy were supplied initially).
|
||||
/// The PRNG algorithms used are assumed to be secure.
|
||||
/// `ThreadRng` is automatically seeded from [`OsRng`] with periodic reseeding
|
||||
/// (every 64 kiB, as well as "soon" after a fork on Unix — see [`ReseedingRng`]
|
||||
/// documentation for details).
|
||||
///
|
||||
/// Security must be considered relative to a thread model and validation
|
||||
/// requirements. `ThreadRng` attempts to meet basic security considerations
|
||||
/// for producing unpredictable random numbers: use a CSPRNG, use a
|
||||
/// recommended platform-specific seed ([`OsRng`]), and avoid
|
||||
/// leaking internal secrets e.g. via [`Debug`] implementation or serialization.
|
||||
/// Memory is not zeroized on drop.
|
||||
///
|
||||
/// [`ReseedingRng`]: crate::rngs::adapter::ReseedingRng
|
||||
/// [`StdRng`]: crate::rngs::StdRng
|
||||
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", feature = "std_rng"))))]
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone)]
|
||||
pub struct ThreadRng {
|
||||
// Rc is explicitly !Send and !Sync
|
||||
rng: Rc<UnsafeCell<ReseedingRng<Core, OsRng>>>,
|
||||
}
|
||||
|
||||
/// Debug implementation does not leak internal state
|
||||
impl fmt::Debug for ThreadRng {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(fmt, "ThreadRng {{ .. }}")
|
||||
}
|
||||
}
|
||||
|
||||
thread_local!(
|
||||
// We require Rc<..> to avoid premature freeing when thread_rng is used
|
||||
// within thread-local destructors. See #968.
|
||||
@ -77,13 +90,23 @@ thread_local!(
|
||||
}
|
||||
);
|
||||
|
||||
/// Retrieve the lazily-initialized thread-local random number generator,
|
||||
/// seeded by the system. Intended to be used in method chaining style,
|
||||
/// e.g. `thread_rng().gen::<i32>()`, or cached locally, e.g.
|
||||
/// `let mut rng = thread_rng();`. Invoked by the `Default` trait, making
|
||||
/// `ThreadRng::default()` equivalent.
|
||||
/// Access the thread-local generator
|
||||
///
|
||||
/// For more information see [`ThreadRng`].
|
||||
/// Returns a reference to the local [`ThreadRng`], initializing the generator
|
||||
/// on the first call on each thread.
|
||||
///
|
||||
/// Example usage:
|
||||
/// ```
|
||||
/// use rand::Rng;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// // rand::random() may be used instead of rand::thread_rng().gen():
|
||||
/// println!("A random boolean: {}", rand::random::<bool>());
|
||||
///
|
||||
/// let mut rng = rand::thread_rng();
|
||||
/// println!("A simulated die roll: {}", rng.gen_range(1..=6));
|
||||
/// # }
|
||||
/// ```
|
||||
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", feature = "std_rng"))))]
|
||||
pub fn thread_rng() -> ThreadRng {
|
||||
let rng = THREAD_RNG_KEY.with(|t| t.clone());
|
||||
@ -92,7 +115,7 @@ pub fn thread_rng() -> ThreadRng {
|
||||
|
||||
impl Default for ThreadRng {
|
||||
fn default() -> ThreadRng {
|
||||
crate::prelude::thread_rng()
|
||||
thread_rng()
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,4 +163,11 @@ mod test {
|
||||
r.gen::<i32>();
|
||||
assert_eq!(r.gen_range(0..1), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_debug_output() {
|
||||
// We don't care about the exact output here, but it must not include
|
||||
// private CSPRNG state or the cache stored by BlockRng!
|
||||
assert_eq!(std::format!("{:?}", crate::thread_rng()), "ThreadRng { .. }");
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user