From 63ce5798c3bae98143693d49ee50cd61b48240d0 Mon Sep 17 00:00:00 2001 From: joboet Date: Mon, 13 Jul 2026 12:03:21 +0200 Subject: [PATCH] std: improve the documentation of the random feature --- library/std/src/random.rs | 85 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 3 deletions(-) diff --git a/library/std/src/random.rs b/library/std/src/random.rs index 88221e7e3b9c9..ef561d1ed0c60 100644 --- a/library/std/src/random.rs +++ b/library/std/src/random.rs @@ -1,4 +1,52 @@ //! Random value generation. +//! +//! This module provides two low-level interfaces for random number generation: +//! * The [`Rng`] trait abstracts over all random number generators (RNGs) and +//! is intended to be used in all cases where the choice of RNG is left to the +//! user. It provides the [`fill_bytes`](Rng::fill_bytes) method that fills a +//! buffer of [`u8`]s with freshly-generated random data. +//! * The [`SystemRng`] implements the [`Rng`] trait by asking the operating +//! system for cryptographically-secure random data on every call to +//! `fill_bytes`. +//! +//! In the future, higher-level interfaces for features like sampling distributions +//! may be added to this module. Until that time, users of `fill_bytes` should +//! take care to avoid sampling bias when using the filled byte buffer to create +//! an instance of another type. In particular, the modulo operation is **not** +//! suitable for constraining the range of an unconstrained number: +//! ```compile_fail +//! let mut buf = [0; 2]; +//! rng.fill_bytes(&mut buf); +//! // 💀 **DO NOT DO THIS** 💀 +//! // Numbers below ca. 22000 will be twice as likely. +//! let very_bad_random_number = u16::from_ne_bytes(buf) % 45000; +//! ``` +//! +//! # Examples +//! +//! Generating a [version 4/variant 1 UUID] represented as text: +//! ``` +//! #![feature(random)] +//! +//! use std::random::{Rng, SystemRng}; +//! +//! fn uuid(rng: &mut impl Rng) -> String { +//! let mut buf = [0; 16]; +//! rng.fill_bytes(&mut buf); +//! // Use little-endian to make the result reproducible across architectures. +//! let bits = u128::from_le_bytes(buf); +//! let g1 = (bits >> 96) as u32; +//! let g2 = (bits >> 80) as u16; +//! let g3 = (0x4000 | (bits >> 64) & 0x0fff) as u16; +//! let g4 = (0x8000 | (bits >> 48) & 0x3fff) as u16; +//! let g5 = (bits & 0xffffffffffff) as u64; +//! format!("{g1:08x}-{g2:04x}-{g3:04x}-{g4:04x}-{g5:012x}") +//! } +//! +//! println!("{}", uuid(&mut SystemRng)); +//! ``` +//! +//! [version 4/variant 1 UUID]: https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random) #[unstable(feature = "random", issue = "130703")] pub use core::random::*; @@ -13,10 +61,28 @@ use crate::sys::random as sys; /// /// The high quality of randomness provided by this source means it can be quite /// slow on some targets. If you need a large quantity of random numbers and -/// security is not a concern, consider using an alternative random number -/// generator (potentially seeded from this one). +/// security is not a concern, you might want to consider using an alternative +/// random number generator. That said, `std` attempts to use the fastest source +/// available on the system that still provides strong security. A custom random +/// number generator will in nearly all cases have weaker security attributes +/// than `SystemRng`. /// -/// If you need to fill a buffer with random bytes, use `SystemRng.fill_bytes(&mut buf)`. +/// # Blocking +/// +/// The underlying syscalls might block the calling thread until there is +/// sufficient [entropy] in the system to seed a procedural random number +/// generator. This is usually only a concern if the program runs immediately +/// after the system boots. +/// +/// # Panicking +/// +/// Calling `fill_bytes` will panic if the system cannot provide the required +/// random data. Due to the blocking behaviour described above, this is a +/// permanent condition in nearly all cases and implies that the system lacks +/// the facilities (hardware or software) necessary for collecting entropy. +/// Non-embedded systems usually do not suffer from this limitation. +/// +/// [entropy]: https://en.wikipedia.org/wiki/Entropy_(information_theory) /// /// # Underlying sources /// @@ -59,6 +125,19 @@ use crate::sys::random as sys; /// [`getrandom`]: https://www.man7.org/linux/man-pages/man2/getrandom.2.html /// [`/dev/urandom`]: https://www.man7.org/linux/man-pages/man4/random.4.html /// [`get-random-bytes`]: https://github.com/WebAssembly/WASI/blob/main/proposals/random/imports.md#get-random-bytes-func +/// +/// # Examples +/// +/// Filling a buffer with random bytes +/// ``` +/// #![feature(random)] +/// +/// use std::random::{Rng, SystemRng}; +/// +/// let mut buf = [0; 16]; +/// SystemRng.fill_bytes(&mut buf); +/// dbg!(buf); +/// ``` #[doc(alias = "getrandom", alias = "getentropy", alias = "arc4random")] #[derive(Default, Debug, Clone, Copy)] #[unstable(feature = "random", issue = "130703")]