Skip to content

Commit 2c3d34d

Browse files
authored
Merge pull request #425 from rust-lang-nursery/blockrng
BlockRng: make core public and remove inner() and inner_mut()
2 parents f25c24e + 736a6e0 commit 2c3d34d

File tree

4 files changed

+43
-43
lines changed

4 files changed

+43
-43
lines changed

rand_core/CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

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

rand_core/src/impls.rs

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -165,18 +165,28 @@ pub fn next_u64_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
165165
impl_uint_from_fill!(rng, u64, 8)
166166
}
167167

168-
/// Wrapper around PRNGs that implement [`BlockRngCore`] to keep a results
169-
/// buffer and offer the methods from [`RngCore`].
168+
/// A wrapper type implementing [`RngCore`] for some type implementing
169+
/// [`BlockRngCore`] with `u32` array buffer; i.e. this can be used to implement
170+
/// a full RNG from just a `generate` function.
171+
///
172+
/// The `core` field may be accessed directly but the results buffer may not.
173+
/// PRNG implementations can simply use a type alias
174+
/// (`pub type MyRng = BlockRng<MyRngCore>;`) but might prefer to use a
175+
/// wrapper type (`pub struct MyRng(BlockRng<MyRngCore>);`); the latter must
176+
/// re-implement `RngCore` but hides the implementation details and allows
177+
/// extra functionality to be defined on the RNG
178+
/// (e.g. `impl MyRng { fn set_stream(...){...} }`).
170179
///
171180
/// `BlockRng` has heavily optimized implementations of the [`RngCore`] methods
172181
/// reading values from the results buffer, as well as
173182
/// calling `BlockRngCore::generate` directly on the output array when
174183
/// `fill_bytes` / `try_fill_bytes` is called on a large array. These methods
175184
/// also handle the bookkeeping of when to generate a new batch of values.
176-
/// No generated values are ever thown away.
185+
/// No generated values are ever thown away and all values are consumed
186+
/// in-order (this may be important for reproducibility).
177187
///
178-
/// Currently `BlockRng` only implements `RngCore` for buffers which are slices
179-
/// of `u32` elements; this may be extended to other types in the future.
188+
/// See also [`BlockRng64`] which uses `u64` array buffers. Currently there is
189+
/// no direct support for other buffer types.
180190
///
181191
/// For easy initialization `BlockRng` also implements [`SeedableRng`].
182192
///
@@ -188,7 +198,8 @@ pub fn next_u64_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
188198
pub struct BlockRng<R: BlockRngCore + ?Sized> {
189199
results: R::Results,
190200
index: usize,
191-
core: R,
201+
/// The *core* part of the RNG, implementing the `generate` function.
202+
pub core: R,
192203
}
193204

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

