Skip to content

Commit 969af18

Browse files
committed
Make top-level documentation more beginner-friendly
1 parent 72056fb commit 969af18

File tree

2 files changed

+188
-132
lines changed

2 files changed

+188
-132
lines changed

src/lib.rs

Lines changed: 144 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,74 @@
99
// except according to those terms.
1010

1111
//! Utilities for random number generation
12-
//!
13-
//! ## Example
14-
//!
15-
//! ```rust
12+
//!
13+
//! Rand provides utilities to generate random numbers, to convert them to
14+
//! useful types and distributions, and some randomness-related algorithms.
15+
//!
16+
//! # Basic use
17+
//!
18+
//! To quickly get you started, the easiest and most high-level way to just get
19+
//! some random value is to use [`random()`].
20+
//!
21+
//! ```
22+
//! let x: u8 = rand::random();
23+
//! println!("{}", x);
24+
//!
25+
//! let y = rand::random::<f64>();
26+
//! println!("{}", y);
27+
//!
28+
//! if rand::random() { // generates a boolean
29+
//! println!("Heads!");
30+
//! }
31+
//! ```
32+
//!
33+
//! This functionality is however very basic. As soon as you need something
34+
//! slightly more specific, like a random value in some range, you have to know
35+
//! a bit more about how things work.
36+
//!
37+
//!
38+
//! # The two-step process to get a random value
39+
//!
40+
//! To get a random value, you usually need two pieces:
41+
//!
42+
//! - a random number generator (RNG);
43+
//! - some function to transform the 'bag of bits' from the RNG to a value you
44+
//! can use (which we call a distribution, although we use the term for a bit
45+
//! more functionality than what fits the meaning).
46+
//!
47+
//! There are many kinds of RNGs, with different trade-offs. Rand comes with a
48+
//! good all-use default, [`ThreadRng`]. Is is easily available through the
49+
//! [`thread_rng()`] function. It is reasonably fast and has good quality (secure
50+
//! and without patterns).
51+
//!
52+
//! To turn the output of the RNG into something usable, you usually want to use
53+
//! the methods from the [`Rng`] trait:
54+
//!
55+
//! - [`gen`] generates a random value appropriate for the type.
56+
//! For example `let val: u16 = rng.gen()` will produces a random value
57+
//! between 0 and `std::u16::MAX`. But for floats the value will be generated
58+
//! uniformly between 0 and 1, which is more useful than a completely random
59+
//! float value (including NaN and infinity);
60+
//! - [`gen_range`] samples from a specific range of values;
61+
//! - [`sample`] samples directly from some distribution, useful for all
62+
//! situations where you need something slightly more complex.
63+
//!
64+
//! [`random()`] is nothing more than `thread_rng().gen()`.
65+
//!
66+
//! ## Further reading
67+
//!
68+
//! The [`rngs` module] provides more background on RNGs. For example: What are
69+
//! [`StdRng`] and [`SmallRng`], and why use them? Why do some RNGs need
70+
//! seeding, and where do you get a seed?
71+
//!
72+
//! The [`distributions` module] provides more documentation on distributions.
73+
//! How do you make [`Rng::gen`] available for a custom type? What are
74+
//! distributions good for? How do you sample from probability distributions?
75+
//!
76+
//!
77+
//! ## Examples
78+
//!
79+
//! ```
1680
//! // Rng is the main trait and needs to be imported:
1781
//! use rand::{Rng, thread_rng};
1882
//!
@@ -21,149 +85,97 @@
2185
//! if rng.gen() { // random bool
2286
//! let x: f64 = rng.gen(); // random number in range (0, 1)
2387
//! println!("x is: {}", x);
88+
//! let char = rng.gen::<char>(); // Sometimes you need type annotation
89+
//! println!("char is: {}", char);
2490
//! println!("Number from 0 to 9: {}", rng.gen_range(0, 10));
2591
//! }
2692
//! ```
2793
//!
28-
//! The key function is [`Rng::gen()`]. It is polymorphic and so can be used to
29-
//! generate many types; the [`Standard`] distribution carries the
30-
//! implementations. In some cases type annotation is required, e.g.
31-
//! `rng.gen::<f64>()`.
3294
//!
33-
//! # Getting random values
95+
//! # Other functionality
3496
//!
35-
//! The most convenient source of randomness is likely [`thread_rng`], which
36-
//! automatically initialises a fast algorithmic generator on first use per
37-
//! thread with thread-local storage.
38-
//!
39-
//! If one wants to obtain random data directly from an external source it is
40-
//! recommended to use [`EntropyRng`] which manages multiple available sources
41-
//! or [`OsRng`] which retrieves random data directly from the OS. It should be
42-
//! noted that this is significantly slower than using a local generator like
43-
//! [`thread_rng`] and potentially much slower if [`EntropyRng`] must fall back to
44-
//! [`JitterRng`] as a source.
45-
//!
46-
//! It is also common to use an algorithmic generator in local memory; this may
47-
//! be faster than `thread_rng` and provides more control. In this case
48-
//! [`StdRng`] — the generator behind [`thread_rng`] — and [`SmallRng`] — a
49-
//! small, fast, weak generator — are good choices; more options can be found in
50-
//! the [`prng`] module as well as in other crates.
51-
//!
52-
//! Local generators need to be seeded. It is recommended to use [`FromEntropy`] or
53-
//! to seed from a strong parent generator with [`from_rng`]:
54-
//!
55-
//! ```
56-
//! # use rand::{Rng, Error};
57-
//! // seed with fresh entropy:
58-
//! use rand::{StdRng, FromEntropy};
59-
//! let mut rng = StdRng::from_entropy();
60-
//! # let v: u32 = rng.gen();
61-
//!
62-
//! // seed from thread_rng:
63-
//! use rand::{SmallRng, SeedableRng, thread_rng};
97+
//! The ability to generate random values is not the only thing Rand provides.
98+
//! Most functionality is available through the [`Rng`] trait, so that is useful
99+
//! to explore. Some of its methods include:
64100
//!
65-
//! # fn try_inner() -> Result<(), Error> {
66-
//! let mut rng = SmallRng::from_rng(thread_rng())?;
67-
//! # let v: u32 = rng.gen();
68-
//! # Ok(())
69-
//! # }
70-
//! # try_inner().unwrap()
71-
//! ```
72-
//!
73-
//! In case you specifically want to have a reproducible stream of "random"
74-
//! data (e.g. to procedurally generate a game world), select a named algorithm
75-
//! (i.e. not [`StdRng`]/[`SmallRng`] which may be adjusted in the future), and
76-
//! use [`SeedableRng::from_seed`] or a constructor specific to the generator
77-
//! (e.g. [`IsaacRng::new_from_u64`]).
78-
//!
79-
//! ## Applying / converting random data
80-
//!
81-
//! The [`RngCore`] trait allows generators to implement a common interface for
82-
//! retrieving random data, but how should you use this? Typically users should
83-
//! use the [`Rng`] trait not [`RngCore`]; this provides more flexible ways to
84-
//! access the same data (e.g. `gen()` can output many more types than
85-
//! `next_u32()` and `next_u64()`; Rust's optimiser should eliminate any
86-
//! overhead). It also provides several useful algorithms,
87-
//! e.g. `gen_bool(p)` to generate events with weighted probability and
88-
//! `shuffle(&mut v[..])` to randomly-order a vector.
89-
//!
90-
//! The [`distributions`] module provides several more ways to convert random
91-
//! data to useful values, e.g. time of decay is often modelled with an
92-
//! exponential distribution, and the log-normal distribution provides a good
93-
//! model of many natural phenomona.
94-
//!
95-
//! The [`seq`] module has a few tools applicable to sliceable or iterable data.
96-
//!
97-
//! ## Cryptographic security
98-
//!
99-
//! First, lets recap some terminology:
101+
//! - [`Rng::sample_iter`] to get an iterator for the choosen distribution.
102+
//! - [`Rng::gen_bool`] to generate events with weighted probability.
103+
//! - [`Rng::fill`] and [`Rng::try_fill`] as fast alternatives to fill a slice
104+
//! of integers.
105+
//! - [`Rng::shuffle`] can be used to shuffle slices.
106+
//! - [`Rng::choose`] to pick one element at random from a slice, and the
107+
//! functions in the [`seq`] module to the pick multiple.
108+
//!
109+
//! Also there is [`distributions::WeightedChoice`], which can be used to pick
110+
//! elements at random with some probability. But it does not work well at the
111+
//! moment and is going through a redesign.
112+
//!
113+
//!
114+
//! # Error handling
115+
//!
116+
//! The story around error handling in Rand is a bit of a practical compromise.
117+
//! On one hand PRNGs and distributions are never supposed to produce an error.
118+
//! Threading error handling through them would be unnecessary and make Rand
119+
//! very unergonomic to use. On the other hand external RNGs, like those from
120+
//! the OS or a hardware device, very well may produce an error.
121+
//!
122+
//! All methods that normally would only be used in combination with a PRNG
123+
//! always just produce a value. This might mean a fallible RNG has to panic
124+
//! if it is unable to return a value when used in combination with these
125+
//! methods.
126+
//!
127+
//! Only the handful of methods that are usually desired for external RNGs can
128+
//! report errors, such as [`Rng::try_fill`], [`RngCore::try_fill_bytes`], and
129+
//! [`SeedableRng::from_rng`].
130+
//!
131+
//!
132+
//! # Distinction between Rand and `rand_core`
133+
//!
134+
//! [`rand_core`] provides all the parts necessary for implementing RNGs, among
135+
//! which are the [`RngCore`] and [`SeedableRng`] traits, and an [`Error`] type.
136+
//! Crates implementing RNGs would ideally depend on [`rand_core`].
137+
//!
138+
//! Common applicaties and libraries however are encouraged to use the Rand
139+
//! crate instead, which re-exports the main traits and error types.
100140
//!
101-
//! - **PRNG:** *Pseudo-Random-Number-Generator* is another name for an
102-
//! *algorithmic generator*
103-
//! - **CSPRNG:** a *Cryptographically Secure* PRNG
104141
//!
105-
//! Security analysis requires a threat model and expert review; we can provide
106-
//! neither, but we can provide a few hints. We assume that the goal is to
107-
//! produce secret apparently-random data. Therefore, we need:
108-
//!
109-
//! - A good source of entropy. A known algorithm given known input data is
110-
//! trivial to predict, and likewise if there's a non-negligable chance that
111-
//! the input to a PRNG is guessable then there's a chance its output is too.
112-
//! We recommend seeding CSPRNGs with [`EntropyRng`] or [`OsRng`] which
113-
//! provide fresh "random" values from an external source.
114-
//! One can also seed from another CSPRNG, e.g. `thread_rng`, which is faster,
115-
//! but adds another component which must be trusted.
116-
//! - A strong algorithmic generator. It is possible to use a good entropy
117-
//! source like `OsRng` directly, and in some cases this is the best option,
118-
//! but for better performance (or if requiring reproducible values generated
119-
//! from a fixed seed) it is common to use a local CSPRNG. The basic security
120-
//! that CSPRNGs must provide is making it infeasible to predict future output
121-
//! given a sample of past output. A further security that *some* CSPRNGs
122-
//! provide is *forward secrecy*; this ensures that in the event that the
123-
//! algorithm's state is revealed, it is infeasible to reconstruct past
124-
//! output. See the [`CryptoRng`] trait and notes on individual algorithms.
125-
//! - To be careful not to leak secrets like keys and CSPRNG's internal state
126-
//! and robust against "side channel attacks". This goes well beyond the scope
127-
//! of random number generation, but this crate takes some precautions:
128-
//! - to avoid printing CSPRNG state in log files, implementations have a
129-
//! custom `Debug` implementation which omits all internal state
130-
//! - `thread_rng` uses [`ReseedingRng`] to periodically refresh its state
131-
//! - in the future we plan to add some protection against fork attacks
132-
//! (where the process is forked and each clone generates the same "random"
133-
//! numbers); this is not yet implemented (see issues #314, #370)
134-
//!
135142
//! # Examples
136143
//!
137144
//! For some inspiration, see the examples:
138-
//!
139-
//! * [Monte Carlo estimation of π](
140-
//! https://github.com/rust-lang-nursery/rand/blob/master/examples/monte-carlo.rs)
141-
//! * [Monty Hall Problem](
142-
//! https://github.com/rust-lang-nursery/rand/blob/master/examples/monty-hall.rs)
143145
//!
144-
//! [`Rng`]: trait.Rng.html
145-
//! [`Rng::gen()`]: trait.Rng.html#method.gen
146+
//! - [Monte Carlo estimation of π](
147+
//! https://github.com/rust-lang-nursery/rand/blob/master/examples/monte-carlo.rs)
148+
//! - [Monty Hall Problem](
149+
//! https://github.com/rust-lang-nursery/rand/blob/master/examples/monty-hall.rs)
150+
//!
151+
//!
152+
//! [`distributions` module]: distributions/index.html
153+
//! [`distributions::WeightedChoice`]: distributions/struct.WeightedChoice.html
154+
//! [`Error`]: struct.Error.html
155+
//! [`gen_range`]: trait.Rng.html#method.gen_range
156+
//! [`gen`]: trait.Rng.html#method.gen
157+
//! [`rand_core`]: https://crates.io/crates/rand_core
158+
//! [`random()`]: fn.random.html
159+
//! [`Rng::choose`]: trait.Rng.html#method.choose
160+
//! [`Rng::fill`]: trait.Rng.html#method.fill
161+
//! [`Rng::gen_bool`]: trait.Rng.html#method.gen_bool
162+
//! [`Rng::gen`]: trait.Rng.html#method.gen
163+
//! [`Rng::sample_iter`]: trait.Rng.html#method.sample_iter
164+
//! [`Rng::shuffle`]: trait.Rng.html#method.shuffle
146165
//! [`RngCore`]: trait.RngCore.html
147-
//! [`FromEntropy`]: trait.FromEntropy.html
148-
//! [`SeedableRng::from_seed`]: trait.SeedableRng.html#tymethod.from_seed
149-
//! [`from_rng`]: trait.SeedableRng.html#method.from_rng
150-
//! [`CryptoRng`]: trait.CryptoRng.html
151-
//! [`thread_rng`]: fn.thread_rng.html
152-
//! [`EntropyRng`]: struct.EntropyRng.html
153-
//! [`OsRng`]: os/struct.OsRng.html
154-
//! [`JitterRng`]: jitter/struct.JitterRng.html
155-
//! [`StdRng`]: struct.StdRng.html
156-
//! [`SmallRng`]: struct.SmallRng.html
157-
//! [`ReseedingRng`]: reseeding/struct.ReseedingRng.html
158-
//! [`prng`]: prng/index.html
159-
//! [`IsaacRng::new_from_u64`]: prng/isaac/struct.IsaacRng.html#method.new_from_u64
160-
//! [`Hc128Rng`]: prng/hc128/struct.Hc128Rng.html
161-
//! [`ChaChaRng`]: prng/chacha/struct.ChaChaRng.html
162-
//! [`IsaacRng`]: prng/isaac/struct.IsaacRng.html
163-
//! [`Isaac64Rng`]: prng/isaac64/struct.Isaac64Rng.html
166+
//! [`RngCore::try_fill_bytes`]: trait.RngCore.html#method.try_fill_bytes
167+
//! [`rngs` module]: rngs/index.html
168+
//! [`Rng`]: trait.Rng.html
169+
//! [`Rng::try_fill`]: trait.Rng.html#method.try_fill
170+
//! [`sample`]: trait.Rng.html#method.sample
171+
//! [`SeedableRng`]: trait.SeedableRng.html
172+
//! [`SeedableRng::from_rng`]: trait.SeedableRng.html#method.from_rng
164173
//! [`seq`]: seq/index.html
165-
//! [`distributions`]: distributions/index.html
166-
//! [`Standard`]: distributions/struct.Standard.html
174+
//! [`SmallRng`]: struct.SmallRng.html
175+
//! [`StdRng`]: struct.StdRng.html
176+
//! [`thread_rng()`]: fn.thread_rng.html
177+
//! [`ThreadRng`]: rngs/struct.ThreadRng.html
178+
167179

