Skip to content

Commit 5033559

Browse files
committed
Make BlockRng{64} fields private
1 parent c5ffc61 commit 5033559

File tree

5 files changed

+127
-115
lines changed

5 files changed

+127
-115
lines changed

rand_core/src/impls.rs

Lines changed: 61 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -191,9 +191,9 @@ pub struct BlockRng<R: BlockRngCore + ?Sized> {
191191
#[cfg_attr(feature="serde-1", serde(bound(
192192
serialize = "R::Results: Serialize",
193193
deserialize = "R::Results: Deserialize<'de>")))]
194-
pub results: R::Results,
195-
pub index: usize,
196-
pub core: R,
194+
results: R::Results,
195+
index: usize,
196+
core: R,
197197
}
198198

199199
// Custom Debug implementation that does not expose the contents of `results`.
@@ -207,6 +207,30 @@ impl<R: BlockRngCore + fmt::Debug> fmt::Debug for BlockRng<R> {
207207
}
208208
}
209209

210+
impl<R: BlockRngCore> BlockRng<R> {
211+
/// Create a new `BlockRng` from an existing RNG implementing
212+
/// `BlockRngCore`. Results will be generated on first use.
213+
pub fn new(core: R) -> BlockRng<R>{
214+
let results_empty = R::Results::default();
215+
BlockRng {
216+
core,
217+
index: results_empty.as_ref().len(),
218+
results: results_empty,
219+
}
220+
}
221+
222+
/// Return a mutable reference the wrapped `BlockRngCore`.
223+
pub fn inner(&mut self) -> &mut R {
224+
&mut self.core
225+
}
226+
227+
// Reset the number of available results.
228+
// This will force a new set of results to be generated on next use.
229+
pub fn reset(&mut self) {
230+
self.index = self.results.as_ref().len();
231+
}
232+
}
233+
210234
impl<R: BlockRngCore<Item=u32>> RngCore for BlockRng<R>
211235
where <R as BlockRngCore>::Results: AsRef<[u32]>
212236
{
@@ -323,21 +347,11 @@ impl<R: BlockRngCore + SeedableRng> SeedableRng for BlockRng<R> {
323347
type Seed = R::Seed;
324348

325349
fn from_seed(seed: Self::Seed) -> Self {
326-
let results_empty = R::Results::default();
327-
Self {
328-
core: R::from_seed(seed),
329-
index: results_empty.as_ref().len(), // generate on first use
330-
results: results_empty,
331-
}
350+
Self::new(R::from_seed(seed))
332351
}
333352

334353
fn from_rng<S: RngCore>(rng: S) -> Result<Self, Error> {
335-
let results_empty = R::Results::default();
336-
Ok(Self {
337-
core: R::from_rng(rng)?,
338-
index: results_empty.as_ref().len(), // generate on first use
339-
results: results_empty,
340-
})
354+
Ok(Self::new(R::from_rng(rng)?))
341355
}
342356
}
343357

@@ -358,10 +372,10 @@ pub struct BlockRng64<R: BlockRngCore + ?Sized> {
358372
#[cfg_attr(feature="serde-1", serde(bound(
359373
serialize = "R::Results: Serialize",
360374
deserialize = "R::Results: Deserialize<'de>")))]
361-
pub results: R::Results,
362-
pub index: usize,
363-
pub half_used: bool, // true if only half of the previous result is used
364-
pub core: R,
375+
results: R::Results,
376+
index: usize,
377+
half_used: bool, // true if only half of the previous result is used
378+
core: R,
365379
}
366380

367381
// Custom Debug implementation that does not expose the contents of `results`.
@@ -376,6 +390,31 @@ impl<R: BlockRngCore + fmt::Debug> fmt::Debug for BlockRng64<R> {
376390
}
377391
}
378392

