diff --git a/Cargo.lock b/Cargo.lock index 7691ea710b..a7e2a9ee3a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,17 +8,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" -[[package]] -name = "chacha20" -version = "0.10.0-rc.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f895fb33c1ad22da4bc79d37c0bddff8aee2ba4575705345eb73b8ffbc386074" -dependencies = [ - "cfg-if", - "cpufeatures", - "rand_core", -] - [[package]] name = "cobs" version = "0.3.0" @@ -28,15 +17,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - [[package]] name = "crossbeam-deque" version = "0.8.6" @@ -83,8 +63,7 @@ checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" [[package]] name = "getrandom" version = "0.4.0-rc.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b99f0d993a2b9b97b9a201193aa8ad21305cde06a3be9a7e1f8f4201e5cc27e" +source = "git+https://github.com/rust-random/getrandom.git?branch=try-rng#69ee78f7ab34873e01eda838cf8a5a6b4a9c6b26" dependencies = [ "cfg-if", "libc", @@ -166,10 +145,10 @@ checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" name = "rand" version = "0.10.0-rc.5" dependencies = [ - "chacha20", "getrandom", "log", "postcard", + "rand_chacha", "rand_core", "rand_pcg", "rayon", @@ -191,8 +170,7 @@ dependencies = [ [[package]] name = "rand_core" version = "0.10.0-rc-3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f66ee92bc15280519ef199a274fe0cafff4245d31bc39aaa31c011ad56cb1f05" +source = "git+https://github.com/rust-random/rand_core.git?branch=merge_rng_traits#85f7d9ba0a13f69e16248166abf72bff29b00de0" [[package]] name = "rand_pcg" diff --git a/Cargo.toml b/Cargo.toml index 622f73ff57..b4e491c9eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -76,7 +76,7 @@ exclude = ["benches", "distr_test"] rand_core = { version = "0.10.0-rc-3", default-features = false } log = { version = "0.4.4", optional = true } serde = { version = "1.0.103", features = ["derive"], optional = true } -chacha20 = { version = "0.10.0-rc.6", default-features = false, features = ["rng"], optional = true } +chacha20 = { path = "rand_chacha", optional = true, package = "rand_chacha" } getrandom = { version = "0.4.0-rc.0", optional = true } [dev-dependencies] @@ -85,3 +85,7 @@ rand_pcg = { path = "rand_pcg", version = "0.10.0-rc.1" } postcard = {version = "1.1.3", default-features = false, features = ["alloc"]} rayon = "1.7" serde_json = "1.0.140" + +[patch.crates-io] +rand_core = { git = "https://github.com/rust-random/rand_core.git", branch = "merge_rng_traits" } +getrandom = { git = "https://github.com/rust-random/getrandom.git", branch = "try-rng" } diff --git a/benches/Cargo.lock b/benches/Cargo.lock index 808227eac8..b896beaa35 100644 --- a/benches/Cargo.lock +++ b/benches/Cargo.lock @@ -58,17 +58,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" -[[package]] -name = "chacha20" -version = "0.10.0-rc.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f895fb33c1ad22da4bc79d37c0bddff8aee2ba4575705345eb73b8ffbc386074" -dependencies = [ - "cfg-if", - "cpufeatures", - "rand_core", -] - [[package]] name = "ciborium" version = "0.2.2" @@ -121,15 +110,6 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - [[package]] name = "criterion" version = "0.5.1" @@ -216,8 +196,7 @@ checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "getrandom" version = "0.4.0-rc.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b99f0d993a2b9b97b9a201193aa8ad21305cde06a3be9a7e1f8f4201e5cc27e" +source = "git+https://github.com/rust-random/getrandom.git?branch=try-rng#69ee78f7ab34873e01eda838cf8a5a6b4a9c6b26" dependencies = [ "cfg-if", "libc", @@ -377,8 +356,8 @@ checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" name = "rand" version = "0.10.0-rc.5" dependencies = [ - "chacha20", "getrandom", + "rand_chacha", "rand_core", ] @@ -393,8 +372,7 @@ dependencies = [ [[package]] name = "rand_core" version = "0.10.0-rc-3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f66ee92bc15280519ef199a274fe0cafff4245d31bc39aaa31c011ad56cb1f05" +source = "git+https://github.com/rust-random/rand_core.git?branch=merge_rng_traits#85f7d9ba0a13f69e16248166abf72bff29b00de0" [[package]] name = "rand_pcg" diff --git a/benches/Cargo.toml b/benches/Cargo.toml index 699186b26f..6621a2a71c 100644 --- a/benches/Cargo.toml +++ b/benches/Cargo.toml @@ -56,3 +56,7 @@ harness = false [[bench]] name = "weighted" harness = false + +[patch.crates-io] +rand_core = { git = "https://github.com/rust-random/rand_core.git", branch = "merge_rng_traits" } +getrandom = { git = "https://github.com/rust-random/getrandom.git", branch = "try-rng" } diff --git a/benches/benches/seq_choose.rs b/benches/benches/seq_choose.rs index a3560a158e..2271ece845 100644 --- a/benches/benches/seq_choose.rs +++ b/benches/benches/seq_choose.rs @@ -99,7 +99,7 @@ pub fn bench(c: &mut Criterion) { bench_rng::(c, "Pcg64"); } -fn bench_rng(c: &mut Criterion, rng_name: &'static str) { +fn bench_rng(c: &mut Criterion, rng_name: &'static str) { for length in [1, 2, 3, 10, 100, 1000].map(black_box) { let name = format!("choose_size-hinted_from_{length}_{rng_name}"); c.bench_function(name.as_str(), |b| { diff --git a/benches/benches/shuffle.rs b/benches/benches/shuffle.rs index f2ccff2e87..bd6960fad4 100644 --- a/benches/benches/shuffle.rs +++ b/benches/benches/shuffle.rs @@ -35,7 +35,7 @@ pub fn bench(c: &mut Criterion) { bench_rng::(c, "Pcg64"); } -fn bench_rng(c: &mut Criterion, rng_name: &'static str) { +fn bench_rng(c: &mut Criterion, rng_name: &'static str) { for length in [1, 2, 3, 10, 100, 1000, 10000].map(black_box) { c.bench_function(format!("shuffle_{length}_{rng_name}").as_str(), |b| { let mut rng = Rng::seed_from_u64(123); diff --git a/examples/print-next.rs b/examples/print-next.rs index e58a98c859..204bfb4b4a 100644 --- a/examples/print-next.rs +++ b/examples/print-next.rs @@ -1,4 +1,4 @@ -use rand::RngCore; +use rand::Rng; fn main() { let mut rng = rand::rng(); diff --git a/rand_chacha/src/chacha.rs b/rand_chacha/src/chacha.rs index a455f0123c..506bfc302f 100644 --- a/rand_chacha/src/chacha.rs +++ b/rand_chacha/src/chacha.rs @@ -9,9 +9,10 @@ //! The ChaCha random number generator. use crate::guts::ChaCha; +use core::convert::Infallible; use core::fmt; use rand_core::block::{BlockRng, CryptoGenerator, Generator}; -use rand_core::{CryptoRng, RngCore, SeedableRng}; +use rand_core::{CryptoRng, SeedableRng, TryRng}; #[cfg(feature = "serde")] use serde::{Deserialize, Deserializer, Serialize, Serializer}; @@ -89,7 +90,7 @@ macro_rules! chacha_impl { /// ``` /// /// This implementation uses an output buffer of sixteen `u32` words, and uses - /// [`BlockRng`] to implement the [`RngCore`] methods. + /// [`BlockRng`] to implement the [`TryRng`] methods. /// /// [^1]: D. J. Bernstein, [*ChaCha, a variant of Salsa20*]( /// https://cr.yp.to/chacha.html) @@ -113,20 +114,22 @@ macro_rules! chacha_impl { } } - impl RngCore for $ChaChaXRng { + impl TryRng for $ChaChaXRng { + type Error = Infallible; + #[inline] - fn next_u32(&mut self) -> u32 { - self.rng.next_word() + fn try_next_u32(&mut self) -> Result { + Ok(self.rng.next_word()) } #[inline] - fn next_u64(&mut self) -> u64 { - self.rng.next_u64_from_u32() + fn try_next_u64(&mut self) -> Result { + Ok(self.rng.next_u64_from_u32()) } #[inline] - fn fill_bytes(&mut self, bytes: &mut [u8]) { - self.rng.fill_bytes(bytes) + fn try_fill_bytes(&mut self, bytes: &mut [u8]) -> Result<(), Infallible> { + Ok(self.rng.fill_bytes(bytes)) } } @@ -306,10 +309,10 @@ chacha_impl!( #[cfg(test)] mod test { - use rand_core::{RngCore, SeedableRng}; - #[cfg(feature = "serde")] use super::{ChaCha8Rng, ChaCha12Rng, ChaCha20Rng}; + use core::convert::Infallible; + use rand_core::{SeedableRng, TryRng}; type ChaChaRng = super::ChaCha20Rng; @@ -336,9 +339,9 @@ mod test { assert_eq!(rng2, decoded2); assert_eq!(rng3, decoded3); - assert_eq!(rng1.next_u32(), decoded1.next_u32()); - assert_eq!(rng2.next_u32(), decoded2.next_u32()); - assert_eq!(rng3.next_u32(), decoded3.next_u32()); + assert_eq!(rng1.try_next_u32(), decoded1.try_next_u32()); + assert_eq!(rng2.try_next_u32(), decoded2.try_next_u32()); + assert_eq!(rng3.try_next_u32(), decoded3.try_next_u32()); } // This test validates that: @@ -367,10 +370,10 @@ mod test { 0, 0, 0, ]; let mut rng1 = ChaChaRng::from_seed(seed); - assert_eq!(rng1.next_u32(), 137206642); + assert_eq!(rng1.try_next_u32(), Ok(137206642)); let mut rng2 = ChaChaRng::from_rng(&mut rng1); - assert_eq!(rng2.next_u32(), 1325750369); + assert_eq!(rng2.try_next_u32(), Ok(1325750369)); } #[test] @@ -382,7 +385,7 @@ mod test { let mut results = [0u32; 16]; for i in results.iter_mut() { - *i = rng.next_u32(); + *i = rng.try_next_u32().unwrap(); } let expected = [ 0xade0b876, 0x903df1a0, 0xe56a5d40, 0x28bd8653, 0xb819d2bd, 0x1aed8da0, 0xccef36a8, @@ -392,7 +395,7 @@ mod test { assert_eq!(results, expected); for i in results.iter_mut() { - *i = rng.next_u32(); + *i = rng.try_next_u32().unwrap(); } let expected = [ 0xbee7079f, 0x7a385155, 0x7c97ba98, 0x0d082d73, 0xa0290fcb, 0x6965e348, 0x3e53c612, @@ -414,12 +417,12 @@ mod test { // Skip block 0 for _ in 0..16 { - rng.next_u32(); + rng.try_next_u32().unwrap(); } let mut results = [0u32; 16]; for i in results.iter_mut() { - *i = rng.next_u32(); + *i = rng.try_next_u32().unwrap(); } let expected = [ 0x2452eb3a, 0x9249f8ec, 0x8d829d9b, 0xddd4ceb1, 0xe8252083, 0x60818b01, 0xf38422b8, @@ -448,10 +451,10 @@ mod test { // Test block 2 by skipping block 0 and 1 let mut rng1 = ChaChaRng::from_seed(seed); for _ in 0..32 { - rng1.next_u32(); + rng1.try_next_u32().unwrap(); } for i in results.iter_mut() { - *i = rng1.next_u32(); + *i = rng1.try_next_u32().unwrap(); } assert_eq!(results, expected); assert_eq!(rng1.get_word_pos(), expected_end); @@ -460,23 +463,23 @@ mod test { let mut rng2 = ChaChaRng::from_seed(seed); rng2.set_word_pos(2 * 16); for i in results.iter_mut() { - *i = rng2.next_u32(); + *i = rng2.try_next_u32().unwrap(); } assert_eq!(results, expected); assert_eq!(rng2.get_word_pos(), expected_end); // Test skipping behaviour with other types let mut buf = [0u8; 32]; - rng2.fill_bytes(&mut buf[..]); + rng2.try_fill_bytes(&mut buf[..]).unwrap(); assert_eq!(rng2.get_word_pos(), expected_end + 8); - rng2.fill_bytes(&mut buf[0..25]); + rng2.try_fill_bytes(&mut buf[0..25]).unwrap(); assert_eq!(rng2.get_word_pos(), expected_end + 15); - rng2.next_u64(); + rng2.try_next_u64().unwrap(); assert_eq!(rng2.get_word_pos(), expected_end + 17); - rng2.next_u32(); - rng2.next_u64(); + rng2.try_next_u32().unwrap(); + rng2.try_next_u64().unwrap(); assert_eq!(rng2.get_word_pos(), expected_end + 20); - rng2.fill_bytes(&mut buf[0..1]); + rng2.try_fill_bytes(&mut buf[0..1]).unwrap(); assert_eq!(rng2.get_word_pos(), expected_end + 21); } @@ -492,9 +495,9 @@ mod test { // i.e., the i-th word of the i-th 16-word block let mut results = [0u32; 16]; for i in results.iter_mut() { - *i = rng.next_u32(); + *i = rng.try_next_u32().unwrap(); for _ in 0..16 { - rng.next_u32(); + rng.try_next_u32().unwrap(); } } let expected = [ @@ -510,7 +513,7 @@ mod test { let seed = [0u8; 32]; let mut rng = ChaChaRng::from_seed(seed); let mut results = [0u8; 32]; - rng.fill_bytes(&mut results); + rng.try_fill_bytes(&mut results).unwrap(); let expected = [ 118, 184, 224, 173, 160, 241, 61, 144, 64, 93, 106, 229, 83, 134, 189, 40, 189, 210, 25, 184, 160, 141, 237, 26, 168, 54, 239, 204, 139, 119, 13, 199, @@ -531,7 +534,7 @@ mod test { let mut results = [0u32; 16]; for i in results.iter_mut() { - *i = rng.next_u32(); + *i = rng.try_next_u32().unwrap(); } let expected = [ 0x374dc6c2, 0x3736d58c, 0xb904e24a, 0xcd3f93ef, 0x88228b1a, 0x96a4dfb3, 0x5b76ab72, @@ -550,16 +553,16 @@ mod test { let mut rng = ChaChaRng::from_seed(seed); let mut clone = rng.clone(); for _ in 0..16 { - assert_eq!(rng.next_u64(), clone.next_u64()); + assert_eq!(rng.try_next_u64(), clone.try_next_u64()); } rng.set_stream(51); for _ in 0..7 { - assert!(rng.next_u32() != clone.next_u32()); + assert!(rng.try_next_u32() != clone.try_next_u32()); } clone.set_stream(51); // switch part way through block for _ in 7..16 { - assert_eq!(rng.next_u32(), clone.next_u32()); + assert_eq!(rng.try_next_u32(), clone.try_next_u32()); } } @@ -596,9 +599,9 @@ mod test { use rand_core::CryptoRng; let mut rng1 = ChaChaRng::from_seed(Default::default()); - let rng2 = &mut rng1.clone() as &mut dyn CryptoRng; + let rng2 = &mut rng1.clone() as &mut dyn CryptoRng; for _ in 0..1000 { - assert_eq!(rng1.next_u64(), rng2.next_u64()); + assert_eq!(rng1.try_next_u64(), rng2.try_next_u64()); } } } diff --git a/rand_chacha/src/lib.rs b/rand_chacha/src/lib.rs index b12f24620f..6e8ee6d22e 100644 --- a/rand_chacha/src/lib.rs +++ b/rand_chacha/src/lib.rs @@ -15,7 +15,7 @@ //! //! This crate provides 8-, 12- and 20-round variants of generators via a "core" //! implementation (of [`block::Generator`]), each with an associated "RNG" type -//! (implementing [`RngCore`]). +//! (implementing [`TryRng`]). //! //! These generators are all deterministic and portable (see [Reproducibility] //! in the book), with testing against reference vectors. @@ -54,15 +54,15 @@ //! //! ## Generation //! -//! Generators implement [`RngCore`], whose methods may be used directly to +//! Generators implement [`TryRng`], whose methods may be used directly to //! generate unbounded integer or byte values. //! ``` -//! use rand_core::{SeedableRng, RngCore}; +//! use rand_core::{SeedableRng, TryRng}; //! use rand_chacha::ChaCha12Rng; //! //! let mut rng = ChaCha12Rng::from_seed(Default::default()); -//! let x = rng.next_u64(); -//! assert_eq!(x, 0x53f955076a9af49b); +//! let x = rng.try_next_u64(); +//! assert_eq!(x, Ok(0x53f955076a9af49b)); //! ``` //! //! It is often more convenient to use the [`rand::Rng`] trait, which provides @@ -74,7 +74,7 @@ //! [Security]: https://rust-random.github.io/book/guide-rngs.html#security //! [Random Values]: https://rust-random.github.io/book/guide-values.html //! [`block::Generator`]: rand_core::block::Generator -//! [`RngCore`]: rand_core::RngCore +//! [`TryRng`]: rand_core::TryRng //! [`SeedableRng`]: rand_core::SeedableRng //! [`SysRng`]: https://docs.rs/rand/latest/rand/rngs/struct.SysRng.html //! [`rand::rng`]: https://docs.rs/rand/latest/rand/fn.rng.html diff --git a/rand_pcg/src/lib.rs b/rand_pcg/src/lib.rs index 1dcabe7fcd..f03db0f7f9 100644 --- a/rand_pcg/src/lib.rs +++ b/rand_pcg/src/lib.rs @@ -54,14 +54,14 @@ //! //! ## Generation //! -//! Generators implement [`RngCore`], whose methods may be used directly to +//! Generators implement [`TryRng`], whose methods may be used directly to //! generate unbounded integer or byte values. //! ``` -//! use rand_core::{SeedableRng, RngCore}; +//! use rand_core::{SeedableRng, TryRng}; //! use rand_pcg::Pcg64Mcg; //! //! let mut rng = Pcg64Mcg::seed_from_u64(0); -//! let x = rng.next_u64(); +//! let x = rng.try_next_u64().unwrap(); //! assert_eq!(x, 0x5603f242407deca2); //! ``` //! @@ -72,7 +72,7 @@ //! [Reproducibility]: https://rust-random.github.io/book/crate-reprod.html //! [Seeding RNGs]: https://rust-random.github.io/book/guide-seeding.html //! [Random Values]: https://rust-random.github.io/book/guide-values.html -//! [`RngCore`]: rand_core::RngCore +//! [`TryRng`]: rand_core::TryRng //! [`SeedableRng`]: rand_core::SeedableRng //! [`SeedableRng::from_rng`]: rand_core::SeedableRng#method.from_rng //! [`rand::rng`]: https://docs.rs/rand/latest/rand/fn.rng.html diff --git a/rand_pcg/src/pcg128.rs b/rand_pcg/src/pcg128.rs index e6c4e02bf6..ffc2eec180 100644 --- a/rand_pcg/src/pcg128.rs +++ b/rand_pcg/src/pcg128.rs @@ -13,8 +13,8 @@ // This is the default multiplier used by PCG for 128-bit state. const MULTIPLIER: u128 = 0x2360_ED05_1FC6_5DA4_4385_DF64_9FCC_F645; -use core::fmt; -use rand_core::{RngCore, SeedableRng, utils}; +use core::{convert::Infallible, fmt}; +use rand_core::{SeedableRng, TryRng, utils}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -111,6 +111,12 @@ impl Lcg128Xsl64 { .wrapping_mul(MULTIPLIER) .wrapping_add(self.increment); } + + #[inline] + fn next_u64(&mut self) -> u64 { + self.step(); + output_xsl_rr(self.state) + } } // Custom Debug implementation that does not expose the internal state @@ -135,21 +141,23 @@ impl SeedableRng for Lcg128Xsl64 { } } -impl RngCore for Lcg128Xsl64 { +impl TryRng for Lcg128Xsl64 { + type Error = Infallible; + #[inline] - fn next_u32(&mut self) -> u32 { - self.next_u64() as u32 + fn try_next_u32(&mut self) -> Result { + Ok(self.next_u64() as u32) } #[inline] - fn next_u64(&mut self) -> u64 { - self.step(); - output_xsl_rr(self.state) + fn try_next_u64(&mut self) -> Result { + Ok(self.next_u64()) } #[inline] - fn fill_bytes(&mut self, dest: &mut [u8]) { + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Infallible> { utils::fill_bytes_via_next_word(dest, || self.next_u64()); + Ok(()) } } @@ -215,6 +223,12 @@ impl Mcg128Xsl64 { // Force low bit to 1, as in C version (C++ uses `state | 3` instead). Mcg128Xsl64 { state: state | 1 } } + + #[inline] + fn next_u64(&mut self) -> u64 { + self.state = self.state.wrapping_mul(MULTIPLIER); + output_xsl_rr(self.state) + } } // Custom Debug implementation that does not expose the internal state @@ -237,21 +251,23 @@ impl SeedableRng for Mcg128Xsl64 { } } -impl RngCore for Mcg128Xsl64 { +impl TryRng for Mcg128Xsl64 { + type Error = Infallible; + #[inline] - fn next_u32(&mut self) -> u32 { - self.next_u64() as u32 + fn try_next_u32(&mut self) -> Result { + Ok(self.next_u64() as u32) } #[inline] - fn next_u64(&mut self) -> u64 { - self.state = self.state.wrapping_mul(MULTIPLIER); - output_xsl_rr(self.state) + fn try_next_u64(&mut self) -> Result { + Ok(self.next_u64()) } #[inline] - fn fill_bytes(&mut self, dest: &mut [u8]) { + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Infallible> { utils::fill_bytes_via_next_word(dest, || self.next_u64()); + Ok(()) } } diff --git a/rand_pcg/src/pcg128cm.rs b/rand_pcg/src/pcg128cm.rs index e9ce218f36..daa8a6c667 100644 --- a/rand_pcg/src/pcg128cm.rs +++ b/rand_pcg/src/pcg128cm.rs @@ -13,8 +13,8 @@ // This is the cheap multiplier used by PCG for 128-bit state. const MULTIPLIER: u64 = 15750249268501108917; -use core::fmt; -use rand_core::{RngCore, SeedableRng, utils}; +use core::{convert::Infallible, fmt}; +use rand_core::{SeedableRng, TryRng, utils}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -116,6 +116,13 @@ impl Lcg128CmDxsm64 { .wrapping_mul(MULTIPLIER as u128) .wrapping_add(self.increment); } + + #[inline] + fn next_u64(&mut self) -> u64 { + let res = output_dxsm(self.state); + self.step(); + res + } } // Custom Debug implementation that does not expose the internal state @@ -140,22 +147,23 @@ impl SeedableRng for Lcg128CmDxsm64 { } } -impl RngCore for Lcg128CmDxsm64 { +impl TryRng for Lcg128CmDxsm64 { + type Error = Infallible; + #[inline] - fn next_u32(&mut self) -> u32 { - self.next_u64() as u32 + fn try_next_u32(&mut self) -> Result { + Ok(self.next_u64() as u32) } #[inline] - fn next_u64(&mut self) -> u64 { - let res = output_dxsm(self.state); - self.step(); - res + fn try_next_u64(&mut self) -> Result { + Ok(self.next_u64()) } #[inline] - fn fill_bytes(&mut self, dest: &mut [u8]) { + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Infallible> { utils::fill_bytes_via_next_word(dest, || self.next_u64()); + Ok(()) } } diff --git a/rand_pcg/src/pcg64.rs b/rand_pcg/src/pcg64.rs index 4eeabfd0be..140408866f 100644 --- a/rand_pcg/src/pcg64.rs +++ b/rand_pcg/src/pcg64.rs @@ -10,8 +10,8 @@ //! PCG random number generators -use core::fmt; -use rand_core::{RngCore, SeedableRng, utils}; +use core::{convert::Infallible, fmt}; +use rand_core::{SeedableRng, TryRng, utils}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -112,6 +112,22 @@ impl Lcg64Xsh32 { .wrapping_mul(MULTIPLIER) .wrapping_add(self.increment); } + + #[inline] + fn next_u32(&mut self) -> u32 { + let state = self.state; + self.step(); + + // Output function XSH RR: xorshift high (bits), followed by a random rotate + // Constants are for 64-bit state, 32-bit output + const ROTATE: u32 = 59; // 64 - 5 + const XSHIFT: u32 = 18; // (5 + 32) / 2 + const SPARE: u32 = 27; // 64 - 32 - 5 + + let rot = (state >> ROTATE) as u32; + let xsh = (((state >> XSHIFT) ^ state) >> SPARE) as u32; + xsh.rotate_right(rot) + } } // Custom Debug implementation that does not expose the internal state @@ -134,30 +150,22 @@ impl SeedableRng for Lcg64Xsh32 { } } -impl RngCore for Lcg64Xsh32 { - #[inline] - fn next_u32(&mut self) -> u32 { - let state = self.state; - self.step(); +impl TryRng for Lcg64Xsh32 { + type Error = Infallible; - // Output function XSH RR: xorshift high (bits), followed by a random rotate - // Constants are for 64-bit state, 32-bit output - const ROTATE: u32 = 59; // 64 - 5 - const XSHIFT: u32 = 18; // (5 + 32) / 2 - const SPARE: u32 = 27; // 64 - 32 - 5 - - let rot = (state >> ROTATE) as u32; - let xsh = (((state >> XSHIFT) ^ state) >> SPARE) as u32; - xsh.rotate_right(rot) + #[inline] + fn try_next_u32(&mut self) -> Result { + Ok(self.next_u32()) } #[inline] - fn next_u64(&mut self) -> u64 { - utils::next_u64_via_u32(self) + fn try_next_u64(&mut self) -> Result { + Ok(utils::next_u64_via_u32(self)) } #[inline] - fn fill_bytes(&mut self, dest: &mut [u8]) { + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Infallible> { utils::fill_bytes_via_next_word(dest, || self.next_u32()); + Ok(()) } } diff --git a/rand_pcg/tests/lcg128cmdxsm64.rs b/rand_pcg/tests/lcg128cmdxsm64.rs index ad6b224681..ccd620a092 100644 --- a/rand_pcg/tests/lcg128cmdxsm64.rs +++ b/rand_pcg/tests/lcg128cmdxsm64.rs @@ -1,4 +1,4 @@ -use rand_core::{RngCore, SeedableRng}; +use rand_core::{SeedableRng, TryRng}; use rand_pcg::{Lcg128CmDxsm64, Pcg64Dxsm}; #[test] @@ -7,7 +7,7 @@ fn test_lcg128cmdxsm64_advancing() { let mut rng1 = Lcg128CmDxsm64::seed_from_u64(seed); let mut rng2 = rng1.clone(); for _ in 0..20 { - rng1.next_u64(); + rng1.try_next_u64().unwrap(); } rng2.advance(20); assert_eq!(rng1, rng2); @@ -21,17 +21,17 @@ fn test_lcg128cmdxsm64_construction() { let seed = [1,2,3,4, 5,6,7,8, 9,10,11,12, 13,14,15,16, 17,18,19,20, 21,22,23,24, 25,26,27,28, 29,30,31,32]; let mut rng1 = Lcg128CmDxsm64::from_seed(seed); - assert_eq!(rng1.next_u64(), 12201417210360370199); + assert_eq!(rng1.try_next_u64(), Ok(12201417210360370199)); let mut rng2 = Lcg128CmDxsm64::from_rng(&mut rng1); - assert_eq!(rng2.next_u64(), 11487972556150888383); + assert_eq!(rng2.try_next_u64(), Ok(11487972556150888383)); let mut rng3 = Lcg128CmDxsm64::seed_from_u64(0); - assert_eq!(rng3.next_u64(), 4111470453933123814); + assert_eq!(rng3.try_next_u64(), Ok(4111470453933123814)); // This is the same as Lcg128CmDxsm64, so we only have a single test: let mut rng4 = Pcg64Dxsm::seed_from_u64(0); - assert_eq!(rng4.next_u64(), 4111470453933123814); + assert_eq!(rng4.try_next_u64(), Ok(4111470453933123814)); } #[test] @@ -41,7 +41,7 @@ fn test_lcg128cmdxsm64_reference() { let mut results = [0u64; 6]; for i in results.iter_mut() { - *i = rng.next_u64(); + *i = rng.try_next_u64().unwrap(); } let expected: [u64; 6] = [ 17331114245835578256, @@ -67,6 +67,6 @@ fn test_lcg128cmdxsm64_serde() { postcard::from_bytes(&buf).expect("Could not deserialize"); for _ in 0..16 { - assert_eq!(rng.next_u64(), deserialized.next_u64()); + assert_eq!(rng.try_next_u64(), Ok(deserialized.next_u64())); } } diff --git a/rand_pcg/tests/lcg128xsl64.rs b/rand_pcg/tests/lcg128xsl64.rs index cbb11fbc21..4a04192d59 100644 --- a/rand_pcg/tests/lcg128xsl64.rs +++ b/rand_pcg/tests/lcg128xsl64.rs @@ -1,4 +1,4 @@ -use rand_core::{RngCore, SeedableRng}; +use rand_core::{SeedableRng, TryRng}; use rand_pcg::{Lcg128Xsl64, Pcg64}; #[test] @@ -7,7 +7,7 @@ fn test_lcg128xsl64_advancing() { let mut rng1 = Lcg128Xsl64::seed_from_u64(seed); let mut rng2 = rng1.clone(); for _ in 0..20 { - rng1.next_u64(); + rng1.try_next_u64().unwrap(); } rng2.advance(20); assert_eq!(rng1, rng2); @@ -21,17 +21,17 @@ fn test_lcg128xsl64_construction() { let seed = [1,2,3,4, 5,6,7,8, 9,10,11,12, 13,14,15,16, 17,18,19,20, 21,22,23,24, 25,26,27,28, 29,30,31,32]; let mut rng1 = Lcg128Xsl64::from_seed(seed); - assert_eq!(rng1.next_u64(), 8740028313290271629); + assert_eq!(rng1.try_next_u64(), Ok(8740028313290271629)); let mut rng2 = Lcg128Xsl64::from_rng(&mut rng1); - assert_eq!(rng2.next_u64(), 1922280315005786345); + assert_eq!(rng2.try_next_u64(), Ok(1922280315005786345)); let mut rng3 = Lcg128Xsl64::seed_from_u64(0); - assert_eq!(rng3.next_u64(), 2354861276966075475); + assert_eq!(rng3.try_next_u64(), Ok(2354861276966075475)); // This is the same as Lcg128Xsl64, so we only have a single test: let mut rng4 = Pcg64::seed_from_u64(0); - assert_eq!(rng4.next_u64(), 2354861276966075475); + assert_eq!(rng4.try_next_u64(), Ok(2354861276966075475)); } #[test] @@ -41,7 +41,7 @@ fn test_lcg128xsl64_reference() { let mut results = [0u64; 6]; for i in results.iter_mut() { - *i = rng.next_u64(); + *i = rng.try_next_u64().unwrap(); } let expected: [u64; 6] = [ 0x86b1da1d72062b68, diff --git a/rand_pcg/tests/lcg64xsh32.rs b/rand_pcg/tests/lcg64xsh32.rs index 40df579e1f..afa23fbfea 100644 --- a/rand_pcg/tests/lcg64xsh32.rs +++ b/rand_pcg/tests/lcg64xsh32.rs @@ -1,4 +1,4 @@ -use rand_core::{RngCore, SeedableRng}; +use rand_core::{SeedableRng, TryRng}; use rand_pcg::{Lcg64Xsh32, Pcg32}; #[test] @@ -7,7 +7,7 @@ fn test_lcg64xsh32_advancing() { let mut rng1 = Lcg64Xsh32::seed_from_u64(seed); let mut rng2 = rng1.clone(); for _ in 0..20 { - rng1.next_u32(); + rng1.try_next_u32().unwrap(); } rng2.advance(20); assert_eq!(rng1, rng2); @@ -19,17 +19,17 @@ fn test_lcg64xsh32_construction() { // Test that various construction techniques produce a working RNG. let seed = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let mut rng1 = Lcg64Xsh32::from_seed(seed); - assert_eq!(rng1.next_u64(), 1204678643940597513); + assert_eq!(rng1.try_next_u64(), Ok(1204678643940597513)); let mut rng2 = Lcg64Xsh32::from_rng(&mut rng1); - assert_eq!(rng2.next_u64(), 12384929573776311845); + assert_eq!(rng2.try_next_u64(), Ok(12384929573776311845)); let mut rng3 = Lcg64Xsh32::seed_from_u64(0); - assert_eq!(rng3.next_u64(), 18195738587432868099); + assert_eq!(rng3.try_next_u64(), Ok(18195738587432868099)); // This is the same as Lcg64Xsh32, so we only have a single test: let mut rng4 = Pcg32::seed_from_u64(0); - assert_eq!(rng4.next_u64(), 18195738587432868099); + assert_eq!(rng4.try_next_u64(), Ok(18195738587432868099)); } #[test] @@ -39,7 +39,7 @@ fn test_lcg64xsh32_reference() { let mut results = [0u32; 6]; for i in results.iter_mut() { - *i = rng.next_u32(); + *i = rng.try_next_u32().unwrap(); } let expected: [u32; 6] = [ 0xa15c02b7, 0x7b47f409, 0xba1d3330, 0x83d2f293, 0xbfa4784b, 0xcbed606e, diff --git a/rand_pcg/tests/mcg128xsl64.rs b/rand_pcg/tests/mcg128xsl64.rs index 0654f06a69..11e368c29c 100644 --- a/rand_pcg/tests/mcg128xsl64.rs +++ b/rand_pcg/tests/mcg128xsl64.rs @@ -1,4 +1,4 @@ -use rand_core::{RngCore, SeedableRng}; +use rand_core::{SeedableRng, TryRng}; use rand_pcg::{Mcg128Xsl64, Pcg64Mcg}; #[test] @@ -7,7 +7,7 @@ fn test_mcg128xsl64_advancing() { let mut rng1 = Mcg128Xsl64::seed_from_u64(seed); let mut rng2 = rng1.clone(); for _ in 0..20 { - rng1.next_u64(); + rng1.try_next_u64().unwrap(); } rng2.advance(20); assert_eq!(rng1, rng2); @@ -19,17 +19,17 @@ fn test_mcg128xsl64_construction() { // Test that various construction techniques produce a working RNG. let seed = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let mut rng1 = Mcg128Xsl64::from_seed(seed); - assert_eq!(rng1.next_u64(), 7071994460355047496); + assert_eq!(rng1.try_next_u64(), Ok(7071994460355047496)); let mut rng2 = Mcg128Xsl64::from_rng(&mut rng1); - assert_eq!(rng2.next_u64(), 12300796107712034932); + assert_eq!(rng2.try_next_u64(), Ok(12300796107712034932)); let mut rng3 = Mcg128Xsl64::seed_from_u64(0); - assert_eq!(rng3.next_u64(), 6198063878555692194); + assert_eq!(rng3.try_next_u64(), Ok(6198063878555692194)); // This is the same as Mcg128Xsl64, so we only have a single test: let mut rng4 = Pcg64Mcg::seed_from_u64(0); - assert_eq!(rng4.next_u64(), 6198063878555692194); + assert_eq!(rng4.try_next_u64(), Ok(6198063878555692194)); } #[test] @@ -39,7 +39,7 @@ fn test_mcg128xsl64_reference() { let mut results = [0u64; 6]; for i in results.iter_mut() { - *i = rng.next_u64(); + *i = rng.try_next_u64().unwrap(); } let expected: [u64; 6] = [ 0x63b4a3a813ce700a, diff --git a/src/distr/other.rs b/src/distr/other.rs index 09be2e488c..00e80e2fd0 100644 --- a/src/distr/other.rs +++ b/src/distr/other.rs @@ -315,11 +315,11 @@ where #[cfg(test)] mod tests { use super::*; - use crate::RngCore; + use crate::InfallibleRng; #[test] fn test_misc() { - let rng: &mut dyn RngCore = &mut crate::test::rng(820); + let rng: &mut dyn InfallibleRng = &mut crate::test::rng(820); rng.sample::(StandardUniform); rng.sample::(StandardUniform); diff --git a/src/distr/uniform.rs b/src/distr/uniform.rs index 5d926021f3..e62868cf26 100644 --- a/src/distr/uniform.rs +++ b/src/distr/uniform.rs @@ -113,7 +113,7 @@ use core::fmt; use core::ops::{Range, RangeInclusive, RangeTo, RangeToInclusive}; use crate::distr::Distribution; -use crate::{Rng, RngCore}; +use crate::{InfallibleRng, Rng}; /// Error type returned from [`Uniform::new`] and `new_inclusive`. #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -421,7 +421,7 @@ where /// for `Rng::random_range`. pub trait SampleRange { /// Generate a sample from the given range. - fn sample_single(self, rng: &mut R) -> Result; + fn sample_single(self, rng: &mut R) -> Result; /// Check whether the range is empty. fn is_empty(&self) -> bool; @@ -429,7 +429,7 @@ pub trait SampleRange { impl SampleRange for Range { #[inline] - fn sample_single(self, rng: &mut R) -> Result { + fn sample_single(self, rng: &mut R) -> Result { T::Sampler::sample_single(self.start, self.end, rng) } @@ -441,7 +441,7 @@ impl SampleRange for Range { impl SampleRange for RangeInclusive { #[inline] - fn sample_single(self, rng: &mut R) -> Result { + fn sample_single(self, rng: &mut R) -> Result { T::Sampler::sample_single_inclusive(self.start(), self.end(), rng) } @@ -455,7 +455,7 @@ macro_rules! impl_sample_range_u { ($t:ty) => { impl SampleRange<$t> for RangeTo<$t> { #[inline] - fn sample_single(self, rng: &mut R) -> Result<$t, Error> { + fn sample_single(self, rng: &mut R) -> Result<$t, Error> { <$t as SampleUniform>::Sampler::sample_single(0, self.end, rng) } @@ -467,7 +467,7 @@ macro_rules! impl_sample_range_u { impl SampleRange<$t> for RangeToInclusive<$t> { #[inline] - fn sample_single(self, rng: &mut R) -> Result<$t, Error> { + fn sample_single(self, rng: &mut R) -> Result<$t, Error> { <$t as SampleUniform>::Sampler::sample_single_inclusive(0, self.end, rng) } diff --git a/src/distr/weighted/weighted_index.rs b/src/distr/weighted/weighted_index.rs index 8772c360db..d0a6572383 100644 --- a/src/distr/weighted/weighted_index.rs +++ b/src/distr/weighted/weighted_index.rs @@ -47,7 +47,7 @@ use serde::{Deserialize, Serialize}; /// /// Sampling from `WeightedIndex` will result in a single call to /// `Uniform::sample` (method of the [`Distribution`] trait), which typically -/// will request a single value from the underlying [`RngCore`], though the +/// will request a single value from the underlying [`Rng`], though the /// exact number depends on the implementation of `Uniform::sample`. /// /// # Example @@ -74,7 +74,7 @@ use serde::{Deserialize, Serialize}; /// ``` /// /// [`Uniform`]: crate::distr::Uniform -/// [`RngCore`]: crate::RngCore +/// [`Rng`]: crate::Rng /// [`rand_distr::weighted`]: https://docs.rs/rand_distr/latest/rand_distr/weighted/index.html #[derive(Debug, Clone, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] diff --git a/src/lib.rs b/src/lib.rs index e831cf2e81..ce302535bc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -100,7 +100,7 @@ macro_rules! error { ($($x:tt)*) => ( pub use rand_core; // Re-exports from rand_core -pub use rand_core::{CryptoRng, RngCore, SeedableRng, TryCryptoRng, TryRngCore}; +pub use rand_core::{CryptoRng, InfallibleRng, SeedableRng, TryRng}; // Public modules pub mod distr; @@ -128,7 +128,7 @@ pub use rng::{Fill, Rng}; #[cfg(feature = "thread_rng")] use crate::distr::{Distribution, StandardUniform}; -/// Adapter to support [`std::io::Read`] over a [`TryRngCore`] +/// Adapter to support [`std::io::Read`] over a [`TryRng`] /// /// # Examples /// @@ -143,10 +143,10 @@ use crate::distr::{Distribution, StandardUniform}; /// ).unwrap(); /// ``` #[cfg(feature = "std")] -pub struct RngReader(pub R); +pub struct RngReader(pub R); #[cfg(feature = "std")] -impl std::io::Read for RngReader { +impl std::io::Read for RngReader { #[inline] fn read(&mut self, buf: &mut [u8]) -> Result { self.0 @@ -157,7 +157,7 @@ impl std::io::Read for RngReader { } #[cfg(feature = "std")] -impl std::fmt::Debug for RngReader { +impl std::fmt::Debug for RngReader { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple("RngReader").finish() } @@ -334,9 +334,10 @@ pub fn fill(dest: &mut [T]) { #[cfg(test)] mod test { use super::*; + use core::convert::Infallible; /// Construct a deterministic RNG with the given seed - pub fn rng(seed: u64) -> impl RngCore { + pub fn rng(seed: u64) -> impl InfallibleRng { // For tests, we want a statistically good, fast, reproducible RNG. // PCG32 will do fine, and will be easy to embed if we ever need to. const INC: u64 = 11634580027462260723; @@ -355,19 +356,22 @@ mod test { #[derive(Clone)] pub struct StepRng(u64, u64); - impl RngCore for StepRng { - fn next_u32(&mut self) -> u32 { - self.next_u64() as u32 + impl TryRng for StepRng { + type Error = Infallible; + + fn try_next_u32(&mut self) -> Result { + self.try_next_u64().map(|x| x as u32) } - fn next_u64(&mut self) -> u64 { + fn try_next_u64(&mut self) -> Result { let res = self.0; self.0 = self.0.wrapping_add(self.1); - res + Ok(res) } - fn fill_bytes(&mut self, dst: &mut [u8]) { + fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Infallible> { rand_core::utils::fill_bytes_via_next_word(dst, || self.next_u64()); + Ok(()) } } diff --git a/src/prelude.rs b/src/prelude.rs index b0f563ad5f..8f45457049 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -32,4 +32,4 @@ pub use crate::rngs::ThreadRng; #[doc(no_inline)] pub use crate::seq::{IndexedMutRandom, IndexedRandom, IteratorRandom, SliceRandom}; #[doc(no_inline)] -pub use crate::{CryptoRng, Rng, RngCore, SeedableRng}; +pub use crate::{CryptoRng, InfallibleRng, Rng, SeedableRng, TryRng}; diff --git a/src/rng.rs b/src/rng.rs index 66af038627..006e899290 100644 --- a/src/rng.rs +++ b/src/rng.rs @@ -13,13 +13,14 @@ use crate::distr::uniform::{SampleRange, SampleUniform}; use crate::distr::{self, Distribution, StandardUniform}; use core::num::Wrapping; use core::{mem, slice}; -use rand_core::RngCore; +use rand_core::InfallibleRng; /// User-level interface for RNGs /// -/// [`RngCore`] is the `dyn`-safe implementation-level interface for Random -/// (Number) Generators. This trait, `Rng`, provides a user-level interface on -/// RNGs. It is implemented automatically for any `R: RngCore`. +/// [`TryRng`] (and its [`InfallibleRng`] trait-alias) is the `dyn`-safe +/// implementation-level interface for Random (Number) Generators. +/// This trait, `Rng`, provides a user-level interface on +/// RNGs. It is implemented automatically for any `R: InfallibleRng`. /// /// This trait must usually be brought into scope via `use rand::Rng;` or /// `use rand::prelude::*;`. @@ -29,11 +30,11 @@ use rand_core::RngCore; /// The basic pattern is `fn foo(rng: &mut R)`. Some /// things are worth noting here: /// -/// - Since `Rng: RngCore` and every `RngCore` implements `Rng`, it makes no -/// difference whether we use `R: Rng` or `R: RngCore`. +/// - Since `Rng: InfallibleRng` and every `InfallibleRng` implements `Rng`, +/// it makes no difference whether we use `R: Rng` or `R: InfallibleRng`. /// - The `+ ?Sized` un-bounding allows functions to be called directly on -/// type-erased references; i.e. `foo(r)` where `r: &mut dyn RngCore`. Without -/// this it would be necessary to write `foo(&mut r)`. +/// type-erased references; i.e. `foo(r)` where `r: &mut dyn InfallibleRng`. +/// Without this it would be necessary to write `foo(&mut r)`. /// /// An alternative pattern is possible: `fn foo(rng: R)`. This has some /// trade-offs. It allows the argument to be consumed directly without a `&mut` @@ -55,7 +56,16 @@ use rand_core::RngCore; /// /// # let v = foo(&mut rand::rng()); /// ``` -pub trait Rng: RngCore { +pub trait Rng: InfallibleRng { + /// Return the next `u32` value + fn next_u32(&mut self) -> u32; + + /// Return the next `u64` value + fn next_u64(&mut self) -> u64; + + /// Fill `dest` with random data + fn fill_bytes(&mut self, dest: &mut [u8]); + /// Return a random value via the [`StandardUniform`] distribution. /// /// # Example @@ -309,7 +319,7 @@ pub trait Rng: RngCore { /// rand::rng().fill(&mut arr[..]); /// ``` /// - /// [`fill_bytes`]: RngCore::fill_bytes + /// [`fill_bytes`]: Self::fill_bytes #[track_caller] fn fill(&mut self, dest: &mut [T]) { Fill::fill_slice(dest, self) @@ -354,7 +364,28 @@ pub trait Rng: RngCore { } } -impl Rng for R {} +impl Rng for R { + #[inline] + fn next_u32(&mut self) -> u32 { + match self.try_next_u32() { + Ok(x) => x, + } + } + + #[inline] + fn next_u64(&mut self) -> u64 { + match self.try_next_u64() { + Ok(x) => x, + } + } + + #[inline] + fn fill_bytes(&mut self, dest: &mut [u8]) { + match self.try_fill_bytes(dest) { + Ok(()) => (), + } + } +} /// Support filling a slice with random data /// @@ -575,7 +606,7 @@ mod test { fn test_rng_trait_object() { use crate::distr::{Distribution, StandardUniform}; let mut rng = rng(109); - let mut r = &mut rng as &mut dyn RngCore; + let mut r = &mut rng as &mut dyn InfallibleRng; r.next_u32(); r.random::(); assert_eq!(r.random_range(0..1), 0); @@ -587,7 +618,7 @@ mod test { fn test_rng_boxed_trait() { use crate::distr::{Distribution, StandardUniform}; let rng = rng(110); - let mut r = Box::new(rng) as Box; + let mut r = Box::new(rng) as Box; r.next_u32(); r.random::(); assert_eq!(r.random_range(0..1), 0); diff --git a/src/rngs/mod.rs b/src/rngs/mod.rs index c99dc3d2ff..98c580fb2f 100644 --- a/src/rngs/mod.rs +++ b/src/rngs/mod.rs @@ -68,7 +68,8 @@ //! //! ## Traits and functionality //! -//! All generators implement [`RngCore`] and thus also [`Rng`][crate::Rng]. +//! All generators implement [`TryRng`]. Most implement [`InfallibleRng`] (i.e. +//! `TryRng`) and thus also implement [`Rng`][crate::Rng]. //! See also the [Random Values] chapter in the book. //! //! Secure RNGs may additionally implement the [`CryptoRng`] trait. @@ -82,7 +83,8 @@ //! [Our RNGs]: https://rust-random.github.io/book/guide-rngs.html //! [Random Values]: https://rust-random.github.io/book/guide-values.html //! [`Rng`]: crate::Rng -//! [`RngCore`]: crate::RngCore +//! [`TryRng`]: crate::TryRng +//! [`InfallibleRng`]: crate::InfallibleRng //! [`CryptoRng`]: crate::CryptoRng //! [`SeedableRng`]: crate::SeedableRng //! [`rdrand`]: https://crates.io/crates/rdrand diff --git a/src/rngs/reseeding.rs b/src/rngs/reseeding.rs index 67bfe7f114..c60ae6e69b 100644 --- a/src/rngs/reseeding.rs +++ b/src/rngs/reseeding.rs @@ -10,10 +10,11 @@ //! A wrapper around another PRNG that reseeds it after it //! generates a certain number of random bytes. +use core::convert::Infallible; use core::mem::size_of_val; use rand_core::block::{BlockRng, CryptoGenerator, Generator}; -use rand_core::{CryptoRng, RngCore, SeedableRng, TryCryptoRng, TryRngCore}; +use rand_core::{CryptoRng, SeedableRng, TryRng}; /// A wrapper around any PRNG that implements [`Generator`], that adds the /// ability to reseed it. @@ -70,12 +71,12 @@ use rand_core::{CryptoRng, RngCore, SeedableRng, TryCryptoRng, TryRngCore}; pub struct ReseedingRng(BlockRng>) where G: Generator + SeedableRng, - Rsdr: TryRngCore; + Rsdr: TryRng; impl ReseedingRng where G: Generator + SeedableRng, - Rsdr: TryRngCore, + Rsdr: TryRng, { /// Create a new `ReseedingRng` from an existing PRNG, combined with a RNG /// to use as reseeder. @@ -99,31 +100,33 @@ where } // TODO: this should be implemented for any type where the inner type -// implements RngCore, but we can't specify that because ReseedingCore is private -impl RngCore for ReseedingRng +// implements TryRng, but we can't specify that because ReseedingCore is private +impl TryRng for ReseedingRng where G: Generator + SeedableRng, - Rsdr: TryRngCore, + Rsdr: TryRng, { + type Error = Infallible; + #[inline(always)] - fn next_u32(&mut self) -> u32 { - self.0.next_word() + fn try_next_u32(&mut self) -> Result { + Ok(self.0.next_word()) } #[inline(always)] - fn next_u64(&mut self) -> u64 { - self.0.next_u64_from_u32() + fn try_next_u64(&mut self) -> Result { + Ok(self.0.next_u64_from_u32()) } - fn fill_bytes(&mut self, dest: &mut [u8]) { - self.0.fill_bytes(dest) + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Infallible> { + Ok(self.0.fill_bytes(dest)) } } impl CryptoRng for ReseedingRng where G: Generator + SeedableRng + CryptoGenerator, - Rsdr: TryCryptoRng, + Rsdr: CryptoRng, { } @@ -138,7 +141,7 @@ struct ReseedingCore { impl Generator for ReseedingCore where G: Generator + SeedableRng, - Rsdr: TryRngCore, + Rsdr: TryRng, { type Output = ::Output; @@ -158,7 +161,7 @@ where impl ReseedingCore where G: Generator + SeedableRng, - Rsdr: TryRngCore, + Rsdr: TryRng, { /// Create a new `ReseedingCore`. /// @@ -214,7 +217,7 @@ where impl CryptoGenerator for ReseedingCore where G: Generator + SeedableRng + CryptoGenerator, - Rsdr: TryCryptoRng, + Rsdr: CryptoRng, { } diff --git a/src/rngs/small.rs b/src/rngs/small.rs index d65ffda05a..3b86378f34 100644 --- a/src/rngs/small.rs +++ b/src/rngs/small.rs @@ -8,7 +8,8 @@ //! A small fast RNG -use rand_core::{RngCore, SeedableRng}; +use core::convert::Infallible; +use rand_core::{SeedableRng, TryRng}; #[cfg(any(target_pointer_width = "32", target_pointer_width = "16"))] type Rng = super::xoshiro128plusplus::Xoshiro128PlusPlus; @@ -61,7 +62,7 @@ type Rng = super::xoshiro256plusplus::Xoshiro256PlusPlus; /// /// ## Generation /// -/// The generators implements [`RngCore`] and thus also [`Rng`][crate::Rng]. +/// The generators implements [`InfallibleRng`] and thus also [`Rng`][crate::Rng]. /// See also the [Random Values] chapter in the book. /// /// [portable]: https://rust-random.github.io/book/crate-reprod.html @@ -95,19 +96,21 @@ impl SeedableRng for SmallRng { } } -impl RngCore for SmallRng { +impl TryRng for SmallRng { + type Error = Infallible; + #[inline(always)] - fn next_u32(&mut self) -> u32 { - self.0.next_u32() + fn try_next_u32(&mut self) -> Result { + self.0.try_next_u32() } #[inline(always)] - fn next_u64(&mut self) -> u64 { - self.0.next_u64() + fn try_next_u64(&mut self) -> Result { + self.0.try_next_u64() } #[inline(always)] - fn fill_bytes(&mut self, dest: &mut [u8]) { - self.0.fill_bytes(dest) + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Infallible> { + self.0.try_fill_bytes(dest) } } diff --git a/src/rngs/std.rs b/src/rngs/std.rs index 82142d8d5f..82b13fef87 100644 --- a/src/rngs/std.rs +++ b/src/rngs/std.rs @@ -8,7 +8,8 @@ //! The standard RNG -use rand_core::{CryptoRng, RngCore, SeedableRng}; +use core::convert::Infallible; +use rand_core::{CryptoRng, SeedableRng, TryRng}; #[cfg(any(test, feature = "sys_rng"))] pub(crate) use chacha20::ChaCha12Core as Core; @@ -56,7 +57,7 @@ use chacha20::ChaCha12Rng as Rng; /// /// ## Generation /// -/// The generators implements [`RngCore`] and thus also [`Rng`][crate::Rng]. +/// The generators implements [`InfallibleRng`] and thus also [`Rng`][crate::Rng]. /// See also the [Random Values] chapter in the book. /// /// [portable]: https://rust-random.github.io/book/crate-reprod.html @@ -69,20 +70,22 @@ use chacha20::ChaCha12Rng as Rng; #[derive(Debug, PartialEq, Eq)] pub struct StdRng(Rng); -impl RngCore for StdRng { +impl TryRng for StdRng { + type Error = Infallible; + #[inline(always)] - fn next_u32(&mut self) -> u32 { - self.0.next_u32() + fn try_next_u32(&mut self) -> Result { + self.0.try_next_u32() } #[inline(always)] - fn next_u64(&mut self) -> u64 { - self.0.next_u64() + fn try_next_u64(&mut self) -> Result { + self.0.try_next_u64() } #[inline(always)] - fn fill_bytes(&mut self, dst: &mut [u8]) { - self.0.fill_bytes(dst) + fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Infallible> { + self.0.try_fill_bytes(dst) } } @@ -101,7 +104,7 @@ impl CryptoRng for StdRng {} #[cfg(test)] mod test { use crate::rngs::StdRng; - use crate::{Rng, RngCore, SeedableRng}; + use crate::{Rng, SeedableRng}; #[test] fn test_stdrng_construction() { diff --git a/src/rngs/thread.rs b/src/rngs/thread.rs index ef6db82244..4b4a10f95d 100644 --- a/src/rngs/thread.rs +++ b/src/rngs/thread.rs @@ -8,13 +8,13 @@ //! Thread-local random number generator -use core::cell::UnsafeCell; +use core::{cell::UnsafeCell, convert::Infallible}; use std::fmt; use std::rc::Rc; use std::thread_local; use super::{ReseedingRng, SysError, SysRng, std::Core}; -use rand_core::{CryptoRng, RngCore}; +use rand_core::{CryptoRng, TryRng}; // Rationale for using `UnsafeCell` in `ThreadRng`: // @@ -162,29 +162,31 @@ impl Default for ThreadRng { } } -impl RngCore for ThreadRng { +impl TryRng for ThreadRng { + type Error = Infallible; + #[inline(always)] - fn next_u32(&mut self) -> u32 { + fn try_next_u32(&mut self) -> Result { // SAFETY: We must make sure to stop using `rng` before anyone else // creates another mutable reference let rng = unsafe { &mut *self.rng.get() }; - rng.next_u32() + rng.try_next_u32() } #[inline(always)] - fn next_u64(&mut self) -> u64 { + fn try_next_u64(&mut self) -> Result { // SAFETY: We must make sure to stop using `rng` before anyone else // creates another mutable reference let rng = unsafe { &mut *self.rng.get() }; - rng.next_u64() + rng.try_next_u64() } #[inline(always)] - fn fill_bytes(&mut self, dest: &mut [u8]) { + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Infallible> { // SAFETY: We must make sure to stop using `rng` before anyone else // creates another mutable reference let rng = unsafe { &mut *self.rng.get() }; - rng.fill_bytes(dest) + rng.try_fill_bytes(dest) } } diff --git a/src/rngs/xoshiro128plusplus.rs b/src/rngs/xoshiro128plusplus.rs index 1e8713db2e..c42f31d235 100644 --- a/src/rngs/xoshiro128plusplus.rs +++ b/src/rngs/xoshiro128plusplus.rs @@ -6,7 +6,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rand_core::{RngCore, SeedableRng, utils}; +use core::convert::Infallible; +use rand_core::{SeedableRng, TryRng, utils}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -63,7 +64,7 @@ impl SeedableRng for Xoshiro128PlusPlus { } } -impl RngCore for Xoshiro128PlusPlus { +impl Xoshiro128PlusPlus { #[inline] fn next_u32(&mut self) -> u32 { let res = self.s[0] @@ -84,22 +85,32 @@ impl RngCore for Xoshiro128PlusPlus { res } +} + +impl TryRng for Xoshiro128PlusPlus { + type Error = Infallible; + + #[inline] + fn try_next_u32(&mut self) -> Result { + Ok(self.next_u32()) + } #[inline] - fn next_u64(&mut self) -> u64 { - utils::next_u64_via_u32(self) + fn try_next_u64(&mut self) -> Result { + Ok(utils::next_u64_via_u32(self)) } #[inline] - fn fill_bytes(&mut self, dst: &mut [u8]) { + fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Infallible> { utils::fill_bytes_via_next_word(dst, || self.next_u32()); + Ok(()) } } #[cfg(test)] mod tests { use super::Xoshiro128PlusPlus; - use rand_core::{RngCore, SeedableRng}; + use rand_core::SeedableRng; #[test] fn reference() { diff --git a/src/rngs/xoshiro256plusplus.rs b/src/rngs/xoshiro256plusplus.rs index b961574150..182bac73c4 100644 --- a/src/rngs/xoshiro256plusplus.rs +++ b/src/rngs/xoshiro256plusplus.rs @@ -6,7 +6,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rand_core::{RngCore, SeedableRng, utils}; +use core::convert::Infallible; +use rand_core::{SeedableRng, TryRng, utils}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -62,15 +63,7 @@ impl SeedableRng for Xoshiro256PlusPlus { } } -impl RngCore for Xoshiro256PlusPlus { - #[inline] - fn next_u32(&mut self) -> u32 { - // The lowest bits have some linear dependencies, so we use the - // upper bits instead. - let val = self.next_u64(); - (val >> 32) as u32 - } - +impl Xoshiro256PlusPlus { #[inline] fn next_u64(&mut self) -> u64 { let res = self.s[0] @@ -91,17 +84,35 @@ impl RngCore for Xoshiro256PlusPlus { res } +} + +impl TryRng for Xoshiro256PlusPlus { + type Error = Infallible; + + #[inline] + fn try_next_u32(&mut self) -> Result { + // The lowest bits have some linear dependencies, so we use the + // upper bits instead. + let val = self.next_u64(); + Ok((val >> 32) as u32) + } + + #[inline] + fn try_next_u64(&mut self) -> Result { + Ok(self.next_u64()) + } #[inline] - fn fill_bytes(&mut self, dst: &mut [u8]) { + fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Infallible> { utils::fill_bytes_via_next_word(dst, || self.next_u64()); + Ok(()) } } #[cfg(test)] mod tests { use super::Xoshiro256PlusPlus; - use rand_core::{RngCore, SeedableRng}; + use rand_core::SeedableRng; #[test] fn reference() { diff --git a/src/seq/coin_flipper.rs b/src/seq/coin_flipper.rs index 7e8f53116c..c8d075c9e3 100644 --- a/src/seq/coin_flipper.rs +++ b/src/seq/coin_flipper.rs @@ -6,15 +6,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::RngCore; +use crate::Rng; -pub(crate) struct CoinFlipper { +pub(crate) struct CoinFlipper { pub rng: R, chunk: u32, // TODO(opt): this should depend on RNG word size chunk_remaining: u32, } -impl CoinFlipper { +impl CoinFlipper { pub fn new(rng: R) -> Self { Self { rng, diff --git a/src/seq/increasing_uniform.rs b/src/seq/increasing_uniform.rs index 10dd48a652..ad83b17dbb 100644 --- a/src/seq/increasing_uniform.rs +++ b/src/seq/increasing_uniform.rs @@ -6,11 +6,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::{Rng, RngCore}; +use crate::Rng; /// Similar to a Uniform distribution, /// but after returning a number in the range [0,n], n is increased by 1. -pub(crate) struct IncreasingUniform { +pub(crate) struct IncreasingUniform { pub rng: R, n: u32, // Chunk is a random number in [0, (n + 1) * (n + 2) *..* (n + chunk_remaining) ) @@ -18,7 +18,7 @@ pub(crate) struct IncreasingUniform { chunk_remaining: u8, } -impl IncreasingUniform { +impl IncreasingUniform { /// Create a dice roller. /// The next item returned will be a random number in the range [0,n] pub fn new(rng: R, n: u32) -> Self {