Merge pull request #880 from vks/vigna2019
rand_xoshiro: Bump minor version
diff --git a/.travis.yml b/.travis.yml
index c375880..bb4ce0f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,158 +1,42 @@
language: rust
sudo: false
-# We support too many combinations of Rust releases, crate features, operating
-# systems, and architectures to even remotely test all combinations.
-# Yet it turns out we can test most of these independent of each other, because
-# they serve different goals or test different pieces of code.
-#
-# RUST RELEASES
-# Goal: make sure we don't use language features unavailable on a certain
-# version, and build without warnings.
-# We have different builders use 4 Rust releases, a pinned stable release,
-# the latest stable, beta and nightly.
-#
-# ARCHITECTURES
-# Goal: test against issues caused by differences in endianness, pointer sizes,
-# etc.
-# We run tests on 4 different architectures.
-# - x64_84, default on Travis (Linux) and AppVeyor (Windows)
-# - i686, second AppVeyor (Windows) configuration
-# - MIPS, big-endian Linux emulated with QEMU (thanks to Trust)
-# - ARMv7, Android emulated with QEMU (thanks to Trust)
-#
-# OPERATING SYSTEMS
-# Goal: test on many operating systems, to verify the OsRng code, which is
-# mostly architecture-independent.
-# We run tests on Linux, OS X, Windows, Android (emulated), and Node.js (using
-# cargo-web).
-# One builder cross-compiles for many of the remaining OSes, which ensures we
-# keep building, but doesn't run tests.
-# OSes supported by Rand but which we can't cross-compile because there
-# is no pre-built standard library available: Dragonfly BSD, Haiku, OpenBSD.
-#
-# CRATE FEATURES, TESTS, AND SUB-CRATES
-# Goal: Run unit tests, doctests, examples, and test benchmarks for all crates,
-# in configurations that cover all interesting combinations of features.
-# Tests run on rand:
-# - test no_std support, but only the unit tests:
-# `cargo test --tests --no-default-features`
-# - run unit tests and doctests with all features which are available on stable:
-# `cargo test --features=serde1,log`
-# - test examples:
-# `cargo test --examples`
-# Additional tests on nightly:
-# - run unit tests and doctests with all features which are available on nightly:
-# `cargo test --all-features`
-# - test no_std support, including the nightly alloc feature:
-# cargo test --tests --no-default-features --features=alloc
-# - run benchmarks as tests:
-# `cargo test --benches --features=nightly`
-# Tests on subcrates:
-# - select crates via --manifest-path (more reliable than --package)
-# - test appropriate feature matrix
-#
-# TODO: SIMD support on stable releases
-# NOTE: SIMD support is unreliable on nightly; we track the latest release
+# Since most OS-specific code has moved to the getrandom crate, we require
+# few target-specific tests here.
+
matrix:
include:
- rust: 1.32.0
- env: DESCRIPTION="Linux, 1.32.0"
+ name: "Linux, 1.32.0"
+ env: ALLOC=0
os: linux
- script:
- # Differs from standard script: rand_pcg features
- - cargo test --tests --no-default-features
- # TODO: add simd_support feature:
- - cargo test --features=serde1,log
- - cargo test --examples
- - cargo test --manifest-path rand_core/Cargo.toml
- - cargo test --manifest-path rand_core/Cargo.toml --no-default-features
- - cargo test --manifest-path rand_distr/Cargo.toml
- - cargo test --manifest-path rand_isaac/Cargo.toml --features=serde1
- # TODO: cannot test rand_pcg due to explicit dependency on i128
- - cargo test --manifest-path rand_xorshift/Cargo.toml --features=serde1
- - cargo test --manifest-path rand_xoshiro/Cargo.toml
- - cargo test --manifest-path rand_chacha/Cargo.toml
- - cargo test --manifest-path rand_hc/Cargo.toml
- - cargo test --manifest-path rand_jitter/Cargo.toml
- - cargo test --manifest-path rand_os/Cargo.toml
-
- - rust: 1.32.0
- env: DESCRIPTION="OSX, 1.32.0"
- os: osx
- script:
- # Differs from standard script: rand_pcg features
- - cargo test --tests --no-default-features
- # TODO: add simd_support feature:
- - cargo test --features=serde1,log
- - cargo test --examples
- - cargo test --manifest-path rand_core/Cargo.toml
- - cargo test --manifest-path rand_core/Cargo.toml --no-default-features
- - cargo test --manifest-path rand_distr/Cargo.toml
- - cargo test --manifest-path rand_isaac/Cargo.toml --features=serde1
- # TODO: cannot test rand_pcg due to explicit dependency on i128
- - cargo test --manifest-path rand_xorshift/Cargo.toml --features=serde1
- - cargo test --manifest-path rand_xoshiro/Cargo.toml
- - cargo test --manifest-path rand_chacha/Cargo.toml
- - cargo test --manifest-path rand_hc/Cargo.toml
- - cargo test --manifest-path rand_jitter/Cargo.toml
- - cargo test --manifest-path rand_os/Cargo.toml
- rust: stable
- env: DESCRIPTION="Linux, stable"
+ name: "Linux, stable"
- rust: stable
- env: DESCRIPTION="OSX+iOS, stable"
+ name: "OSX+iOS, stable"
os: osx
install:
- rustup target add aarch64-apple-ios
script:
- # Differs from standard script: includes aarch64-apple-ios cross-build
- - cargo test --tests --no-default-features
- # TODO: add simd_support feature:
- - cargo test --features=serde1,log
- - cargo test --examples
- - cargo test --manifest-path rand_core/Cargo.toml
- - cargo test --manifest-path rand_core/Cargo.toml --no-default-features
- - cargo test --manifest-path rand_distr/Cargo.toml
- - cargo test --manifest-path rand_isaac/Cargo.toml --features=serde1
- - cargo test --manifest-path rand_pcg/Cargo.toml --features=serde1
- - cargo test --manifest-path rand_xorshift/Cargo.toml --features=serde1
- - cargo test --manifest-path rand_xoshiro/Cargo.toml
- - cargo test --manifest-path rand_chacha/Cargo.toml
- - cargo test --manifest-path rand_hc/Cargo.toml
- - cargo test --manifest-path rand_jitter/Cargo.toml
- - cargo test --manifest-path rand_os/Cargo.toml
+ - bash utils/ci/script.sh
- cargo build --target=aarch64-apple-ios
- rust: beta
- env: DESCRIPTION="Linux, beta"
+ name: "Linux, beta"
- rust: nightly
os: linux
- env: DESCRIPTION="Linux, nightly, docs"
+ name: "Linux, nightly, docs"
+ env: NIGHTLY=1
install:
- cargo --list | egrep "^\s*deadlinks$" -q || cargo install cargo-deadlinks
- cargo deadlinks -V
before_script:
- pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH
script:
- # Differs from standard script: alloc feature, all features, doc build
- - cargo test --tests --no-default-features --features=alloc
- - cargo test --all-features
- - cargo test --benches --features=nightly
- - cargo test --examples
- - cargo test --manifest-path rand_core/Cargo.toml
- - cargo test --manifest-path rand_core/Cargo.toml --no-default-features --features=alloc
- - cargo test --manifest-path rand_distr/Cargo.toml
- - cargo test --manifest-path rand_isaac/Cargo.toml --features=serde1
- - cargo test --manifest-path rand_pcg/Cargo.toml --features=serde1
- - cargo test --manifest-path rand_xorshift/Cargo.toml --features=serde1
- - cargo test --manifest-path rand_xoshiro/Cargo.toml
- - cargo test --manifest-path rand_chacha/Cargo.toml
- - cargo test --manifest-path rand_hc/Cargo.toml
- - cargo test --manifest-path rand_jitter/Cargo.toml
- - cargo test --manifest-path rand_os/Cargo.toml
+ - bash utils/ci/script.sh
# remove cached documentation, otherwise files from previous PRs can get included
- rm -rf target/doc
- cargo doc --no-deps --all --all-features
@@ -160,103 +44,20 @@
after_success:
- travis-cargo --only nightly doc-upload
- - rust: nightly
- os: osx
- env: DESCRIPTION="OSX, nightly, docs"
- install:
- - cargo --list | egrep "^\s*deadlinks$" -q || cargo install cargo-deadlinks
- - cargo deadlinks -V
- script:
- # Differs from standard script: alloc feature, all features, doc build
- - cargo test --tests --no-default-features --features=alloc
- - cargo test --all-features
- - cargo test --benches --features=nightly
- - cargo test --examples
- - cargo test --manifest-path rand_core/Cargo.toml
- - cargo test --manifest-path rand_core/Cargo.toml --no-default-features --features=alloc
- - cargo test --manifest-path rand_distr/Cargo.toml
- - cargo test --manifest-path rand_isaac/Cargo.toml --features=serde1
- - cargo test --manifest-path rand_pcg/Cargo.toml --features=serde1
- - cargo test --manifest-path rand_xorshift/Cargo.toml --features=serde1
- - cargo test --manifest-path rand_xoshiro/Cargo.toml
- - cargo test --manifest-path rand_chacha/Cargo.toml
- - cargo test --manifest-path rand_hc/Cargo.toml
- - cargo test --manifest-path rand_jitter/Cargo.toml
- - cargo test --manifest-path rand_os/Cargo.toml
- # 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
-
- - rust: nightly
- env: DESCRIPTION="WASM via emscripten, stdweb and wasm-bindgen"
- install:
- - rustup target add wasm32-unknown-unknown
- - rustup target add wasm32-unknown-emscripten
- - nvm install 9
- - ./utils/ci/install_cargo_web.sh
- - cargo web prepare-emscripten
- - cargo web -V
- - cargo list | grep install-update || cargo install -f cargo-update
- - cargo install-update -i cargo-update wasm-bindgen-cli wasm-pack
- addons:
- chrome: stable
- script:
- # Testing wasm32-unknown-emscripten fails because of rust-lang/rust#49877
- # However, we can still build and link all tests to make sure that works.
- # This is actually useful as it finds stuff such as rust-random/rand#669
- - EMCC_CFLAGS="-s ERROR_ON_UNDEFINED_SYMBOLS=0" cargo web test --target wasm32-unknown-emscripten --no-run
- #- cargo web test --target wasm32-unknown-emscripten
- #- cargo web test --nodejs --target wasm32-unknown-emscripten
- #- cargo build --target wasm32-unknown-unknown # without any features
- - cargo build --target wasm32-unknown-unknown --features=wasm-bindgen
- - cargo web test --target wasm32-unknown-unknown --features=stdweb
- - cargo build --manifest-path tests/wasm_bindgen/Cargo.toml --target wasm32-unknown-unknown
- - wasm-bindgen --nodejs target/wasm32-unknown-unknown/debug/rand_wasm_bindgen_test.wasm --out-dir tests/wasm_bindgen/js
- - node tests/wasm_bindgen/js/index.js
- - wasm-pack test --node tests/wasm_bindgen
-
- - rust: nightly
- env: DESCRIPTION="cross-platform builder (doesn't run tests)"
- install:
- - rustup target add x86_64-sun-solaris
- - rustup target add x86_64-unknown-cloudabi
- - rustup target add x86_64-unknown-freebsd
- #- rustup target add x86_64-unknown-fuchsia
- - rustup target add x86_64-unknown-netbsd
- - rustup target add x86_64-unknown-redox
- script:
- # Test the top-level crate with all features:
- - cargo build --target=x86_64-sun-solaris --all-features
- - cargo build --target=x86_64-unknown-cloudabi --all-features
- - cargo build --target=x86_64-unknown-freebsd --all-features
- #- cargo build --target=x86_64-unknown-fuchsia --all-features
- - cargo build --target=x86_64-unknown-netbsd --all-features
- - cargo build --target=x86_64-unknown-redox --all-features
-
- # Trust cross-built/emulated targets. We must repeat all non-default values.
+ # This target catches endianness issues
- rust: stable
sudo: required
dist: trusty
services: docker
- env: DESCRIPTION="Linux (MIPS, big-endian)" TARGET=mips-unknown-linux-gnu
+ name: "Linux (MIPS, big-endian)"
+ env: TARGET=mips-unknown-linux-gnu
install:
- sh utils/ci/install.sh
- source ~/.cargo/env || true
- script:
- - bash utils/ci/script.sh
- - rust: stable
- sudo: required
- dist: trusty
- services: docker
- env: DESCRIPTION="Android (ARMv7)" TARGET=armv7-linux-androideabi
- install:
- - sh utils/ci/install.sh
- - source ~/.cargo/env || true
- script:
- - bash utils/ci/script.sh
+
+ # This target checks we really can build no_std binaries
- rust: nightly
- env: DESCRIPTION="no_std platform test"
+ name: "no_std platform test"
install:
- rustup target add thumbv6m-none-eabi
script:
@@ -265,42 +66,35 @@
- rust: nightly
os: linux
- env: DESCRIPTION="Miri, nightly"
+ name: "Miri, nightly"
script:
- sh utils/ci/miri.sh
+
+ - rust: nightly
+ os: linux
+ name: "Minimal dep versions"
+ script:
+ - cargo generate-lockfile -Z minimal-versions
+ - bash utils/ci/script.sh
before_install:
- set -e
- rustup self update
script:
- - cargo test --tests --no-default-features
- - cargo test --tests --no-default-features --features getrandom
- # TODO: add simd_support feature:
- - cargo test --features=serde1,log
- - cargo test --examples
- - cargo test --manifest-path rand_core/Cargo.toml
- - cargo test --manifest-path rand_core/Cargo.toml --no-default-features
- - cargo test --manifest-path rand_distr/Cargo.toml
- - cargo test --manifest-path rand_isaac/Cargo.toml --features=serde1
- - cargo test --manifest-path rand_pcg/Cargo.toml --features=serde1
- - cargo test --manifest-path rand_xorshift/Cargo.toml --features=serde1
- - cargo test --manifest-path rand_xoshiro/Cargo.toml
- - cargo test --manifest-path rand_chacha/Cargo.toml
- - cargo test --manifest-path rand_hc/Cargo.toml
- - cargo test --manifest-path rand_jitter/Cargo.toml
- - cargo test --manifest-path rand_os/Cargo.toml
+ - bash utils/ci/script.sh
after_script: set +e
-cache:
- cargo: true
- directories:
- - .local/share/cargo-web
+# Cache: this seems to do more harm than good
+#cache:
+ #cargo: true
+ #directories:
+ #- .local/share/cargo-web
-before_cache:
- # Travis can't cache files that are not readable by "others"
- - chmod -R a+r $HOME/.cargo
+#before_cache:
+ ## Travis can't cache files that are not readable by "others"
+ #- chmod -R a+r $HOME/.cargo
env:
global:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 88fba02..a2ae496 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@
## [Unreleased]
- Fix `no_std` behaviour, appropriately enable c2-chacha's `std` feature (#844)
- Add a `no_std` target to CI to continously evaluate `no_std` status (#844)
+- `alloc` feature in `no_std` is available since Rust 1.36 (#856)
## [0.7.0] - 2019-06-28
diff --git a/Cargo.toml b/Cargo.toml
index 5f30603..fead913 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -57,8 +57,10 @@
rand_core = { path = "rand_core", version = "0.5" }
rand_pcg = { path = "rand_pcg", version = "0.2", optional = true }
# Do not depend on 'getrandom_package' directly; use the 'getrandom' feature!
+# This is a dependency because: we forward wasm feature flags
+# This is renamed because: we need getrandom to depend on rand_core/getrandom
getrandom_package = { version = "0.1.1", package = "getrandom", optional = true }
-log = { version = "0.4", optional = true }
+log = { version = "0.4.4", optional = true }
[dependencies.packed_simd]
# NOTE: so far no version works reliably due to dependence on unstable features
diff --git a/README.md b/README.md
index b9d43e9..5acbadb 100644
--- a/README.md
+++ b/README.md
@@ -84,7 +84,7 @@
Rand is built with these features enabled by default:
- `std` enables functionality dependent on the `std` lib
-- `alloc` (implied by `std`) enables functionality requiring an allocator
+- `alloc` (implied by `std`) enables functionality requiring an allocator (when using this feature in `no_std`, Rand requires Rustc version 1.36 or greater)
- `getrandom` (implied by `std`) is an optional dependency providing the code
behind `rngs::OsRng`
diff --git a/appveyor.yml b/appveyor.yml
index ef0b4bf..a4cfbee 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -32,12 +32,14 @@
build: false
test_script:
- - cargo test --tests --no-default-features --features alloc
- # TODO: use --all-features once simd_support is sufficiently stable:
+ - cargo test --tests --no-default-features
+ - cargo test --tests --no-default-features --features=alloc,getrandom
+ # all stable features:
- cargo test --features=serde1,log
- cargo test --benches --features=nightly
- cargo test --examples
- cargo test --manifest-path rand_core/Cargo.toml
+ - cargo test --manifest-path rand_core/Cargo.toml --no-default-features
- cargo test --manifest-path rand_core/Cargo.toml --no-default-features --features=alloc
- cargo test --manifest-path rand_distr/Cargo.toml
- cargo test --manifest-path rand_isaac/Cargo.toml --features=serde1
@@ -46,4 +48,5 @@
- cargo test --manifest-path rand_xoshiro/Cargo.toml
- cargo test --manifest-path rand_chacha/Cargo.toml
- cargo test --manifest-path rand_hc/Cargo.toml
+ - cargo test --manifest-path rand_jitter/Cargo.toml
- cargo test --manifest-path rand_os/Cargo.toml
diff --git a/benches/weighted.rs b/benches/weighted.rs
new file mode 100644
index 0000000..5ddca3f
--- /dev/null
+++ b/benches/weighted.rs
@@ -0,0 +1,36 @@
+// Copyright 2019 Developers of the Rand project.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(test)]
+
+extern crate test;
+
+use test::Bencher;
+use rand::Rng;
+use rand::distributions::WeightedIndex;
+
+#[bench]
+fn weighted_index_creation(b: &mut Bencher) {
+ let mut rng = rand::thread_rng();
+ let weights = [1u32, 2, 4, 0, 5, 1, 7, 1, 2, 3, 4, 5, 6, 7];
+ b.iter(|| {
+ let distr = WeightedIndex::new(weights.to_vec()).unwrap();
+ rng.sample(distr)
+ })
+}
+
+#[bench]
+fn weighted_index_modification(b: &mut Bencher) {
+ let mut rng = rand::thread_rng();
+ let weights = [1u32, 2, 3, 0, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7];
+ let mut distr = WeightedIndex::new(weights.to_vec()).unwrap();
+ b.iter(|| {
+ distr.update_weights(&[(2, &4), (5, &1)]).unwrap();
+ rng.sample(&distr)
+ })
+}
diff --git a/rand_core/CHANGELOG.md b/rand_core/CHANGELOG.md
index 4542a3b..dfdd692 100644
--- a/rand_core/CHANGELOG.md
+++ b/rand_core/CHANGELOG.md
@@ -4,38 +4,55 @@
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.5.1] - 2019-08-28
+- `OsRng` added to `rand_core` (#863)
+- `Error::INTERNAL_START` and `Error::CUSTOM_START` constants (#864)
+- `Error::raw_os_error` method (#864)
+- `Debug` and `Display` formatting for `getrandom` error codes without `std` (#864)
+### Changed
+- `alloc` feature in `no_std` is available since Rust 1.36 (#856)
+- Added `#[inline]` to `Error` conversion methods (#864)
+
## [0.5.0] - 2019-06-06
+### Changed
- Enable testing with Miri and fix incorrect pointer usages (#779, #780, #781, #783, #784)
- Rewrite `Error` type and adjust API (#800)
- Adjust usage of `#[inline]` for `BlockRng` and `BlockRng64`
## [0.4.0] - 2019-01-24
+### Changed
- Disable the `std` feature by default (#702)
## [0.3.0] - 2018-09-24
+### Added
- Add `SeedableRng::seed_from_u64` for convenient seeding. (#537)
## [0.2.1] - 2018-06-08
+### Added
- References to a `CryptoRng` now also implement `CryptoRng`. (#470)
## [0.2.0] - 2018-05-21
+### Changed
- Enable the `std` feature by default. (#409)
- Remove `BlockRng{64}::inner` and `BlockRng::inner_mut`; instead making `core` public
-- Add `BlockRng{64}::index` and `BlockRng{64}::generate_and_set`. (#374, #419)
- Change `BlockRngCore::Results` bound to also require `AsMut<[Self::Item]>`. (#419)
+### Added
+- Add `BlockRng{64}::index` and `BlockRng{64}::generate_and_set`. (#374, #419)
- Implement `std::io::Read` for RngCore. (#434)
## [0.1.0] - 2018-04-17
-(Split out of the Rand crate, changes here are relative to rand 0.4.2)
+(Split out of the Rand crate, changes here are relative to rand 0.4.2.)
+### Added
- `RngCore` and `SeedableRng` are now part of `rand_core`. (#288)
- Add modules to help implementing RNGs `impl` and `le`. (#209, #228)
- Add `Error` and `ErrorKind`. (#225)
- Add `CryptoRng` marker trait. (#273)
- Add `BlockRngCore` trait. (#281)
- Add `BlockRng` and `BlockRng64` wrappers to help implementations. (#281, #325)
+- Add `RngCore::try_fill_bytes`. (#225)
+### Changed
- Revise the `SeedableRng` trait. (#233)
- Remove default implementations for `RngCore::next_u64` and `RngCore::fill_bytes`. (#288)
-- Add `RngCore::try_fill_bytes`. (#225)
## [0.0.1] - 2017-09-14 (yanked)
Experimental version as part of the rand crate refactor.
diff --git a/rand_core/Cargo.toml b/rand_core/Cargo.toml
index b9042c0..e52af5f 100644
--- a/rand_core/Cargo.toml
+++ b/rand_core/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "rand_core"
-version = "0.5.0"
+version = "0.5.1"
authors = ["The Rand Project Developers", "The Rust Project Developers"]
license = "MIT OR Apache-2.0"
readme = "README.md"
diff --git a/rand_core/src/error.rs b/rand_core/src/error.rs
index 7e8f0c9..30b095c 100644
--- a/rand_core/src/error.rs
+++ b/rand_core/src/error.rs
@@ -17,7 +17,6 @@
/// In order to be compatible with `std` and `no_std`, this type has two
/// possible implementations: with `std` a boxed `Error` trait object is stored,
/// while with `no_std` we merely store an error code.
-#[derive(Debug)]
pub struct Error {
#[cfg(feature="std")]
inner: Box<dyn std::error::Error + Send + Sync + 'static>,
@@ -32,6 +31,7 @@
///
/// See also `From<NonZeroU32>`, which is available with and without `std`.
#[cfg(feature="std")]
+ #[inline]
pub fn new<E>(err: E) -> Self
where E: Into<Box<dyn std::error::Error + Send + Sync + 'static>>
{
@@ -43,6 +43,7 @@
/// When configured with `std`, this is a trivial operation and never
/// panics. Without `std`, this method is simply unavailable.
#[cfg(feature="std")]
+ #[inline]
pub fn inner(&self) -> &(dyn std::error::Error + Send + Sync + 'static) {
&*self.inner
}
@@ -52,15 +53,45 @@
/// When configured with `std`, this is a trivial operation and never
/// panics. Without `std`, this method is simply unavailable.
#[cfg(feature="std")]
+ #[inline]
pub fn take_inner(self) -> Box<dyn std::error::Error + Send + Sync + 'static> {
self.inner
}
+ /// Codes below this point represent OS Errors (i.e. positive i32 values).
+ /// Codes at or above this point, but below [`Error::CUSTOM_START`] are
+ /// reserved for use by the `rand` and `getrandom` crates.
+ pub const INTERNAL_START: u32 = 1 << 31;
+
+ /// Codes at or above this point can be used by users to define their own
+ /// custom errors.
+ pub const CUSTOM_START: u32 = (1 << 31) + (1 << 30);
+
+ /// Extract the raw OS error code (if this error came from the OS)
+ ///
+ /// This method is identical to `std::io::Error::raw_os_error()`, except
+ /// that it works in `no_std` contexts. If this method returns `None`, the
+ /// error value can still be formatted via the `Diplay` implementation.
+ #[inline]
+ pub fn raw_os_error(&self) -> Option<i32> {
+ #[cfg(feature="std")] {
+ if let Some(e) = self.inner.downcast_ref::<std::io::Error>() {
+ return e.raw_os_error();
+ }
+ }
+ match self.code() {
+ Some(code) if u32::from(code) < Self::INTERNAL_START =>
+ Some(u32::from(code) as i32),
+ _ => None,
+ }
+ }
+
/// Retrieve the error code, if any.
///
/// If this `Error` was constructed via `From<NonZeroU32>`, then this method
/// will return this `NonZeroU32` code (for `no_std` this is always the
/// case). Otherwise, this method will return `None`.
+ #[inline]
pub fn code(&self) -> Option<NonZeroU32> {
#[cfg(feature="std")] {
self.inner.downcast_ref::<ErrorCode>().map(|c| c.0)
@@ -71,18 +102,36 @@
}
}
+impl fmt::Debug for Error {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ #[cfg(feature="std")] {
+ write!(f, "Error {{ inner: {:?} }}", self.inner)
+ }
+ #[cfg(all(feature="getrandom", not(feature="std")))] {
+ getrandom::Error::from(self.code).fmt(f)
+ }
+ #[cfg(not(feature="getrandom"))] {
+ write!(f, "Error {{ code: {} }}", self.code)
+ }
+ }
+}
+
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
#[cfg(feature="std")] {
write!(f, "{}", self.inner)
}
- #[cfg(not(feature="std"))] {
+ #[cfg(all(feature="getrandom", not(feature="std")))] {
+ getrandom::Error::from(self.code).fmt(f)
+ }
+ #[cfg(not(feature="getrandom"))] {
write!(f, "error code {}", self.code)
}
}
}
impl From<NonZeroU32> for Error {
+ #[inline]
fn from(code: NonZeroU32) -> Self {
#[cfg(feature="std")] {
Error { inner: Box::new(ErrorCode(code)) }
@@ -95,6 +144,7 @@
#[cfg(feature="getrandom")]
impl From<getrandom::Error> for Error {
+ #[inline]
fn from(error: getrandom::Error) -> Self {
#[cfg(feature="std")] {
Error { inner: Box::new(error) }
@@ -107,6 +157,7 @@
#[cfg(feature="std")]
impl std::error::Error for Error {
+ #[inline]
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.inner.source()
}
@@ -114,8 +165,13 @@
#[cfg(feature="std")]
impl From<Error> for std::io::Error {
+ #[inline]
fn from(error: Error) -> Self {
- std::io::Error::new(std::io::ErrorKind::Other, error)
+ if let Some(code) = error.raw_os_error() {
+ std::io::Error::from_raw_os_error(code)
+ } else {
+ std::io::Error::new(std::io::ErrorKind::Other, error)
+ }
}
}
diff --git a/rand_core/src/lib.rs b/rand_core/src/lib.rs
index 96b9457..d8e0189 100644
--- a/rand_core/src/lib.rs
+++ b/rand_core/src/lib.rs
@@ -38,7 +38,6 @@
#![allow(clippy::unreadable_literal)]
#![cfg_attr(not(feature="std"), no_std)]
-#![cfg_attr(all(feature="alloc", not(feature="std")), feature(alloc))]
use core::default::Default;
@@ -49,12 +48,14 @@
#[cfg(all(feature="alloc", not(feature="std")))] use alloc::boxed::Box;
pub use error::Error;
+#[cfg(feature="getrandom")] pub use os::OsRng;
mod error;
pub mod block;
pub mod impls;
pub mod le;
+#[cfg(feature="getrandom")] mod os;
/// The core of a random number generator.
diff --git a/src/rngs/os.rs b/rand_core/src/os.rs
similarity index 80%
rename from src/rngs/os.rs
rename to rand_core/src/os.rs
index 46c3483..fc23a57 100644
--- a/src/rngs/os.rs
+++ b/rand_core/src/os.rs
@@ -9,8 +9,8 @@
//! Interface to the random number generator of the operating system.
// Note: keep this code in sync with the rand_os crate!
-use crate::getrandom::getrandom;
-use rand_core::{CryptoRng, RngCore, Error, impls};
+use getrandom::getrandom;
+use crate::{CryptoRng, RngCore, Error, impls};
/// A random number generator that retrieves randomness from from the
/// operating system.
@@ -20,6 +20,9 @@
/// The implementation is provided by the [getrandom] crate. Refer to
/// [getrandom] documentation for details.
///
+/// This struct is only available when specifying the crate feature `getrandom`
+/// or `std`. When using the `rand` lib, it is also available as `rand::rngs::OsRng`.
+///
/// # Blocking and error handling
///
/// It is possible that when used during early boot the first call to `OsRng`
@@ -33,30 +36,17 @@
///
/// # Usage example
/// ```
-/// use rand::rngs::{StdRng, OsRng};
-/// use rand::{RngCore, SeedableRng};
+/// use rand_core::{RngCore, OsRng};
///
/// let mut key = [0u8; 16];
/// OsRng.fill_bytes(&mut key);
/// let random_u64 = OsRng.next_u64();
-///
-/// // OsRng is especially useful for seeding other RNGs (see also from_entropy)
-/// let mut rng = StdRng::from_rng(OsRng).unwrap();
-/// let _ = rng.next_u32();
/// ```
///
/// [getrandom]: https://crates.io/crates/getrandom
#[derive(Clone, Copy, Debug, Default)]
pub struct OsRng;
-impl OsRng {
- /// Create a new `OsRng`.
- #[deprecated(since="0.7.0", note="replace OsRng::new().unwrap() with just OsRng")]
- pub fn new() -> Result<OsRng, Error> {
- Ok(OsRng)
- }
-}
-
impl CryptoRng for OsRng {}
impl RngCore for OsRng {
diff --git a/rand_distr/Cargo.toml b/rand_distr/Cargo.toml
index 315a5b0..8fbf33b 100644
--- a/rand_distr/Cargo.toml
+++ b/rand_distr/Cargo.toml
@@ -24,4 +24,4 @@
[dev-dependencies]
rand_pcg = { version = "0.2", path = "../rand_pcg" }
# Histogram implementation for testing uniformity
-average = "0.9.2"
+average = "0.10.3"
diff --git a/rand_isaac/Cargo.toml b/rand_isaac/Cargo.toml
index c11c305..a63ab18 100644
--- a/rand_isaac/Cargo.toml
+++ b/rand_isaac/Cargo.toml
@@ -23,9 +23,11 @@
[dependencies]
rand_core = { path = "../rand_core", version = "0.5" }
-serde = { version = "1", features = ["derive"], optional = true }
+serde = { version = "1.0.63", features = ["derive"], optional = true }
+# Not a direct dependency but required to boost the minimum version:
+serde_derive = { version = "1.0.63", optional = true }
[dev-dependencies]
# This is for testing serde, unfortunately we can't specify feature-gated dev
# deps yet, see: https://github.com/rust-lang/cargo/issues/1596
-bincode = "1"
+bincode = "1.1.4"
diff --git a/rand_jitter/CHANGELOG.md b/rand_jitter/CHANGELOG.md
index 9dd6c0a..9f4bb7e 100644
--- a/rand_jitter/CHANGELOG.md
+++ b/rand_jitter/CHANGELOG.md
@@ -4,6 +4,11 @@
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.1] - 2019-08-16
+### Changed
+- `TimerError` changed to `repr(u32)` (#864)
+- `TimerError` enum values all increased by `1<<30` to match new `rand_core::Error` range (#864)
+
## [0.2.0] - 2019-06-06
- Bump `rand_core` version
- Support new `Error` type in `rand_core` 0.5
diff --git a/rand_jitter/Cargo.toml b/rand_jitter/Cargo.toml
index 7380f70..5b7e3c3 100644
--- a/rand_jitter/Cargo.toml
+++ b/rand_jitter/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "rand_jitter"
-version = "0.2.0"
+version = "0.2.1"
authors = ["The Rand Project Developers"]
license = "MIT OR Apache-2.0"
readme = "README.md"
diff --git a/rand_jitter/src/error.rs b/rand_jitter/src/error.rs
index 3ea72c3..b54fffa 100644
--- a/rand_jitter/src/error.rs
+++ b/rand_jitter/src/error.rs
@@ -10,24 +10,28 @@
use rand_core::Error;
use core::fmt;
+/// Base code for all `JitterRng` errors
+const ERROR_BASE: u32 = 0xAE53_0400;
+
/// An error that can occur when [`JitterRng::test_timer`] fails.
///
-/// All variants have a value of 0x6e530400 = 1850934272 plus a small
+/// All variants have a value of 0xAE530400 = 2924676096 plus a small
/// increment (1 through 5).
///
/// [`JitterRng::test_timer`]: crate::JitterRng::test_timer
#[derive(Debug, Clone, PartialEq, Eq)]
+#[repr(u32)]
pub enum TimerError {
/// No timer available.
- NoTimer = 0x6e530401,
+ NoTimer = ERROR_BASE + 1,
/// Timer too coarse to use as an entropy source.
- CoarseTimer = 0x6e530402,
+ CoarseTimer = ERROR_BASE + 2,
/// Timer is not monotonically increasing.
- NotMonotonic = 0x6e530403,
+ NotMonotonic = ERROR_BASE + 3,
/// Variations of deltas of time too small.
- TinyVariantions = 0x6e530404,
+ TinyVariantions = ERROR_BASE + 4,
/// Too many stuck results (indicating no added entropy).
- TooManyStuck = 0x6e530405,
+ TooManyStuck = ERROR_BASE + 5,
#[doc(hidden)]
__Nonexhaustive,
}
diff --git a/rand_os/CHANGELOG.md b/rand_os/CHANGELOG.md
index 9b8f208..c80befd 100644
--- a/rand_os/CHANGELOG.md
+++ b/rand_os/CHANGELOG.md
@@ -4,6 +4,10 @@
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] - 2019-08-28
+### Changed
+- `OsRng` added to `rand_core`, rendering this crate deprecated (#863)
+
## [0.2.1] - 2019-08-08
### Fixed
- Fix `no_std` support.
diff --git a/rand_os/Cargo.toml b/rand_os/Cargo.toml
index 6edf27d..c8010e2 100644
--- a/rand_os/Cargo.toml
+++ b/rand_os/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "rand_os"
-version = "0.2.1"
+version = "0.2.2"
authors = ["The Rand Project Developers"]
license = "MIT OR Apache-2.0"
readme = "README.md"
diff --git a/rand_os/README.md b/rand_os/README.md
index 8ed8c50..7b68b35 100644
--- a/rand_os/README.md
+++ b/rand_os/README.md
@@ -11,6 +11,8 @@
A random number generator that retrieves randomness straight from the
operating system.
+**This crate is deprecated:** `OsRng` is available in `rand_core` since version 0.5.1.
+
This crate provides `OsRng` as a shim around
[getrandom](https://crates.io/crates/getrandom)
implementing `RngCore` from [rand_core](https://crates.io/crates/rand_core).
diff --git a/rand_os/src/lib.rs b/rand_os/src/lib.rs
index 9090ab8..abfdf79 100644
--- a/rand_os/src/lib.rs
+++ b/rand_os/src/lib.rs
@@ -19,6 +19,8 @@
#![no_std] // but see getrandom crate
+#![deprecated(since="0.2.2", note="OsRng is now provided by rand_core and rand")]
+
pub use rand_core; // re-export
use getrandom::getrandom;
@@ -45,6 +47,7 @@
///
/// # Usage example
/// ```
+/// #![allow(deprecated)]
/// use rand_os::rand_core::RngCore;
/// use rand_os::OsRng;
///
diff --git a/src/distributions/weighted/mod.rs b/src/distributions/weighted/mod.rs
index 5c2cd97..2711637 100644
--- a/src/distributions/weighted/mod.rs
+++ b/src/distributions/weighted/mod.rs
@@ -84,6 +84,7 @@
#[derive(Debug, Clone)]
pub struct WeightedIndex<X: SampleUniform + PartialOrd> {
cumulative_weights: Vec<X>,
+ total_weight: X,
weight_distribution: X::Sampler,
}
@@ -125,9 +126,98 @@
if total_weight == zero {
return Err(WeightedError::AllWeightsZero);
}
- let distr = X::Sampler::new(zero, total_weight);
+ let distr = X::Sampler::new(zero, total_weight.clone());
- Ok(WeightedIndex { cumulative_weights: weights, weight_distribution: distr })
+ Ok(WeightedIndex { cumulative_weights: weights, total_weight, weight_distribution: distr })
+ }
+
+ /// Update a subset of weights, without changing the number of weights.
+ ///
+ /// `new_weights` must be sorted by the index.
+ ///
+ /// Using this method instead of `new` might be more efficient if only a small number of
+ /// weights is modified. No allocations are performed, unless the weight type `X` uses
+ /// allocation internally.
+ ///
+ /// In case of error, `self` is not modified.
+ pub fn update_weights(&mut self, new_weights: &[(usize, &X)]) -> Result<(), WeightedError>
+ where X: for<'a> ::core::ops::AddAssign<&'a X> +
+ for<'a> ::core::ops::SubAssign<&'a X> +
+ Clone +
+ Default {
+ if new_weights.is_empty() {
+ return Ok(());
+ }
+
+ let zero = <X as Default>::default();
+
+ let mut total_weight = self.total_weight.clone();
+
+ // Check for errors first, so we don't modify `self` in case something
+ // goes wrong.
+ let mut prev_i = None;
+ for &(i, w) in new_weights {
+ if let Some(old_i) = prev_i {
+ if old_i >= i {
+ return Err(WeightedError::InvalidWeight);
+ }
+ }
+ if *w < zero {
+ return Err(WeightedError::InvalidWeight);
+ }
+ if i >= self.cumulative_weights.len() + 1 {
+ return Err(WeightedError::TooMany);
+ }
+
+ let mut old_w = if i < self.cumulative_weights.len() {
+ self.cumulative_weights[i].clone()
+ } else {
+ self.total_weight.clone()
+ };
+ if i > 0 {
+ old_w -= &self.cumulative_weights[i - 1];
+ }
+
+ total_weight -= &old_w;
+ total_weight += w;
+ prev_i = Some(i);
+ }
+ if total_weight == zero {
+ return Err(WeightedError::AllWeightsZero);
+ }
+
+ // Update the weights. Because we checked all the preconditions in the
+ // previous loop, this should never panic.
+ let mut iter = new_weights.iter();
+
+ let mut prev_weight = zero.clone();
+ let mut next_new_weight = iter.next();
+ let &(first_new_index, _) = next_new_weight.unwrap();
+ let mut cumulative_weight = if first_new_index > 0 {
+ self.cumulative_weights[first_new_index - 1].clone()
+ } else {
+ zero.clone()
+ };
+ for i in first_new_index..self.cumulative_weights.len() {
+ match next_new_weight {
+ Some(&(j, w)) if i == j => {
+ cumulative_weight += w;
+ next_new_weight = iter.next();
+ },
+ _ => {
+ let mut tmp = self.cumulative_weights[i].clone();
+ tmp -= &prev_weight; // We know this is positive.
+ cumulative_weight += &tmp;
+ }
+ }
+ prev_weight = cumulative_weight.clone();
+ core::mem::swap(&mut prev_weight, &mut self.cumulative_weights[i]);
+ }
+
+ self.total_weight = total_weight;
+ self.weight_distribution = X::Sampler::new(zero, self.total_weight.clone());
+
+ Ok(())
}
}
@@ -201,6 +291,31 @@
assert_eq!(WeightedIndex::new(&[-10, 20, 1, 30]).unwrap_err(), WeightedError::InvalidWeight);
assert_eq!(WeightedIndex::new(&[-10]).unwrap_err(), WeightedError::InvalidWeight);
}
+
+ #[test]
+ fn test_update_weights() {
+ let data = [
+ (&[10u32, 2, 3, 4][..],
+ &[(1, &100), (2, &4)][..], // positive change
+ &[10, 100, 4, 4][..]),
+ (&[1u32, 2, 3, 0, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7][..],
+ &[(2, &1), (5, &1), (13, &100)][..], // negative change and last element
+ &[1u32, 2, 1, 0, 5, 1, 7, 1, 2, 3, 4, 5, 6, 100][..]),
+ ];
+
+ for (weights, update, expected_weights) in data.into_iter() {
+ let total_weight = weights.iter().sum::<u32>();
+ let mut distr = WeightedIndex::new(weights.to_vec()).unwrap();
+ assert_eq!(distr.total_weight, total_weight);
+
+ distr.update_weights(update).unwrap();
+ let expected_total_weight = expected_weights.iter().sum::<u32>();
+ let expected_distr = WeightedIndex::new(expected_weights.to_vec()).unwrap();
+ assert_eq!(distr.total_weight, expected_total_weight);
+ assert_eq!(distr.total_weight, expected_distr.total_weight);
+ assert_eq!(distr.cumulative_weights, expected_distr.cumulative_weights);
+ }
+ }
}
/// Error type returned from `WeightedIndex::new`.
diff --git a/src/lib.rs b/src/lib.rs
index 5d8fa23..53b043c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -50,7 +50,6 @@
#![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_attr(all(feature="simd_support", feature="nightly"), feature(stdsimd))]
#![allow(clippy::excessive_precision, clippy::unreadable_literal, clippy::float_cmp)]
@@ -58,9 +57,6 @@
#[cfg(all(feature="alloc", not(feature="std")))]
extern crate alloc;
-#[cfg(feature = "getrandom")]
-use getrandom_package as getrandom;
-
#[allow(unused)]
macro_rules! trace { ($($x:tt)*) => (
#[cfg(feature = "log")] {
@@ -438,7 +434,7 @@
}
}
}
-
+
impl AsByteSliceMut for [Wrapping<$t>] {
fn as_byte_slice_mut(&mut self) -> &mut [u8] {
if self.len() == 0 {
@@ -602,7 +598,7 @@
rng.fill(&mut array[..]);
assert_eq!(array, [x as u32, (x >> 32) as u32]);
assert_eq!(rng.next_u32(), x as u32);
-
+
// Check equivalence using wrapped arrays
let mut warray = [Wrapping(0u32); 2];
rng.fill(&mut warray[..]);
diff --git a/src/rngs/mod.rs b/src/rngs/mod.rs
index f9cfe80..abf3243 100644
--- a/src/rngs/mod.rs
+++ b/src/rngs/mod.rs
@@ -116,5 +116,4 @@
pub use self::std::StdRng;
#[cfg(feature="std")] pub use self::thread::ThreadRng;
-#[cfg(feature="getrandom")] mod os;
-#[cfg(feature="getrandom")] pub use self::os::OsRng;
+#[cfg(feature="getrandom")] pub use rand_core::OsRng;
diff --git a/src/rngs/std.rs b/src/rngs/std.rs
index 22e08ae..8ebe6b8 100644
--- a/src/rngs/std.rs
+++ b/src/rngs/std.rs
@@ -10,8 +10,11 @@
use crate::{RngCore, CryptoRng, Error, SeedableRng};
-#[cfg(target_os = "emscripten")] pub(crate) use rand_hc::Hc128Core as Core;
-#[cfg(not(target_os = "emscripten"))] pub(crate) use rand_chacha::ChaCha20Core as Core;
+#[cfg(all(any(test, feature = "std"), target_os = "emscripten"))]
+pub(crate) use rand_hc::Hc128Core as Core;
+#[cfg(all(any(test, feature = "std"), not(target_os = "emscripten")))]
+pub(crate) use rand_chacha::ChaCha20Core as Core;
+
#[cfg(target_os = "emscripten")] use rand_hc::Hc128Rng as Rng;
#[cfg(not(target_os = "emscripten"))] use rand_chacha::ChaCha20Rng as Rng;
diff --git a/utils/ci/script.sh b/utils/ci/script.sh
index 852a850..bd011d5 100644
--- a/utils/ci/script.sh
+++ b/utils/ci/script.sh
@@ -2,23 +2,56 @@
set -ex
+# ----- Options -----
+
+# TARGET enables cross-building
+if [ -z $TARGET ]; then
+ CARGO=cargo
+else
+ CARGO=cross
+ TARGET="--target $TARGET"
+fi
+
+# ALLOC defaults on; is disabled for rustc < 1.36
+if [ -z $ALLOC ]; then
+ ALLOC=1
+fi
+
+# NIGHTLY defaults off
+
+
+# ----- Script -----
+
main() {
- cross test --target $TARGET --tests --no-default-features
- # TODO: add simd_support feature:
- cross test --target $TARGET --features=log
- cross test --target $TARGET --examples
- cross test --target $TARGET --manifest-path rand_core/Cargo.toml
- cross test --target $TARGET --manifest-path rand_core/Cargo.toml --features=serde1
- cross test --target $TARGET --manifest-path rand_core/Cargo.toml --no-default-features
- cross test --target $TARGET --manifest-path rand_distr/Cargo.toml
- cross test --target $TARGET --manifest-path rand_isaac/Cargo.toml --features=serde1
- cross test --target $TARGET --manifest-path rand_pcg/Cargo.toml --features=serde1
- cross test --target $TARGET --manifest-path rand_xorshift/Cargo.toml --features=serde1
- cross test --target $TARGET --manifest-path rand_xoshiro/Cargo.toml --features=serde1
- cross test --target $TARGET --manifest-path rand_chacha/Cargo.toml
- cross test --target $TARGET --manifest-path rand_hc/Cargo.toml
- cross test --target $TARGET --manifest-path rand_os/Cargo.toml
- cross test --target $TARGET --manifest-path rand_jitter/Cargo.toml
+ if [ "0$NIGHTLY" -ge 1 ]; then
+ $CARGO test $TARGET --all-features
+ $CARGO test $TARGET --benches --features=nightly
+ else
+ # all stable features:
+ $CARGO test $TARGET --features=serde1,log,small_rng
+ fi
+
+ if [ "$ALLOC" -ge 1 ]; then
+ $CARGO test $TARGET --tests --no-default-features --features=alloc,getrandom,small_rng
+ $CARGO test $TARGET --manifest-path rand_core/Cargo.toml --no-default-features --features=alloc
+ fi
+
+ $CARGO test $TARGET --tests --no-default-features
+ $CARGO test $TARGET --examples
+
+ $CARGO test $TARGET --manifest-path rand_core/Cargo.toml
+ $CARGO test $TARGET --manifest-path rand_core/Cargo.toml --no-default-features
+ $CARGO test $TARGET --manifest-path rand_core/Cargo.toml --no-default-features --features=getrandom
+
+ $CARGO test $TARGET --manifest-path rand_distr/Cargo.toml
+ $CARGO test $TARGET --manifest-path rand_isaac/Cargo.toml --features=serde1
+ $CARGO test $TARGET --manifest-path rand_pcg/Cargo.toml --features=serde1
+ $CARGO test $TARGET --manifest-path rand_xorshift/Cargo.toml --features=serde1
+ $CARGO test $TARGET --manifest-path rand_xoshiro/Cargo.toml
+ $CARGO test $TARGET --manifest-path rand_chacha/Cargo.toml
+ $CARGO test $TARGET --manifest-path rand_hc/Cargo.toml
+ $CARGO test $TARGET --manifest-path rand_jitter/Cargo.toml
+ $CARGO test $TARGET --manifest-path rand_os/Cargo.toml
}
# we don't run the "test phase" when doing deploys