diff --git a/.travis.yml b/.travis.yml index 7d3633b9a6d..089ae4cf5f0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,26 +6,27 @@ sudo: false # - pinned stable, latest stable, beta and nightly Rust releases # - Linux, OS X, Android, iOS, bare metal (i.e. no_std) # - x86_64, ARMv7, a Big-Endian arch (MIPS) +# HACK: use --tests to disable doc-tests for rand_core 0.2 (see #619) matrix: include: - rust: 1.22.0 install: script: - cargo test --tests --no-default-features - - cargo test --package rand_core --no-default-features + - cargo test --package rand_core:0.2.2 --no-default-features --tests - cargo test --features serde1,log - rust: stable os: osx install: script: - cargo test --tests --no-default-features - - cargo test --package rand_core --no-default-features + - cargo test --package rand_core:0.2.2 --no-default-features --tests - cargo test --features serde1,log - rust: beta install: script: - cargo test --tests --no-default-features - - cargo test --package rand_core --no-default-features + - cargo test --package rand_core:0.2.2 --no-default-features --tests - cargo test --features serde1,log - rust: nightly install: @@ -34,13 +35,13 @@ matrix: - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH script: - cargo test --tests --no-default-features --features=alloc - - cargo test --package rand_core --no-default-features --features=alloc,serde1 + - cargo test --package rand_core:0.2.2 --no-default-features --features=alloc,serde1 --tests - cargo test --features serde1,log,nightly,alloc - cargo test --all --benches # remove cached documentation, otherwise files from previous PRs can get included - - rm -rf target/doc - - cargo doc --no-deps --all --all-features - - cargo deadlinks --dir target/doc + #- rm -rf target/doc + #- cargo doc --no-deps --all --all-features + #- cargo deadlinks --dir target/doc after_success: - travis-cargo --only nightly doc-upload diff --git a/appveyor.yml b/appveyor.yml index 97d3ce6fda1..a2bf7f98917 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -32,8 +32,8 @@ install: build: false test_script: - - cargo test --all # cannot use --all and --features together + - cargo test --all --tests # cannot use --all and --features together - cargo test --all --benches - cargo test --features serde1,log,nightly - cargo test --tests --no-default-features --features=alloc,serde1 - - cargo test --package rand_core --no-default-features --features=alloc,serde1 + - cargo test --package rand_core:0.2.2 --no-default-features --features=alloc,serde1 --tests diff --git a/rand_core/CHANGELOG.md b/rand_core/CHANGELOG.md index 5885e17515b..76da38bb750 100644 --- a/rand_core/CHANGELOG.md +++ b/rand_core/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. 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.2.2] - 2018-10-03 +Create a compatibility shim around 0.3. + ## [0.2.1] - 2018-06-08 - References to a `CryptoRng` now also implement `CryptoRng`. (#470) diff --git a/rand_core/Cargo.toml b/rand_core/Cargo.toml index a6acfc3fe23..d74b5cfd565 100644 --- a/rand_core/Cargo.toml +++ b/rand_core/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "rand_core" -version = "0.2.1" # NB: When modifying, also modify html_root_url in lib.rs +version = "0.2.2" # NB: When modifying, also modify html_root_url in lib.rs authors = ["The Rust Project Developers"] license = "MIT/Apache-2.0" readme = "README.md" -repository = "https://github.com/rust-lang-nursery/rand" +repository = "https://github.com/rust-random/rand" documentation = "https://docs.rs/rand_core" homepage = "https://crates.io/crates/rand_core" description = """ @@ -14,15 +14,13 @@ keywords = ["random", "rng"] categories = ["algorithms", "no-std"] [badges] -travis-ci = { repository = "rust-lang-nursery/rand" } -appveyor = { repository = "alexcrichton/rand" } +travis-ci = { repository = "rust-random/rand" } +appveyor = { repository = "rust-random/rand" } [features] -default = ["std"] -std = ["alloc"] # use std library; should be default but for above bug -alloc = [] # enables Vec and Box support without std -serde1 = ["serde", "serde_derive"] # enables serde for BlockRng wrapper +std = ["rand_core/std"] # use std library; should be default but for above bug +alloc = ["rand_core/alloc"] # enables Vec and Box support without std +serde1 = ["rand_core/serde1"] # enables serde for BlockRng wrapper [dependencies] -serde = { version = "1", optional = true } -serde_derive = { version = "^1.0.38", optional = true } +rand_core = { version = "0.3", default-features = false } diff --git a/rand_core/README.md b/rand_core/README.md index 29492224ca7..94ee8c5cc11 100644 --- a/rand_core/README.md +++ b/rand_core/README.md @@ -9,6 +9,8 @@ Core traits and error types of the [rand] library, plus tools for implementing RNGs. +This version of `rand_core` is a compatibility shim around version 0.3. + This crate is intended for use when implementing the core trait, `RngCore`; it defines the core traits to be implemented as well as several small functions to aid in their implementation and types required for error handling. diff --git a/rand_core/src/lib.rs b/rand_core/src/lib.rs index 1b9c24c0fa4..0d1550ca21a 100644 --- a/rand_core/src/lib.rs +++ b/rand_core/src/lib.rs @@ -10,6 +10,8 @@ //! Random number generation traits //! +//! This version of `rand_core` is a compatibility shim around version 0.3. +//! //! This crate is mainly of interest to crates publishing implementations of //! [`RngCore`]. Other users are encouraged to use the [rand] crate instead //! which re-exports the main traits and error types. @@ -35,370 +37,16 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://docs.rs/rand_core/0.2.1")] + html_root_url = "https://docs.rs/rand_core/0.2.2")] #![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))] - -#[cfg(feature="std")] extern crate core; -#[cfg(all(feature = "alloc", not(feature="std")))] extern crate alloc; -#[cfg(feature="serde1")] extern crate serde; -#[cfg(feature="serde1")] #[macro_use] extern crate serde_derive; - - -use core::default::Default; -use core::convert::AsMut; - -#[cfg(all(feature="alloc", not(feature="std")))] use alloc::boxed::Box; - -pub use error::{ErrorKind, Error}; - - -mod error; -pub mod block; -pub mod impls; -pub mod le; - - -/// The core of a random number generator. -/// -/// This trait encapsulates the low-level functionality common to all -/// generators, and is the "back end", to be implemented by generators. -/// End users should normally use [`Rng`] from the [rand] crate, which is -/// automatically implemented for every type implementing `RngCore`. -/// -/// Three different methods for generating random data are provided since the -/// optimal implementation of each is dependent on the type of generator. There -/// is no required relationship between the output of each; e.g. many -/// implementations of [`fill_bytes`] consume a whole number of `u32` or `u64` -/// values and drop any remaining unused bytes. -/// -/// The [`try_fill_bytes`] method is a variant of [`fill_bytes`] allowing error -/// handling; it is not deemed sufficiently useful to add equivalents for -/// [`next_u32`] or [`next_u64`] since the latter methods are almost always used -/// with algorithmic generators (PRNGs), which are normally infallible. -/// -/// Algorithmic generators implementing [`SeedableRng`] should normally have -/// *portable, reproducible* output, i.e. fix Endianness when converting values -/// to avoid platform differences, and avoid making any changes which affect -/// output (except by communicating that the release has breaking changes). -/// -/// Typically implementators will implement only one of the methods available -/// in this trait directly, then use the helper functions from the -/// [`rand_core::impls`] module to implement the other methods. -/// -/// It is recommended that implementations also implement: -/// -/// - `Debug` with a custom implementation which *does not* print any internal -/// state (at least, [`CryptoRng`]s should not risk leaking state through -/// `Debug`). -/// - `Serialize` and `Deserialize` (from Serde), preferably making Serde -/// support optional at the crate level in PRNG libs. -/// - `Clone`, if possible. -/// - *never* implement `Copy` (accidental copies may cause repeated values). -/// - *do not* implement `Default` for pseudorandom generators, but instead -/// implement [`SeedableRng`], to guide users towards proper seeding. -/// External / hardware RNGs can choose to implement `Default`. -/// - `Eq` and `PartialEq` could be implemented, but are probably not useful. -/// -/// # Example -/// -/// A simple example, obviously not generating very *random* output: -/// -/// ``` -/// #![allow(dead_code)] -/// use rand_core::{RngCore, Error, impls}; -/// -/// struct CountingRng(u64); -/// -/// impl RngCore for CountingRng { -/// fn next_u32(&mut self) -> u32 { -/// self.next_u64() as u32 -/// } -/// -/// fn next_u64(&mut self) -> u64 { -/// self.0 += 1; -/// self.0 -/// } -/// -/// fn fill_bytes(&mut self, dest: &mut [u8]) { -/// impls::fill_bytes_via_next(self, dest) -/// } -/// -/// fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { -/// Ok(self.fill_bytes(dest)) -/// } -/// } -/// ``` -/// -/// [rand]: https://crates.io/crates/rand -/// [`Rng`]: ../rand/trait.Rng.html -/// [`SeedableRng`]: trait.SeedableRng.html -/// [`rand_core::impls`]: ../rand_core/impls/index.html -/// [`try_fill_bytes`]: trait.RngCore.html#tymethod.try_fill_bytes -/// [`fill_bytes`]: trait.RngCore.html#tymethod.fill_bytes -/// [`next_u32`]: trait.RngCore.html#tymethod.next_u32 -/// [`next_u64`]: trait.RngCore.html#tymethod.next_u64 -/// [`CryptoRng`]: trait.CryptoRng.html -pub trait RngCore { - /// Return the next random `u32`. - /// - /// RNGs must implement at least one method from this trait directly. In - /// the case this method is not implemented directly, it can be implemented - /// using `self.next_u64() as u32` or - /// [via `fill_bytes`](../rand_core/impls/fn.next_u32_via_fill.html). - fn next_u32(&mut self) -> u32; - - /// Return the next random `u64`. - /// - /// RNGs must implement at least one method from this trait directly. In - /// the case this method is not implemented directly, it can be implemented - /// [via `next_u32`](../rand_core/impls/fn.next_u64_via_u32.html) or - /// [via `fill_bytes`](../rand_core/impls/fn.next_u64_via_fill.html). - fn next_u64(&mut self) -> u64; - - /// Fill `dest` with random data. - /// - /// RNGs must implement at least one method from this trait directly. In - /// the case this method is not implemented directly, it can be implemented - /// [via `next_u*`](../rand_core/impls/fn.fill_bytes_via_next.html) or - /// via `try_fill_bytes`; if this generator can fail the implementation - /// must choose how best to handle errors here (e.g. panic with a - /// descriptive message or log a warning and retry a few times). - /// - /// This method should guarantee that `dest` is entirely filled - /// with new data, and may panic if this is impossible - /// (e.g. reading past the end of a file that is being used as the - /// source of randomness). - fn fill_bytes(&mut self, dest: &mut [u8]); - - /// Fill `dest` entirely with random data. - /// - /// This is the only method which allows an RNG to report errors while - /// generating random data thus making this the primary method implemented - /// by external (true) RNGs (e.g. `OsRng`) which can fail. It may be used - /// directly to generate keys and to seed (infallible) PRNGs. - /// - /// Other than error handling, this method is identical to [`fill_bytes`]; - /// thus this may be implemented using `Ok(self.fill_bytes(dest))` or - /// `fill_bytes` may be implemented with - /// `self.try_fill_bytes(dest).unwrap()` or more specific error handling. - /// - /// [`fill_bytes`]: trait.RngCore.html#method.fill_bytes - fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error>; -} - -/// A marker trait used to indicate that an [`RngCore`] or [`BlockRngCore`] -/// implementation is supposed to be cryptographically secure. -/// -/// *Cryptographically secure generators*, also known as *CSPRNGs*, should -/// satisfy an additional properties over other generators: given the first -/// *k* bits of an algorithm's output -/// sequence, it should not be possible using polynomial-time algorithms to -/// predict the next bit with probability significantly greater than 50%. -/// -/// Some generators may satisfy an additional property, however this is not -/// required by this trait: if the CSPRNG's state is revealed, it should not be -/// computationally-feasible to reconstruct output prior to this. Some other -/// generators allow backwards-computation and are consided *reversible*. -/// -/// Note that this trait is provided for guidance only and cannot guarantee -/// suitability for cryptographic applications. In general it should only be -/// implemented for well-reviewed code implementing well-regarded algorithms. -/// -/// Note also that use of a `CryptoRng` does not protect against other -/// weaknesses such as seeding from a weak entropy source or leaking state. -/// -/// [`RngCore`]: trait.RngCore.html -/// [`BlockRngCore`]: ../rand_core/block/trait.BlockRngCore.html -pub trait CryptoRng {} - -/// A random number generator that can be explicitly seeded. -/// -/// This trait encapsulates the low-level functionality common to all -/// pseudo-random number generators (PRNGs, or algorithmic generators). -/// -/// The [`rand::FromEntropy`] trait is automatically implemented for every type -/// implementing `SeedableRng`, providing a convenient `from_entropy()` -/// constructor. -/// -/// [`rand::FromEntropy`]: ../rand/trait.FromEntropy.html -pub trait SeedableRng: Sized { - /// Seed type, which is restricted to types mutably-dereferencable as `u8` - /// arrays (we recommend `[u8; N]` for some `N`). - /// - /// It is recommended to seed PRNGs with a seed of at least circa 100 bits, - /// which means an array of `[u8; 12]` or greater to avoid picking RNGs with - /// partially overlapping periods. - /// - /// For cryptographic RNG's a seed of 256 bits is recommended, `[u8; 32]`. - /// - /// - /// # Implementing `SeedableRng` for RNGs with large seeds - /// - /// Note that the required traits `core::default::Default` and - /// `core::convert::AsMut` are not implemented for large arrays - /// `[u8; N]` with `N` > 32. To be able to implement the traits required by - /// `SeedableRng` for RNGs with such large seeds, the newtype pattern can be - /// used: - /// - /// ``` - /// use rand_core::SeedableRng; - /// - /// const N: usize = 64; - /// pub struct MyRngSeed(pub [u8; N]); - /// pub struct MyRng(MyRngSeed); - /// - /// impl Default for MyRngSeed { - /// fn default() -> MyRngSeed { - /// MyRngSeed([0; N]) - /// } - /// } - /// - /// impl AsMut<[u8]> for MyRngSeed { - /// fn as_mut(&mut self) -> &mut [u8] { - /// &mut self.0 - /// } - /// } - /// - /// impl SeedableRng for MyRng { - /// type Seed = MyRngSeed; - /// - /// fn from_seed(seed: MyRngSeed) -> MyRng { - /// MyRng(seed) - /// } - /// } - /// ``` - type Seed: Sized + Default + AsMut<[u8]>; - - /// Create a new PRNG using the given seed. - /// - /// PRNG implementations are allowed to assume that bits in the seed are - /// well distributed. That means usually that the number of one and zero - /// bits are about equal, and values like 0, 1 and (size - 1) are unlikely. - /// - /// PRNG implementations are recommended to be reproducible. A PRNG seeded - /// using this function with a fixed seed should produce the same sequence - /// of output in the future and on different architectures (with for example - /// different endianness). - /// - /// It is however not required that this function yield the same state as a - /// reference implementation of the PRNG given equivalent seed; if necessary - /// another constructor replicating behaviour from a reference - /// implementation can be added. - /// - /// PRNG implementations should make sure `from_seed` never panics. In the - /// case that some special values (like an all zero seed) are not viable - /// seeds it is preferable to map these to alternative constant value(s), - /// for example `0xBAD5EEDu32` or `0x0DDB1A5E5BAD5EEDu64` ("odd biases? bad - /// seed"). This is assuming only a small number of values must be rejected. - fn from_seed(seed: Self::Seed) -> Self; - - /// Create a new PRNG seeded from another `Rng`. - /// - /// This is the recommended way to initialize PRNGs with fresh entropy. The - /// [`FromEntropy`] trait provides a convenient `from_entropy` method - /// based on `from_rng`. - /// - /// Usage of this method is not recommended when reproducibility is required - /// since implementing PRNGs are not required to fix Endianness and are - /// allowed to modify implementations in new releases. - /// - /// It is important to use a good source of randomness to initialize the - /// PRNG. Cryptographic PRNG may be rendered insecure when seeded from a - /// non-cryptographic PRNG or with insufficient entropy. - /// Many non-cryptographic PRNGs will show statistical bias in their first - /// results if their seed numbers are small or if there is a simple pattern - /// between them. - /// - /// Prefer to seed from a strong external entropy source like [`OsRng`] or - /// from a cryptographic PRNG; if creating a new generator for cryptographic - /// uses you *must* seed from a strong source. - /// - /// Seeding a small PRNG from another small PRNG is possible, but - /// something to be careful with. An extreme example of how this can go - /// wrong is seeding an Xorshift RNG from another Xorshift RNG, which - /// will effectively clone the generator. In general seeding from a - /// generator which is hard to predict is probably okay. - /// - /// PRNG implementations are allowed to assume that a good RNG is provided - /// for seeding, and that it is cryptographically secure when appropriate. - /// - /// [`FromEntropy`]: ../rand/trait.FromEntropy.html - /// [`OsRng`]: ../rand/rngs/struct.OsRng.html - fn from_rng(mut rng: R) -> Result { - let mut seed = Self::Seed::default(); - rng.try_fill_bytes(seed.as_mut())?; - Ok(Self::from_seed(seed)) - } -} - -// Implement `RngCore` for references to an `RngCore`. -// Force inlining all functions, so that it is up to the `RngCore` -// implementation and the optimizer to decide on inlining. -impl<'a, R: RngCore + ?Sized> RngCore for &'a mut R { - #[inline(always)] - fn next_u32(&mut self) -> u32 { - (**self).next_u32() - } - - #[inline(always)] - fn next_u64(&mut self) -> u64 { - (**self).next_u64() - } - - #[inline(always)] - fn fill_bytes(&mut self, dest: &mut [u8]) { - (**self).fill_bytes(dest) - } - - #[inline(always)] - fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { - (**self).try_fill_bytes(dest) - } -} - -// Implement `RngCore` for boxed references to an `RngCore`. -// Force inlining all functions, so that it is up to the `RngCore` -// implementation and the optimizer to decide on inlining. -#[cfg(feature="alloc")] -impl RngCore for Box { - #[inline(always)] - fn next_u32(&mut self) -> u32 { - (**self).next_u32() - } - - #[inline(always)] - fn next_u64(&mut self) -> u64 { - (**self).next_u64() - } - - #[inline(always)] - fn fill_bytes(&mut self, dest: &mut [u8]) { - (**self).fill_bytes(dest) - } - - #[inline(always)] - fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { - (**self).try_fill_bytes(dest) - } -} - -#[cfg(feature="std")] -impl std::io::Read for RngCore { - fn read(&mut self, buf: &mut [u8]) -> Result { - self.try_fill_bytes(buf)?; - Ok(buf.len()) - } -} +#![no_std] -// Implement `CryptoRng` for references to an `CryptoRng`. -impl<'a, R: CryptoRng + ?Sized> CryptoRng for &'a mut R {} +extern crate rand_core as core3; -// Implement `CryptoRng` for boxed references to an `CryptoRng`. -#[cfg(feature="alloc")] -impl CryptoRng for Box {} +pub use core3::{ErrorKind, Error}; +pub use core3::{block, impls, le}; +pub use core3::{RngCore, CryptoRng, SeedableRng}; diff --git a/src/distributions/other.rs b/src/distributions/other.rs index ef8ce63b8b0..f23d2b85e51 100644 --- a/src/distributions/other.rs +++ b/src/distributions/other.rs @@ -174,7 +174,7 @@ impl Distribution> for Standard where Standard: Distribution { mod tests { use {Rng, RngCore, Standard}; use distributions::Alphanumeric; - #[cfg(all(not(feature="std"), feature="alloc"))] use alloc::String; + #[cfg(all(not(feature="std"), feature="alloc"))] use alloc::string::String; #[test] fn test_misc() { diff --git a/src/seq.rs b/src/seq.rs index 68f7ab08edc..4170677f69f 100644 --- a/src/seq.rs +++ b/src/seq.rs @@ -15,9 +15,9 @@ use super::Rng; // This crate is only enabled when either std or alloc is available. // BTreeMap is not as fast in tests, but better than nothing. #[cfg(feature="std")] use std::collections::HashMap; -#[cfg(not(feature="std"))] use alloc::btree_map::BTreeMap; +#[cfg(not(feature="std"))] use alloc::collections::btree_map::BTreeMap; -#[cfg(not(feature="std"))] use alloc::Vec; +#[cfg(not(feature="std"))] use alloc::vec::Vec; /// Randomly sample `amount` elements from a finite iterator. /// @@ -227,7 +227,7 @@ mod test { use super::*; use {XorShiftRng, Rng, SeedableRng}; #[cfg(not(feature="std"))] - use alloc::Vec; + use alloc::vec::Vec; #[test] fn test_sample_iter() { diff --git a/utils/ci/script.sh b/utils/ci/script.sh index 21188f38d29..d0fec19a6a6 100644 --- a/utils/ci/script.sh +++ b/utils/ci/script.sh @@ -13,12 +13,12 @@ main() { if [ ! -z $NIGHTLY ]; then # have nightly Rust cross test --tests --no-default-features --features alloc --target $TARGET - cross test --package rand_core --no-default-features --features alloc --target $TARGET + cross test --package rand_core:0.2.2 --no-default-features --features alloc --target $TARGET --tests cross test --features serde1,log,nightly,alloc --target $TARGET cross test --all --benches --target $TARGET else # have stable Rust cross test --tests --no-default-features --target $TARGET - cross test --package rand_core --no-default-features --target $TARGET + cross test --package rand_core:0.2.2 --no-default-features --target $TARGET --tests cross test --features serde1,log --target $TARGET fi }