Skip to content

Commit f5e3b45

Browse files
authored
Move SeedableRng and UnwrapErr into separate modules (#63)
Minor code reorganization to make it a bit easier to read.
1 parent e591ff2 commit f5e3b45

File tree

3 files changed

+284
-278
lines changed

3 files changed

+284
-278
lines changed

src/lib.rs

Lines changed: 6 additions & 278 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,14 @@ pub use core::convert::Infallible;
1414

1515
pub mod block;
1616
pub mod utils;
17+
18+
mod seedable_rng;
19+
mod unwrap_err;
1720
mod word;
1821

22+
pub use seedable_rng::SeedableRng;
23+
pub use unwrap_err::UnwrapErr;
24+
1925
/// Trait for infallible random number generators
2026
///
2127
/// `Rng` is a sub-trait of [`TryRng`] for infallible generators.
@@ -243,281 +249,3 @@ where
243249
pub trait TryCryptoRng: TryRng {}
244250

245251
impl<R: DerefMut> TryCryptoRng for R where R::Target: TryCryptoRng {}
246-
247-
/// Wrapper around [`TryRng`] implementation which implements [`Rng`]
248-
/// by panicking on potential errors.
249-
///
250-
/// # Examples
251-
///
252-
/// ```rust
253-
/// # use rand_core::{UnwrapErr, TryRng, Rng};
254-
/// fn with_try_rng<R: TryRng>(mut rng: R) {
255-
/// // rng does not impl Rng:
256-
/// let _ = rng.try_next_u32(); // okay
257-
/// // let _ = rng.next_u32(); // error
258-
///
259-
/// // An adapter borrowing rng:
260-
/// let _ = UnwrapErr(&mut rng).next_u32();
261-
///
262-
/// // An adapter moving rng:
263-
/// let mut rng = UnwrapErr(rng);
264-
/// let _ = rng.next_u32();
265-
/// }
266-
///
267-
/// fn call_with_unsized_try_rng<R: TryRng + ?Sized>(rng: &mut R) {
268-
/// // R is unsized, thus we must use &mut R:
269-
/// let mut rng = UnwrapErr(rng);
270-
/// let _ = rng.next_u32();
271-
/// }
272-
/// ```
273-
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash)]
274-
pub struct UnwrapErr<R: TryRng>(pub R);
275-
276-
impl<R: TryRng> TryRng for UnwrapErr<R> {
277-
type Error = Infallible;
278-
279-
#[inline]
280-
fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
281-
self.0
282-
.try_next_u32()
283-
.map_err(|err| panic!("rand_core::UnwrapErr: failed to unwrap: {err}"))
284-
}
285-
286-
#[inline]
287-
fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
288-
self.0
289-
.try_next_u64()
290-
.map_err(|err| panic!("rand_core::UnwrapErr: failed to unwrap: {err}"))
291-
}
292-
293-
#[inline]
294-
fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Self::Error> {
295-
self.0
296-
.try_fill_bytes(dst)
297-
.map_err(|err| panic!("rand_core::UnwrapErr: failed to unwrap: {err}"))
298-
}
299-
}
300-
301-
impl<R: TryCryptoRng> TryCryptoRng for UnwrapErr<R> {}
302-
303-
impl<'r, R: TryRng + ?Sized> UnwrapErr<&'r mut R> {
304-
/// Reborrow with a new lifetime
305-
///
306-
/// Rust allows references like `&T` or `&mut T` to be "reborrowed" through
307-
/// coercion: essentially, the pointer is copied under a new, shorter, lifetime.
308-
/// Until rfcs#1403 lands, reborrows on user types require a method call.
309-
#[inline(always)]
310-
pub fn re<'b>(&'b mut self) -> UnwrapErr<&'b mut R>
311-
where
312-
'r: 'b,
313-
{
314-
UnwrapErr(self.0)
315-
}
316-
}
317-
318-
/// A random number generator that can be explicitly seeded.
319-
///
320-
/// This trait encapsulates the low-level functionality common to all
321-
/// pseudo-random number generators (PRNGs, or algorithmic generators).
322-
///
323-
/// A generator implementing `SeedableRng` will usually be deterministic, but
324-
/// beware that portability and reproducibility of results **is not implied**.
325-
/// Refer to documentation of the generator, noting that generators named after
326-
/// a specific algorithm are usually tested for reproducibility against a
327-
/// reference vector, while `SmallRng` and `StdRng` specifically opt out of
328-
/// reproducibility guarantees.
329-
///
330-
/// [`rand`]: https://docs.rs/rand
331-
pub trait SeedableRng: Sized {
332-
/// Seed type, which is restricted to types mutably-dereferenceable as `u8`
333-
/// arrays (we recommend `[u8; N]` for some `N`).
334-
///
335-
/// It is recommended to seed PRNGs with a seed of at least circa 100 bits,
336-
/// which means an array of `[u8; 12]` or greater to avoid picking RNGs with
337-
/// partially overlapping periods.
338-
///
339-
/// For cryptographic RNG's a seed of 256 bits is recommended, `[u8; 32]`.
340-
///
341-
///
342-
/// # Implementing `SeedableRng` for RNGs with large seeds
343-
///
344-
/// Note that [`Default`] is not implemented for large arrays `[u8; N]` with
345-
/// `N` > 32. To be able to implement the traits required by `SeedableRng`
346-
/// for RNGs with such large seeds, the newtype pattern can be used:
347-
///
348-
/// ```
349-
/// use rand_core::SeedableRng;
350-
///
351-
/// const N: usize = 64;
352-
/// #[derive(Clone)]
353-
/// pub struct MyRngSeed(pub [u8; N]);
354-
/// # #[allow(dead_code)]
355-
/// pub struct MyRng(MyRngSeed);
356-
///
357-
/// impl Default for MyRngSeed {
358-
/// fn default() -> MyRngSeed {
359-
/// MyRngSeed([0; N])
360-
/// }
361-
/// }
362-
///
363-
/// impl AsRef<[u8]> for MyRngSeed {
364-
/// fn as_ref(&self) -> &[u8] {
365-
/// &self.0
366-
/// }
367-
/// }
368-
///
369-
/// impl AsMut<[u8]> for MyRngSeed {
370-
/// fn as_mut(&mut self) -> &mut [u8] {
371-
/// &mut self.0
372-
/// }
373-
/// }
374-
///
375-
/// impl SeedableRng for MyRng {
376-
/// type Seed = MyRngSeed;
377-
///
378-
/// fn from_seed(seed: MyRngSeed) -> MyRng {
379-
/// MyRng(seed)
380-
/// }
381-
/// }
382-
/// ```
383-
type Seed: Clone + Default + AsRef<[u8]> + AsMut<[u8]>;
384-
385-
/// Create a new PRNG using the given seed.
386-
///
387-
/// PRNG implementations are allowed to assume that bits in the seed are
388-
/// well distributed. That means usually that the number of one and zero
389-
/// bits are roughly equal, and values like 0, 1 and (size - 1) are unlikely.
390-
/// Note that many non-cryptographic PRNGs will show poor quality output
391-
/// if this is not adhered to. If you wish to seed from simple numbers, use
392-
/// `seed_from_u64` instead.
393-
///
394-
/// All PRNG implementations should be reproducible unless otherwise noted:
395-
/// given a fixed `seed`, the same sequence of output should be produced
396-
/// on all runs, library versions and architectures (e.g. check endianness).
397-
/// Any "value-breaking" changes to the generator should require bumping at
398-
/// least the minor version and documentation of the change.
399-
///
400-
/// It is not required that this function yield the same state as a
401-
/// reference implementation of the PRNG given equivalent seed; if necessary
402-
/// another constructor replicating behaviour from a reference
403-
/// implementation can be added.
404-
///
405-
/// PRNG implementations should make sure `from_seed` never panics. In the
406-
/// case that some special values (like an all zero seed) are not viable
407-
/// seeds it is preferable to map these to alternative constant value(s),
408-
/// for example `0xBAD5EEDu32` or `0x0DDB1A5E5BAD5EEDu64` ("odd biases? bad
409-
/// seed"). This is assuming only a small number of values must be rejected.
410-
fn from_seed(seed: Self::Seed) -> Self;
411-
412-
/// Create a new PRNG using a `u64` seed.
413-
///
414-
/// This is a convenience-wrapper around `from_seed` to allow construction
415-
/// of any `SeedableRng` from a simple `u64` value. It is designed such that
416-
/// low Hamming Weight numbers like 0 and 1 can be used and should still
417-
/// result in good, independent seeds to the PRNG which is returned.
418-
///
419-
/// This **is not suitable for cryptography**, as should be clear given that
420-
/// the input size is only 64 bits.
421-
///
422-
/// Implementations for PRNGs *may* provide their own implementations of
423-
/// this function, but the default implementation should be good enough for
424-
/// all purposes. *Changing* the implementation of this function should be
425-
/// considered a value-breaking change.
426-
fn seed_from_u64(mut state: u64) -> Self {
427-
// We use PCG32 to generate a u32 sequence, and copy to the seed
428-
fn pcg32(state: &mut u64) -> [u8; 4] {
429-
const MUL: u64 = 6364136223846793005;
430-
const INC: u64 = 11634580027462260723;
431-
432-
// We advance the state first (to get away from the input value,
433-
// in case it has low Hamming Weight).
434-
*state = state.wrapping_mul(MUL).wrapping_add(INC);
435-
let state = *state;
436-
437-
// Use PCG output function with to_le to generate x:
438-
let xorshifted = (((state >> 18) ^ state) >> 27) as u32;
439-
let rot = (state >> 59) as u32;
440-
let x = xorshifted.rotate_right(rot);
441-
x.to_le_bytes()
442-
}
443-
444-
let mut seed = Self::Seed::default();
445-
let mut iter = seed.as_mut().chunks_exact_mut(4);
446-
for chunk in &mut iter {
447-
chunk.copy_from_slice(&pcg32(&mut state));
448-
}
449-
let rem = iter.into_remainder();
450-
if !rem.is_empty() {
451-
rem.copy_from_slice(&pcg32(&mut state)[..rem.len()]);
452-
}
453-
454-
Self::from_seed(seed)
455-
}
456-
457-
/// Create a new PRNG seeded from an infallible `Rng`.
458-
///
459-
/// This may be useful when needing to rapidly seed many PRNGs from a master
460-
/// PRNG, and to allow forking of PRNGs. It may be considered deterministic.
461-
///
462-
/// The master PRNG should be at least as high quality as the child PRNGs.
463-
/// When seeding non-cryptographic child PRNGs, we recommend using a
464-
/// different algorithm for the master PRNG (ideally a CSPRNG) to avoid
465-
/// correlations between the child PRNGs. If this is not possible (e.g.
466-
/// forking using small non-crypto PRNGs) ensure that your PRNG has a good
467-
/// mixing function on the output or consider use of a hash function with
468-
/// `from_seed`.
469-
///
470-
/// Note that seeding `XorShiftRng` from another `XorShiftRng` provides an
471-
/// extreme example of what can go wrong: the new PRNG will be a clone
472-
/// of the parent.
473-
///
474-
/// PRNG implementations are allowed to assume that a good RNG is provided
475-
/// for seeding, and that it is cryptographically secure when appropriate.
476-
/// As of `rand` 0.7 / `rand_core` 0.5, implementations overriding this
477-
/// method should ensure the implementation satisfies reproducibility
478-
/// (in prior versions this was not required).
479-
///
480-
/// [`rand`]: https://docs.rs/rand
481-
fn from_rng<R: Rng + ?Sized>(rng: &mut R) -> Self {
482-
let mut seed = Self::Seed::default();
483-
rng.fill_bytes(seed.as_mut());
484-
Self::from_seed(seed)
485-
}
486-
487-
/// Create a new PRNG seeded from a potentially fallible `Rng`.
488-
///
489-
/// See [`from_rng`][SeedableRng::from_rng] docs for more information.
490-
fn try_from_rng<R: TryRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
491-
let mut seed = Self::Seed::default();
492-
rng.try_fill_bytes(seed.as_mut())?;
493-
Ok(Self::from_seed(seed))
494-
}
495-
496-
/// Fork this PRNG
497-
///
498-
/// This creates a new PRNG from the current one by initializing a new one and
499-
/// seeding it from the current one.
500-
///
501-
/// This is useful when initializing a PRNG for a thread
502-
fn fork(&mut self) -> Self
503-
where
504-
Self: Rng,
505-
{
506-
Self::from_rng(self)
507-
}
508-
509-
/// Fork this PRNG
510-
///
511-
/// This creates a new PRNG from the current one by initializing a new one and
512-
/// seeding it from the current one.
513-
///
514-
/// This is useful when initializing a PRNG for a thread.
515-
///
516-
/// This is the failable equivalent to [`SeedableRng::fork`]
517-
fn try_fork(&mut self) -> Result<Self, Self::Error>
518-
where
519-
Self: TryRng,
520-
{
521-
Self::try_from_rng(self)
522-
}
523-
}

0 commit comments

Comments
 (0)