From 0dddc2c5593fae7dc473b9f1d5774f1caa5e61c2 Mon Sep 17 00:00:00 2001 From: Alex Saveau Date: Wed, 7 Dec 2022 02:18:04 -0800 Subject: [PATCH] Add read_adapter to avoid dynamic dispatch (#1267) * Add read_adapter to avoid dynamic dispatch * Get rid of the dyn Read impl since we can't deprecate it --- rand_core/src/lib.rs | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/rand_core/src/lib.rs b/rand_core/src/lib.rs index 1234a566..70baf78d 100644 --- a/rand_core/src/lib.rs +++ b/rand_core/src/lib.rs @@ -41,8 +41,8 @@ use core::convert::AsMut; use core::default::Default; -#[cfg(feature = "std")] extern crate std; #[cfg(feature = "alloc")] extern crate alloc; +#[cfg(feature = "std")] extern crate std; #[cfg(feature = "alloc")] use alloc::boxed::Box; pub use error::Error; @@ -182,6 +182,13 @@ pub trait RngCore { /// `fill_bytes` may be implemented with /// `self.try_fill_bytes(dest).unwrap()` or more specific error handling. fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error>; + + /// Convert an [`RngCore`] to a [`RngReadAdapter`]. + #[cfg(feature = "std")] + fn read_adapter(&mut self) -> RngReadAdapter<'_, Self> + where Self: Sized { + RngReadAdapter { inner: self } + } } /// A marker trait used to indicate that an [`RngCore`] or [`BlockRngCore`] @@ -469,14 +476,37 @@ impl RngCore for Box { } } +/// Adapter that enables reading through a [`io::Read`](std::io::Read) from a [`RngCore`]. +/// +/// # Examples +/// +/// ```rust +/// # use std::{io, io::Read}; +/// # use std::fs::File; +/// # use rand_core::{OsRng, RngCore}; +/// +/// io::copy(&mut OsRng.read_adapter().take(100), &mut File::create("/tmp/random.bytes").unwrap()).unwrap(); +/// ``` #[cfg(feature = "std")] -impl std::io::Read for dyn RngCore { +pub struct RngReadAdapter<'a, R: RngCore + ?Sized> { + inner: &'a mut R, +} + +#[cfg(feature = "std")] +impl std::io::Read for RngReadAdapter<'_, R> { fn read(&mut self, buf: &mut [u8]) -> Result { - self.try_fill_bytes(buf)?; + self.inner.try_fill_bytes(buf)?; Ok(buf.len()) } } +#[cfg(feature = "std")] +impl std::fmt::Debug for RngReadAdapter<'_, R> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("ReadAdapter").finish() + } +} + // Implement `CryptoRng` for references to a `CryptoRng`. impl<'a, R: CryptoRng + ?Sized> CryptoRng for &'a mut R {}