Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rand core changes #419

Merged
merged 6 commits into from
May 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion rand_core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).


## [0.1.0] - TODO - date
## [0.2.0] - Unreleased
- Enable the `std` feature by default. (#409)
- Change `BlockRng64::inner` and add `BlockRng64::inner_mut` to mirror `BlockRng`. (#419)
- Add `BlockRng{64}::index` and `BlockRng{64}::generate_and_set`. (#374, #419)
- Change `BlockRngCore::Results` bound to also require `AsMut<[Self::Item]>`. (#419)

## [0.1.0] - 2018-04-17
(Split out of the Rand crate, changes here are relative to rand 0.4.2)
- `RngCore` and `SeedableRng` are now part of `rand_core`. (#288)
- Add modules to help implementing RNGs `impl` and `le`. (#209, #228)
Expand Down
2 changes: 1 addition & 1 deletion rand_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ serde1 = ["serde", "serde_derive"] # enables serde for BlockRng wrapper

[dependencies]
serde = { version = "1", optional = true }
serde_derive = { version = "1", optional = true }
serde_derive = { version = "^1.0.38", optional = true }
39 changes: 27 additions & 12 deletions rand_core/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ use core::cmp::min;
use core::mem::size_of;
use {RngCore, BlockRngCore, CryptoRng, SeedableRng, Error};

#[cfg(feature="serde1")] use serde::{Serialize, Deserialize};

/// Implement `next_u64` via `next_u32`, little-endian order.
pub fn next_u64_via_u32<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
Expand Down Expand Up @@ -187,9 +186,6 @@ pub fn next_u64_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
#[derive(Clone)]
#[cfg_attr(feature="serde1", derive(Serialize, Deserialize))]
pub struct BlockRng<R: BlockRngCore + ?Sized> {
#[cfg_attr(feature="serde1", serde(bound(
serialize = "R::Results: Serialize",
deserialize = "R::Results: Deserialize<'de>")))]
results: R::Results,
index: usize,
core: R,
Expand Down Expand Up @@ -253,7 +249,7 @@ impl<R: BlockRngCore> BlockRng<R> {
}

impl<R: BlockRngCore<Item=u32>> RngCore for BlockRng<R>
where <R as BlockRngCore>::Results: AsRef<[u32]>
where <R as BlockRngCore>::Results: AsRef<[u32]> + AsMut<[u32]>
{
#[inline(always)]
fn next_u32(&mut self) -> u32 {
Expand Down Expand Up @@ -386,9 +382,6 @@ impl<R: BlockRngCore + SeedableRng> SeedableRng for BlockRng<R> {
#[derive(Clone)]
#[cfg_attr(feature="serde1", derive(Serialize, Deserialize))]
pub struct BlockRng64<R: BlockRngCore + ?Sized> {
#[cfg_attr(feature="serde1", serde(bound(
serialize = "R::Results: Serialize",
deserialize = "R::Results: Deserialize<'de>")))]
results: R::Results,
index: usize,
half_used: bool, // true if only half of the previous result is used
Expand Down Expand Up @@ -420,20 +413,42 @@ impl<R: BlockRngCore> BlockRng64<R> {
}
}

/// Return a reference the wrapped `BlockRngCore`.
pub fn inner(&self) -> &R {
&self.core
}

/// Return a mutable reference the wrapped `BlockRngCore`.
pub fn inner(&mut self) -> &mut R {
pub fn inner_mut(&mut self) -> &mut R {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we must expose both inner and inner_mut and we will always have exactly one "core", there doesn't seem to be any advantage over just making core a pub field (which would be nicer syntactically). Since we have to make a breaking change here anyway (and probably no other users will be affected yet), shall we just do this?

For the other fields there is some advantage in keeping them private, but not really for core I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it matters much one way or the other. It feels a little strange to me to have one public field, but the rest private.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It works reasonably well IMO — typical usage is like ChaChaRng(BlockRng { core: ChaChaCore, .. }); i.e. the outer type is free to access the inner type however is deemed fit, whereas the other fields are not quite so straightforward.

&mut self.core
}

// Reset the number of available results.
// This will force a new set of results to be generated on next use.
/// Get the index into the result buffer.
///
/// If this is equal to or larger than the size of the result buffer then
/// the buffer is "empty" and `generate()` must be called to produce new
/// results.
pub fn index(&self) -> usize {
self.index
}

/// 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();
}

/// Generate a new set of results immediately, setting the index to the
/// given value.
pub fn generate_and_set(&mut self, index: usize) {
assert!(index < self.results.as_ref().len());
self.core.generate(&mut self.results);
self.index = index;
}
}

impl<R: BlockRngCore<Item=u64>> RngCore for BlockRng64<R>
where <R as BlockRngCore>::Results: AsRef<[u64]>
where <R as BlockRngCore>::Results: AsRef<[u64]> + AsMut<[u64]>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we actually need the new bound here? (Also for BlockRng above.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I initially tried to add the bound only on BlockRngCore, but it doesn't compile without the bound in a few more places.

{
#[inline(always)]
fn next_u32(&mut self) -> u32 {
Expand Down
5 changes: 4 additions & 1 deletion rand_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@
html_favicon_url = "https://www.rust-lang.org/favicon.ico",
html_root_url = "https://docs.rs/rand_core/0.1.0")]

#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![doc(test(attr(allow(unused_variables), deny(warnings))))]

#![cfg_attr(not(feature="std"), no_std)]
#![cfg_attr(all(feature="alloc", not(feature="std")), feature(alloc))]
Expand Down Expand Up @@ -107,6 +109,7 @@ pub mod le;
/// A simple example, obviously not generating very *random* output:
///
/// ```rust
/// #![allow(dead_code)]
/// use rand_core::{RngCore, Error, impls};
///
/// struct CountingRng(u64);
Expand Down Expand Up @@ -235,7 +238,7 @@ pub trait BlockRngCore {

/// Results type. This is the 'block' an RNG implementing `BlockRngCore`
/// generates, which will usually be an array like `[u32; 16]`.
type Results: AsRef<[Self::Item]> + Default;
type Results: AsRef<[Self::Item]> + AsMut<[Self::Item]> + Default;

/// Generate a new block of results.
fn generate(&mut self, results: &mut Self::Results);
Expand Down
7 changes: 7 additions & 0 deletions src/prng/isaac_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ impl<T> ::core::convert::AsRef<[T]> for IsaacArray<T> {
}
}

impl<T> ::core::convert::AsMut<[T]> for IsaacArray<T> {
#[inline(always)]
fn as_mut(&mut self) -> &mut [T] {
&mut self.inner[..]
}
}

impl<T> ::core::ops::Deref for IsaacArray<T> {
type Target = [T; RAND_SIZE];
#[inline(always)]
Expand Down
2 changes: 1 addition & 1 deletion src/reseeding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ where R: BlockRngCore + SeedableRng,
// implements RngCore, but we can't specify that because ReseedingCore is private
impl<R, Rsdr: RngCore> RngCore for ReseedingRng<R, Rsdr>
where R: BlockRngCore<Item = u32> + SeedableRng,
<R as BlockRngCore>::Results: AsRef<[u32]>
<R as BlockRngCore>::Results: AsRef<[u32]> + AsMut<[u32]>
{
#[inline(always)]
fn next_u32(&mut self) -> u32 {
Expand Down