diff --git a/benches/distributions.rs b/benches/distributions.rs index fd6b5ae0304..478619c5112 100644 --- a/benches/distributions.rs +++ b/benches/distributions.rs @@ -10,7 +10,8 @@ const RAND_BENCH_N: u64 = 1000; use std::mem::size_of; use test::Bencher; -use rand::{Rng, FromEntropy, XorShiftRng}; +use rand::{Rng, FromEntropy}; +use rand::prng::XorShiftRng; use rand::distributions::*; macro_rules! distr_int { diff --git a/src/deprecated.rs b/src/deprecated.rs new file mode 100644 index 00000000000..aa1a3d89611 --- /dev/null +++ b/src/deprecated.rs @@ -0,0 +1,502 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// https://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Deprecated re-exports (we can't add deprecation warnings otherwise) + +#![allow(deprecated)] + +use {prng, rngs}; +use {RngCore, CryptoRng, SeedableRng, Error}; +use rand_core::block::BlockRngCore; + +#[cfg(feature="std")] +use std::io::Read; + +#[derive(Clone, Debug)] +#[deprecated(since="0.6.0", + note="import with rand::prng::IsaacRng instead, or use the newer Hc128Rng")] +pub struct IsaacRng(prng::IsaacRng); + +impl RngCore for IsaacRng { + #[inline(always)] + fn next_u32(&mut self) -> u32 { + self.0.next_u32() + } + + #[inline(always)] + fn next_u64(&mut self) -> u64 { + self.0.next_u64() + } + + #[inline(always)] + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.0.fill_bytes(dest); + } + + #[inline(always)] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + self.0.try_fill_bytes(dest) + } +} + +impl SeedableRng for IsaacRng { + type Seed = ::Seed; + + fn from_seed(seed: Self::Seed) -> Self { + IsaacRng(prng::IsaacRng::from_seed(seed)) + } + + fn from_rng(rng: R) -> Result { + prng::IsaacRng::from_rng(rng).map(IsaacRng) + } +} + +impl IsaacRng { + pub fn new_from_u64(seed: u64) -> Self { + IsaacRng(prng::IsaacRng::new_from_u64(seed)) + } +} + + +#[derive(Clone, Debug)] +#[deprecated(since="0.6.0", + note="import with rand::prng::Isaac64Rng instead, or use newer Hc128Rng")] +pub struct Isaac64Rng(prng::Isaac64Rng); + +impl RngCore for Isaac64Rng { + #[inline(always)] + fn next_u32(&mut self) -> u32 { + self.0.next_u32() + } + + #[inline(always)] + fn next_u64(&mut self) -> u64 { + self.0.next_u64() + } + + #[inline(always)] + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.0.fill_bytes(dest); + } + + #[inline(always)] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + self.0.try_fill_bytes(dest) + } +} + +impl SeedableRng for Isaac64Rng { + type Seed = ::Seed; + + fn from_seed(seed: Self::Seed) -> Self { + Isaac64Rng(prng::Isaac64Rng::from_seed(seed)) + } + + fn from_rng(rng: R) -> Result { + prng::Isaac64Rng::from_rng(rng).map(Isaac64Rng) + } +} + +impl Isaac64Rng { + pub fn new_from_u64(seed: u64) -> Self { + Isaac64Rng(prng::Isaac64Rng::new_from_u64(seed)) + } +} + + +#[derive(Clone, Debug)] +#[deprecated(since="0.6.0", note="import with rand::prng::ChaChaRng instead")] +pub struct ChaChaRng(prng::ChaChaRng); + +impl RngCore for ChaChaRng { + #[inline(always)] + fn next_u32(&mut self) -> u32 { + self.0.next_u32() + } + + #[inline(always)] + fn next_u64(&mut self) -> u64 { + self.0.next_u64() + } + + #[inline(always)] + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.0.fill_bytes(dest); + } + + #[inline(always)] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + self.0.try_fill_bytes(dest) + } +} + +impl SeedableRng for ChaChaRng { + type Seed = ::Seed; + + fn from_seed(seed: Self::Seed) -> Self { + ChaChaRng(prng::ChaChaRng::from_seed(seed)) + } + + fn from_rng(rng: R) -> Result { + prng::ChaChaRng::from_rng(rng).map(ChaChaRng) + } +} + +impl ChaChaRng { + #[cfg(feature = "i128_support")] + pub fn get_word_pos(&self) -> u128 { + self.0.get_word_pos() + } + + #[cfg(feature = "i128_support")] + pub fn set_word_pos(&mut self, word_offset: u128) { + self.0.set_word_pos(word_offset) + } + + pub fn set_stream(&mut self, stream: u64) { + self.0.set_stream(stream) + } +} + +impl CryptoRng for ChaChaRng {} + + +#[derive(Clone, Debug)] +#[deprecated(since="0.6.0", note="import with rand::prng::XorShiftRng instead")] +pub struct XorShiftRng(prng::XorShiftRng); + +impl RngCore for XorShiftRng { + #[inline(always)] + fn next_u32(&mut self) -> u32 { + self.0.next_u32() + } + + #[inline(always)] + fn next_u64(&mut self) -> u64 { + self.0.next_u64() + } + + #[inline(always)] + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.0.fill_bytes(dest); + } + + #[inline(always)] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + self.0.try_fill_bytes(dest) + } +} + +impl SeedableRng for XorShiftRng { + type Seed = ::Seed; + + fn from_seed(seed: Self::Seed) -> Self { + XorShiftRng(prng::XorShiftRng::from_seed(seed)) + } + + fn from_rng(rng: R) -> Result { + prng::XorShiftRng::from_rng(rng).map(XorShiftRng) + } +} + + +#[derive(Clone, Debug)] +#[deprecated(since="0.6.0", + note="import with rand::prelude::* or rand::rngs::StdRng instead")] +pub struct StdRng(rngs::StdRng); + +impl RngCore for StdRng { + #[inline(always)] + fn next_u32(&mut self) -> u32 { + self.0.next_u32() + } + + #[inline(always)] + fn next_u64(&mut self) -> u64 { + self.0.next_u64() + } + + #[inline(always)] + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.0.fill_bytes(dest); + } + + #[inline(always)] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + self.0.try_fill_bytes(dest) + } +} + +impl SeedableRng for StdRng { + type Seed = ::Seed; + + fn from_seed(seed: Self::Seed) -> Self { + StdRng(rngs::StdRng::from_seed(seed)) + } + + fn from_rng(rng: R) -> Result { + rngs::StdRng::from_rng(rng).map(StdRng) + } +} + +impl CryptoRng for StdRng {} + + +#[cfg(feature="std")] +#[derive(Clone, Debug)] +#[deprecated(since="0.6.0", note="import with rand::rngs::OsRng instead")] +pub struct OsRng(rngs::OsRng); + +#[cfg(feature="std")] +impl RngCore for OsRng { + #[inline(always)] + fn next_u32(&mut self) -> u32 { + self.0.next_u32() + } + + #[inline(always)] + fn next_u64(&mut self) -> u64 { + self.0.next_u64() + } + + #[inline(always)] + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.0.fill_bytes(dest); + } + + #[inline(always)] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + self.0.try_fill_bytes(dest) + } +} + +#[cfg(feature="std")] +impl OsRng { + pub fn new() -> Result { + rngs::OsRng::new().map(OsRng) + } +} + +#[cfg(feature="std")] +impl CryptoRng for OsRng {} + + +#[cfg(feature="std")] +#[derive(Debug)] +#[deprecated(since="0.6.0", note="import with rand::rngs::EntropyRng instead")] +pub struct EntropyRng(rngs::EntropyRng); + +#[cfg(feature="std")] +impl RngCore for EntropyRng { + #[inline(always)] + fn next_u32(&mut self) -> u32 { + self.0.next_u32() + } + + #[inline(always)] + fn next_u64(&mut self) -> u64 { + self.0.next_u64() + } + + #[inline(always)] + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.0.fill_bytes(dest); + } + + #[inline(always)] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + self.0.try_fill_bytes(dest) + } +} + +#[cfg(feature="std")] +impl EntropyRng { + pub fn new() -> Self { + EntropyRng(rngs::EntropyRng::new()) + } +} + +#[cfg(feature="std")] +impl Default for EntropyRng { + fn default() -> Self { + EntropyRng::new() + } +} + +#[cfg(feature="std")] +impl CryptoRng for EntropyRng {} + + +#[derive(Clone, Debug)] +#[deprecated(since="0.6.0", note="import with rand::rngs::JitterRng instead")] +pub struct JitterRng(rngs::JitterRng); + +impl RngCore for JitterRng { + #[inline(always)] + fn next_u32(&mut self) -> u32 { + self.0.next_u32() + } + + #[inline(always)] + fn next_u64(&mut self) -> u64 { + self.0.next_u64() + } + + #[inline(always)] + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.0.fill_bytes(dest); + } + + #[inline(always)] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + self.0.try_fill_bytes(dest) + } +} + +impl JitterRng { + #[cfg(feature="std")] + pub fn new() -> Result { + rngs::JitterRng::new().map(JitterRng) + } + + pub fn new_with_timer(timer: fn() -> u64) -> JitterRng { + JitterRng(rngs::JitterRng::new_with_timer(timer)) + } + + pub fn set_rounds(&mut self, rounds: u8) { + self.0.set_rounds(rounds) + } + + pub fn test_timer(&mut self) -> Result { + self.0.test_timer() + } + + #[cfg(feature="std")] + pub fn timer_stats(&mut self, var_rounds: bool) -> i64 { + self.0.timer_stats(var_rounds) + } +} + +impl CryptoRng for JitterRng {} + + +#[cfg(feature="std")] +#[derive(Clone, Debug)] +#[deprecated(since="0.6.0", + note="import with rand::prelude::* or rand::rngs::ThreadRng instead")] +pub struct ThreadRng(rngs::ThreadRng); + +#[cfg(feature="std")] +impl RngCore for ThreadRng { + #[inline(always)] + fn next_u32(&mut self) -> u32 { + self.0.next_u32() + } + + #[inline(always)] + fn next_u64(&mut self) -> u64 { + self.0.next_u64() + } + + #[inline(always)] + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.0.fill_bytes(dest); + } + + #[inline(always)] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + self.0.try_fill_bytes(dest) + } +} + +#[cfg(feature="std")] +impl CryptoRng for ThreadRng {} + + +#[cfg(feature="std")] +#[derive(Debug)] +#[deprecated(since="0.6.0", note="import with rand::rngs::adapter::ReadRng instead")] +pub struct ReadRng(rngs::adapter::ReadRng); + +#[cfg(feature="std")] +impl RngCore for ReadRng { + #[inline(always)] + fn next_u32(&mut self) -> u32 { + self.0.next_u32() + } + + #[inline(always)] + fn next_u64(&mut self) -> u64 { + self.0.next_u64() + } + + #[inline(always)] + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.0.fill_bytes(dest); + } + + #[inline(always)] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + self.0.try_fill_bytes(dest) + } +} + +#[cfg(feature="std")] +impl ReadRng { + pub fn new(r: R) -> ReadRng { + ReadRng(rngs::adapter::ReadRng::new(r)) + } +} + + +#[derive(Clone, Debug)] +pub struct ReseedingRng(rngs::adapter::ReseedingRng) +where R: BlockRngCore + SeedableRng, + Rsdr: RngCore; + +impl RngCore for ReseedingRng +where R: BlockRngCore + SeedableRng, + ::Results: AsRef<[u32]> + AsMut<[u32]> +{ + #[inline(always)] + fn next_u32(&mut self) -> u32 { + self.0.next_u32() + } + + #[inline(always)] + fn next_u64(&mut self) -> u64 { + self.0.next_u64() + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.0.fill_bytes(dest) + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + self.0.try_fill_bytes(dest) + } +} + +impl ReseedingRng +where R: BlockRngCore + SeedableRng, + Rsdr: RngCore +{ + pub fn new(rng: R, threshold: u64, reseeder: Rsdr) -> Self { + ReseedingRng(rngs::adapter::ReseedingRng::new(rng, threshold, reseeder)) + } + + pub fn reseed(&mut self) -> Result<(), Error> { + self.0.reseed() + } +} + +impl CryptoRng for ReseedingRng +where R: BlockRngCore + SeedableRng + CryptoRng, + Rsdr: RngCore + CryptoRng {} diff --git a/src/lib.rs b/src/lib.rs index 6d6d762b3cb..464ce5c5c24 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -273,28 +273,51 @@ pub mod rngs; //////////////////////////////////////////////////////////////////////////////// // Compatibility re-exports. Documentation is hidden; will be removed eventually. -#[cfg(feature="std")] #[doc(hidden)] pub use rngs::adapter::read; -#[doc(hidden)] pub use rngs::adapter::ReseedingRng; +#[doc(hidden)] mod deprecated; -#[doc(hidden)] pub use rngs::jitter; -#[cfg(feature="std")] #[doc(hidden)] pub use rngs::{os, EntropyRng, OsRng}; +#[allow(deprecated)] +#[doc(hidden)] pub use deprecated::ReseedingRng; -#[doc(hidden)] pub use prng::{ChaChaRng, IsaacRng, Isaac64Rng, XorShiftRng}; -#[doc(hidden)] pub use rngs::StdRng; +#[allow(deprecated)] +#[cfg(feature="std")] #[doc(hidden)] pub use deprecated::{EntropyRng, OsRng}; +#[allow(deprecated)] +#[doc(hidden)] pub use deprecated::{ChaChaRng, IsaacRng, Isaac64Rng, XorShiftRng}; +#[allow(deprecated)] +#[doc(hidden)] pub use deprecated::StdRng; + +#[allow(deprecated)] +#[doc(hidden)] +pub mod jitter { + pub use deprecated::JitterRng; + pub use rngs::TimerError; +} +#[allow(deprecated)] +#[cfg(feature="std")] +#[doc(hidden)] +pub mod os { + pub use deprecated::OsRng; +} +#[allow(deprecated)] #[doc(hidden)] pub mod chacha { - //! The ChaCha random number generator. - pub use prng::ChaChaRng; + pub use deprecated::ChaChaRng; } +#[allow(deprecated)] #[doc(hidden)] pub mod isaac { - //! The ISAAC random number generator. - pub use prng::{IsaacRng, Isaac64Rng}; + pub use deprecated::{IsaacRng, Isaac64Rng}; +} +#[allow(deprecated)] +#[cfg(feature="std")] +#[doc(hidden)] +pub mod read { + pub use deprecated::ReadRng; } -#[cfg(feature="std")] #[doc(hidden)] pub use rngs::ThreadRng; +#[allow(deprecated)] +#[cfg(feature="std")] #[doc(hidden)] pub use deprecated::ThreadRng; //////////////////////////////////////////////////////////////////////////////// @@ -788,7 +811,7 @@ pub trait FromEntropy: SeedableRng { #[cfg(feature="std")] impl FromEntropy for R { fn from_entropy() -> R { - R::from_rng(EntropyRng::new()).unwrap_or_else(|err| + R::from_rng(rngs::EntropyRng::new()).unwrap_or_else(|err| panic!("FromEntropy::from_entropy() failed: {}", err)) } } @@ -846,6 +869,7 @@ pub fn random() -> T where Standard: Distribution { #[cfg(test)] mod test { use rngs::mock::StepRng; + use rngs::StdRng; use super::*; #[cfg(all(not(feature="std"), feature="alloc"))] use alloc::boxed::Box; diff --git a/src/rngs/adapter/read.rs b/src/rngs/adapter/read.rs index de75f978cd3..4f6325c32b6 100644 --- a/src/rngs/adapter/read.rs +++ b/src/rngs/adapter/read.rs @@ -33,10 +33,11 @@ use rand_core::{RngCore, Error, ErrorKind, impls}; /// # Example /// /// ``` -/// use rand::{read, Rng}; +/// use rand::Rng; +/// use rand::rngs::adapter::ReadRng; /// /// let data = vec![1, 2, 3, 4, 5, 6, 7, 8]; -/// let mut rng = read::ReadRng::new(&data[..]); +/// let mut rng = ReadRng::new(&data[..]); /// println!("{:x}", rng.gen::()); /// ``` /// diff --git a/src/rngs/jitter.rs b/src/rngs/jitter.rs index a31a1df67e3..6aa30294ffd 100644 --- a/src/rngs/jitter.rs +++ b/src/rngs/jitter.rs @@ -66,7 +66,7 @@ const MEMORY_SIZE: usize = MEMORY_BLOCKS * MEMORY_BLOCKSIZE; /// Use the following code using [`timer_stats`] to collect the data: /// /// ```no_run -/// use rand::jitter::JitterRng; +/// use rand::rngs::JitterRng; /// # /// # use std::error::Error; /// # use std::fs::File; @@ -313,7 +313,7 @@ impl JitterRng { /// /// ``` /// # use rand::{Rng, Error}; - /// use rand::jitter::JitterRng; + /// use rand::rngs::JitterRng; /// /// # fn try_inner() -> Result<(), Error> { /// fn get_nstime() -> u64 { @@ -607,7 +607,6 @@ impl JitterRng { /// of the failure will be returned. /// /// [`TimerError`]: enum.TimerError.html - #[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))] pub fn test_timer(&mut self) -> Result { debug!("JitterRng: testing timer ..."); // We could add a check for system capabilities such as `clock_getres` @@ -744,10 +743,6 @@ impl JitterRng { Ok(log2_lookup[delta_average as usize]) } } - #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] - pub fn test_timer(&mut self) -> Result { - return Err(TimerError::NoTimer); - } /// Statistical test: return the timer delta of one normal run of the /// `JitterRng` entropy collector. @@ -763,14 +758,13 @@ impl JitterRng { /// /// See [Quality testing](struct.JitterRng.html#quality-testing) on how to /// use `timer_stats` to test the quality of `JitterRng`. - #[cfg(feature="std")] pub fn timer_stats(&mut self, var_rounds: bool) -> i64 { let mut mem = [0; MEMORY_SIZE]; - let time = platform::get_nstime(); + let time = (self.timer)(); self.memaccess(&mut mem, var_rounds); self.lfsr_time(time, var_rounds); - let time2 = platform::get_nstime(); + let time2 = (self.timer)(); time2.wrapping_sub(time) as i64 } } @@ -814,7 +808,12 @@ mod platform { #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] pub fn get_nstime() -> u64 { - unreachable!() + // We don't use the timer from the standard library, because it panics + // at runtime. + // + // There is no accurate timer available on Wasm platforms, to help + // prevent fingerprinting or timing side-channel attacks. + 0 // Will make `test_timer` fail with `NoTimer`. } } @@ -864,7 +863,7 @@ impl CryptoRng for JitterRng {} #[cfg(test)] mod test_jitter_init { - use jitter::JitterRng; + use super::JitterRng; #[cfg(feature="std")] #[test] diff --git a/src/rngs/mod.rs b/src/rngs/mod.rs index 3e5c3fa79b9..29546eb1360 100644 --- a/src/rngs/mod.rs +++ b/src/rngs/mod.rs @@ -166,10 +166,10 @@ pub mod adapter; #[cfg(feature="std")] mod entropy; -#[doc(hidden)] pub mod jitter; +mod jitter; pub mod mock; // Public so we don't export `StepRng` directly, making it a bit // more clear it is intended for testing. -#[cfg(feature="std")] #[doc(hidden)] pub mod os; +#[cfg(feature="std")] mod os; mod small; mod std; #[cfg(feature="std")] pub(crate) mod thread; diff --git a/src/rngs/os.rs b/src/rngs/os.rs index 01fdfb0c1f5..dae2e171c5a 100644 --- a/src/rngs/os.rs +++ b/src/rngs/os.rs @@ -1106,7 +1106,7 @@ mod imp { #[cfg(test)] mod test { use RngCore; - use OsRng; + use super::OsRng; #[test] fn test_os_rng() { diff --git a/src/seq.rs b/src/seq.rs index 68f7ab08edc..bf29153f0fc 100644 --- a/src/seq.rs +++ b/src/seq.rs @@ -225,7 +225,8 @@ fn sample_indices_cache( #[cfg(test)] mod test { use super::*; - use {XorShiftRng, Rng, SeedableRng}; + use {Rng, SeedableRng}; + use prng::XorShiftRng; #[cfg(not(feature="std"))] use alloc::Vec;