Skip to content

Commit

Permalink
rand_core: add blanket impl of TryRngCore for RngCore
Browse files Browse the repository at this point in the history
  • Loading branch information
newpavlov committed Sep 27, 2024
1 parent f263820 commit da637dd
Show file tree
Hide file tree
Showing 11 changed files with 57 additions and 171 deletions.
2 changes: 0 additions & 2 deletions rand_chacha/src/chacha.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,6 @@ macro_rules! chacha_impl {

impl CryptoRng for $ChaChaXRng {}

rand_core::impl_try_crypto_rng_from_crypto_rng!($ChaChaXRng);

impl From<$ChaChaXCore> for $ChaChaXRng {
fn from(core: $ChaChaXCore) -> Self {
$ChaChaXRng {
Expand Down
88 changes: 0 additions & 88 deletions rand_core/src/blanket_impls.rs

This file was deleted.

8 changes: 4 additions & 4 deletions rand_core/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,12 +250,12 @@ impl<R: BlockRngCore + SeedableRng> SeedableRng for BlockRng<R> {
}

#[inline(always)]
fn from_rng(rng: impl RngCore) -> Self {
fn from_rng(rng: &mut impl RngCore) -> Self {
Self::new(R::from_rng(rng))
}

#[inline(always)]
fn try_from_rng<S: TryRngCore>(rng: S) -> Result<Self, S::Error> {
fn try_from_rng<S: TryRngCore>(rng: &mut S) -> Result<Self, S::Error> {
R::try_from_rng(rng).map(Self::new)
}
}
Expand Down Expand Up @@ -415,12 +415,12 @@ impl<R: BlockRngCore + SeedableRng> SeedableRng for BlockRng64<R> {
}

#[inline(always)]
fn from_rng(rng: impl RngCore) -> Self {
fn from_rng(rng: &mut impl RngCore) -> Self {
Self::new(R::from_rng(rng))
}

#[inline(always)]
fn try_from_rng<S: TryRngCore>(rng: S) -> Result<Self, S::Error> {
fn try_from_rng<S: TryRngCore>(rng: &mut S) -> Result<Self, S::Error> {
R::try_from_rng(rng).map(Self::new)
}
}
Expand Down
54 changes: 0 additions & 54 deletions rand_core/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,60 +160,6 @@ pub fn next_u64_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
u64::from_le_bytes(buf)
}

/// Implement [`TryRngCore`][crate::TryRngCore] for a type implementing [`RngCore`].
///
/// Ideally, `rand_core` would define blanket impls for this, but they conflict with blanket impls
/// for `&mut R` and `Box<R>`, so until specialziation is stabilized, implementer crates
/// have to implement `TryRngCore` directly.
#[macro_export]
macro_rules! impl_try_rng_from_rng_core {
($t:ty) => {
impl $crate::TryRngCore for $t {
type Error = core::convert::Infallible;

#[inline]
fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
Ok($crate::RngCore::next_u32(self))
}

#[inline]
fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
Ok($crate::RngCore::next_u64(self))
}

#[inline]
fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Self::Error> {
$crate::RngCore::fill_bytes(self, dst);
Ok(())
}
}
};
}

/// Implement [`TryCryptoRng`] and [`TryRngCore`] for a type implementing [`CryptoRng`].
///
/// Ideally, `rand_core` would define blanket impls for this, but they conflict with blanket impls
/// for `&mut R` and `Box<R>`, so until specialziation is stabilized, implementer crates
/// have to implement `TryRngCore` and `TryCryptoRng` directly.
///
/// [`TryCryptoRng`]: crate::TryCryptoRng
/// [`TryRngCore`]: crate::TryRngCore
/// [`CryptoRng`]: crate::CryptoRng
#[macro_export]
macro_rules! impl_try_crypto_rng_from_crypto_rng {
($t:ty) => {
$crate::impl_try_rng_from_rng_core!($t);

impl $crate::TryCryptoRng for $t {}

/// Check at compile time that `$t` implements `CryptoRng`
const _: () = {
const fn check_crypto_rng_impl<T: $crate::CryptoRng>() {}
check_crypto_rng_impl::<$t>();
};
};
}

#[cfg(test)]
mod test {
use super::*;
Expand Down
62 changes: 51 additions & 11 deletions rand_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,8 @@ extern crate alloc;
#[cfg(feature = "std")]
extern crate std;

use core::fmt;
use core::{fmt, ops::DerefMut};

mod blanket_impls;
pub mod block;
pub mod impls;
pub mod le;
Expand Down Expand Up @@ -83,9 +82,9 @@ pub use os::OsRng;
/// in this trait directly, then use the helper functions from the
/// [`impls`] module to implement the other methods.
///
/// Implementors of [`RngCore`] SHOULD also implement the [`TryRngCore`]
/// trait with the `Error` associated type being equal to [`Infallible`].
/// It can be done using the [`impl_try_rng_from_rng_core!`] macro.
/// 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:
///
Expand Down Expand Up @@ -162,13 +161,24 @@ pub trait RngCore {
fn fill_bytes(&mut self, dst: &mut [u8]);
}

impl<T: DerefMut> RngCore for T
where
T::Target: RngCore,
{
fn next_u32(&mut self) -> u32 {
self.deref_mut().next_u32()
}
fn next_u64(&mut self) -> u64 {
self.deref_mut().next_u64()
}
fn fill_bytes(&mut self, dst: &mut [u8]) {
self.deref_mut().fill_bytes(dst);
}
}

/// A marker trait used to indicate that an [`RngCore`] implementation is
/// supposed to be cryptographically secure.
///
/// Implementors of [`CryptoRng`] SHOULD also implement the [`TryCryptoRng`]
/// trait with the `Error` associated type being equal to [`Infallible`].
/// It can be done using the [`impl_try_crypto_rng_from_crypto_rng!`] macro.
///
/// *Cryptographically secure generators*, also known as *CSPRNGs*, should
/// satisfy an additional properties over other generators: given the first
/// *k* bits of an algorithm's output
Expand All @@ -187,10 +197,15 @@ pub trait RngCore {
/// Note also that use of a `CryptoRng` does not protect against other
/// weaknesses such as seeding from a weak entropy source or leaking state.
///
/// Note that implementors of [`CryptoRng`] also automatically implement
/// the [`TryCryptoRng`] trait.
///
/// [`BlockRngCore`]: block::BlockRngCore
/// [`Infallible`]: core::convert::Infallible
pub trait CryptoRng: RngCore {}

impl<T: DerefMut> CryptoRng for T where T::Target: CryptoRng {}

/// A potentially fallible version of [`RngCore`].
///
/// This trait is primarily used for IO-based generators such as [`OsRng`].
Expand Down Expand Up @@ -233,12 +248,37 @@ pub trait TryRngCore {
}
}

// 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<R>`, etc.
impl<R: RngCore> TryRngCore for R {
type Error = core::convert::Infallible;

#[inline]
fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
Ok(self.next_u32())
}

#[inline]
fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
Ok(self.next_u64())
}

#[inline]
fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Self::Error> {
self.fill_bytes(dst);
Ok(())
}
}

/// A marker trait used to indicate that a [`TryRngCore`] implementation is
/// supposed to be cryptographically secure.
///
/// See [`CryptoRng`] docs for more information about cryptographically secure generators.
pub trait TryCryptoRng: TryRngCore {}

impl<R: CryptoRng> TryCryptoRng for R {}

/// Wrapper around [`TryRngCore`] implementation which implements [`RngCore`]
/// by panicking on potential errors.
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash)]
Expand Down Expand Up @@ -416,7 +456,7 @@ pub trait SeedableRng: Sized {
/// (in prior versions this was not required).
///
/// [`rand`]: https://docs.rs/rand
fn from_rng(mut rng: impl RngCore) -> Self {
fn from_rng(rng: &mut impl RngCore) -> Self {
let mut seed = Self::Seed::default();
rng.fill_bytes(seed.as_mut());
Self::from_seed(seed)
Expand All @@ -425,7 +465,7 @@ pub trait SeedableRng: Sized {
/// Create a new PRNG seeded from a potentially fallible `Rng`.
///
/// See [`from_rng`][SeedableRng::from_rng] docs for more information.
fn try_from_rng<R: TryRngCore>(mut rng: R) -> Result<Self, R::Error> {
fn try_from_rng<R: TryRngCore>(rng: &mut R) -> Result<Self, R::Error> {
let mut seed = Self::Seed::default();
rng.try_fill_bytes(seed.as_mut())?;
Ok(Self::from_seed(seed))
Expand Down
4 changes: 2 additions & 2 deletions src/rng.rs
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ mod test {

#[test]
fn test_rng_mut_ref() {
fn use_rng(mut r: impl Rng) {
fn use_rng(r: &mut impl Rng) {
let _ = r.next_u32();
}

Expand All @@ -566,7 +566,7 @@ mod test {
r.next_u32();
r.random::<i32>();
assert_eq!(r.gen_range(0..1), 0);
let _c: u8 = Standard.sample(&mut r);
let _c: u8 = Standard.sample(r);
}

#[test]
Expand Down
2 changes: 0 additions & 2 deletions src/rngs/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,6 @@ impl RngCore for StepRng {
}
}

rand_core::impl_try_rng_from_rng_core!(StepRng);

#[cfg(test)]
mod tests {
#[cfg(any(feature = "alloc", feature = "serde"))]
Expand Down
2 changes: 0 additions & 2 deletions src/rngs/small.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,6 @@ impl RngCore for SmallRng {
}
}

rand_core::impl_try_rng_from_rng_core!(SmallRng);

impl SmallRng {
/// Construct an instance seeded from the thread-local RNG
///
Expand Down
2 changes: 0 additions & 2 deletions src/rngs/std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,6 @@ impl SeedableRng for StdRng {

impl CryptoRng for StdRng {}

rand_core::impl_try_crypto_rng_from_crypto_rng!(StdRng);

#[cfg(test)]
mod test {
use crate::rngs::StdRng;
Expand Down
2 changes: 0 additions & 2 deletions src/rngs/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,6 @@ impl RngCore for ThreadRng {

impl CryptoRng for ThreadRng {}

rand_core::impl_try_crypto_rng_from_crypto_rng!(ThreadRng);

#[cfg(test)]
mod test {
#[test]
Expand Down
2 changes: 0 additions & 2 deletions src/rngs/xoshiro256plusplus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,6 @@ impl RngCore for Xoshiro256PlusPlus {
}
}

rand_core::impl_try_rng_from_rng_core!(Xoshiro256PlusPlus);

#[cfg(test)]
mod tests {
use super::Xoshiro256PlusPlus;
Expand Down

0 comments on commit da637dd

Please sign in to comment.