393+
impl<R: BlockRngCore> BlockRng64<R> {
394+
/// Create a new `BlockRng` from an existing RNG implementing
395+
/// `BlockRngCore`. Results will be generated on first use.
396+
pub fn new(core: R) -> BlockRng64<R>{
397+
let results_empty = R::Results::default();
398+
BlockRng64 {
399+
core,
400+
index: results_empty.as_ref().len(),
401+
half_used: false,
402+
results: results_empty,
403+
}
404+
}
405+
406+
/// Return a mutable reference the wrapped `BlockRngCore`.
407+
pub fn inner(&mut self) -> &mut R {
408+
&mut self.core
409+
}
410+
411+
// Reset the number of available results.
412+
// This will force a new set of results to be generated on next use.
413+
pub fn reset(&mut self) {
414+
self.index = self.results.as_ref().len();
415+
}
416+
}
417+
379418
impl<R: BlockRngCore<Item=u64>> RngCore for BlockRng64<R>
380419
where <R as BlockRngCore>::Results: AsRef<[u64]>
381420
{
@@ -424,6 +463,7 @@ where <R as BlockRngCore>::Results: AsRef<[u64]>
424463
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
425464
fn fill_bytes(&mut self, dest: &mut [u8]) {
426465
let mut filled = 0;
466+
self.half_used = false;
427467

428468
// Continue filling from the current set of results
429469
if self.index < self.results.as_ref().len() {
@@ -486,23 +526,11 @@ impl<R: BlockRngCore + SeedableRng> SeedableRng for BlockRng64<R> {
486526
type Seed = R::Seed;
487527

488528
fn from_seed(seed: Self::Seed) -> Self {
489-
let results_empty = R::Results::default();
490-
Self {
491-
core: R::from_seed(seed),
492-
index: results_empty.as_ref().len(), // generate on first use
493-
half_used: false,
494-
results: results_empty,
495-
}
529+
Self::new(R::from_seed(seed))
496530
}
497531

498532
fn from_rng<S: RngCore>(rng: S) -> Result<Self, Error> {
499-
let results_empty = R::Results::default();
500-
Ok(Self {
501-
core: R::from_rng(rng)?,
502-
index: results_empty.as_ref().len(), // generate on first use
503-
half_used: false,
504-
results: results_empty,
505-
})
533+
Ok(Self::new(R::from_rng(rng)?))
506534
}
507535
}
508536

src/prng/chacha.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,8 @@ impl ChaChaRng {
156156
/// assert_eq!(rng1.next_u32(), rng2.next_u32());
157157
/// ```
158158
pub fn set_counter(&mut self, counter_low: u64, counter_high: u64) {
159-
self.0.core.set_counter(counter_low, counter_high);
160-
self.0.index = STATE_WORDS; // force recomputation on next use
159+
self.0.inner().set_counter(counter_low, counter_high);
160+
self.0.reset(); // force recomputation on next use
161161
}
162162

163163
/// Sets the number of rounds to run the ChaCha core algorithm per block to
@@ -179,8 +179,8 @@ impl ChaChaRng {
179179
/// assert_eq!(rng.next_u32(), 0x2fef003e);
180180
/// ```
181181
pub fn set_rounds(&mut self, rounds: usize) {
182-
self.0.core.set_rounds(rounds);
183-
self.0.index = STATE_WORDS; // force recomputation on next use
182+
self.0.inner().set_rounds(rounds);
183+
self.0.reset(); // force recomputation on next use
184184
}
185185
}
186186

src/prng/isaac.rs

Lines changed: 22 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -128,28 +128,15 @@ impl IsaacRng {
128128
///
129129
/// DEPRECATED. `IsaacRng::new_from_u64(0)` will produce identical results.
130130
#[deprecated(since="0.5.0", note="use the NewRng or SeedableRng trait")]
131-
pub fn new_unseeded() -> IsaacRng {
131+
pub fn new_unseeded() -> Self {
132132
Self::new_from_u64(0)
133133
}
134134

135-
/// Create an ISAAC random number generator using an u64 as seed.
135+
/// Create an ISAAC random number generator using an `u64` as seed.
136136
/// If `seed == 0` this will produce the same stream of random numbers as
137137
/// the reference implementation when used unseeded.
138-
pub fn new_from_u64(seed: u64) -> IsaacRng {
139-
let mut key = [w(0); RAND_SIZE];
140-
key[0] = w(seed as u32);
141-
key[1] = w((seed >> 32) as u32);
142-
IsaacRng(BlockRng {
143-
// Initialize with only one pass.
144-
// A second pass does not improve the quality here, because all of
145-
// the seed was already available in the first round.
146-
// Not doing the second pass has the small advantage that if
147-
// `seed == 0` this method produces exactly the same state as the
148-
// reference implementation when used unseeded.
149-
core: IsaacCore::init(key, 1),
150-
results: IsaacArray::default(),
151-
index: RAND_SIZE, // generate on first use
152-
})
138+
pub fn new_from_u64(seed: u64) -> Self {
139+
IsaacRng(BlockRng::new(IsaacCore::new_from_u64(seed)))
153140
}
154141
}
155142

@@ -318,6 +305,22 @@ impl IsaacCore {
318305

319306
Self { mem, a: w(0), b: w(0), c: w(0) }
320307
}
308+
309+
/// Create an ISAAC random number generator using an `u64` as seed.
310+
/// If `seed == 0` this will produce the same stream of random numbers as
311+
/// the reference implementation when used unseeded.
312+
fn new_from_u64(seed: u64) -> Self {
313+
let mut key = [w(0); RAND_SIZE];
314+
key[0] = w(seed as u32);
315+
key[1] = w((seed >> 32) as u32);
316+
// Initialize with only one pass.
317+
// A second pass does not improve the quality here, because all of the
318+
// seed was already available in the first round.
319+
// Not doing the second pass has the small advantage that if
320+
// `seed == 0` this method produces exactly the same state as the
321+
// reference implementation when used unseeded.
322+
Self::init(key, 1)
323+
}
321324
}
322325

323326
impl SeedableRng for IsaacCore {
@@ -470,20 +473,8 @@ mod test {
470473
let mut read = BufReader::new(&buf[..]);
471474
let mut deserialized: IsaacRng = bincode::deserialize_from(&mut read).expect("Could not deserialize");
472475

473-
assert_eq!(rng.0.index, deserialized.0.index);
474-
/* Can't assert directly because of the array size */
475-
for (orig,deser) in rng.0.results.iter().zip(deserialized.0.results.iter()) {
476-
assert_eq!(orig, deser);
477-
}
478-
for (orig,deser) in rng.0.core.mem.iter().zip(deserialized.0.core.mem.iter()) {
479-
assert_eq!(orig, deser);
480-
}
481-
assert_eq!(rng.0.core.a, deserialized.0.core.a);
482-
assert_eq!(rng.0.core.b, deserialized.0.core.b);
483-
assert_eq!(rng.0.core.c, deserialized.0.core.c);
484-
485-
for _ in 0..16 {
486-
assert_eq!(rng.next_u64(), deserialized.next_u64());
476+
for _ in 0..300 { // more than the 256 buffered results
477+
assert_eq!(rng.next_u32(), deserialized.next_u32());
487478
}
488479
}
489480
}

src/prng/isaac64.rs

Lines changed: 20 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -118,28 +118,17 @@ impl Isaac64Rng {
118118
///
119119
/// DEPRECATED. `Isaac64Rng::new_from_u64(0)` will produce identical results.
120120
#[deprecated(since="0.5.0", note="use the NewRng or SeedableRng trait")]
121-
pub fn new_unseeded() -> Isaac64Rng {
121+
pub fn new_unseeded() -> Self {
122122
Self::new_from_u64(0)
123123
}
124124

125-
/// Create an ISAAC-64 random number generator using an u64 as seed.
125+
/// Create an ISAAC-64 random number generator using an `u64` as seed.
126126
/// If `seed == 0` this will produce the same stream of random numbers as
127127
/// the reference implementation when used unseeded.
128-
pub fn new_from_u64(seed: u64) -> Isaac64Rng {
128+
pub fn new_from_u64(seed: u64) -> Self {
129129
let mut key = [w(0); RAND_SIZE];
130130
key[0] = w(seed);
131-
Isaac64Rng(BlockRng64 {
132-
// Initialize with only one pass.
133-
// A second pass does not improve the quality here, because all of
134-
// the seed was already available in the first round.
135-
// Not doing the second pass has the small advantage that if
136-
// `seed == 0` this method produces exactly the same state as the
137-
// reference implementation when used unseeded.
138-
core: Isaac64Core::init(key, 1),
139-
results: IsaacArray::default(),
140-
index: RAND_SIZE, // generate on first use
141-
half_used: false,
142-
})
131+
Isaac64Rng(BlockRng64::new(Isaac64Core::new_from_u64(seed)))
143132
}
144133
}
145134

@@ -283,6 +272,21 @@ impl Isaac64Core {
283272

284273
Self { mem, a: w(0), b: w(0), c: w(0) }
285274
}
275+
276+
/// Create an ISAAC-64 random number generator using an `u64` as seed.
277+
/// If `seed == 0` this will produce the same stream of random numbers as
278+
/// the reference implementation when used unseeded.
279+
pub fn new_from_u64(seed: u64) -> Self {
280+
let mut key = [w(0); RAND_SIZE];
281+
key[0] = w(seed);
282+
// Initialize with only one pass.
283+
// A second pass does not improve the quality here, because all of the
284+
// seed was already available in the first round.
285+
// Not doing the second pass has the small advantage that if
286+
// `seed == 0` this method produces exactly the same state as the
287+
// reference implementation when used unseeded.
288+
Self::init(key, 1)
289+
}
286290
}
287291

288292
impl SeedableRng for Isaac64Core {
@@ -463,20 +467,7 @@ mod test {
463467
let mut read = BufReader::new(&buf[..]);
464468
let mut deserialized: Isaac64Rng = bincode::deserialize_from(&mut read).expect("Could not deserialize");
465469

466-
assert_eq!(rng.0.index, deserialized.0.index);
467-
assert_eq!(rng.0.half_used, deserialized.0.half_used);
468-
/* Can't assert directly because of the array size */
469-
for (orig,deser) in rng.0.results.iter().zip(deserialized.0.results.iter()) {
470-
assert_eq!(orig, deser);
471-
}
472-
for (orig,deser) in rng.0.core.mem.iter().zip(deserialized.0.core.mem.iter()) {
473-
assert_eq!(orig, deser);
474-
}
475-
assert_eq!(rng.0.core.a, deserialized.0.core.a);
476-
assert_eq!(rng.0.core.b, deserialized.0.core.b);
477-
assert_eq!(rng.0.core.c, deserialized.0.core.c);
478-
479-
for _ in 0..16 {
470+
for _ in 0..300 { // more than the 256 buffered results
480471
assert_eq!(rng.next_u64(), deserialized.next_u64());
481472
}
482473
}

src/reseeding.rs

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -68,28 +68,13 @@ where R: BlockRngCore + SeedableRng,
6868
/// * `rng`: the random number generator to use.
6969
/// * `threshold`: the number of generated bytes after which to reseed the RNG.
7070
/// * `reseeder`: the RNG to use for reseeding.
71-
pub fn new(rng: R, threshold: u64, reseeder: Rsdr)
72-
-> ReseedingRng<R, Rsdr>
73-
{
74-
assert!(threshold <= ::core::i64::MAX as u64);
75-
let results_empty = R::Results::default();
76-
ReseedingRng(
77-
BlockRng {
78-
core: ReseedingCore {
79-
inner: rng,
80-
reseeder,
81-
threshold: threshold as i64,
82-
bytes_until_reseed: threshold as i64,
83-
},
84-
index: results_empty.as_ref().len(), // generate on first use
85-
results: results_empty,
86-
}
87-
)
71+
pub fn new(rng: R, threshold: u64, reseeder: Rsdr) -> Self {
72+
ReseedingRng(BlockRng::new(ReseedingCore::new(rng, threshold, reseeder)))
8873
}
8974

9075
/// Reseed the internal PRNG.
9176
pub fn reseed(&mut self) -> Result<(), Error> {
92-
self.0.core.reseed()
77+
self.0.inner().reseed()
9378
}
9479
}
9580

@@ -154,6 +139,23 @@ impl<R, Rsdr> ReseedingCore<R, Rsdr>
154139
where R: BlockRngCore + SeedableRng,
155140
Rsdr: RngCore
156141
{
142+
/// Create a new `ReseedingCore` with the given parameters.
143+
///
144+
/// # Arguments
145+
///
146+
/// * `rng`: the random number generator to use.
147+
/// * `threshold`: the number of generated bytes after which to reseed the RNG.
148+
/// * `reseeder`: the RNG to use for reseeding.
149+
pub fn new(rng: R, threshold: u64, reseeder: Rsdr) -> Self {
150+
assert!(threshold <= ::core::i64::MAX as u64);
151+
ReseedingCore {
152+
inner: rng,
153+
reseeder,
154+
threshold: threshold as i64,
155+
bytes_until_reseed: threshold as i64,
156+
}
157+
}
158+
157159
/// Reseed the internal PRNG.
158160
fn reseed(&mut self) -> Result<(), Error> {
159161
R::from_rng(&mut self.reseeder).map(|result| {

0 commit comments

Comments
 (0)