diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 75e68cc..57ee9ad 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -29,6 +29,7 @@ - [Updating to 0.7](update-0.7.md) - [Updating to 0.8](update-0.8.md) - [Updating to 0.9](update-0.9.md) + - [Updating to 0.10](update-0.10.md) - [Contributing](contributing.md) - [Documentation](contrib-doc.md) diff --git a/src/guide-data.md b/src/guide-data.md index 8873e85..514b23e 100644 --- a/src/guide-data.md +++ b/src/guide-data.md @@ -1,8 +1,7 @@ # Random data ```rust -# extern crate rand; -# use rand::RngCore; +# use rand::Rng; # fn main() { // get some random data: let mut data = [0u8; 8]; diff --git a/src/guide-dist.md b/src/guide-dist.md index d620fb1..58c7dd4 100644 --- a/src/guide-dist.md +++ b/src/guide-dist.md @@ -94,7 +94,7 @@ Lets go over the distributions by type: - For enums, you have to implement uniform sampling yourself. For example, you could use the following approach: ```rust,noplayground - # use rand::{Rng, distr::{Distribution, StandardUniform}}; + # use rand::{Rng, RngExt, distr::{Distribution, StandardUniform}}; pub enum Food { Burger, Pizza, diff --git a/src/guide-gen.md b/src/guide-gen.md index a589b84..e0578a7 100644 --- a/src/guide-gen.md +++ b/src/guide-gen.md @@ -7,9 +7,7 @@ This section concerns theory; see also the chapter on [random number generators](guide-rngs.md). ```rust -# extern crate rand; -# extern crate rand_chacha; -use rand::{Rng, SeedableRng}; +use rand::{RngExt, SeedableRng}; # fn main() { // prepare a non-deterministic random number generator: @@ -17,7 +15,7 @@ let mut rng = rand::rng(); println!("{}", rng.random::()); // prints an unknown value // prepare a deterministic generator: -let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(123); +let mut rng = rand::rngs::ChaCha8Rng::seed_from_u64(123); println!("{}", rng.random::()); // prints -416273517 # } ``` diff --git a/src/guide-parallel.md b/src/guide-parallel.md index 0afd816..422677e 100644 --- a/src/guide-parallel.md +++ b/src/guide-parallel.md @@ -108,7 +108,7 @@ non-deterministic simulation too. ```rust use rand::distr::{Distribution, Uniform}; -use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng}; +use rand::{SeedableRng, rngs::ChaCha8Rng}; use rayon::prelude::*; static SEED: u64 = 0; diff --git a/src/guide-rngs.md b/src/guide-rngs.md index 730f96e..b10c9eb 100644 --- a/src/guide-rngs.md +++ b/src/guide-rngs.md @@ -247,9 +247,17 @@ seeded with a secure random key. Should the key be known or guessable, all output of the CSPRNG is easy to guess. This implies that the seed should come from a trusted source; usually either the OS or another CSPRNG. For this purpose, we recommend using the [`getrandom`] crate which interfaces the OS's -secure random interface. [`SeedableRng::from_os_rng`] is a wrapper around -[`getrandom`] for convenience. Alternatively, using a user-space CSPRNG such as -[`ThreadRng`] for seeding should be sufficient. +secure random interface. Alternatively, using a user-space CSPRNG such as +[`rand::make_rng()`] or [`ThreadRng`] for seeding should be sufficient. In code: +```rust +use rand::{rngs::ChaCha12Rng, rngs::SysRng, SeedableRng}; + +/// Seed explicitly from SysRng: +let mut rng1 = ChaCha12Rng::try_from_rng(&mut SysRng).unwrap(); + +/// Seed from ThreadRng (or SysRng if ThreadRng is not available): +let mut rng2: ChaCha12Rng = rand::make_rng(); +``` Further, it should be obvious that the internal state of a CSPRNG must be kept secret. With that in mind, our implementations do not provide direct @@ -335,5 +343,5 @@ by P. Hellekalek. [NIST]: https://www.nist.gov/ [ECRYPT]: http://www.ecrypt.eu.org/ [`getrandom`]: https://docs.rs/getrandom/ -[`SeedableRng::from_os_rng`]: https://docs.rs/rand/latest/rand/trait.SeedableRng.html#method.from_os_rng [zeroize]: https://crates.io/crates/zeroize +[`rand::make_rng()`]: https://docs.rs/rand/latest/rand/fn.make_rng.html diff --git a/src/guide-seeding.md b/src/guide-seeding.md index bf01de4..e27363f 100644 --- a/src/guide-seeding.md +++ b/src/guide-seeding.md @@ -25,16 +25,14 @@ PRNGs may be seeded directly from such a value with [`SeedableRng::from_seed`]. ### Fresh entropy -Using a fresh seed (direct from the OS) is easy using [`SeedableRng::from_os_rng`]: +Using a fresh seed is easy using [`rand::make_rng()`]: ```rust,editable -# extern crate rand; -# extern crate rand_chacha; use rand::prelude::*; -use rand_chacha::ChaCha20Rng; +use rand::rngs::ChaCha20Rng; fn main() { - let mut rng = ChaCha20Rng::from_os_rng(); + let mut rng: ChaCha20Rng = rand::make_rng(); println!("{}", rng.random_range(0..100)); } ``` @@ -47,7 +45,6 @@ Quite obviously, another RNG may be used to fill a seed. We provide a convenience method for this: ```rust,editable -# extern crate rand; use rand::prelude::*; fn main() { @@ -60,10 +57,8 @@ But, say you want to save a key and use it later. For that you need to be a little bit more explicit: ```rust,editable -# extern crate rand; -# extern crate rand_chacha; use rand::prelude::*; -use rand_chacha::ChaCha8Rng; +use rand::rngs::ChaCha8Rng; fn main() { let mut seed: ::Seed = Default::default(); @@ -91,10 +86,8 @@ number while providing good bit-avalanche (so that two similar numbers such as 0 and 1 translate to very different seeds and independent RNG sequences). ```rust,editable -# extern crate rand; -# extern crate rand_chacha; use rand::prelude::*; -use rand_chacha::ChaCha8Rng; +use rand::rngs::ChaCha8Rng; fn main() { let mut rng = ChaCha8Rng::seed_from_u64(2); @@ -150,7 +143,7 @@ function such as Argon2 must be used. [`SeedableRng::from_seed`]: https://docs.rs/rand_core/latest/rand_core/trait.SeedableRng.html#tymethod.from_seed [`SeedableRng::from_rng`]: https://docs.rs/rand_core/latest/rand_core/trait.SeedableRng.html#method.from_rng [`SeedableRng::seed_from_u64`]: https://docs.rs/rand_core/latest/rand_core/trait.SeedableRng.html#method.seed_from_u64 -[`SeedableRng::from_os_rng`]: https://docs.rs/rand_core/latest/rand_core/trait.SeedableRng.html#method.from_os_rng [`XorShiftRng`]: https://docs.rs/rand_xorshift/latest/rand_xorshift/struct.XorShiftRng.html [`ChaCha8Rng`]: https://docs.rs/rand_chacha/latest/rand_chacha/struct.ChaCha8Rng.html [`rand_seeder`]: https://github.com/rust-random/seeder/ +[`rand::make_rng()`]: https://docs.rs/rand/latest/rand/fn.make_rng.html diff --git a/src/guide-start.md b/src/guide-start.md index d497718..bb8421f 100644 --- a/src/guide-start.md +++ b/src/guide-start.md @@ -11,7 +11,6 @@ cargo add rand --features small_rng Now, paste the following into `src/main.rs`: ```rust -# extern crate rand; use rand::prelude::*; fn main() { diff --git a/src/guide-test-fn-rng.md b/src/guide-test-fn-rng.md index a480366..e40bffe 100644 --- a/src/guide-test-fn-rng.md +++ b/src/guide-test-fn-rng.md @@ -3,9 +3,9 @@ Occasionally a function that uses random number generators might need to be tested. For functions that need to be tested with test vectors, the following approach might be adapted: ```rust -use rand::{TryCryptoRng, rngs::OsRng}; +use rand::{TryCryptoRng, rngs::SysRng}; -pub struct CryptoOperations { +pub struct CryptoOperations { rng: R } @@ -30,7 +30,7 @@ impl CryptoOperations { } fn main() { - let rng = OsRng; + let rng = SysRng; let mut crypto_ops = ::new(rng); let mut secret: [u8; 8] = *b"\x00\x01\x02\x03\x04\x05\x06\x07"; diff --git a/src/guide-values.md b/src/guide-values.md index c57b393..0ff2eb1 100644 --- a/src/guide-values.md +++ b/src/guide-values.md @@ -38,8 +38,7 @@ Finally, it has a function to sample from arbitrary distributions: Examples: ```rust -# extern crate rand; -use rand::Rng; +use rand::RngExt; # fn main() { let mut rng = rand::rng(); @@ -58,7 +57,6 @@ println!("roll = {}", rng.random_range(1..=6)); Additionally, the [`random`] function is a short-cut to [`Rng::random`] on the [`rng()`]: ```rust -# extern crate rand; # use rand::Rng; # fn main() { println!("Tossing a coin..."); @@ -92,8 +90,7 @@ according to reasonable logic: Given that, we can implement the [`StandardUniform`] distribution for our own types: ```rust -# extern crate rand; -use rand::Rng; +use rand::{Rng, RngExt}; use rand::distr::{Distribution, StandardUniform, Uniform}; use std::f64::consts::TAU; // = 2π diff --git a/src/quick-start.md b/src/quick-start.md index cdaa065..a3a05d3 100644 --- a/src/quick-start.md +++ b/src/quick-start.md @@ -6,7 +6,6 @@ or the [guide]. Lets kick things off with an example ```rust,editable -# extern crate rand; // import commonly used items from the prelude: use rand::prelude::*; @@ -82,12 +81,10 @@ See the [RNGs] section for more RNGs, but avoid `SmallRng` and `StdRng` if you care about reproducible results. ```rust,editable -# extern crate rand; -# extern crate rand_chacha; -use rand::{Rng, SeedableRng}; +use rand::{rngs::ChaCha8Rng, RngExt, SeedableRng}; fn main() { - let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(10); + let mut rng = ChaCha8Rng::seed_from_u64(10); println!("Random f32: {}", rng.random::()); } ``` diff --git a/src/update-0.10.md b/src/update-0.10.md new file mode 100644 index 0000000..a2d1119 --- /dev/null +++ b/src/update-0.10.md @@ -0,0 +1,88 @@ +# Updating to 0.10 + +In the following, instructions are provided for porting your code from +`rand 0.9` to `rand 0.10`. + +The following is a migration guide focussing on potentially-breaking changes. For a full list of changes, see the relevant changelogs: + +- [CHANGELOG.md](https://github.com/rust-random/rand/blob/master/CHANGELOG.md). +- [rand_core/CHANGELOG.md](https://docs.rs/crate/rand_core/latest/source/CHANGELOG.md). + + +## [Try]Rng traits + +The `rand_core` traits `RngCore, TryRngCore` were renamed to `Rng, TryRng` and the `rand` trait `Rng` to `RngExt` respectively. + +The relationship between these traits also changed; previously, every `R: RngCore` implemented `TryRngCore` but otherwise the two traits were independent; now `Rng: TryRng` and every `R: TryRng + ?Sized` implements `Rng`. + +Further, while we previously implemented `R: RngCore` for every `R: DerefMut where R::Target: RngCore`, we were unable to do so due to conflicting-trait errors (solving this would have required specialization or negative trait bounds). Now, we implement `R: TryRng` for every `R: DerefMut where R::Target: TryRng` which thus implies `R: Rng` for every `R: DerefMut where R::Target: Rng`. + +The biggest impact here is that infallible PRNGs must implement `TryRng` with `Error = Infallible` instead of implementing `RngCore`. + +Users of `rand` will often need to import `rand::RngExt` may need to migrate from `R: RngCore` to `R: Rng` (noting that where `R: Rng` was previously used it may be preferable to keep `R: Rng` even though the direct replacement would be `R: RngExt`; the two bounds are equivalent for `R: Sized`). + + +## SysRng + +`rand_core::OsRng` has been replaced with `getrandom::SysRng` (also available as `rand::rngs::SysRng`). + +The methods `SeedableRng::from_os_rng` and `try_from_os_rng` have thus been removed. [`rand::make_rng()`] is provided as a partial replacement; otherwise use `SomeRng::try_from_rng(&mut SysRng).unwrap()`. + + +## PRNGs + +`StdRng` is now provided by `chacha20` instead of `rand_chacha`. For the time being both packages are maintained, but `rand_chacha` is likely to be discontinued in the future. The `ChaCha{8,12,20}Rng` types are a direct replacement for the like-named `rand_chacha` types; these maintain reproducibility of output and have a similar API. + +Note that `rand::rngs` now provides several named PRNGs, making it simpler to write [reproducible](crate-reprod.md) code: `ChaCha{8,12,20}Rng`, `Xoshiro{128,256}PlusPlus`. + +Other PRNG crates have been updated with minimal changes (though this may not remain the case indefinitely; see [rngs#98](https://github.com/rust-random/rngs/issues/98)). One new crate has been added: [rand_sfc](https://docs.rs/rand_sfc/latest/rand_sfc/). + +### Clone and serialization support + +`StdRng` and `ChaCha{8,12,20}Rng` no longer implement `Clone` or the [serde] traits. This was a deliberate choice to prevent accidental key-stream duplication or persisting to external storage. Note that it remains possible to clone or serialize these RNGs by reconstructing a new instance with the same key, then setting the stream (if applicable) and word position. For example: +```rust,editable +use rand::{rngs::ChaCha8Rng, Rng, SeedableRng}; + +let mut rng1: ChaCha8Rng = rand::make_rng(); +let _ = rng1.next_u64(); + +let mut rng2 = ChaCha8Rng::from_seed(rng1.get_seed()); +rng2.set_stream(rng1.get_stream()); +rng2.set_word_pos(rng1.get_word_pos()); + +assert_eq!(rng1.next_u64(), rng2.next_u64()); +``` + + +## Other changes + +`TryRngCore::read_adapter` was replaced with `rand::RngReader`. + +### ReseedingRng + +`ReseedingRng` has been removed without replacement since, as far as we have been able to discern, `ThreadRng` is the only important use-case. We have thus opted to move its functionality into `ThreadRng` as an implementation detail. + + +## Dependencies + +Rand crates now require **`rustc`** version 1.85.0 or later. + +The dependency on **`getrandom`** was bumped to version 0.4. See [the getrandom CHANGELOG](https://github.com/rust-random/getrandom/blob/master/CHANGELOG.md). + +### Features + +Feature flags: + +- `os_rng` was renamed to `sys_rng` +- `thread_rng`, `std_rng` and `sys_rng` are no longer enabled by default (TODO: this is not yet confirmed) +- `small_rng` has been removed; its functionality is always available +- `chacha` is a new flag, enabling `rand::rngs::ChaCha{8,12,20}Rng` + + +## Reproducibility + +There are no known value-breaking changes to `rand` in v0.10. + + +[serde]: https://serde.rs/ +[`rand::make_rng()`]: https://docs.rs/rand/latest/rand/fn.make_rng.html diff --git a/src/update-0.5.md b/src/update-0.5.md index 0924ab4..efecff3 100644 --- a/src/update-0.5.md +++ b/src/update-0.5.md @@ -75,7 +75,8 @@ any type supporting `SeedableRng`, and provides construction from fresh, strong entropy: ```rust,noplayground -use rand_0_5::{ChaChaRng, FromEntropy}; +# extern crate rand_0_5 as rand; +use rand::{ChaChaRng, FromEntropy}; let mut rng = ChaChaRng::from_entropy(); ``` @@ -121,7 +122,8 @@ A new `Error` type has been added, designed explicitly for no-std compatibility, simplicity, and enough flexibility for our uses (carrying a `cause` when possible): ```rust,noplayground -# use rand_0_5::ErrorKind; +# extern crate rand_0_5 as rand; +# use rand::ErrorKind; pub struct Error { pub kind: ErrorKind, pub msg: &'static str, @@ -183,10 +185,9 @@ The method `ChaChaRng::set_counter` has been replaced by two new methods, method may be emulated as follows: ```rust,noplayground -# extern crate rand; -# extern crate rand_chacha; +# extern crate rand_0_5 as rand; # use rand::prelude::*; -# use rand_chacha::ChaChaRng; +# use rand_chacha_0_1::ChaChaRng; # fn main() { let lower = 88293; let higher = 9300932; diff --git a/src/update-0.8.md b/src/update-0.8.md index 471ce6b..2ed7ac5 100644 --- a/src/update-0.8.md +++ b/src/update-0.8.md @@ -53,9 +53,9 @@ let b: u32 = Standard.sample_iter(rng).next().unwrap(); ``` can be replaced with the following code: ```rust,noplayground -# extern crate rand; -# use rand_0_8::prelude::*; -# use rand_0_8::distributions::Standard; +# extern crate rand_0_8 as rand; +# use rand::prelude::*; +# use rand::distributions::Standard; # fn main () { let mut rng = thread_rng(); let a: u32 = Standard.sample_iter(&mut rng).next().unwrap(); @@ -131,10 +131,10 @@ Several smaller changes occurred to rand distributions: ``` With Rand 0.8, this is equivalent to the following: ```rust,noplayground - # extern crate rand; - # use rand_0_8::{distributions::Alphanumeric, Rng}; + # extern crate rand_0_8 as rand; + # use rand::{distributions::Alphanumeric, Rng}; # fn main() { - # let mut rng = rand_0_8::thread_rng(); + # let mut rng = rand::thread_rng(); let chars: String = std::iter::repeat(()) .map(|()| rng.sample(Alphanumeric)) .map(char::from) diff --git a/src/update-0.9.md b/src/update-0.9.md index 254c01a..4310334 100644 --- a/src/update-0.9.md +++ b/src/update-0.9.md @@ -6,7 +6,7 @@ In the following, instructions are provided for porting your code from The following is a migration guide focussing on potentially-breaking changes. For a full list of changes, see the relevant changelogs: - [CHANGELOG.md](https://github.com/rust-random/rand/blob/master/CHANGELOG.md). -- [rand_core/CHANGELOG.md](https://github.com/rust-random/rand/blob/master/rand_core/CHANGELOG.md). +- [rand_core/CHANGELOG.md](https://docs.rs/crate/rand_core/latest/source/CHANGELOG.md). - [rand_distr/CHANGELOG.md](https://github.com/rust-random/rand/blob/master/rand_distr/CHANGELOG.md). ## Renamed functions and methods diff --git a/tests/Cargo.toml b/tests/Cargo.toml index 36154e3..d8b6dea 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -6,14 +6,14 @@ publish = false [dependencies] doc-comment = "0.3.3" -rand = { version = "0.9" } +rand = { version = "0.10", features = ["chacha"] } rand_0_8 = { package = "rand", version = "0.8", features = ["small_rng"] } rand_0_7 = { package = "rand", version = "0.7" } rand_0_5 = { package = "rand", version = "0.5" } -rand_pcg = { version = "0.9" } -rand_chacha = { version = "0.9" } +rand_pcg = { version = "0.10" } +rand_chacha_0_1 = { package = "rand_chacha", version = "0.1" } rand_distr = { version = "0.5" } rand_distr_0_4 = { package = "rand_distr", version = "0.4" } rand_distr_0_2 = { package = "rand_distr", version = "0.2" } -rand_seeder = { version = "0.4" } +rand_seeder = { version = "0.5" } rayon = "1.5.3"