Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Rename BlockRngCore -> Generator
  • Loading branch information
dhardy committed Nov 30, 2025
commit 977f74e24910545371a8c4b1899f816c04f4deac
78 changes: 37 additions & 41 deletions src/block.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! The `BlockRngCore` trait and implementation helpers
//! The `Generator` trait and implementation helpers
//!
//! The [`BlockRngCore`] trait exists to assist in the implementation of RNGs
//! The [`Generator`] trait exists to assist in the implementation of RNGs
//! which generate a block of data in a cache instead of returning generated
//! values directly.
//!
Expand All @@ -15,11 +15,11 @@
//!
//! ```no_run
//! use rand_core::{RngCore, SeedableRng};
//! use rand_core::block::{BlockRngCore, BlockRng};
//! use rand_core::block::{Generator, BlockRng};
//!
//! struct MyRngCore;
//!
//! impl BlockRngCore for MyRngCore {
//! impl Generator for MyRngCore {
//! type Results = [u32; 16];
//!
//! fn generate(&mut self, results: &mut Self::Results) {
Expand All @@ -34,26 +34,22 @@
//! }
//! }
//!
//! // optionally, also implement CryptoBlockRng for MyRngCore
//! // optionally, also implement CryptoGenerator for MyRngCore
//!
//! // Final RNG.
//! let mut rng = BlockRng::<MyRngCore>::seed_from_u64(0);
//! println!("First value: {}", rng.next_u32());
//! ```
//!
//! [`BlockRngCore`]: crate::block::BlockRngCore
//! [`Generator`]: crate::block::Generator
//! [`fill_bytes`]: RngCore::fill_bytes

use crate::le::fill_via_chunks;
use crate::{CryptoRng, RngCore, SeedableRng, TryRngCore};
use core::fmt;

