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
This commit is contained in:
Alex Saveau 2022-12-07 02:18:04 -08:00 committed by GitHub
parent 50b9a44741
commit 0dddc2c559
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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<R: RngCore + ?Sized> RngCore for Box<R> {
}
}
/// 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<R: RngCore + ?Sized> std::io::Read for RngReadAdapter<'_, R> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
self.try_fill_bytes(buf)?;
self.inner.try_fill_bytes(buf)?;
Ok(buf.len())
}
}
#[cfg(feature = "std")]
impl<R: RngCore + ?Sized> 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 {}