Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BlockRng: make core public and remove inner() and inner_mut() #425

Merged
merged 1 commit into from
May 7, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion rand_core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [0.2.0] - Unreleased
- Enable the `std` feature by default. (#409)
- Change `BlockRng64::inner` and add `BlockRng64::inner_mut` to mirror `BlockRng`. (#419)
- Remove `BlockRng{64}::inner` and `BlockRng::inner_mut`; instead making `core` public
- Add `BlockRng{64}::index` and `BlockRng{64}::generate_and_set`. (#374, #419)
- Change `BlockRngCore::Results` bound to also require `AsMut<[Self::Item]>`. (#419)

Expand Down
60 changes: 31 additions & 29 deletions rand_core/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,18 +165,28 @@ pub fn next_u64_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
impl_uint_from_fill!(rng, u64, 8)
}

/// Wrapper around PRNGs that implement [`BlockRngCore`] to keep a results
/// buffer and offer the methods from [`RngCore`].
/// A wrapper type implementing [`RngCore`] for some type implementing
/// [`BlockRngCore`] 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.
/// PRNG implementations can simply use a type alias
/// (`pub type MyRng = BlockRng<MyRngCore>;`) but might prefer to use a
/// wrapper type (`pub struct MyRng(BlockRng<MyRngCore>);`); the latter must
/// re-implement `RngCore` but hides the implementation details and allows
/// extra functionality to be defined on the RNG
/// (e.g. `impl MyRng { fn set_stream(...){...} }`).
///
/// `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
/// `fill_bytes` / `try_fill_bytes` is called on a large array. These methods
/// also handle the bookkeeping of when to generate a new batch of values.
/// No generated values are ever thown away.
/// No generated values are ever thown away and all values are consumed
/// in-order (this may be important for reproducibility).
///
/// Currently `BlockRng` only implements `RngCore` for buffers which are slices
/// of `u32` elements; this may be extended to other types in the future.
/// See also [`BlockRng64`] which uses `u64` array buffers. Currently there is
/// no direct support for other buffer types.
///
/// For easy initialization `BlockRng` also implements [`SeedableRng`].
///
Expand All @@ -188,7 +198,8 @@ pub fn next_u64_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
pub struct BlockRng<R: BlockRngCore + ?Sized> {
results: R::Results,
index: usize,
core: R,
/// The *core* part of the RNG, implementing the `generate` function.
pub core: R,
}

// Custom Debug implementation that does not expose the contents of `results`.
Expand All @@ -214,16 +225,6 @@ impl<R: BlockRngCore> BlockRng<R> {
}
}

/// Return a reference the wrapped `BlockRngCore`.
pub fn inner(&self) -> &R {
&self.core
}

/// Return a mutable reference the wrapped `BlockRngCore`.
pub fn inner_mut(&mut self) -> &mut R {
&mut self.core
}

/// Get the index into the result buffer.
///
/// If this is equal to or larger than the size of the result buffer then
Expand Down Expand Up @@ -370,12 +371,20 @@ impl<R: BlockRngCore + SeedableRng> SeedableRng for BlockRng<R> {



/// Wrapper around PRNGs that implement [`BlockRngCore`] to keep a results
/// buffer and offer the methods from [`RngCore`].
/// A wrapper type implementing [`RngCore`] for some type implementing
/// [`BlockRngCore`] 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
/// on `u64` values.
///
/// Like [`BlockRng`], this wrapper does not throw away whole results and does
/// use all generated values in-order. The behaviour of `next_u32` is however
/// a bit special: half of a `u64` is consumed, leaving the other half in the
/// buffer. If the next function called is `next_u32` then the other half is
/// then consumed, however both `next_u64` and `fill_bytes` discard any
/// half-consumed `u64`s when called.
///
/// [`BlockRngCore`]: ../BlockRngCore.t.html
/// [`RngCore`]: ../RngCore.t.html
/// [`BlockRng`]: struct.BlockRng.html
Expand All @@ -385,7 +394,8 @@ pub struct BlockRng64<R: BlockRngCore + ?Sized> {
results: R::Results,
index: usize,
half_used: bool, // true if only half of the previous result is used
core: R,
/// The *core* part of the RNG, implementing the `generate` function.
pub core: R,
}

// Custom Debug implementation that does not expose the contents of `results`.
Expand Down Expand Up @@ -413,16 +423,6 @@ impl<R: BlockRngCore> BlockRng64<R> {
}
}

/// Return a reference the wrapped `BlockRngCore`.
pub fn inner(&self) -> &R {
&self.core
}

/// Return a mutable reference the wrapped `BlockRngCore`.
pub fn inner_mut(&mut self) -> &mut R {
&mut self.core
}

/// Get the index into the result buffer.
///
/// If this is equal to or larger than the size of the result buffer then
Expand All @@ -436,6 +436,7 @@ impl<R: BlockRngCore> BlockRng64<R> {
/// This will force a new set of results to be generated on next use.
pub fn reset(&mut self) {
self.index = self.results.as_ref().len();
self.half_used = false;
}

/// Generate a new set of results immediately, setting the index to the
Expand All @@ -444,6 +445,7 @@ impl<R: BlockRngCore> BlockRng64<R> {
assert!(index < self.results.as_ref().len());
self.core.generate(&mut self.results);
self.index = index;
self.half_used = false;
}
}

Expand Down
20 changes: 9 additions & 11 deletions src/prng/chacha.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,8 @@ impl ChaChaRng {
/// feature is enabled. In the future this will be enabled by default.
#[cfg(feature = "i128_support")]
pub fn get_word_pos(&self) -> u128 {
let core = self.0.inner();
let mut c = (core.state[13] as u64) << 32
| (core.state[12] as u64);
let mut c = (self.0.core.state[13] as u64) << 32
| (self.0.core.state[12] as u64);
let mut index = self.0.index();
// c is the end of the last block generated, unless index is at end
if index >= STATE_WORDS {
Expand All @@ -163,8 +162,8 @@ impl ChaChaRng {
pub fn set_word_pos(&mut self, word_offset: u128) {
let index = (word_offset as usize) & 0xF;
let counter = (word_offset >> 4) as u64;
self.0.inner_mut().state[12] = counter as u32;
self.0.inner_mut().state[13] = (counter >> 32) as u32;
self.0.core.state[12] = counter as u32;
self.0.core.state[13] = (counter >> 32) as u32;
if index != 0 {
self.0.generate_and_set(index); // also increments counter
} else {
Expand All @@ -185,17 +184,16 @@ impl ChaChaRng {
/// indirectly via `set_word_pos`), but this is not directly supported.
pub fn set_stream(&mut self, stream: u64) {
let index = self.0.index();
self.0.inner_mut().state[14] = stream as u32;
self.0.inner_mut().state[15] = (stream >> 32) as u32;
self.0.core.state[14] = stream as u32;
self.0.core.state[15] = (stream >> 32) as u32;
if index < STATE_WORDS {
// we need to regenerate a partial result buffer
{
// reverse of counter adjustment in generate()
let core = self.0.inner_mut();
if core.state[12] == 0 {
core.state[13] = core.state[13].wrapping_sub(1);
if self.0.core.state[12] == 0 {
self.0.core.state[13] = self.0.core.state[13].wrapping_sub(1);
}
core.state[12] = core.state[12].wrapping_sub(1);
self.0.core.state[12] = self.0.core.state[12].wrapping_sub(1);
}
self.0.generate_and_set(index);
}
Expand Down
4 changes: 2 additions & 2 deletions src/reseeding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ where R: BlockRngCore + SeedableRng,

/// Reseed the internal PRNG.
pub fn reseed(&mut self) -> Result<(), Error> {
self.0.inner_mut().reseed()
self.0.core.reseed()
}
}

Expand Down Expand Up @@ -112,7 +112,7 @@ where R: BlockRngCore + SeedableRng + Clone,
fn clone(&self) -> ReseedingRng<R, Rsdr> {
// Recreating `BlockRng` seems easier than cloning it and resetting
// the index.
ReseedingRng(BlockRng::new(self.0.inner().clone()))
ReseedingRng(BlockRng::new(self.0.core.clone()))
}
}

Expand Down