diff --git a/src/block.rs b/src/block.rs index d8b6e12a..34335a06 100644 --- a/src/block.rs +++ b/src/block.rs @@ -14,7 +14,8 @@ //! # Example //! //! ``` -//! use rand_core::{RngCore, SeedableRng}; +//! use core::convert::Infallible; +//! use rand_core::{TryRng, SeedableRng}; //! use rand_core::block::{Generator, BlockRng}; //! //! struct MyRngCore { @@ -45,28 +46,30 @@ //! } //! } //! -//! impl RngCore for MyRng { +//! impl TryRng for MyRng { +//! type Error = Infallible; +//! //! #[inline] -//! fn next_u32(&mut self) -> u32 { -//! self.0.next_word() +//! fn try_next_u32(&mut self) -> Result { +//! Ok(self.0.next_word()) //! } //! //! #[inline] -//! 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()) //! } //! //! #[inline] -//! fn fill_bytes(&mut self, bytes: &mut [u8]) { -//! self.0.fill_bytes(bytes) +//! fn try_fill_bytes(&mut self, bytes: &mut [u8]) -> Result<(), Infallible> { +//! Ok(self.0.fill_bytes(bytes)) //! } //! } //! //! // And if applicable: impl CryptoRng for MyRng {} //! //! let mut rng = MyRng::seed_from_u64(0); -//! println!("First value: {}", rng.next_u32()); -//! # assert_eq!(rng.next_u32(), 1171109249); +//! println!("First value: {}", rng.try_next_u32().unwrap()); +//! # assert_eq!(rng.try_next_u32(), Ok(1171109249)); //! ``` //! //! # ReseedingRng diff --git a/src/lib.rs b/src/lib.rs index a7323bc7..d3927ec4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,137 +13,12 @@ clippy::undocumented_unsafe_blocks )] -use core::{fmt, ops::DerefMut}; +use core::{convert::Infallible, fmt, ops::DerefMut}; pub mod block; pub mod utils; mod word; -/// Implementation-level interface for RNGs -/// -/// This trait encapsulates the low-level functionality common to all -/// generators, and is the "back end", to be implemented by generators. -/// End users should normally use the [`rand::Rng`] trait -/// which is automatically implemented for every type implementing `RngCore`. -/// -/// Three different methods for generating random data are provided since the -/// optimal implementation of each is dependent on the type of generator. There -/// is no required relationship between the output of each; e.g. many -/// implementations of [`fill_bytes`] consume a whole number of `u32` or `u64` -/// values and drop any remaining unused bytes. The same can happen with the -/// [`next_u32`] and [`next_u64`] methods, implementations may discard some -/// random bits for efficiency. -/// -/// # Properties of a generator -/// -/// Implementers should produce bits uniformly. Pathological RNGs (e.g. constant -/// or counting generators which rarely change some bits) may cause issues in -/// consumers of random data, for example dead-locks in rejection samplers and -/// obviously non-random output (e.g. a counting generator may result in -/// apparently-constant output from a uniform-ranged distribution). -/// -/// Algorithmic generators implementing [`SeedableRng`] should normally have -/// *portable, reproducible* output, i.e. fix Endianness when converting values -/// to avoid platform differences, and avoid making any changes which affect -/// output (except by communicating that the release has breaking changes). -/// -/// # Implementing `RngCore` -/// -/// Typically an RNG will implement only one of the methods available -/// in this trait directly, then use the helper functions from the -/// [`utils`] module to implement the other methods. -/// -/// Note that implementors of [`RngCore`] also automatically implement -/// the [`TryRngCore`] trait with the `Error` associated type being -/// equal to [`Infallible`]. -/// -/// It is recommended that implementations also implement: -/// -/// - `Debug` with a custom implementation which *does not* print any internal -/// state (at least, [`CryptoRng`]s should not risk leaking state through -/// `Debug`). -/// - `Serialize` and `Deserialize` (from Serde), preferably making Serde -/// support optional at the crate level in PRNG libs. -/// - `Clone`, if possible. -/// - *never* implement `Copy` (accidental copies may cause repeated values). -/// - *do not* implement `Default` for pseudorandom generators, but instead -/// implement [`SeedableRng`], to guide users towards proper seeding. -/// External / hardware RNGs can choose to implement `Default`. -/// - `Eq` and `PartialEq` could be implemented, but are probably not useful. -/// -/// [`rand::Rng`]: https://docs.rs/rand/latest/rand/trait.Rng.html -/// [`fill_bytes`]: RngCore::fill_bytes -/// [`next_u32`]: RngCore::next_u32 -/// [`next_u64`]: RngCore::next_u64 -/// [`Infallible`]: core::convert::Infallible -pub trait RngCore { - /// Return the next random `u32`. - fn next_u32(&mut self) -> u32; - - /// Return the next random `u64`. - fn next_u64(&mut self) -> u64; - - /// Fill `dest` with random data. - /// - /// This method should guarantee that `dest` is entirely filled - /// with new data, and may panic if this is impossible - /// (e.g. reading past the end of a file that is being used as the - /// source of randomness). - fn fill_bytes(&mut self, dst: &mut [u8]); -} - -impl RngCore for T -where - T::Target: RngCore, -{ - #[inline] - fn next_u32(&mut self) -> u32 { - self.deref_mut().next_u32() - } - - #[inline] - fn next_u64(&mut self) -> u64 { - self.deref_mut().next_u64() - } - - #[inline] - fn fill_bytes(&mut self, dst: &mut [u8]) { - self.deref_mut().fill_bytes(dst); - } -} - -/// A marker trait over [`RngCore`] for securely unpredictable RNGs -/// -/// This marker trait indicates that the implementing generator is intended, -/// when correctly seeded and protected from side-channel attacks such as a -/// leaking of state, to be a cryptographically secure generator. This trait is -/// provided as a tool to aid review of cryptographic code, but does not by -/// itself guarantee suitability for cryptographic applications. -/// -/// Implementors of `CryptoRng` automatically implement the [`TryCryptoRng`] -/// trait. -/// -/// Implementors of `CryptoRng` should only implement [`Default`] if the -/// `default()` instances are themselves secure generators: for example if the -/// implementing type is a stateless interface over a secure external generator -/// (like [`OsRng`]) or if the `default()` instance uses a strong, fresh seed. -/// -/// Formally, a CSPRNG (Cryptographically Secure Pseudo-Random Number Generator) -/// should satisfy an additional property over other generators: assuming that -/// the generator has been appropriately seeded and has unknown state, then -/// given the first *k* bits of an algorithm's output -/// sequence, it should not be possible using polynomial-time algorithms to -/// predict the next bit with probability significantly greater than 50%. -/// -/// An optional property of CSPRNGs is backtracking resistance: if the CSPRNG's -/// state is revealed, it will not be computationally-feasible to reconstruct -/// prior output values. This property is not required by `CryptoRng`. -/// -/// [`OsRng`]: https://docs.rs/rand/latest/rand/rngs/struct.OsRng.html -pub trait CryptoRng: RngCore {} - -impl CryptoRng for T where T::Target: CryptoRng {} - /// A potentially fallible variant of [`RngCore`] /// /// This trait is a generalization of [`RngCore`] to support potentially- @@ -158,7 +33,7 @@ impl CryptoRng for T where T::Target: CryptoRng {} /// panic in case the underlying fallible RNG yields an error. /// /// [`OsRng`]: https://docs.rs/rand/latest/rand/rngs/struct.OsRng.html -pub trait TryRngCore { +pub trait TryRng { /// The type returned in the event of a RNG error. type Error: fmt::Debug + fmt::Display; @@ -176,39 +51,35 @@ pub trait TryRngCore { { UnwrapErr(self) } - - /// Wrap RNG with the [`UnwrapMut`] wrapper. - fn unwrap_mut(&mut self) -> UnwrapMut<'_, Self> { - UnwrapMut(self) - } } -// Note that, unfortunately, this blanket impl prevents us from implementing -// `TryRngCore` for types which can be dereferenced to `TryRngCore`, i.e. `TryRngCore` -// will not be automatically implemented for `&mut R`, `Box`, etc. -impl TryRngCore for R { - type Error = core::convert::Infallible; +impl TryRng for T +where + T::Target: TryRng, +{ + type Error = ::Error; #[inline] fn try_next_u32(&mut self) -> Result { - Ok(self.next_u32()) + self.deref_mut().try_next_u32() } #[inline] fn try_next_u64(&mut self) -> Result { - Ok(self.next_u64()) + self.deref_mut().try_next_u64() } #[inline] fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Self::Error> { - self.fill_bytes(dst); - Ok(()) + self.deref_mut().try_fill_bytes(dst) } } -/// A marker trait over [`TryRngCore`] for securely unpredictable RNGs -/// -/// This trait is like [`CryptoRng`] but for the trait [`TryRngCore`]. +/// An infallible [`TryRng`] +pub trait InfallibleRng: TryRng {} +impl> InfallibleRng for R {} + +/// A marker trait over [`TryRng`] for securely unpredictable RNGs /// /// This marker trait indicates that the implementing generator is intended, /// when correctly seeded and protected from side-channel attacks such as a @@ -216,79 +87,55 @@ impl TryRngCore for R { /// provided as a tool to aid review of cryptographic code, but does not by /// itself guarantee suitability for cryptographic applications. /// -/// Implementors of `TryCryptoRng` should only implement [`Default`] if the +/// Implementors of `CryptoRng` should only implement [`Default`] if the /// `default()` instances are themselves secure generators: for example if the /// implementing type is a stateless interface over a secure external generator /// (like [`OsRng`]) or if the `default()` instance uses a strong, fresh seed. /// /// [`OsRng`]: https://docs.rs/rand/latest/rand/rngs/struct.OsRng.html -pub trait TryCryptoRng: TryRngCore {} - -impl TryCryptoRng for R {} +pub trait CryptoRng: TryRng {} -/// Wrapper around [`TryRngCore`] implementation which implements [`RngCore`] +/// Wrapper around [`TryRng`] implementation which implements [`RngCore`] /// by panicking on potential errors. #[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash)] -pub struct UnwrapErr(pub R); +pub struct UnwrapErr(pub R); + +impl TryRng for UnwrapErr { + type Error = Infallible; -impl RngCore for UnwrapErr { #[inline] - fn next_u32(&mut self) -> u32 { - self.0.try_next_u32().unwrap() + fn try_next_u32(&mut self) -> Result { + Ok(self.0.try_next_u32().unwrap()) } #[inline] - fn next_u64(&mut self) -> u64 { - self.0.try_next_u64().unwrap() + fn try_next_u64(&mut self) -> Result { + Ok(self.0.try_next_u64().unwrap()) } #[inline] - fn fill_bytes(&mut self, dst: &mut [u8]) { - self.0.try_fill_bytes(dst).unwrap() + fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Infallible> { + Ok(self.0.try_fill_bytes(dst).unwrap()) } } -impl CryptoRng for UnwrapErr {} - -/// Wrapper around [`TryRngCore`] implementation which implements [`RngCore`] -/// by panicking on potential errors. -#[derive(Debug, Eq, PartialEq, Hash)] -pub struct UnwrapMut<'r, R: TryRngCore + ?Sized>(pub &'r mut R); +impl CryptoRng for UnwrapErr {} -impl<'r, R: TryRngCore + ?Sized> UnwrapMut<'r, R> { +impl<'r, R: TryRng + ?Sized> UnwrapErr<&'r mut R> { /// Reborrow with a new lifetime /// /// Rust allows references like `&T` or `&mut T` to be "reborrowed" through /// coercion: essentially, the pointer is copied under a new, shorter, lifetime. /// Until rfcs#1403 lands, reborrows on user types require a method call. #[inline(always)] - pub fn re<'b>(&'b mut self) -> UnwrapMut<'b, R> + pub fn re<'b>(&'b mut self) -> UnwrapErr<&'b mut R> where 'r: 'b, { - UnwrapMut(self.0) + UnwrapErr(&mut self.0) } } -impl RngCore for UnwrapMut<'_, R> { - #[inline] - fn next_u32(&mut self) -> u32 { - self.0.try_next_u32().unwrap() - } - - #[inline] - fn next_u64(&mut self) -> u64 { - self.0.try_next_u64().unwrap() - } - - #[inline] - fn fill_bytes(&mut self, dst: &mut [u8]) { - self.0.try_fill_bytes(dst).unwrap() - } -} - -impl CryptoRng for UnwrapMut<'_, R> {} - /// A random number generator that can be explicitly seeded. /// /// This trait encapsulates the low-level functionality common to all @@ -452,16 +299,18 @@ pub trait SeedableRng: Sized { /// (in prior versions this was not required). /// /// [`rand`]: https://docs.rs/rand - fn from_rng(rng: &mut R) -> Self { + fn from_rng(rng: &mut R) -> Self { let mut seed = Self::Seed::default(); - rng.fill_bytes(seed.as_mut()); + match rng.try_fill_bytes(seed.as_mut()) { + Ok(()) => {} + } Self::from_seed(seed) } /// Create a new PRNG seeded from a potentially fallible `Rng`. /// /// See [`from_rng`][SeedableRng::from_rng] docs for more information. - fn try_from_rng(rng: &mut R) -> Result { + fn try_from_rng(rng: &mut R) -> Result { let mut seed = Self::Seed::default(); rng.try_fill_bytes(seed.as_mut())?; Ok(Self::from_seed(seed)) @@ -475,7 +324,7 @@ pub trait SeedableRng: Sized { /// This is useful when initializing a PRNG for a thread fn fork(&mut self) -> Self where - Self: RngCore, + Self: InfallibleRng, { Self::from_rng(self) } @@ -490,7 +339,7 @@ pub trait SeedableRng: Sized { /// This is the failable equivalent to [`SeedableRng::fork`] fn try_fork(&mut self) -> Result where - Self: TryRngCore, + Self: TryRng, { Self::try_from_rng(self) } @@ -543,14 +392,16 @@ mod test { // A stub RNG. struct SomeRng; - impl RngCore for SomeRng { - fn next_u32(&mut self) -> u32 { + impl TryRng for SomeRng { + type Error = Infallible; + + fn try_next_u32(&mut self) -> Result { unimplemented!() } - fn next_u64(&mut self) -> u64 { + fn try_next_u64(&mut self) -> Result { unimplemented!() } - fn fill_bytes(&mut self, _: &mut [u8]) { + fn try_fill_bytes(&mut self, _dst: &mut [u8]) -> Result<(), Self::Error> { unimplemented!() } } @@ -559,33 +410,15 @@ mod test { #[test] fn dyn_rngcore_to_tryrngcore() { - // Illustrates the need for `+ ?Sized` bound in `impl TryRngCore for R`. + // Illustrates the need for `+ ?Sized` bound in `impl TryRng for R`. // A method in another crate taking a fallible RNG - fn third_party_api(_rng: &mut (impl TryRngCore + ?Sized)) -> bool { + fn third_party_api(_rng: &mut (impl TryRng + ?Sized)) -> bool { true } // A method in our crate requiring an infallible RNG - fn my_api(rng: &mut dyn RngCore) -> bool { - // We want to call the method above - third_party_api(rng) - } - - assert!(my_api(&mut SomeRng)); - } - - #[test] - fn dyn_cryptorng_to_trycryptorng() { - // Illustrates the need for `+ ?Sized` bound in `impl TryCryptoRng for R`. - - // A method in another crate taking a fallible RNG - fn third_party_api(_rng: &mut (impl TryCryptoRng + ?Sized)) -> bool { - true - } - - // A method in our crate requiring an infallible RNG - fn my_api(rng: &mut dyn CryptoRng) -> bool { + fn my_api(rng: &mut dyn InfallibleRng) -> bool { // We want to call the method above third_party_api(rng) } @@ -596,31 +429,14 @@ mod test { #[test] fn dyn_unwrap_mut_tryrngcore() { // Illustrates the need for `+ ?Sized` bound in - // `impl RngCore for UnwrapMut<'_, R>`. - - fn third_party_api(_rng: &mut impl RngCore) -> bool { - true - } - - fn my_api(rng: &mut (impl TryRngCore + ?Sized)) -> bool { - let mut infallible_rng = rng.unwrap_mut(); - third_party_api(&mut infallible_rng) - } - - assert!(my_api(&mut SomeRng)); - } - - #[test] - fn dyn_unwrap_mut_trycryptorng() { - // Illustrates the need for `+ ?Sized` bound in - // `impl CryptoRng for UnwrapMut<'_, R>`. + // `impl InfallibleRng for UnwrapMut<'_, R>`. - fn third_party_api(_rng: &mut impl CryptoRng) -> bool { + fn third_party_api(_rng: &mut impl InfallibleRng) -> bool { true } - fn my_api(rng: &mut (impl TryCryptoRng + ?Sized)) -> bool { - let mut infallible_rng = rng.unwrap_mut(); + fn my_api(rng: &mut (impl TryRng + ?Sized)) -> bool { + let mut infallible_rng = rng.unwrap_err(); third_party_api(&mut infallible_rng) } @@ -631,7 +447,7 @@ mod test { fn reborrow_unwrap_mut() { struct FourRng; - impl TryRngCore for FourRng { + impl TryRng for FourRng { type Error = core::convert::Infallible; fn try_next_u32(&mut self) -> Result { Ok(4) @@ -645,14 +461,14 @@ mod test { } let mut rng = FourRng; - let mut rng = rng.unwrap_mut(); + let mut rng = (&mut rng).unwrap_err(); - assert_eq!(rng.next_u32(), 4); + assert_eq!(rng.try_next_u32(), Ok(4)); { let mut rng2 = rng.re(); - assert_eq!(rng2.next_u32(), 4); + assert_eq!(rng2.try_next_u32(), Ok(4)); // Make sure rng2 is dropped. } - assert_eq!(rng.next_u32(), 4); + assert_eq!(rng.try_next_u32(), Ok(4)); } } diff --git a/src/utils.rs b/src/utils.rs index 4fcd294c..30ba097c 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -39,7 +39,7 @@ //! We demonstrate a simple multiplicative congruential generator (MCG), taken //! from M.E. O'Neill's blog post //! [Does It Beat the Minimal Standard?](https://www.pcg-random.org/posts/does-it-beat-the-minimal-standard.html). -//! ``` +//! ```ignore //! use rand_core::{RngCore, SeedableRng, utils}; //! //! pub struct Mcg128(u128); @@ -80,23 +80,27 @@ //! # assert_eq!(buf, [154, 23, 43, 68, 75]); //! ``` -use crate::RngCore; +use crate::InfallibleRng; #[allow(unused)] use crate::SeedableRng; pub use crate::word::Word; /// Implement `next_u64` via `next_u32`, little-endian order. #[inline] -pub fn next_u64_via_u32(rng: &mut R) -> u64 { +pub fn next_u64_via_u32(rng: &mut R) -> u64 { // Use LE; we explicitly generate one value before the next. - let x = u64::from(rng.next_u32()); - let y = u64::from(rng.next_u32()); + let x: u64 = match rng.try_next_u32() { + Ok(x) => x.into(), + }; + let y: u64 = match rng.try_next_u32() { + Ok(y) => y.into(), + }; (y << 32) | x } /// Fill `dst` with bytes using `next_word` /// -/// This may be used to implement [`RngCore::fill_bytes`] over `next_u32` or +/// This may be used to implement [`InfallibleRng::fill_bytes`] over `next_u32` or /// `next_u64`. Words are used in order of generation. The last word may be /// partially discarded. #[inline] @@ -113,12 +117,14 @@ pub fn fill_bytes_via_next_word(dst: &mut [u8], mut next_word: impl FnM } } -/// Yield a word using [`RngCore::fill_bytes`] +/// Yield a word using [`InfallibleRng::fill_bytes`] /// /// This may be used to implement `next_u32` or `next_u64`. -pub fn next_word_via_fill(rng: &mut R) -> W { +pub fn next_word_via_fill(rng: &mut R) -> W { let mut buf: W::Bytes = Default::default(); - rng.fill_bytes(buf.as_mut()); + match rng.try_fill_bytes(buf.as_mut()) { + Ok(()) => {} + } W::from_le_bytes(buf) }