Skip to content

Commit 78d1ea1

Browse files
committed
Introduce rand_core::impl_try_* macros instead of blanket impl
1 parent 0fe2383 commit 78d1ea1

File tree

11 files changed

+162
-70
lines changed

11 files changed

+162
-70
lines changed

rand_chacha/src/chacha.rs

+2
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,8 @@ macro_rules! chacha_impl {
253253

254254
impl CryptoRng for $ChaChaXRng {}
255255

256+
rand_core::impl_try_crypto_rng_from_crypto_rng!($ChaChaXRng);
257+
256258
impl From<$ChaChaXCore> for $ChaChaXRng {
257259
fn from(core: $ChaChaXCore) -> Self {
258260
$ChaChaXRng {

rand_core/src/blanket_impls.rs

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#[cfg(feature = "alloc")] use alloc::boxed::Box;
2+
3+
use crate::{CryptoRng, RngCore, TryCryptoRng, TryRngCore};
4+
5+
impl<'a, R: RngCore + ?Sized> RngCore for &'a mut R {
6+
#[inline(always)]
7+
fn next_u32(&mut self) -> u32 {
8+
R::next_u32(self)
9+
}
10+
11+
#[inline(always)]
12+
fn next_u64(&mut self) -> u64 {
13+
R::next_u64(self)
14+
}
15+
16+
#[inline(always)]
17+
fn fill_bytes(&mut self, dst: &mut [u8]) {
18+
R::fill_bytes(self, dst)
19+
}
20+
}
21+
22+
impl<'a, R: CryptoRng + ?Sized> CryptoRng for &'a mut R {}
23+
24+
impl<'a, R: TryRngCore + ?Sized> TryRngCore for &'a mut R {
25+
type Error = R::Error;
26+
27+
#[inline(always)]
28+
fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
29+
R::try_next_u32(self)
30+
}
31+
32+
#[inline(always)]
33+
fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
34+
R::try_next_u64(self)
35+
}
36+
37+
#[inline(always)]
38+
fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Self::Error> {
39+
R::try_fill_bytes(self, dst)
40+
}
41+
}
42+
43+
impl<'a, R: TryCryptoRng + ?Sized> TryCryptoRng for &'a mut R {}
44+
45+
#[cfg(feature = "alloc")]
46+
impl<R: RngCore + ?Sized> RngCore for Box<R> {
47+
#[inline(always)]
48+
fn next_u32(&mut self) -> u32 {
49+
R::next_u32(self)
50+
}
51+
52+
#[inline(always)]
53+
fn next_u64(&mut self) -> u64 {
54+
R::next_u64(self)
55+
}
56+
57+
#[inline(always)]
58+
fn fill_bytes(&mut self, dest: &mut [u8]) {
59+
R::fill_bytes(self, dest)
60+
}
61+
}
62+
63+
#[cfg(feature = "alloc")]
64+
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
65+
impl<R: CryptoRng + ?Sized> CryptoRng for Box<R> {}
66+
67+
#[cfg(feature = "alloc")]
68+
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
69+
impl<R: TryRngCore + ?Sized> TryRngCore for Box<R> {
70+
type Error = R::Error;
71+
72+
#[inline(always)]
73+
fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
74+
R::try_next_u32(self)
75+
}
76+
77+
#[inline(always)]
78+
fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
79+
R::try_next_u64(self)
80+
}
81+
82+
#[inline(always)]
83+
fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Self::Error> {
84+
R::try_fill_bytes(self, dst)
85+
}
86+
}
87+
88+
#[cfg(feature = "alloc")]
89+
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
90+
impl<R: TryCryptoRng + ?Sized> TryCryptoRng for Box<R> {}

rand_core/src/block.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
//! [`fill_bytes`]: RngCore::fill_bytes
5555
5656
use crate::impls::{fill_via_u32_chunks, fill_via_u64_chunks};
57-
use crate::{CryptoRng, RngCore, SeedableRng};
57+
use crate::{CryptoRng, RngCore, SeedableRng, TryRngCore};
5858
use core::fmt;
5959
#[cfg(feature = "serde1")] use serde::{Deserialize, Serialize};
6060

@@ -249,9 +249,14 @@ impl<R: BlockRngCore + SeedableRng> SeedableRng for BlockRng<R> {
249249
}
250250

251251
#[inline(always)]
252-
fn from_rng<S: RngCore>(rng: S) -> Self {
252+
fn from_rng(rng: impl RngCore) -> Self {
253253
Self::new(R::from_rng(rng))
254254
}
255+
256+
#[inline(always)]
257+
fn try_from_rng<S: TryRngCore>(rng: S) -> Result<Self, S::Error> {
258+
R::try_from_rng(rng).map(Self::new)
259+
}
255260
}
256261

