Skip to content

Commit 204b9e4

Browse files
committed
Make BlockRng{64} fields private
1 parent 6f64310 commit 204b9e4

File tree

5 files changed

+133
-118
lines changed

5 files changed

+133
-118
lines changed

rand_core/src/impls.rs

Lines changed: 67 additions & 34 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,35 @@ 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 reference the wrapped `BlockRngCore`.
223+
pub fn inner(&self) -> &R {
224+
&self.core
225+
}
226+
227+
/// Return a mutable reference the wrapped `BlockRngCore`.
228+
pub fn inner_mut(&mut self) -> &mut R {
229+
&mut self.core
230+
}
231+
232+
// Reset the number of available results.
233+
// This will force a new set of results to be generated on next use.
234+
pub fn reset(&mut self) {
235+
self.index = self.results.as_ref().len();
236+
}
237+
}
238+
210239
impl<R: BlockRngCore<Item=u32>> RngCore for BlockRng<R>
211240
where <R as BlockRngCore>::Results: AsRef<[u32]>
212241
{
@@ -323,21 +352,11 @@ impl<R: BlockRngCore + SeedableRng> SeedableRng for BlockRng<R> {
323352
type Seed = R::Seed;
324353

325354
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-
}
355+
Self::new(R::from_seed(seed))
332356
}
333357

334358
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-
})
359+
Ok(Self::new(R::from_rng(rng)?))
341360
}
342361
}
343362

@@ -358,10 +377,10 @@ pub struct BlockRng64<R: BlockRngCore + ?Sized> {
358377
#[cfg_attr(feature="serde-1", serde(bound(
359378
serialize = "R::Results: Serialize",
360379
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,
380+
results: R::Results,
381+
index: usize,
382+
half_used: bool, // true if only half of the previous result is used
383+
core: R,
365384
}
366385

367386
// Custom Debug implementation that does not expose the contents of `results`.
@@ -376,6 +395,31 @@ impl<R: BlockRngCore + fmt::Debug> fmt::Debug for BlockRng64<R> {
376395
}
377396
}
378397

398+
impl<R: BlockRngCore> BlockRng64<R> {
399+
/// Create a new `BlockRng` from an existing RNG implementing
400+
/// `BlockRngCore`. Results will be generated on first use.
401+
pub fn new(core: R) -> BlockRng64<R>{
402+
let results_empty = R::Results::default();
403+
BlockRng64 {
404+
core,
405+
index: results_empty.as_ref().len(),
406+
half_used: false,
407+
results: results_empty,
408+
}
409+
}
410+
411+
/// Return a mutable reference the wrapped `BlockRngCore`.
412+
pub fn inner(&mut self) -> &mut R {
413+
&mut self.core
414+
}
415+
416+
// Reset the number of available results.
417+
// This will force a new set of results to be generated on next use.
418+
pub fn reset(&mut self) {
419+
self.index = self.results.as_ref().len();
420+
}
421+
}
422+
379423
impl<R: BlockRngCore<Item=u64>> RngCore for BlockRng64<R>
380424
where <R as BlockRngCore>::Results: AsRef<[u64]>
381425
{
@@ -424,6 +468,7 @@ where <R as BlockRngCore>::Results: AsRef<[u64]>
424468
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
425469
fn fill_bytes(&mut self, dest: &mut [u8]) {
426470
let mut filled = 0;
471+
self.half_used = false;
427472

428473
// Continue filling from the current set of results
429474
if self.index < self.results.as_ref().len() {
@@ -461,11 +506,11 @@ where <R as BlockRngCore>::Results: AsRef<[u64]>
461506
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
462507
fn fill_bytes(&mut self, dest: &mut [u8]) {
463508
let mut read_len = 0;
509+
self.half_used = false;
464510
while read_len < dest.len() {
465511
if self.index as usize >= self.results.as_ref().len() {
466512
self.core.generate(&mut self.results);
467513
self.index = 0;
468-
self.half_used = false;
469514
}
470515

471516
let (consumed_u64, filled_u8) =
@@ -486,23 +531,11 @@ impl<R: BlockRngCore + SeedableRng> SeedableRng for BlockRng64<R> {
486531
type Seed = R::Seed;
487532

488533
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-
}
534+
Self::new(R::from_seed(seed))
496535
}
497536

498537
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-
})
538+
Ok(Self::new(R::from_rng(rng)?))
506539
}
507540
}
508541

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_mut().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_mut().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 & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -118,28 +118,15 @@ 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 {
129-
let mut key = [w(0); RAND_SIZE];
130-
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-
})
128+
pub fn new_from_u64(seed: u64) -> Self {
129+
Isaac64Rng(BlockRng64::new(Isaac64Core::new_from_u64(seed)))
143130
}
144131
}
145132

@@ -283,6 +270,21 @@ impl Isaac64Core {
283270

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

288290
impl SeedableRng for Isaac64Core {
@@ -463,20 +465,7 @@ mod test {
463465
let mut read = BufReader::new(&buf[..]);
464466
let mut deserialized: Isaac64Rng = bincode::deserialize_from(&mut read).expect("Could not deserialize");
465467

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 {
468+
for _ in 0..300 { // more than the 256 buffered results
480469
assert_eq!(rng.next_u64(), deserialized.next_u64());
481470
}
482471
}

0 commit comments

Comments
 (0)