217-
/// Return a reference the wrapped `BlockRngCore`.
218-
pub fn inner(&self) -> &R {
219-
&self.core
220-
}
221-
222-
/// Return a mutable reference the wrapped `BlockRngCore`.
223-
pub fn inner_mut(&mut self) -> &mut R {
224-
&mut self.core
225-
}
226-
227228
/// Get the index into the result buffer.
228229
///
229230
/// If this is equal to or larger than the size of the result buffer then
@@ -370,12 +371,20 @@ impl<R: BlockRngCore + SeedableRng> SeedableRng for BlockRng<R> {
370371

371372

372373

373-
/// Wrapper around PRNGs that implement [`BlockRngCore`] to keep a results
374-
/// buffer and offer the methods from [`RngCore`].
374+
/// A wrapper type implementing [`RngCore`] for some type implementing
375+
/// [`BlockRngCore`] with `u64` array buffer; i.e. this can be used to implement
376+
/// a full RNG from just a `generate` function.
375377
///
376378
/// This is similar to [`BlockRng`], but specialized for algorithms that operate
377379
/// on `u64` values.
378380
///
381+
/// Like [`BlockRng`], this wrapper does not throw away whole results and does
382+
/// use all generated values in-order. The behaviour of `next_u32` is however
383+
/// a bit special: half of a `u64` is consumed, leaving the other half in the
384+
/// buffer. If the next function called is `next_u32` then the other half is
385+
/// then consumed, however both `next_u64` and `fill_bytes` discard any
386+
/// half-consumed `u64`s when called.
387+
///
379388
/// [`BlockRngCore`]: ../BlockRngCore.t.html
380389
/// [`RngCore`]: ../RngCore.t.html
381390
/// [`BlockRng`]: struct.BlockRng.html
@@ -385,7 +394,8 @@ pub struct BlockRng64<R: BlockRngCore + ?Sized> {
385394
results: R::Results,
386395
index: usize,
387396
half_used: bool, // true if only half of the previous result is used
388-
core: R,
397+
/// The *core* part of the RNG, implementing the `generate` function.
398+
pub core: R,
389399
}
390400

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

416-
/// Return a reference the wrapped `BlockRngCore`.
417-
pub fn inner(&self) -> &R {
418-
&self.core
419-
}
420-
421-
/// Return a mutable reference the wrapped `BlockRngCore`.
422-
pub fn inner_mut(&mut self) -> &mut R {
423-
&mut self.core
424-
}
425-
426426
/// Get the index into the result buffer.
427427
///
428428
/// If this is equal to or larger than the size of the result buffer then
@@ -436,6 +436,7 @@ impl<R: BlockRngCore> BlockRng64<R> {
436436
/// This will force a new set of results to be generated on next use.
437437
pub fn reset(&mut self) {
438438
self.index = self.results.as_ref().len();
439+
self.half_used = false;
439440
}
440441

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

src/prng/chacha.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,8 @@ impl ChaChaRng {
138138
/// feature is enabled. In the future this will be enabled by default.
139139
#[cfg(feature = "i128_support")]
140140
pub fn get_word_pos(&self) -> u128 {
141-
let core = self.0.inner();
142-
let mut c = (core.state[13] as u64) << 32
143-
| (core.state[12] as u64);
141+
let mut c = (self.0.core.state[13] as u64) << 32
142+
| (self.0.core.state[12] as u64);
144143
let mut index = self.0.index();
145144
// c is the end of the last block generated, unless index is at end
146145
if index >= STATE_WORDS {
@@ -163,8 +162,8 @@ impl ChaChaRng {
163162
pub fn set_word_pos(&mut self, word_offset: u128) {
164163
let index = (word_offset as usize) & 0xF;
165164
let counter = (word_offset >> 4) as u64;
166-
self.0.inner_mut().state[12] = counter as u32;
167-
self.0.inner_mut().state[13] = (counter >> 32) as u32;
165+
self.0.core.state[12] = counter as u32;
166+
self.0.core.state[13] = (counter >> 32) as u32;
168167
if index != 0 {
169168
self.0.generate_and_set(index); // also increments counter
170169
} else {
@@ -185,17 +184,16 @@ impl ChaChaRng {
185184
/// indirectly via `set_word_pos`), but this is not directly supported.
186185
pub fn set_stream(&mut self, stream: u64) {
187186
let index = self.0.index();
188-
self.0.inner_mut().state[14] = stream as u32;
189-
self.0.inner_mut().state[15] = (stream >> 32) as u32;
187+
self.0.core.state[14] = stream as u32;
188+
self.0.core.state[15] = (stream >> 32) as u32;
190189
if index < STATE_WORDS {
191190
// we need to regenerate a partial result buffer
192191
{
193192
// reverse of counter adjustment in generate()
194-
let core = self.0.inner_mut();
195-
if core.state[12] == 0 {
196-
core.state[13] = core.state[13].wrapping_sub(1);
193+
if self.0.core.state[12] == 0 {
194+
self.0.core.state[13] = self.0.core.state[13].wrapping_sub(1);
197195
}
198-
core.state[12] = core.state[12].wrapping_sub(1);
196+
self.0.core.state[12] = self.0.core.state[12].wrapping_sub(1);
199197
}
200198
self.0.generate_and_set(index);
201199
}

src/reseeding.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ where R: BlockRngCore + SeedableRng,
7676

7777
/// Reseed the internal PRNG.
7878
pub fn reseed(&mut self) -> Result<(), Error> {
79-
self.0.inner_mut().reseed()
79+
self.0.core.reseed()
8080
}
8181
}
8282

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

0 commit comments

Comments
 (0)