257262
impl<R: CryptoBlockRng + BlockRngCore<Item = u32>> CryptoRng for BlockRng<R> {}
@@ -409,9 +414,14 @@ impl<R: BlockRngCore + SeedableRng> SeedableRng for BlockRng64<R> {
409414
}
410415

411416
#[inline(always)]
412-
fn from_rng<S: RngCore>(rng: S) -> Self {
417+
fn from_rng(rng: impl RngCore) -> Self {
413418
Self::new(R::from_rng(rng))
414419
}
420+
421+
#[inline(always)]
422+
fn try_from_rng<S: TryRngCore>(rng: S) -> Result<Self, S::Error> {
423+
R::try_from_rng(rng).map(Self::new)
424+
}
415425
}
416426

417427
impl<R: CryptoBlockRng + BlockRngCore<Item = u64>> CryptoRng for BlockRng64<R> {}

rand_core/src/impls.rs

+43
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,49 @@ pub fn next_u64_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
160160
u64::from_le_bytes(buf)
161161
}
162162

163+
/// Implement [`TryRngCore`] for a type implementing [`RngCore`].
164+
///
165+
/// Ideally, `rand_core` would define blanket impls for this, but they conflict with blanket impls
166+
/// for `&mut R` and `Box<R>`, so until specialziation is stabilized, implementer crates
167+
/// have to implement `TryRngCore` directly.
168+
#[macro_export]
169+
macro_rules! impl_try_rng_from_rng_core {
170+
($t:ty) => {
171+
impl $crate::TryRngCore for $t {
172+
type Error = core::convert::Infallible;
173+
174+
#[inline]
175+
fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
176+
Ok(self.next_u32())
177+
}
178+
179+
#[inline]
180+
fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
181+
Ok(self.next_u64())
182+
}
183+
184+
#[inline]
185+
fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Self::Error> {
186+
self.fill_bytes(dst);
187+
Ok(())
188+
}
189+
}
190+
};
191+
}
192+
193+
/// Implement [`TryCryptoRng`] for a type implementing [`CryptoRng`].
194+
///
195+
/// Ideally, `rand_core` would define blanket impls for this, but they conflict with blanket impls
196+
/// for `&mut R` and `Box<R>`, so until specialziation is stabilized, implementer crates
197+
/// have to implement `TryRngCore` and `TryCryptoRng` directly.
198+
#[macro_export]
199+
macro_rules! impl_try_crypto_rng_from_crypto_rng {
200+
($t:ty) => {
201+
$crate::impl_try_rng_from_rng_core!($t);
202+
impl $crate::TryCryptoRng for $t {}
203+
};
204+
}
205+
163206
#[cfg(test)]
164207
mod test {
165208
use super::*;

rand_core/src/lib.rs

+4-67
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@
3737

3838
#[cfg(feature = "alloc")] extern crate alloc;
3939
#[cfg(feature = "std")] extern crate std;
40-
#[cfg(feature = "alloc")] use alloc::boxed::Box;
4140

42-
use core::{convert::Infallible, fmt};
41+
use core::fmt;
4342

43+
mod blanket_impls;
4444
pub mod block;
4545
pub mod impls;
4646
pub mod le;
@@ -207,28 +207,6 @@ pub trait TryRngCore {
207207
/// See [`CryptoRng`] docs for more information.
208208
pub trait TryCryptoRng: TryRngCore {}
209209

210-
impl<R: RngCore> TryRngCore for R {
211-
type Error = Infallible;
212-
213-
#[inline]
214-
fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
215-
Ok(self.next_u32())
216-
}
217-
218-
#[inline]
219-
fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
220-
Ok(self.next_u64())
221-
}
222-
223-
#[inline]
224-
fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Self::Error> {
225-
self.fill_bytes(dst);
226-
Ok(())
227-
}
228-
}
229-
230-
impl<R: CryptoRng> TryCryptoRng for R {}
231-
232210
/// Wrapper around [`TryCryptoRng`] implementation which implements [`RngCore`]
233211
/// by panicking on potential errors.
234212
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash)]
@@ -401,7 +379,7 @@ pub trait SeedableRng: Sized {
401379
/// (in prior versions this was not required).
402380
///
403381
/// [`rand`]: https://docs.rs/rand
404-
fn from_rng<R: RngCore>(mut rng: R) -> Self {
382+
fn from_rng(mut rng: impl RngCore) -> Self {
405383
let mut seed = Self::Seed::default();
406384
rng.fill_bytes(seed.as_mut());
407385
Self::from_seed(seed)
@@ -410,7 +388,7 @@ pub trait SeedableRng: Sized {
410388
/// Create a new PRNG seeded from a potentially fallible `Rng`.
411389
///
412390
/// See [`from_rng`][SeedableRng::from_rng] docs for more infromation.
413-
fn try_from_rng<R: TryRngCore>(rng: &mut R) -> Result<Self, R::Error> {
391+
fn try_from_rng<R: TryRngCore>(mut rng: R) -> Result<Self, R::Error> {
414392
let mut seed = Self::Seed::default();
415393
rng.try_fill_bytes(seed.as_mut())?;
416394
Ok(Self::from_seed(seed))
@@ -461,47 +439,6 @@ pub trait SeedableRng: Sized {
461439
}
462440
}
463441

464-
impl<'a, R: RngCore + ?Sized> RngCore for &'a mut R {
465-
#[inline(always)]
466-
fn next_u32(&mut self) -> u32 {
467-
R::next_u32(self)
468-
}
469-
470-
#[inline(always)]
471-
fn next_u64(&mut self) -> u64 {
472-
R::next_u64(self)
473-
}
474-
475-
#[inline(always)]
476-
fn fill_bytes(&mut self, dst: &mut [u8]) {
477-
R::fill_bytes(self, dst)
478-
}
479-
}
480-
481-
impl<'a, R: CryptoRng + ?Sized> CryptoRng for &'a mut R {}
482-
483-
#[cfg(feature = "alloc")]
484-
impl<R: RngCore + ?Sized> RngCore for Box<R> {
485-
#[inline(always)]
486-
fn next_u32(&mut self) -> u32 {
487-
R::next_u32(self)
488-
}
489-
490-
#[inline(always)]
491-
fn next_u64(&mut self) -> u64 {
492-
R::next_u64(self)
493-
}
494-
495-
#[inline(always)]
496-
fn fill_bytes(&mut self, dest: &mut [u8]) {
497-
R::fill_bytes(self, dest)
498-
}
499-
}
500-
501-
#[cfg(feature = "alloc")]
502-
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
503-
impl<R: CryptoRng + ?Sized> CryptoRng for Box<R> {}
504-
505442
/// Adapter that enables reading through a [`io::Read`](std::io::Read) from a [`RngCore`].
506443
///
507444
/// # Examples

src/rngs/mock.rs

+2
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ impl RngCore for StepRng {
7474
}
7575
}
7676

77+
rand_core::impl_try_rng_from_rng_core!(StepRng);
78+
7779
#[cfg(test)]
7880
mod tests {
7981
#[cfg(any(feature = "alloc", feature = "serde1"))] use super::StepRng;

src/rngs/small.rs

+2
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ impl RngCore for SmallRng {
5959
}
6060
}
6161

62+
rand_core::impl_try_rng_from_rng_core!(SmallRng);
63+
6264
impl SmallRng {
6365
/// Construct an instance seeded from another `Rng`
6466
///

src/rngs/std.rs

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ impl SeedableRng for StdRng {
6363

6464
impl CryptoRng for StdRng {}
6565

66+
rand_core::impl_try_crypto_rng_from_crypto_rng!(StdRng);
6667

6768
#[cfg(test)]
6869
mod test {

src/rngs/thread.rs

+1
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ impl RngCore for ThreadRng {
179179

180180
impl CryptoRng for ThreadRng {}
181181

182+
rand_core::impl_try_crypto_rng_from_crypto_rng!(ThreadRng);
182183

183184
#[cfg(test)]
184185
mod test {

src/rngs/xoshiro128plusplus.rs

+2
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ impl RngCore for Xoshiro128PlusPlus {
9191
}
9292
}
9393

94+
rand_core::impl_try_rng_from_rng_core!(Xoshiro128PlusPlus);
95+
9496
#[cfg(test)]
9597
mod tests {
9698
use super::Xoshiro128PlusPlus;

src/rngs/xoshiro256plusplus.rs

+2
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ impl RngCore for Xoshiro256PlusPlus {
9494
}
9595
}
9696

97+
rand_core::impl_try_rng_from_rng_core!(Xoshiro256PlusPlus);
98+
9799
#[cfg(test)]
98100
mod tests {
99101
use super::Xoshiro256PlusPlus;

0 commit comments

Comments
 (0)