Skip to content

Commit f2d07f3

Browse files
committed
Add InfallibleRng marker trait
1 parent b45e892 commit f2d07f3

File tree

10 files changed

+111
-66
lines changed

10 files changed

+111
-66
lines changed

rand_chacha/src/chacha.rs

+49-33
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@
1414
use self::core::fmt;
1515
use crate::guts::ChaCha;
1616
use rand_core::block::{BlockRng, BlockRngCore, CryptoBlockRng};
17-
use rand_core::{CryptoRng, Error, RngCore, SeedableRng};
17+
use rand_core::{CryptoRng, Error, InfallibleRng, RngCore, SeedableRng};
1818

19-
#[cfg(feature = "serde1")] use serde::{Serialize, Deserialize, Serializer, Deserializer};
19+
#[cfg(feature = "serde1")]
20+
use serde::{Deserialize, Deserializer, Serialize, Serializer};
2021

2122
// NB. this must remain consistent with some currently hard-coded numbers in this module
2223
const BUF_BLOCKS: u8 = 4;
@@ -85,6 +86,7 @@ macro_rules! chacha_impl {
8586
impl BlockRngCore for $ChaChaXCore {
8687
type Item = u32;
8788
type Results = Array64<u32>;
89+
8890
#[inline]
8991
fn generate(&mut self, r: &mut Self::Results) {
9092
self.state.refill4($rounds, &mut r.0);
@@ -93,9 +95,12 @@ macro_rules! chacha_impl {
9395

9496
impl SeedableRng for $ChaChaXCore {
9597
type Seed = [u8; 32];
98+
9699
#[inline]
97100
fn from_seed(seed: Self::Seed) -> Self {
98-
$ChaChaXCore { state: ChaCha::new(&seed, &[0u8; 8]) }
101+
$ChaChaXCore {
102+
state: ChaCha::new(&seed, &[0u8; 8]),
103+
}
99104
}
100105
}
101106

@@ -146,6 +151,7 @@ macro_rules! chacha_impl {
146151

147152
impl SeedableRng for $ChaChaXRng {
148153
type Seed = [u8; 32];
154+
149155
#[inline]
150156
fn from_seed(seed: Self::Seed) -> Self {
151157
let core = $ChaChaXCore::from_seed(seed);
@@ -160,14 +166,17 @@ macro_rules! chacha_impl {
160166
fn next_u32(&mut self) -> u32 {
161167
self.rng.next_u32()
162168
}
169+
163170
#[inline]
164171
fn next_u64(&mut self) -> u64 {
165172
self.rng.next_u64()
166173
}
174+
167175
#[inline]
168176
fn fill_bytes(&mut self, bytes: &mut [u8]) {
169177
self.rng.fill_bytes(bytes)
170178
}
179+
171180
#[inline]
172181
fn try_fill_bytes(&mut self, bytes: &mut [u8]) -> Result<(), Error> {
173182
self.rng.try_fill_bytes(bytes)
@@ -209,11 +218,9 @@ macro_rules! chacha_impl {
209218
#[inline]
210219
pub fn set_word_pos(&mut self, word_offset: u128) {
211220
let block = (word_offset / u128::from(BLOCK_WORDS)) as u64;
221+
self.rng.core.state.set_block_pos(block);
212222
self.rng
213-
.core
214-
.state
215-
.set_block_pos(block);
216-
self.rng.generate_and_set((word_offset % u128::from(BLOCK_WORDS)) as usize);
223+
.generate_and_set((word_offset % u128::from(BLOCK_WORDS)) as usize);
217224
}
218225

219226
/// Set the stream number.
@@ -229,10 +236,7 @@ macro_rules! chacha_impl {
229236
/// indirectly via `set_word_pos`), but this is not directly supported.
230237
#[inline]
231238
pub fn set_stream(&mut self, stream: u64) {
232-
self.rng
233-
.core
234-
.state
235-
.set_nonce(stream);
239+
self.rng.core.state.set_nonce(stream);
236240
if self.rng.index() != 64 {
237241
let wp = self.get_word_pos();
238242
self.set_word_pos(wp);
@@ -242,24 +246,20 @@ macro_rules! chacha_impl {
242246
/// Get the stream number.
243247
#[inline]
244248
pub fn get_stream(&self) -> u64 {
245-
self.rng
246-
.core
247-
.state
248-
.get_nonce()
249+
self.rng.core.state.get_nonce()
249250
}
250251

251252
/// Get the seed.
252253
#[inline]
253254
pub fn get_seed(&self) -> [u8; 32] {
254-
self.rng
255-
.core
256-
.state
257-
.get_seed()
255+
self.rng.core.state.get_seed()
258256
}
259257
}
260258

261259
impl CryptoRng for $ChaChaXRng {}
262260

261+
impl InfallibleRng for $ChaChaXRng {}
262+
263263
impl From<$ChaChaXCore> for $ChaChaXRng {
264264
fn from(core: $ChaChaXCore) -> Self {
265265
$ChaChaXRng {
@@ -286,22 +286,20 @@ macro_rules! chacha_impl {
286286
}
287287
#[cfg(feature = "serde1")]
288288
impl<'de> Deserialize<'de> for $ChaChaXRng {
289-
fn deserialize<D>(d: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
289+
fn deserialize<D>(d: D) -> Result<Self, D::Error>
290+
where D: Deserializer<'de> {
290291
$abst::$ChaChaXRng::deserialize(d).map(|x| Self::from(&x))
291292
}
292293
}
293294

294295
mod $abst {
295-
#[cfg(feature = "serde1")] use serde::{Serialize, Deserialize};
296+
#[cfg(feature = "serde1")] use serde::{Deserialize, Serialize};
296297

297298
// The abstract state of a ChaCha stream, independent of implementation choices. The
298299
// comparison and serialization of this object is considered a semver-covered part of
299300
// the API.
300301
#[derive(Debug, PartialEq, Eq)]
301-
#[cfg_attr(
302-
feature = "serde1",
303-
derive(Serialize, Deserialize),
304-
)]
302+
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
305303
pub(crate) struct $ChaChaXRng {
306304
seed: [u8; 32],
307305
stream: u64,
@@ -331,27 +329,45 @@ macro_rules! chacha_impl {
331329
}
332330
}
333331
}
334-
}
332+
};
335333
}
336334

337-
chacha_impl!(ChaCha20Core, ChaCha20Rng, 10, "ChaCha with 20 rounds", abstract20);
338-
chacha_impl!(ChaCha12Core, ChaCha12Rng, 6, "ChaCha with 12 rounds", abstract12);
339-
chacha_impl!(ChaCha8Core, ChaCha8Rng, 4, "ChaCha with 8 rounds", abstract8);
335+
chacha_impl!(
336+
ChaCha20Core,
337+
ChaCha20Rng,
338+
10,
339+
"ChaCha with 20 rounds",
340+
abstract20
341+
);
342+
chacha_impl!(
343+
ChaCha12Core,
344+
ChaCha12Rng,
345+
6,
346+
"ChaCha with 12 rounds",
347+
abstract12
348+
);
349+
chacha_impl!(
350+
ChaCha8Core,
351+
ChaCha8Rng,
352+
4,
353+
"ChaCha with 8 rounds",
354+
abstract8
355+
);
340356

341357
#[cfg(test)]
342358
mod test {
343359
use rand_core::{RngCore, SeedableRng};
344360

345-
#[cfg(feature = "serde1")] use super::{ChaCha20Rng, ChaCha12Rng, ChaCha8Rng};
361+
#[cfg(feature = "serde1")] use super::{ChaCha12Rng, ChaCha20Rng, ChaCha8Rng};
346362

347363
type ChaChaRng = super::ChaCha20Rng;
348364

349365
#[cfg(feature = "serde1")]
350366
#[test]
351367
fn test_chacha_serde_roundtrip() {
352368
let seed = [
353-
1, 0, 52, 0, 0, 0, 0, 0, 1, 0, 10, 0, 22, 32, 0, 0, 2, 0, 55, 49, 0, 11, 0, 0, 3, 0, 0, 0, 0,
354-
0, 2, 92,
369+
1, 0, 52, 0, 0, 0, 0, 0, 1, 0, 10, 0, 22, 32, 0, 0, 2, 0, 55, 49, 0, 11, 0, 0, 3, 0, 0,
370+
0, 0, 0, 2, 92,
355371
];
356372
let mut rng1 = ChaCha20Rng::from_seed(seed);
357373
let mut rng2 = ChaCha12Rng::from_seed(seed);
@@ -598,7 +614,7 @@ mod test {
598614

599615
#[test]
600616
fn test_chacha_word_pos_wrap_exact() {
601-
use super::{BUF_BLOCKS, BLOCK_WORDS};
617+
use super::{BLOCK_WORDS, BUF_BLOCKS};
602618
let mut rng = ChaChaRng::from_seed(Default::default());
603619
// refilling the buffer in set_word_pos will wrap the block counter to 0
604620
let last_block = (1 << 68) - u128::from(BUF_BLOCKS * BLOCK_WORDS);

rand_core/src/lib.rs

+8
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,14 @@ pub trait RngCore {
212212
/// [`BlockRngCore`]: block::BlockRngCore
213213
pub trait CryptoRng: RngCore {}
214214

215+
/// A marker trait used to indicate that an [`RngCore`] implementation is
216+
/// supposed to never return errors from the [`RngCore::try_fill_bytes`] method
217+
/// and never panic on unwrapping [`Error`] while calling other methods.
218+
///
219+
/// This trait is usually implemented by PRNGs, as opposed to OS, hardware,
220+
/// and periodically-reseeded RNGs, which may fail with IO errors.
221+
pub trait InfallibleRng: RngCore {}
222+
215223
/// A random number generator that can be explicitly seeded.
216224
///
217225
/// This trait encapsulates the low-level functionality common to all

rand_pcg/src/pcg128.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
const MULTIPLIER: u128 = 0x2360_ED05_1FC6_5DA4_4385_DF64_9FCC_F645;
1515

1616
use core::fmt;
17-
use rand_core::{impls, le, Error, RngCore, SeedableRng};
17+
use rand_core::{impls, le, Error, InfallibleRng, RngCore, SeedableRng};
1818
#[cfg(feature = "serde1")] use serde::{Deserialize, Serialize};
1919

2020
/// A PCG random number generator (XSL RR 128/64 (LCG) variant).
@@ -159,6 +159,7 @@ impl RngCore for Lcg128Xsl64 {
159159
}
160160
}
161161

162+
impl InfallibleRng for Lcg128Xsl64 {}
162163

163164
/// A PCG random number generator (XSL 128/64 (MCG) variant).
164165
///
@@ -280,3 +281,5 @@ fn output_xsl_rr(state: u128) -> u64 {
280281
let xsl = ((state >> XSHIFT) as u64) ^ (state as u64);
281282
xsl.rotate_right(rot)
282283
}
284+
285+
impl InfallibleRng for Mcg128Xsl64 {}

rand_pcg/src/pcg128cm.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
const MULTIPLIER: u64 = 15750249268501108917;
1515

1616
use core::fmt;
17-
use rand_core::{impls, le, Error, RngCore, SeedableRng};
17+
use rand_core::{impls, le, Error, InfallibleRng, RngCore, SeedableRng};
1818
#[cfg(feature = "serde1")] use serde::{Deserialize, Serialize};
1919

2020
/// A PCG random number generator (CM DXSM 128/64 (LCG) variant).
@@ -165,6 +165,8 @@ impl RngCore for Lcg128CmDxsm64 {
165165
}
166166
}
167167

168+
impl InfallibleRng for Lcg128CmDxsm64 {}
169+
168170
#[inline(always)]
169171
fn output_dxsm(state: u128) -> u64 {
170172
// See https://github.com/imneme/pcg-cpp/blob/ffd522e7188bef30a00c74dc7eb9de5faff90092/include/pcg_random.hpp#L1016

rand_pcg/src/pcg64.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
//! PCG random number generators
1212
1313
use core::fmt;
14-
use rand_core::{impls, le, Error, RngCore, SeedableRng};
14+
use rand_core::{impls, le, Error, InfallibleRng, RngCore, SeedableRng};
1515
#[cfg(feature = "serde1")] use serde::{Deserialize, Serialize};
1616

1717
// This is the default multiplier used by PCG for 64-bit state.
@@ -167,3 +167,5 @@ impl RngCore for Lcg64Xsh32 {
167167
Ok(())
168168
}
169169
}
170+
171+
impl InfallibleRng for Lcg64Xsh32 {}

src/rngs/mock.rs

+7-9
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@
88

99
//! Mock random number generator
1010
11-
use rand_core::{impls, Error, RngCore};
11+
use rand_core::{impls, Error, InfallibleRng, RngCore};
1212

13-
#[cfg(feature = "serde1")]
14-
use serde::{Serialize, Deserialize};
13+
#[cfg(feature = "serde1")] use serde::{Deserialize, Serialize};
1514

1615
/// A mock generator yielding very predictable output
1716
///
@@ -81,10 +80,11 @@ impl RngCore for StepRng {
8180
}
8281
}
8382

83+
impl InfallibleRng for StepRng {}
84+
8485
#[cfg(test)]
8586
mod tests {
86-
#[cfg(any(feature = "alloc", feature = "serde1"))]
87-
use super::StepRng;
87+
#[cfg(any(feature = "alloc", feature = "serde1"))] use super::StepRng;
8888

8989
#[test]
9090
#[cfg(feature = "serde1")]
@@ -94,18 +94,16 @@ mod tests {
9494
bincode::deserialize(&bincode::serialize(&some_rng).unwrap()).unwrap();
9595
assert_eq!(some_rng.v, de_some_rng.v);
9696
assert_eq!(some_rng.a, de_some_rng.a);
97-
9897
}
9998

10099
#[test]
101100
#[cfg(feature = "alloc")]
102101
fn test_bool() {
103-
use crate::{Rng, distributions::Standard};
102+
use crate::{distributions::Standard, Rng};
104103

105104
// If this result ever changes, update doc on StepRng!
106105
let rng = StepRng::new(0, 1 << 31);
107-
let result: alloc::vec::Vec<bool> =
108-
rng.sample_iter(Standard).take(6).collect();
106+
let result: alloc::vec::Vec<bool> = rng.sample_iter(Standard).take(6).collect();
109107
assert_eq!(&result, &[false, true, false, true, false, true]);
110108
}
111109
}

src/rngs/small.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
//! A small fast RNG
1010
11-
use rand_core::{Error, RngCore, SeedableRng};
11+
use rand_core::{Error, InfallibleRng, RngCore, SeedableRng};
1212

1313
#[cfg(target_pointer_width = "64")]
1414
type Rng = super::xoshiro256plusplus::Xoshiro256PlusPlus;
@@ -64,6 +64,8 @@ impl RngCore for SmallRng {
6464
}
6565
}
6666

67+
impl InfallibleRng for SmallRng {}
68+
6769
impl SmallRng {
6870
/// Construct an instance seeded from another `Rng`
6971
///

src/rngs/std.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,17 @@
1010
1111
use crate::{CryptoRng, Error, RngCore, SeedableRng};
1212

13-
#[cfg(feature = "getrandom")]
14-
pub(crate) use rand_chacha::ChaCha12Core as Core;
13+
#[cfg(feature = "getrandom")] pub(crate) use rand_chacha::ChaCha12Core as Core;
1514

1615
use rand_chacha::ChaCha12Rng as Rng;
16+
use rand_core::InfallibleRng;
1717

1818
/// The standard RNG. The PRNG algorithm in `StdRng` is chosen to be efficient
1919
/// on the current platform, to be statistically strong and unpredictable
2020
/// (meaning a cryptographically secure PRNG).
2121
///
2222
/// The current algorithm used is the ChaCha block cipher with 12 rounds. Please
23-
/// see this relevant [rand issue] for the discussion. This may change as new
23+
/// see this relevant [rand issue] for the discussion. This may change as new
2424
/// evidence of cipher security and performance becomes available.
2525
///
2626
/// The algorithm is deterministic but should not be considered reproducible
@@ -73,6 +73,8 @@ impl SeedableRng for StdRng {
7373

7474
impl CryptoRng for StdRng {}
7575

76+
impl InfallibleRng for StdRng {}
77+
7678

7779
#[cfg(test)]
7880
mod test {

0 commit comments

Comments
 (0)