/// A trait for RNGs which do not generate random numbers individually, but in
/// blocks (typically `[u32; N]`). This technique is commonly used by
/// cryptographic RNGs to improve performance.
///
/// See the [module][crate::block] documentation for details.
pub trait BlockRngCore {
/// A random (block) generator
pub trait Generator {
/// Results type. This is the 'block' an RNG implementing `BlockRngCore`
/// generates, which will usually be an array like `[u32; 16]`.
type Results;
Expand All @@ -62,14 +58,20 @@ pub trait BlockRngCore {
fn generate(&mut self, results: &mut Self::Results);
}

/// A marker trait used to indicate that an [`RngCore`] implementation is
/// supposed to be cryptographically secure.
/// A cryptographically secure generator
///
/// This is a marker trait used to indicate that a [`Generator`] implementation
/// is supposed to be cryptographically secure.
///
/// Mock generators should not implement this trait *except* under a
/// `#[cfg(test)]` attribute to ensure that mock "crypto" generators cannot be
/// used in production.
///
/// See [`CryptoRng`] docs for more information.
pub trait CryptoBlockRng: BlockRngCore {}
pub trait CryptoGenerator: Generator {}

/// A wrapper type implementing [`RngCore`] for some type implementing
/// [`BlockRngCore`] with `u32` array buffer; i.e. this can be used to implement
/// [`Generator`] with `u32` array buffer; i.e. this can be used to implement
/// a full RNG from just a `generate` function.
///
/// The `core` field may be accessed directly but the results buffer may not.
Expand All @@ -82,7 +84,7 @@ pub trait CryptoBlockRng: BlockRngCore {}
///
/// `BlockRng` has heavily optimized implementations of the [`RngCore`] methods
/// reading values from the results buffer, as well as
/// calling [`BlockRngCore::generate`] directly on the output array when
/// calling [`Generator::generate`] directly on the output array when
/// [`fill_bytes`] is called on a large array. These methods also handle
/// the bookkeeping of when to generate a new batch of values.
///
Expand All @@ -102,15 +104,15 @@ pub trait CryptoBlockRng: BlockRngCore {}
/// [`next_u64`]: RngCore::next_u64
/// [`fill_bytes`]: RngCore::fill_bytes
#[derive(Clone)]
pub struct BlockRng<R: BlockRngCore> {
pub struct BlockRng<R: Generator> {
results: R::Results,
index: usize,
/// The *core* part of the RNG, implementing the `generate` function.
pub core: R,
}

// Custom Debug implementation that does not expose the contents of `results`.
impl<const N: usize, R: BlockRngCore<Results = [u32; N]> + fmt::Debug> fmt::Debug for BlockRng<R> {
impl<const N: usize, R: Generator<Results = [u32; N]> + fmt::Debug> fmt::Debug for BlockRng<R> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("BlockRng")
.field("core", &self.core)
Expand All @@ -120,9 +122,9 @@ impl<const N: usize, R: BlockRngCore<Results = [u32; N]> + fmt::Debug> fmt::Debu
}
}

impl<const N: usize, R: BlockRngCore<Results = [u32; N]>> BlockRng<R> {
impl<const N: usize, R: Generator<Results = [u32; N]>> BlockRng<R> {
/// Create a new `BlockRng` from an existing RNG implementing
/// `BlockRngCore`. Results will be generated on first use.
/// `Generator`. Results will be generated on first use.
#[inline]
pub fn new(core: R) -> BlockRng<R> {
BlockRng {
Expand Down Expand Up @@ -159,7 +161,7 @@ impl<const N: usize, R: BlockRngCore<Results = [u32; N]>> BlockRng<R> {
}
}

impl<const N: usize, R: BlockRngCore<Results = [u32; N]>> RngCore for BlockRng<R> {
impl<const N: usize, R: Generator<Results = [u32; N]>> RngCore for BlockRng<R> {
#[inline]
fn next_u32(&mut self) -> u32 {
if self.index >= self.results.as_ref().len() {
Expand Down Expand Up @@ -212,9 +214,7 @@ impl<const N: usize, R: BlockRngCore<Results = [u32; N]>> RngCore for BlockRng<R
}
}

impl<const N: usize, R: BlockRngCore<Results = [u32; N]> + SeedableRng> SeedableRng
for BlockRng<R>
{
impl<const N: usize, R: Generator<Results = [u32; N]> + SeedableRng> SeedableRng for BlockRng<R> {
type Seed = R::Seed;

#[inline(always)]
Expand All @@ -238,10 +238,10 @@ impl<const N: usize, R: BlockRngCore<Results = [u32; N]> + SeedableRng> Seedable
}
}

impl<const N: usize, R: CryptoBlockRng<Results = [u32; N]>> CryptoRng for BlockRng<R> {}
impl<const N: usize, R: CryptoGenerator<Results = [u32; N]>> CryptoRng for BlockRng<R> {}

/// A wrapper type implementing [`RngCore`] for some type implementing
/// [`BlockRngCore`] with `u64` array buffer; i.e. this can be used to implement
/// [`Generator`] with `u64` array buffer; i.e. this can be used to implement
/// a full RNG from just a `generate` function.
///
/// This is similar to [`BlockRng`], but specialized for algorithms that operate
Expand All @@ -261,7 +261,7 @@ impl<const N: usize, R: CryptoBlockRng<Results = [u32; N]>> CryptoRng for BlockR
/// [`next_u64`]: RngCore::next_u64
/// [`fill_bytes`]: RngCore::fill_bytes
#[derive(Clone)]
pub struct BlockRng64<R: BlockRngCore + ?Sized> {
pub struct BlockRng64<R: Generator + ?Sized> {
results: R::Results,
index: usize,
half_used: bool, // true if only half of the previous result is used
Expand All @@ -270,9 +270,7 @@ pub struct BlockRng64<R: BlockRngCore + ?Sized> {
}

// Custom Debug implementation that does not expose the contents of `results`.
impl<const N: usize, R: BlockRngCore<Results = [u64; N]> + fmt::Debug> fmt::Debug
for BlockRng64<R>
{
impl<const N: usize, R: Generator<Results = [u64; N]> + fmt::Debug> fmt::Debug for BlockRng64<R> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("BlockRng64")
.field("core", &self.core)
Expand All @@ -283,9 +281,9 @@ impl<const N: usize, R: BlockRngCore<Results = [u64; N]> + fmt::Debug> fmt::Debu
}
}

impl<const N: usize, R: BlockRngCore<Results = [u64; N]>> BlockRng64<R> {
impl<const N: usize, R: Generator<Results = [u64; N]>> BlockRng64<R> {
/// Create a new `BlockRng` from an existing RNG implementing
/// `BlockRngCore`. Results will be generated on first use.
/// `Generator`. Results will be generated on first use.
#[inline]
pub fn new(core: R) -> BlockRng64<R> {
let results_empty = [0; N];
Expand Down Expand Up @@ -326,7 +324,7 @@ impl<const N: usize, R: BlockRngCore<Results = [u64; N]>> BlockRng64<R> {
}
}

impl<const N: usize, R: BlockRngCore<Results = [u64; N]>> RngCore for BlockRng64<R> {
impl<const N: usize, R: Generator<Results = [u64; N]>> RngCore for BlockRng64<R> {
#[inline]
fn next_u32(&mut self) -> u32 {
let mut index = self.index - self.half_used as usize;
Expand Down Expand Up @@ -378,9 +376,7 @@ impl<const N: usize, R: BlockRngCore<Results = [u64; N]>> RngCore for BlockRng64
}
}

impl<const N: usize, R: BlockRngCore<Results = [u64; N]> + SeedableRng> SeedableRng
for BlockRng64<R>
{
impl<const N: usize, R: Generator<Results = [u64; N]> + SeedableRng> SeedableRng for BlockRng64<R> {
type Seed = R::Seed;

#[inline(always)]
Expand All @@ -404,19 +400,19 @@ impl<const N: usize, R: BlockRngCore<Results = [u64; N]> + SeedableRng> Seedable
}
}

impl<const N: usize, R: CryptoBlockRng<Results = [u64; N]>> CryptoRng for BlockRng64<R> {}
impl<const N: usize, R: CryptoGenerator<Results = [u64; N]>> CryptoRng for BlockRng64<R> {}

#[cfg(test)]
mod test {
use crate::block::{BlockRng, BlockRng64, BlockRngCore};
use crate::block::{BlockRng, BlockRng64, Generator};
use crate::{RngCore, SeedableRng};

#[derive(Debug, Clone)]
struct DummyRng {
counter: u32,
}

impl BlockRngCore for DummyRng {
impl Generator for DummyRng {
type Results = [u32; 16];

fn generate(&mut self, results: &mut Self::Results) {
Expand Down Expand Up @@ -466,7 +462,7 @@ mod test {
counter: u64,
}

impl BlockRngCore for DummyRng64 {
impl Generator for DummyRng64 {
type Results = [u64; 8];

fn generate(&mut self, results: &mut Self::Results) {
Expand Down