168180
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
169181
html_favicon_url = "https://www.rust-lang.org/favicon.ico",

src/prng/mod.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,50 @@
3939
//! short periods for some seeds. If one PRNG is seeded from another using the
4040
//! same algorithm, it is possible that both will yield the same sequence of
4141
//! values (with some lag).
42+
//!
43+
//! ## Cryptographic security
44+
//!
45+
//! First, lets recap some terminology:
46+
//!
47+
//! - **PRNG:** *Pseudo-Random-Number-Generator* is another name for an
48+
//! *algorithmic generator*
49+
//! - **CSPRNG:** a *Cryptographically Secure* PRNG
50+
//!
51+
//! Security analysis requires a threat model and expert review; we can provide
52+
//! neither, but we can provide a few hints. We assume that the goal is to
53+
//! produce secret apparently-random data. Therefore, we need:
54+
//!
55+
//! - A good source of entropy. A known algorithm given known input data is
56+
//! trivial to predict, and likewise if there's a non-negligable chance that
57+
//! the input to a PRNG is guessable then there's a chance its output is too.
58+
//! We recommend seeding CSPRNGs with [`EntropyRng`] or [`OsRng`] which
59+
//! provide fresh "random" values from an external source.
60+
//! One can also seed from another CSPRNG, e.g. [`thread_rng`], which is faster,
61+
//! but adds another component which must be trusted.
62+
//! - A strong algorithmic generator. It is possible to use a good entropy
63+
//! source like [`OsRng`] directly, and in some cases this is the best option,
64+
//! but for better performance (or if requiring reproducible values generated
65+
//! from a fixed seed) it is common to use a local CSPRNG. The basic security
66+
//! that CSPRNGs must provide is making it infeasible to predict future output
67+
//! given a sample of past output. A further security that *some* CSPRNGs
68+
//! provide is *forward secrecy*; this ensures that in the event that the
69+
//! algorithm's state is revealed, it is infeasible to reconstruct past
70+
//! output. See the [`CryptoRng`] trait and notes on individual algorithms.
71+
//! - To be careful not to leak secrets like keys and CSPRNG's internal state
72+
//! and robust against "side channel attacks". This goes well beyond the scope
73+
//! of random number generation, but this crate takes some precautions:
74+
//! - to avoid printing CSPRNG state in log files, implementations have a
75+
//! custom `Debug` implementation which omits all internal state
76+
//! - [`thread_rng`] uses [`ReseedingRng`] to periodically refresh its state
77+
//! - in the future we plan to add some protection against fork attacks
78+
//! (where the process is forked and each clone generates the same "random"
79+
//! numbers); this is not yet implemented (see issues #314, #370)
80+
//!
81+
//! [`CryptoRng`]: ../trait.CryptoRng.html
82+
//! [`EntropyRng`]: ../rngs/struct.EntropyRng.html
83+
//! [`OsRng`]: ../rngs/struct.OsRng.html
84+
//! [`ReseedingRng`]: ../rngs/struct.ReseedingRng.html
85+
//! [`thread_rng`]: ../fn.thread_rng.html
4286
4387
pub mod chacha;
4488
pub mod hc128;

0 commit comments

Comments
 (0)