Make BlockRng{64} fields private
This commit is contained in:
parent
6f6431043c
commit
204b9e48b2
@ -191,9 +191,9 @@ pub struct BlockRng<R: BlockRngCore + ?Sized> {
|
||||
#[cfg_attr(feature="serde-1", serde(bound(
|
||||
serialize = "R::Results: Serialize",
|
||||
deserialize = "R::Results: Deserialize<'de>")))]
|
||||
pub results: R::Results,
|
||||
pub index: usize,
|
||||
pub core: R,
|
||||
results: R::Results,
|
||||
index: usize,
|
||||
core: R,
|
||||
}
|
||||
|
||||
// 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> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: BlockRngCore> BlockRng<R> {
|
||||
/// Create a new `BlockRng` from an existing RNG implementing
|
||||
/// `BlockRngCore`. Results will be generated on first use.
|
||||
pub fn new(core: R) -> BlockRng<R>{
|
||||
let results_empty = R::Results::default();
|
||||
BlockRng {
|
||||
core,
|
||||
index: results_empty.as_ref().len(),
|
||||
results: results_empty,
|
||||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
}
|
||||
|
||||
// Reset the number of available results.
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: BlockRngCore<Item=u32>> RngCore for BlockRng<R>
|
||||
where <R as BlockRngCore>::Results: AsRef<[u32]>
|
||||
{
|
||||
@ -323,21 +352,11 @@ impl<R: BlockRngCore + SeedableRng> SeedableRng for BlockRng<R> {
|
||||
type Seed = R::Seed;
|
||||
|
||||
fn from_seed(seed: Self::Seed) -> Self {
|
||||
let results_empty = R::Results::default();
|
||||
Self {
|
||||
core: R::from_seed(seed),
|
||||
index: results_empty.as_ref().len(), // generate on first use
|
||||
results: results_empty,
|
||||
}
|
||||
Self::new(R::from_seed(seed))
|
||||
}
|
||||
|
||||
fn from_rng<S: RngCore>(rng: S) -> Result<Self, Error> {
|
||||
let results_empty = R::Results::default();
|
||||
Ok(Self {
|
||||
core: R::from_rng(rng)?,
|
||||
index: results_empty.as_ref().len(), // generate on first use
|
||||
results: results_empty,
|
||||
})
|
||||
Ok(Self::new(R::from_rng(rng)?))
|
||||
}
|
||||
}
|
||||
|
||||
@ -358,10 +377,10 @@ pub struct BlockRng64<R: BlockRngCore + ?Sized> {
|
||||
#[cfg_attr(feature="serde-1", serde(bound(
|
||||
serialize = "R::Results: Serialize",
|
||||
deserialize = "R::Results: Deserialize<'de>")))]
|
||||
pub results: R::Results,
|
||||
pub index: usize,
|
||||
pub half_used: bool, // true if only half of the previous result is used
|
||||
pub core: R,
|
||||
results: R::Results,
|
||||
index: usize,
|
||||
half_used: bool, // true if only half of the previous result is used
|
||||
core: R,
|
||||
}
|
||||
|
||||
// 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> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: BlockRngCore> BlockRng64<R> {
|
||||
/// Create a new `BlockRng` from an existing RNG implementing
|
||||
/// `BlockRngCore`. Results will be generated on first use.
|
||||
pub fn new(core: R) -> BlockRng64<R>{
|
||||
let results_empty = R::Results::default();
|
||||
BlockRng64 {
|
||||
core,
|
||||
index: results_empty.as_ref().len(),
|
||||
half_used: false,
|
||||
results: results_empty,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a mutable reference the wrapped `BlockRngCore`.
|
||||
pub fn inner(&mut self) -> &mut R {
|
||||
&mut self.core
|
||||
}
|
||||
|
||||
// Reset the number of available results.
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: BlockRngCore<Item=u64>> RngCore for BlockRng64<R>
|
||||
where <R as BlockRngCore>::Results: AsRef<[u64]>
|
||||
{
|
||||
@ -424,6 +468,7 @@ where <R as BlockRngCore>::Results: AsRef<[u64]>
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
fn fill_bytes(&mut self, dest: &mut [u8]) {
|
||||
let mut filled = 0;
|
||||
self.half_used = false;
|
||||
|
||||
// Continue filling from the current set of results
|
||||
if self.index < self.results.as_ref().len() {
|
||||
@ -461,11 +506,11 @@ where <R as BlockRngCore>::Results: AsRef<[u64]>
|
||||
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
|
||||
fn fill_bytes(&mut self, dest: &mut [u8]) {
|
||||
let mut read_len = 0;
|
||||
self.half_used = false;
|
||||
while read_len < dest.len() {
|
||||
if self.index as usize >= self.results.as_ref().len() {
|
||||
self.core.generate(&mut self.results);
|
||||
self.index = 0;
|
||||
self.half_used = false;
|
||||
}
|
||||
|
||||
let (consumed_u64, filled_u8) =
|
||||
@ -486,23 +531,11 @@ impl<R: BlockRngCore + SeedableRng> SeedableRng for BlockRng64<R> {
|
||||
type Seed = R::Seed;
|
||||
|
||||
fn from_seed(seed: Self::Seed) -> Self {
|
||||
let results_empty = R::Results::default();
|
||||
Self {
|
||||
core: R::from_seed(seed),
|
||||
index: results_empty.as_ref().len(), // generate on first use
|
||||
half_used: false,
|
||||
results: results_empty,
|
||||
}
|
||||
Self::new(R::from_seed(seed))
|
||||
}
|
||||
|
||||
fn from_rng<S: RngCore>(rng: S) -> Result<Self, Error> {
|
||||
let results_empty = R::Results::default();
|
||||
Ok(Self {
|
||||
core: R::from_rng(rng)?,
|
||||
index: results_empty.as_ref().len(), // generate on first use
|
||||
half_used: false,
|
||||
results: results_empty,
|
||||
})
|
||||
Ok(Self::new(R::from_rng(rng)?))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,8 +156,8 @@ impl ChaChaRng {
|
||||
/// assert_eq!(rng1.next_u32(), rng2.next_u32());
|
||||
/// ```
|
||||
pub fn set_counter(&mut self, counter_low: u64, counter_high: u64) {
|
||||
self.0.core.set_counter(counter_low, counter_high);
|
||||
self.0.index = STATE_WORDS; // force recomputation on next use
|
||||
self.0.inner_mut().set_counter(counter_low, counter_high);
|
||||
self.0.reset(); // force recomputation on next use
|
||||
}
|
||||
|
||||
/// Sets the number of rounds to run the ChaCha core algorithm per block to
|
||||
@ -179,8 +179,8 @@ impl ChaChaRng {
|
||||
/// assert_eq!(rng.next_u32(), 0x2fef003e);
|
||||
/// ```
|
||||
pub fn set_rounds(&mut self, rounds: usize) {
|
||||
self.0.core.set_rounds(rounds);
|
||||
self.0.index = STATE_WORDS; // force recomputation on next use
|
||||
self.0.inner_mut().set_rounds(rounds);
|
||||
self.0.reset(); // force recomputation on next use
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,28 +128,15 @@ impl IsaacRng {
|
||||
///
|
||||
/// DEPRECATED. `IsaacRng::new_from_u64(0)` will produce identical results.
|
||||
#[deprecated(since="0.5.0", note="use the NewRng or SeedableRng trait")]
|
||||
pub fn new_unseeded() -> IsaacRng {
|
||||
pub fn new_unseeded() -> Self {
|
||||
Self::new_from_u64(0)
|
||||
}
|
||||
|
||||
/// Create an ISAAC random number generator using an u64 as seed.
|
||||
/// Create an ISAAC random number generator using an `u64` as seed.
|
||||
/// If `seed == 0` this will produce the same stream of random numbers as
|
||||
/// the reference implementation when used unseeded.
|
||||
pub fn new_from_u64(seed: u64) -> IsaacRng {
|
||||
let mut key = [w(0); RAND_SIZE];
|
||||
key[0] = w(seed as u32);
|
||||
key[1] = w((seed >> 32) as u32);
|
||||
IsaacRng(BlockRng {
|
||||
// Initialize with only one pass.
|
||||
// A second pass does not improve the quality here, because all of
|
||||
// the seed was already available in the first round.
|
||||
// Not doing the second pass has the small advantage that if
|
||||
// `seed == 0` this method produces exactly the same state as the
|
||||
// reference implementation when used unseeded.
|
||||
core: IsaacCore::init(key, 1),
|
||||
results: IsaacArray::default(),
|
||||
index: RAND_SIZE, // generate on first use
|
||||
})
|
||||
pub fn new_from_u64(seed: u64) -> Self {
|
||||
IsaacRng(BlockRng::new(IsaacCore::new_from_u64(seed)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -318,6 +305,22 @@ impl IsaacCore {
|
||||
|
||||
Self { mem, a: w(0), b: w(0), c: w(0) }
|
||||
}
|
||||
|
||||
/// Create an ISAAC random number generator using an `u64` as seed.
|
||||
/// If `seed == 0` this will produce the same stream of random numbers as
|
||||
/// the reference implementation when used unseeded.
|
||||
fn new_from_u64(seed: u64) -> Self {
|
||||
let mut key = [w(0); RAND_SIZE];
|
||||
key[0] = w(seed as u32);
|
||||
key[1] = w((seed >> 32) as u32);
|
||||
// Initialize with only one pass.
|
||||
// A second pass does not improve the quality here, because all of the
|
||||
// seed was already available in the first round.
|
||||
// Not doing the second pass has the small advantage that if
|
||||
// `seed == 0` this method produces exactly the same state as the
|
||||
// reference implementation when used unseeded.
|
||||
Self::init(key, 1)
|
||||
}
|
||||
}
|
||||
|
||||
impl SeedableRng for IsaacCore {
|
||||
@ -470,20 +473,8 @@ mod test {
|
||||
let mut read = BufReader::new(&buf[..]);
|
||||
let mut deserialized: IsaacRng = bincode::deserialize_from(&mut read).expect("Could not deserialize");
|
||||
|
||||
assert_eq!(rng.0.index, deserialized.0.index);
|
||||
/* Can't assert directly because of the array size */
|
||||
for (orig,deser) in rng.0.results.iter().zip(deserialized.0.results.iter()) {
|
||||
assert_eq!(orig, deser);
|
||||
}
|
||||
for (orig,deser) in rng.0.core.mem.iter().zip(deserialized.0.core.mem.iter()) {
|
||||
assert_eq!(orig, deser);
|
||||
}
|
||||
assert_eq!(rng.0.core.a, deserialized.0.core.a);
|
||||
assert_eq!(rng.0.core.b, deserialized.0.core.b);
|
||||
assert_eq!(rng.0.core.c, deserialized.0.core.c);
|
||||
|
||||
for _ in 0..16 {
|
||||
assert_eq!(rng.next_u64(), deserialized.next_u64());
|
||||
for _ in 0..300 { // more than the 256 buffered results
|
||||
assert_eq!(rng.next_u32(), deserialized.next_u32());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -118,28 +118,15 @@ impl Isaac64Rng {
|
||||
///
|
||||
/// DEPRECATED. `Isaac64Rng::new_from_u64(0)` will produce identical results.
|
||||
#[deprecated(since="0.5.0", note="use the NewRng or SeedableRng trait")]
|
||||
pub fn new_unseeded() -> Isaac64Rng {
|
||||
pub fn new_unseeded() -> Self {
|
||||
Self::new_from_u64(0)
|
||||
}
|
||||
|
||||
/// Create an ISAAC-64 random number generator using an u64 as seed.
|
||||
/// Create an ISAAC-64 random number generator using an `u64` as seed.
|
||||
/// If `seed == 0` this will produce the same stream of random numbers as
|
||||
/// the reference implementation when used unseeded.
|
||||
pub fn new_from_u64(seed: u64) -> Isaac64Rng {
|
||||
let mut key = [w(0); RAND_SIZE];
|
||||
key[0] = w(seed);
|
||||
Isaac64Rng(BlockRng64 {
|
||||
// Initialize with only one pass.
|
||||
// A second pass does not improve the quality here, because all of
|
||||
// the seed was already available in the first round.
|
||||
// Not doing the second pass has the small advantage that if
|
||||
// `seed == 0` this method produces exactly the same state as the
|
||||
// reference implementation when used unseeded.
|
||||
core: Isaac64Core::init(key, 1),
|
||||
results: IsaacArray::default(),
|
||||
index: RAND_SIZE, // generate on first use
|
||||
half_used: false,
|
||||
})
|
||||
pub fn new_from_u64(seed: u64) -> Self {
|
||||
Isaac64Rng(BlockRng64::new(Isaac64Core::new_from_u64(seed)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -283,6 +270,21 @@ impl Isaac64Core {
|
||||
|
||||
Self { mem, a: w(0), b: w(0), c: w(0) }
|
||||
}
|
||||
|
||||
/// Create an ISAAC-64 random number generator using an `u64` as seed.
|
||||
/// If `seed == 0` this will produce the same stream of random numbers as
|
||||
/// the reference implementation when used unseeded.
|
||||
pub fn new_from_u64(seed: u64) -> Self {
|
||||
let mut key = [w(0); RAND_SIZE];
|
||||
key[0] = w(seed);
|
||||
// Initialize with only one pass.
|
||||
// A second pass does not improve the quality here, because all of the
|
||||
// seed was already available in the first round.
|
||||
// Not doing the second pass has the small advantage that if
|
||||
// `seed == 0` this method produces exactly the same state as the
|
||||
// reference implementation when used unseeded.
|
||||
Self::init(key, 1)
|
||||
}
|
||||
}
|
||||
|
||||
impl SeedableRng for Isaac64Core {
|
||||
@ -463,20 +465,7 @@ mod test {
|
||||
let mut read = BufReader::new(&buf[..]);
|
||||
let mut deserialized: Isaac64Rng = bincode::deserialize_from(&mut read).expect("Could not deserialize");
|
||||
|
||||
assert_eq!(rng.0.index, deserialized.0.index);
|
||||
assert_eq!(rng.0.half_used, deserialized.0.half_used);
|
||||
/* Can't assert directly because of the array size */
|
||||
for (orig,deser) in rng.0.results.iter().zip(deserialized.0.results.iter()) {
|
||||
assert_eq!(orig, deser);
|
||||
}
|
||||
for (orig,deser) in rng.0.core.mem.iter().zip(deserialized.0.core.mem.iter()) {
|
||||
assert_eq!(orig, deser);
|
||||
}
|
||||
assert_eq!(rng.0.core.a, deserialized.0.core.a);
|
||||
assert_eq!(rng.0.core.b, deserialized.0.core.b);
|
||||
assert_eq!(rng.0.core.c, deserialized.0.core.c);
|
||||
|
||||
for _ in 0..16 {
|
||||
for _ in 0..300 { // more than the 256 buffered results
|
||||
assert_eq!(rng.next_u64(), deserialized.next_u64());
|
||||
}
|
||||
}
|
||||
|
@ -68,28 +68,13 @@ where R: BlockRngCore + SeedableRng,
|
||||
/// * `rng`: the random number generator to use.
|
||||
/// * `threshold`: the number of generated bytes after which to reseed the RNG.
|
||||
/// * `reseeder`: the RNG to use for reseeding.
|
||||
pub fn new(rng: R, threshold: u64, reseeder: Rsdr)
|
||||
-> ReseedingRng<R, Rsdr>
|
||||
{
|
||||
assert!(threshold <= ::core::i64::MAX as u64);
|
||||
let results_empty = R::Results::default();
|
||||
ReseedingRng(
|
||||
BlockRng {
|
||||
core: ReseedingCore {
|
||||
inner: rng,
|
||||
reseeder,
|
||||
threshold: threshold as i64,
|
||||
bytes_until_reseed: threshold as i64,
|
||||
},
|
||||
index: results_empty.as_ref().len(), // generate on first use
|
||||
results: results_empty,
|
||||
}
|
||||
)
|
||||
pub fn new(rng: R, threshold: u64, reseeder: Rsdr) -> Self {
|
||||
ReseedingRng(BlockRng::new(ReseedingCore::new(rng, threshold, reseeder)))
|
||||
}
|
||||
|
||||
/// Reseed the internal PRNG.
|
||||
pub fn reseed(&mut self) -> Result<(), Error> {
|
||||
self.0.core.reseed()
|
||||
self.0.inner_mut().reseed()
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,6 +139,23 @@ impl<R, Rsdr> ReseedingCore<R, Rsdr>
|
||||
where R: BlockRngCore + SeedableRng,
|
||||
Rsdr: RngCore
|
||||
{
|
||||
/// Create a new `ReseedingCore` with the given parameters.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `rng`: the random number generator to use.
|
||||
/// * `threshold`: the number of generated bytes after which to reseed the RNG.
|
||||
/// * `reseeder`: the RNG to use for reseeding.
|
||||
pub fn new(rng: R, threshold: u64, reseeder: Rsdr) -> Self {
|
||||
assert!(threshold <= ::core::i64::MAX as u64);
|
||||
ReseedingCore {
|
||||
inner: rng,
|
||||
reseeder,
|
||||
threshold: threshold as i64,
|
||||
bytes_until_reseed: threshold as i64,
|
||||
}
|
||||
}
|
||||
|
||||
/// Reseed the internal PRNG.
|
||||
fn reseed(&mut self) -> Result<(), Error> {
|
||||
R::from_rng(&mut self.reseeder).map(|result| {
|
||||
|
Loading…
x
Reference in New Issue
Block a user