Skip to content

Commit

Permalink
Try using an associated type
Browse files Browse the repository at this point in the history
  • Loading branch information
pitdicker committed Jan 1, 2018
1 parent 7e4ffd0 commit bf44bb1
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 46 deletions.
17 changes: 12 additions & 5 deletions rand_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,22 +160,27 @@ pub trait CryptoRng: Rng {}
/// Trait for RNG's that do not generate random numbers one at a time, but in
/// blocks. Especially for cryptographic RNG's it is common to generate 16 or
/// more results at a time.
pub trait BlockRngCore<T>: Sized {
type Results: AsRef<[T]> + Default;
pub trait BlockRngCore: Sized {
type Word;
type Results: AsRef<[Self::Word]> + Default;

fn generate(&mut self, results: &mut Self::Results);
}

#[derive(Debug, Clone)]
pub struct BlockRng<R: BlockRngCore<u32>> {
pub struct BlockRng<R: BlockRngCore> {
pub core: R,
pub results: R::Results,
pub index: usize,
pub half_used: bool, // Only used for u64 rng's,
// true if only half of the previous result is used
}

impl<R: BlockRngCore<u32>> Rng for BlockRng<R> {
impl<R> Rng for BlockRng<R>
where
R: BlockRngCore<Word=u32>,
R::Results: AsRef<[R::Word]>
{
#[inline]
fn next_u32(&mut self) -> u32 {
if self.index >= self.results.as_ref().len() {
Expand Down Expand Up @@ -362,7 +367,9 @@ impl<R: BlockRngCore<u64>> Rng for BlockRng<R> {
}
*/

impl<R: BlockRngCore<u32> + SeedableRng> SeedableRng for BlockRng<R> {
impl<R> SeedableRng for BlockRng<R>
where R: BlockRngCore + SeedableRng,
{
type Seed = R::Seed;

fn from_seed(seed: Self::Seed) -> Self {
Expand Down
3 changes: 2 additions & 1 deletion src/prng/chacha.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,8 @@ macro_rules! double_round{
}}
}

impl BlockRngCore<u32> for ChaChaCore {
impl BlockRngCore for ChaChaCore {
type Word = u32;
type Results = [u32; STATE_WORDS];

fn generate(&mut self, results: &mut Self::Results) {
Expand Down
3 changes: 2 additions & 1 deletion src/prng/hc128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ impl Clone for Hc128Core {
}
}

impl BlockRngCore<u32> for Hc128Core {
impl BlockRngCore for Hc128Core {
type Word = u32;
type Results = [u32; 16];

fn generate(&mut self, results: &mut Self::Results) {
Expand Down
3 changes: 2 additions & 1 deletion src/prng/isaac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,8 @@ impl ::core::default::Default for IsaacArray {
fn default() -> IsaacArray { IsaacArray([0u32; RAND_SIZE]) }
}

impl BlockRngCore<u32> for IsaacCore {
impl BlockRngCore for IsaacCore {
type Word = u32;
type Results = IsaacArray;

/// Refills the output buffer (`results`)
Expand Down
5 changes: 3 additions & 2 deletions src/prng/isaac64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ const RAND_SIZE: usize = 1 << RAND_SIZE_LEN;
/// (http://burtleburtle.net/bob/rand/isaac.html)
pub struct Isaac64Rng {
core: Isaac64Core,
results: <Isaac64Core as BlockRngCore<u64>>::Results,
results: <Isaac64Core as BlockRngCore>::Results,
index: usize,
half_used: bool, // true if only half of the previous result is used
}
Expand Down Expand Up @@ -147,7 +147,8 @@ impl Clone for Isaac64Core {
}
}

impl BlockRngCore<u64> for Isaac64Core {
impl BlockRngCore for Isaac64Core {
type Word = u64;
type Results = Isaac64Array;

/// Refills the output buffer (`results`)
Expand Down
97 changes: 61 additions & 36 deletions src/reseeding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,39 +161,54 @@ impl<R: SeedableRng, Rsdr: Reseeder<R>> ReseedingRng<R, Rsdr> {
}


/*

//#[derive(Clone)]
pub struct ReseedingBlockRng<R: BlockRngCore<u32> + SeedableRng, Rsdr: Reseeder<R>>(BlockRng<ReseedingWrapper<R, Rsdr>>);
pub struct ReseedingBlockRng<R, Rsdr>
where
R: BlockRngCore<Word=u32> + SeedableRng,
R::Results: AsRef<[R::Word]>,
Rsdr: Reseeder<R>
{
rng: BlockRng<ReseedingCore<R, Rsdr>>
}

// FIXME
impl<R, Rsdr> ::core::fmt::Debug for ReseedingBlockRng<R, Rsdr>
where R: BlockRngCore<u32> + SeedableRng,
Rsdr: Reseeder<R>
{
where
R: BlockRngCore<Word=u32> + SeedableRng,
R::Results: AsRef<[R::Word]>,
Rsdr: Reseeder<R>
{
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
write!(f, "ReseedingBlockRng {{}}")
}
}
impl<R: BlockRngCore<u32> + SeedableRng, Rsdr: Reseeder<R>> Rng for ReseedingBlockRng<R, Rsdr> {

impl<R, Rsdr> Rng for ReseedingBlockRng<R, Rsdr>
where
R: BlockRngCore<Word=u32> + SeedableRng,
R::Results: AsRef<[u32]>,
Rsdr: Reseeder<R>
{
#[inline]
fn next_u32(&mut self) -> u32 {
self.0.next_u32()
self.rng.next_u32()
}

#[inline]
fn next_u64(&mut self) -> u64 {
self.0.next_u64()
self.rng.next_u64()
}

#[inline]
#[cfg(feature = "i128_support")]
fn next_u128(&mut self) -> u128 {
self.0.next_u128()
self.rng.next_u128()
}

#[inline]
fn fill_bytes(&mut self, dest: &mut [u8]) {
self.0.fill_bytes(dest)
self.rng.fill_bytes(dest)
}

// As an optimization we try to write directly into the output buffer.
Expand All @@ -204,35 +219,35 @@ impl<R: BlockRngCore<u32> + SeedableRng, Rsdr: Reseeder<R>> Rng for ReseedingBlo
let mut filled = 0;

// Continue filling from the current set of results
if self.0.index < self.0.results.as_ref().len() {
if self.rng.index < self.rng.results.as_ref().len() {
let (consumed_u32, filled_u8) =
impls::fill_via_u32_chunks(&self.0.results.as_ref()[self.0.index..],
impls::fill_via_u32_chunks(&self.rng.results.as_ref()[self.rng.index..],
dest);

self.0.index += consumed_u32;
self.rng.index += consumed_u32;
filled += filled_u8;
}

let len_remainder = (dest.len() - filled) % self.0.results.as_ref().len();
let len_remainder = (dest.len() - filled) % self.rng.results.as_ref().len();
let len_direct = dest.len() - len_remainder;

while filled < len_direct {
let dest_u32: &mut R::Results = unsafe {
::core::mem::transmute(dest[filled..].as_mut_ptr())
};
self.0.generate(dest);
filled += self.0.results.as_ref().len() * 4;
self.rng.core.try_generate(dest);
filled += self.rng.results.as_ref().len() * 4;
}
self.0.index = self.0.results.as_ref().len();
self.rng.index = self.rng.results.as_ref().len();

if len_remainder > 0 {
self.0.generate(&mut self.0.results);
self.rng.core.try_generate(&mut self.rng.results);

let (consumed_u32, _) =
impls::fill_via_u32_chunks(&mut self.0.results.as_ref(),
impls::fill_via_u32_chunks(&mut self.rng.results.as_ref(),
&mut dest[filled..]);

self.0.index = consumed_u32;
self.rng.index = consumed_u32;
};
Ok(())
}
Expand All @@ -241,31 +256,37 @@ impl<R: BlockRngCore<u32> + SeedableRng, Rsdr: Reseeder<R>> Rng for ReseedingBlo
fn try_fill(&mut self, dest: &mut [u8]) -> Result<(), Error> {
let mut read_len = 0;
while read_len < dest.len() {
if self.0.index >= self.0.results.as_ref().len() {
let succes = self.0.try_generate(&mut self.0.results);
self.0.index = 0;
if self.rng.index >= self.rng.results.as_ref().len() {
let succes = self.rng.try_generate(&mut self.rng.results);
self.rng.index = 0;
}
let (consumed_u32, filled_u8) =
impls::fill_via_u32_chunks(&self.0.results.as_ref()[self.0.index..],
impls::fill_via_u32_chunks(&self.rng.results.as_ref()[self.rng.index..],
&mut dest[read_len..]);

self.0.index += consumed_u32;
self.rng.index += consumed_u32;
read_len += filled_u8;
};
succes
}
}

#[derive(Debug, Clone)]
struct ReseedingWrapper<R: BlockRngCore<u32> + SeedableRng, Rsdr: Reseeder<R>> {
struct ReseedingCore<R: BlockRngCore + SeedableRng, Rsdr: Reseeder<R>> {
core: R,
threshold: i64,
bytes_until_reseed: i64,
reseeder: Rsdr,
}

impl<R: BlockRngCore<u32> + SeedableRng, Rsdr: Reseeder<R>> BlockRngCore<u32> for ReseedingWrapper<R, Rsdr> {
type Results = <R as BlockRngCore<u32>>::Results;
impl<R, Rsdr> BlockRngCore for ReseedingCore<R, Rsdr>
where
R: BlockRngCore<Word=u32> + SeedableRng,
R::Results: AsRef<[R::Word]>, // FIXME
Rsdr: Reseeder<R>
{
type Word = u32;
type Results = R::Results;

fn generate(&mut self, results: &mut Self::Results) {
if self.bytes_until_reseed <= 0 { self.reseed(); }
Expand All @@ -274,7 +295,12 @@ impl<R: BlockRngCore<u32> + SeedableRng, Rsdr: Reseeder<R>> BlockRngCore<u32> fo
}
}

impl<R: BlockRngCore<u32> + SeedableRng, Rsdr: Reseeder<R>> ReseedingWrapper<R, Rsdr> {
impl<R, Rsdr> ReseedingCore<R, Rsdr>
where
R: BlockRngCore<Word=u32> + SeedableRng,
R::Results: AsRef<[R::Word]>, // FIXME
Rsdr: Reseeder<R>
{
/// Reseed the internal RNG.
/// On error, this may delay reseeding or not reseed at all.
#[inline(never)]
Expand Down Expand Up @@ -319,20 +345,19 @@ impl<R: BlockRngCore<u32> + SeedableRng, Rsdr: Reseeder<R>> ReseedingWrapper<R,
Ok(())
}

fn try_generate(&mut self, results: &mut <Self as BlockRngCore<u32>>::Results) {
fn try_generate(&mut self, results: &mut <Self as BlockRngCore>::Results) {
if self.bytes_until_reseed <= 0 { self.try_reseed(); }
self.bytes_until_reseed -= results.as_ref().len() as i64 * 4;
self.core.generate(results);
}
}

*/




/*
#[derive(Debug, Clone)]
pub struct ReseedingBlockRng<R: BlockRngCore<u32> + SeedableRng, Rsdr: Reseeder<R>> {
pub struct ReseedingBlockRng<R: BlockRngCore + SeedableRng, Rsdr: Reseeder<R>> {
core: R,
results: R::Results,
index: usize,
Expand All @@ -342,7 +367,7 @@ pub struct ReseedingBlockRng<R: BlockRngCore<u32> + SeedableRng, Rsdr: Reseeder<
reseeder: Rsdr,
}
impl<R: BlockRngCore<u32> + SeedableRng, Rsdr: Reseeder<R>> ReseedingBlockRng<R, Rsdr> { // FIXME
impl<R: BlockRngCore + SeedableRng, Rsdr: Reseeder<R>> ReseedingBlockRng<R, Rsdr> { // FIXME
/// Create a new `ReseedingBlockRng` with the given parameters.
pub fn new(threshold: u64, reseeder: Rsdr) -> ReseedingBlockRng<R, Rsdr> {
assert!(threshold <= ::core::i64::MAX as u64);
Expand Down Expand Up @@ -412,7 +437,7 @@ impl<R: BlockRngCore<u32> + SeedableRng, Rsdr: Reseeder<R>> ReseedingBlockRng<R,
}
impl<R: BlockRngCore<u32> + SeedableRng, Rsdr: Reseeder<R>> Rng for ReseedingBlockRng<R, Rsdr> {
impl<R: BlockRngCore + SeedableRng, Rsdr: Reseeder<R>> Rng for ReseedingBlockRng<R, Rsdr> {
#[inline]
fn next_u32(&mut self) -> u32 {
if self.index >= self.results.as_ref().len() {
Expand Down Expand Up @@ -521,7 +546,7 @@ impl<R: BlockRngCore<u32> + SeedableRng, Rsdr: Reseeder<R>> Rng for ReseedingBlo
Ok(self.fill_bytes(dest))
}
}

*/


/// Something that can be used to reseed an RNG via `ReseedingRng`.
Expand Down

0 comments on commit bf44bb1

Please sign in to comment.