From 1c815142bfa29107b31d7df971a504af393b81b4 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Fri, 8 Jul 2016 19:48:24 -0700 Subject: [PATCH 1/8] Add ability to compile for core * Add dependency on core_io * Change mentions of std to core * Cfg-out everything that doesn't work in core --- Cargo.toml | 7 ++++++- src/chacha.rs | 2 +- src/distributions/mod.rs | 17 +++++++++-------- src/distributions/range.rs | 6 +++--- src/isaac.rs | 6 +++--- src/lib.rs | 36 ++++++++++++++++++++++++++++-------- src/rand_impls.rs | 4 ++-- src/read.rs | 5 +++-- src/reseeding.rs | 2 +- 9 files changed, 56 insertions(+), 29 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 851b1ca2128..2743137c403 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,12 @@ Random number generators and other randomness functionality. keywords = ["random", "rng"] [dependencies] -libc = "0.2" +libc = { version = "0.2", optional = true } +core_io = { version = "0.0", optional = true } + +[features] +default = ["libc"] +no_std = ["core_io"] [dev-dependencies] log = "0.3.0" diff --git a/src/chacha.rs b/src/chacha.rs index a347ec51f2c..f3870f5ebeb 100644 --- a/src/chacha.rs +++ b/src/chacha.rs @@ -10,7 +10,7 @@ //! The ChaCha random number generator. -use std::num::Wrapping as w; +use core::num::Wrapping as w; use {Rng, SeedableRng, Rand, w32}; const KEY_WORDS : usize = 8; // 8 words for the 256-bit key diff --git a/src/distributions/mod.rs b/src/distributions/mod.rs index 50f9d955bbc..ee0959bd2ae 100644 --- a/src/distributions/mod.rs +++ b/src/distributions/mod.rs @@ -17,19 +17,19 @@ //! internally. The `IndependentSample` trait is for generating values //! that do not need to record state. -use std::marker; +use core::marker; use {Rng, Rand}; pub use self::range::Range; -pub use self::gamma::{Gamma, ChiSquared, FisherF, StudentT}; -pub use self::normal::{Normal, LogNormal}; -pub use self::exponential::Exp; +#[cfg(not(feature="no_std"))] pub use self::gamma::{Gamma, ChiSquared, FisherF, StudentT}; +#[cfg(not(feature="no_std"))] pub use self::normal::{Normal, LogNormal}; +#[cfg(not(feature="no_std"))] pub use self::exponential::Exp; pub mod range; -pub mod gamma; -pub mod normal; -pub mod exponential; +#[cfg(not(feature="no_std"))] pub mod gamma; +#[cfg(not(feature="no_std"))] pub mod normal; +#[cfg(not(feature="no_std"))] pub mod exponential; /// Types that can be used to create a random instance of `Support`. pub trait Sample { @@ -201,7 +201,7 @@ impl<'a, T: Clone> IndependentSample for WeightedChoice<'a, T> { } } -mod ziggurat_tables; +#[cfg(not(feature="no_std"))] mod ziggurat_tables; /// Sample a random number using the Ziggurat method (specifically the /// ZIGNOR variant from Doornik 2005). Most of the arguments are @@ -218,6 +218,7 @@ mod ziggurat_tables; // the perf improvement (25-50%) is definitely worth the extra code // size from force-inlining. +#[cfg(not(feature="no_std"))] #[inline(always)] fn ziggurat( rng: &mut R, diff --git a/src/distributions/range.rs b/src/distributions/range.rs index 3cf47be0207..945c3dd1bda 100644 --- a/src/distributions/range.rs +++ b/src/distributions/range.rs @@ -12,7 +12,7 @@ // this is surprisingly complicated to be both generic & correct -use std::num::Wrapping as w; +use core::num::Wrapping as w; use Rng; use distributions::{Sample, IndependentSample}; @@ -98,7 +98,7 @@ macro_rules! integer_impl { fn construct_range(low: $ty, high: $ty) -> Range<$ty> { let range = (w(high as $unsigned) - w(low as $unsigned)).0; - let unsigned_max: $unsigned = ::std::$unsigned::MAX; + let unsigned_max: $unsigned = ::core::$unsigned::MAX; // this is the largest number that fits into $unsigned // that `range` divides evenly, so, if we've sampled @@ -185,7 +185,7 @@ mod tests { $( let v: &[($ty, $ty)] = &[(0, 10), (10, 127), - (::std::$ty::MIN, ::std::$ty::MAX)]; + (::core::$ty::MIN, ::core::$ty::MAX)]; for &(low, high) in v.iter() { let mut sampler: Range<$ty> = Range::new(low, high); for _ in 0..1000 { diff --git a/src/isaac.rs b/src/isaac.rs index 42de3523fb0..ea8f6c1137b 100644 --- a/src/isaac.rs +++ b/src/isaac.rs @@ -12,9 +12,9 @@ #![allow(non_camel_case_types)] -use std::slice; -use std::iter::repeat; -use std::num::Wrapping as w; +use core::slice; +use core::iter::repeat; +use core::num::Wrapping as w; use {Rng, SeedableRng, Rand, w32, w64}; diff --git a/src/lib.rs b/src/lib.rs index 472e4ece331..36ba9c0cff6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -241,16 +241,26 @@ html_favicon_url = "https://www.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/rand/")] +#![cfg_attr(feature="no_std",no_std)] +#![cfg_attr(feature="no_std",feature(alloc,collections))] + #[cfg(test)] #[macro_use] extern crate log; -use std::cell::RefCell; -use std::marker; -use std::mem; -use std::io; -use std::rc::Rc; -use std::num::Wrapping as w; +#[cfg(not(feature="no_std"))] extern crate core; +#[cfg(feature="no_std")] extern crate core_io as io; +#[cfg(feature="no_std")] extern crate alloc; +#[cfg(feature="no_std")] extern crate collections; + +#[cfg(not(feature="no_std"))] use core::cell::RefCell; +use core::marker; +use core::mem; +#[cfg(not(feature="no_std"))] use std::io; +#[cfg(not(feature="no_std"))] use std::rc::Rc; +use core::num::Wrapping as w; +#[cfg(feature="no_std")] use alloc::boxed::Box; +#[cfg(feature="no_std")] use collections::vec::Vec; -pub use os::OsRng; +#[cfg(not(feature="no_std"))] pub use os::OsRng; pub use isaac::{IsaacRng, Isaac64Rng}; pub use chacha::ChaChaRng; @@ -268,7 +278,7 @@ pub mod isaac; pub mod chacha; pub mod reseeding; mod rand_impls; -pub mod os; +#[cfg(not(feature="no_std"))] pub mod os; pub mod read; #[allow(bad_style)] @@ -810,6 +820,7 @@ impl StdRng { /// /// Reading the randomness from the OS may fail, and any error is /// propagated via the `io::Result` return value. + #[cfg(not(feature="no_std"))] pub fn new() -> io::Result { OsRng::new().map(|mut r| StdRng { rng: r.gen() }) } @@ -848,6 +859,7 @@ impl<'a> SeedableRng<&'a [usize]> for StdRng { /// /// This will read randomness from the operating system to seed the /// generator. +#[cfg(not(feature="no_std"))] pub fn weak_rng() -> XorShiftRng { match OsRng::new() { Ok(mut r) => r.gen(), @@ -856,8 +868,10 @@ pub fn weak_rng() -> XorShiftRng { } /// Controls how the thread-local RNG is reseeded. +#[cfg(not(feature="no_std"))] struct ThreadRngReseeder; +#[cfg(not(feature="no_std"))] impl reseeding::Reseeder for ThreadRngReseeder { fn reseed(&mut self, rng: &mut StdRng) { *rng = match StdRng::new() { @@ -866,11 +880,14 @@ impl reseeding::Reseeder for ThreadRngReseeder { } } } +#[cfg(not(feature="no_std"))] const THREAD_RNG_RESEED_THRESHOLD: u64 = 32_768; +#[cfg(not(feature="no_std"))] type ThreadRngInner = reseeding::ReseedingRng; /// The thread-local RNG. #[derive(Clone)] +#[cfg(not(feature="no_std"))] pub struct ThreadRng { rng: Rc>, } @@ -886,6 +903,7 @@ pub struct ThreadRng { /// if the operating system random number generator is rigged to give /// the same sequence always. If absolute consistency is required, /// explicitly select an RNG, e.g. `IsaacRng` or `Isaac64Rng`. +#[cfg(not(feature="no_std"))] pub fn thread_rng() -> ThreadRng { // used to make space in TLS for a random number generator thread_local!(static THREAD_RNG_KEY: Rc> = { @@ -902,6 +920,7 @@ pub fn thread_rng() -> ThreadRng { ThreadRng { rng: THREAD_RNG_KEY.with(|t| t.clone()) } } +#[cfg(not(feature="no_std"))] impl Rng for ThreadRng { fn next_u32(&mut self) -> u32 { self.rng.borrow_mut().next_u32() @@ -959,6 +978,7 @@ impl Rng for ThreadRng { /// *x = rng.gen(); /// } /// ``` +#[cfg(not(feature="no_std"))] #[inline] pub fn random() -> T { thread_rng().gen() diff --git a/src/rand_impls.rs b/src/rand_impls.rs index 5a7e3de0b03..0d501a62f11 100644 --- a/src/rand_impls.rs +++ b/src/rand_impls.rs @@ -10,8 +10,8 @@ //! The implementations of `Rand` for the built-in types. -use std::char; -use std::mem; +use core::char; +use core::mem; use {Rand,Rng}; diff --git a/src/read.rs b/src/read.rs index 9e420bcde4e..c884825decd 100644 --- a/src/read.rs +++ b/src/read.rs @@ -10,8 +10,9 @@ //! A wrapper around any Read to treat it as an RNG. -use std::io::{self, Read}; -use std::mem; +#[cfg(not(feature="no_std"))] use std::io::{self, Read}; +#[cfg(feature="no_std")] use io::{self, Read}; +use core::mem; use Rng; /// An RNG that reads random bytes straight from a `Read`. This will diff --git a/src/reseeding.rs b/src/reseeding.rs index 39e464d7f8b..6585516fcdb 100644 --- a/src/reseeding.rs +++ b/src/reseeding.rs @@ -11,7 +11,7 @@ //! A wrapper around another RNG that reseeds it after it //! generates a certain number of random bytes. -use std::default::Default; +use core::default::Default; use {Rng, SeedableRng}; From 4601525792e347b648fcc21bf0b45b67e9efd3c0 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Fri, 8 Jul 2016 20:20:15 -0700 Subject: [PATCH 2/8] Fix build for Rust versions before core was stable --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 36ba9c0cff6..f5bf568d4ed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -246,7 +246,7 @@ #[cfg(test)] #[macro_use] extern crate log; -#[cfg(not(feature="no_std"))] extern crate core; +#[cfg(not(feature="no_std"))] extern crate std as core; #[cfg(feature="no_std")] extern crate core_io as io; #[cfg(feature="no_std")] extern crate alloc; #[cfg(feature="no_std")] extern crate collections; From 3bad2cb290226bcd11d8aa34f24f8741ab7491e5 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Sat, 9 Jul 2016 13:18:06 -0700 Subject: [PATCH 3/8] Add more features to support stable --- Cargo.toml | 6 ++++-- src/lib.rs | 17 ++++++++++------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2743137c403..f7759c0b9ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,11 +15,13 @@ keywords = ["random", "rng"] [dependencies] libc = { version = "0.2", optional = true } -core_io = { version = "0.0", optional = true } +core_io = { version = "0.0", optional = true } # enable use of read module on no_std [features] default = ["libc"] -no_std = ["core_io"] +no_std = [] +box = [] # enable use of Box on no_std, requires alloc crate and feature +vec = [] # enable use of Vec on no_std, requires collections crate and feature [dev-dependencies] log = "0.3.0" diff --git a/src/lib.rs b/src/lib.rs index f5bf568d4ed..21d89dddd2f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -242,14 +242,15 @@ html_root_url = "https://doc.rust-lang.org/rand/")] #![cfg_attr(feature="no_std",no_std)] -#![cfg_attr(feature="no_std",feature(alloc,collections))] +#![cfg_attr(feature="box",feature(alloc))] +#![cfg_attr(feature="vec",feature(collections))] #[cfg(test)] #[macro_use] extern crate log; #[cfg(not(feature="no_std"))] extern crate std as core; -#[cfg(feature="no_std")] extern crate core_io as io; -#[cfg(feature="no_std")] extern crate alloc; -#[cfg(feature="no_std")] extern crate collections; +#[cfg(feature="core_io")] extern crate core_io as io; +#[cfg(feature="box")] extern crate alloc; +#[cfg(feature="vec")] extern crate collections; #[cfg(not(feature="no_std"))] use core::cell::RefCell; use core::marker; @@ -257,8 +258,8 @@ use core::mem; #[cfg(not(feature="no_std"))] use std::io; #[cfg(not(feature="no_std"))] use std::rc::Rc; use core::num::Wrapping as w; -#[cfg(feature="no_std")] use alloc::boxed::Box; -#[cfg(feature="no_std")] use collections::vec::Vec; +#[cfg(feature="box")] use alloc::boxed::Box; +#[cfg(feature="vec")] use collections::vec::Vec; #[cfg(not(feature="no_std"))] pub use os::OsRng; @@ -279,7 +280,7 @@ pub mod chacha; pub mod reseeding; mod rand_impls; #[cfg(not(feature="no_std"))] pub mod os; -pub mod read; +#[cfg(any(not(feature="no_std"),feature="core_io"))] pub mod read; #[allow(bad_style)] type w64 = w; @@ -586,6 +587,7 @@ impl<'a, R: ?Sized> Rng for &'a mut R where R: Rng { } } +#[cfg(any(feature="box",not(feature="no_std")))] impl Rng for Box where R: Rng { fn next_u32(&mut self) -> u32 { (**self).next_u32() @@ -995,6 +997,7 @@ pub fn random() -> T { /// let sample = sample(&mut rng, 1..100, 5); /// println!("{:?}", sample); /// ``` +#[cfg(any(feature="vec",not(feature="no_std")))] pub fn sample(rng: &mut R, iterable: I, amount: usize) -> Vec where I: IntoIterator, R: Rng, From 6896e258a0ff1da0eb561842a0c32371bd181fd6 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Sun, 10 Jul 2016 12:01:18 -0700 Subject: [PATCH 4/8] Switch from no_std feature to default-on std feature --- Cargo.toml | 10 ++++---- src/distributions/mod.rs | 16 ++++++------ src/lib.rs | 54 ++++++++++++++++++++-------------------- src/read.rs | 4 +-- 4 files changed, 42 insertions(+), 42 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f7759c0b9ad..7ae193cd6d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,13 +15,13 @@ keywords = ["random", "rng"] [dependencies] libc = { version = "0.2", optional = true } -core_io = { version = "0.0", optional = true } # enable use of read module on no_std +core_io = { version = "0.0", optional = true } # enable use of read module on not(std) [features] -default = ["libc"] -no_std = [] -box = [] # enable use of Box on no_std, requires alloc crate and feature -vec = [] # enable use of Vec on no_std, requires collections crate and feature +default = ["std"] +std = ["libc"] +box = [] # enable use of Box on not(std), requires alloc crate and feature +vec = [] # enable use of Vec on not(std), requires collections crate and feature [dev-dependencies] log = "0.3.0" diff --git a/src/distributions/mod.rs b/src/distributions/mod.rs index ee0959bd2ae..c70a24c6e41 100644 --- a/src/distributions/mod.rs +++ b/src/distributions/mod.rs @@ -22,14 +22,14 @@ use core::marker; use {Rng, Rand}; pub use self::range::Range; -#[cfg(not(feature="no_std"))] pub use self::gamma::{Gamma, ChiSquared, FisherF, StudentT}; -#[cfg(not(feature="no_std"))] pub use self::normal::{Normal, LogNormal}; -#[cfg(not(feature="no_std"))] pub use self::exponential::Exp; +#[cfg(feature="std")] pub use self::gamma::{Gamma, ChiSquared, FisherF, StudentT}; +#[cfg(feature="std")] pub use self::normal::{Normal, LogNormal}; +#[cfg(feature="std")] pub use self::exponential::Exp; pub mod range; -#[cfg(not(feature="no_std"))] pub mod gamma; -#[cfg(not(feature="no_std"))] pub mod normal; -#[cfg(not(feature="no_std"))] pub mod exponential; +#[cfg(feature="std")] pub mod gamma; +#[cfg(feature="std")] pub mod normal; +#[cfg(feature="std")] pub mod exponential; /// Types that can be used to create a random instance of `Support`. pub trait Sample { @@ -201,7 +201,7 @@ impl<'a, T: Clone> IndependentSample for WeightedChoice<'a, T> { } } -#[cfg(not(feature="no_std"))] mod ziggurat_tables; +#[cfg(feature="std")] mod ziggurat_tables; /// Sample a random number using the Ziggurat method (specifically the /// ZIGNOR variant from Doornik 2005). Most of the arguments are @@ -218,7 +218,7 @@ impl<'a, T: Clone> IndependentSample for WeightedChoice<'a, T> { // the perf improvement (25-50%) is definitely worth the extra code // size from force-inlining. -#[cfg(not(feature="no_std"))] +#[cfg(feature="std")] #[inline(always)] fn ziggurat( rng: &mut R, diff --git a/src/lib.rs b/src/lib.rs index 21d89dddd2f..56e68c32538 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -241,27 +241,27 @@ html_favicon_url = "https://www.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/rand/")] -#![cfg_attr(feature="no_std",no_std)] -#![cfg_attr(feature="box",feature(alloc))] -#![cfg_attr(feature="vec",feature(collections))] +#![cfg_attr(not(feature="std"),no_std)] +#![cfg_attr(all(feature="box",not(feature="std")),feature(alloc))] +#![cfg_attr(all(feature="vec",not(feature="std")),feature(collections))] #[cfg(test)] #[macro_use] extern crate log; -#[cfg(not(feature="no_std"))] extern crate std as core; -#[cfg(feature="core_io")] extern crate core_io as io; -#[cfg(feature="box")] extern crate alloc; -#[cfg(feature="vec")] extern crate collections; +#[cfg(feature="std")] extern crate std as core; +#[cfg(all(feature="core_io",not(feature="std")))] extern crate core_io as io; +#[cfg(all(feature="box",not(feature="std")))] extern crate alloc; +#[cfg(all(feature="vec",not(feature="std")))] extern crate collections; -#[cfg(not(feature="no_std"))] use core::cell::RefCell; +#[cfg(feature="std")] use core::cell::RefCell; use core::marker; use core::mem; -#[cfg(not(feature="no_std"))] use std::io; -#[cfg(not(feature="no_std"))] use std::rc::Rc; +#[cfg(feature="std")] use std::io; +#[cfg(feature="std")] use std::rc::Rc; use core::num::Wrapping as w; -#[cfg(feature="box")] use alloc::boxed::Box; -#[cfg(feature="vec")] use collections::vec::Vec; +#[cfg(all(feature="box",not(feature="std")))] use alloc::boxed::Box; +#[cfg(all(feature="vec",not(feature="std")))] use collections::vec::Vec; -#[cfg(not(feature="no_std"))] pub use os::OsRng; +#[cfg(feature="std")] pub use os::OsRng; pub use isaac::{IsaacRng, Isaac64Rng}; pub use chacha::ChaChaRng; @@ -279,8 +279,8 @@ pub mod isaac; pub mod chacha; pub mod reseeding; mod rand_impls; -#[cfg(not(feature="no_std"))] pub mod os; -#[cfg(any(not(feature="no_std"),feature="core_io"))] pub mod read; +#[cfg(feature="std")] pub mod os; +#[cfg(any(feature="std",feature="core_io"))] pub mod read; #[allow(bad_style)] type w64 = w; @@ -587,7 +587,7 @@ impl<'a, R: ?Sized> Rng for &'a mut R where R: Rng { } } -#[cfg(any(feature="box",not(feature="no_std")))] +#[cfg(any(feature="box",feature="std"))] impl Rng for Box where R: Rng { fn next_u32(&mut self) -> u32 { (**self).next_u32() @@ -822,7 +822,7 @@ impl StdRng { /// /// Reading the randomness from the OS may fail, and any error is /// propagated via the `io::Result` return value. - #[cfg(not(feature="no_std"))] + #[cfg(feature="std")] pub fn new() -> io::Result { OsRng::new().map(|mut r| StdRng { rng: r.gen() }) } @@ -861,7 +861,7 @@ impl<'a> SeedableRng<&'a [usize]> for StdRng { /// /// This will read randomness from the operating system to seed the /// generator. -#[cfg(not(feature="no_std"))] +#[cfg(feature="std")] pub fn weak_rng() -> XorShiftRng { match OsRng::new() { Ok(mut r) => r.gen(), @@ -870,10 +870,10 @@ pub fn weak_rng() -> XorShiftRng { } /// Controls how the thread-local RNG is reseeded. -#[cfg(not(feature="no_std"))] +#[cfg(feature="std")] struct ThreadRngReseeder; -#[cfg(not(feature="no_std"))] +#[cfg(feature="std")] impl reseeding::Reseeder for ThreadRngReseeder { fn reseed(&mut self, rng: &mut StdRng) { *rng = match StdRng::new() { @@ -882,14 +882,14 @@ impl reseeding::Reseeder for ThreadRngReseeder { } } } -#[cfg(not(feature="no_std"))] +#[cfg(feature="std")] const THREAD_RNG_RESEED_THRESHOLD: u64 = 32_768; -#[cfg(not(feature="no_std"))] +#[cfg(feature="std")] type ThreadRngInner = reseeding::ReseedingRng; /// The thread-local RNG. #[derive(Clone)] -#[cfg(not(feature="no_std"))] +#[cfg(feature="std")] pub struct ThreadRng { rng: Rc>, } @@ -905,7 +905,7 @@ pub struct ThreadRng { /// if the operating system random number generator is rigged to give /// the same sequence always. If absolute consistency is required, /// explicitly select an RNG, e.g. `IsaacRng` or `Isaac64Rng`. -#[cfg(not(feature="no_std"))] +#[cfg(feature="std")] pub fn thread_rng() -> ThreadRng { // used to make space in TLS for a random number generator thread_local!(static THREAD_RNG_KEY: Rc> = { @@ -922,7 +922,7 @@ pub fn thread_rng() -> ThreadRng { ThreadRng { rng: THREAD_RNG_KEY.with(|t| t.clone()) } } -#[cfg(not(feature="no_std"))] +#[cfg(feature="std")] impl Rng for ThreadRng { fn next_u32(&mut self) -> u32 { self.rng.borrow_mut().next_u32() @@ -980,7 +980,7 @@ impl Rng for ThreadRng { /// *x = rng.gen(); /// } /// ``` -#[cfg(not(feature="no_std"))] +#[cfg(feature="std")] #[inline] pub fn random() -> T { thread_rng().gen() @@ -997,7 +997,7 @@ pub fn random() -> T { /// let sample = sample(&mut rng, 1..100, 5); /// println!("{:?}", sample); /// ``` -#[cfg(any(feature="vec",not(feature="no_std")))] +#[cfg(any(feature="vec",feature="std"))] pub fn sample(rng: &mut R, iterable: I, amount: usize) -> Vec where I: IntoIterator, R: Rng, diff --git a/src/read.rs b/src/read.rs index c884825decd..ad78fab6fe7 100644 --- a/src/read.rs +++ b/src/read.rs @@ -10,8 +10,8 @@ //! A wrapper around any Read to treat it as an RNG. -#[cfg(not(feature="no_std"))] use std::io::{self, Read}; -#[cfg(feature="no_std")] use io::{self, Read}; +#[cfg(not(feature="std"))] use io::{self, Read}; +#[cfg(feature="std")] use std::io::{self, Read}; use core::mem; use Rng; From 2c7ba02457a52b609a8bc313ce771eefedb03ea8 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Wed, 2 Nov 2016 17:20:00 -0700 Subject: [PATCH 5/8] Bump core_io version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 7ae193cd6d0..f20328e164f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ keywords = ["random", "rng"] [dependencies] libc = { version = "0.2", optional = true } -core_io = { version = "0.0", optional = true } # enable use of read module on not(std) +core_io = { version = "0.1", optional = true } # enable use of read module on not(std) [features] default = ["std"] From d6239ee4b8cddbe5d71dc802786c7e9d1de09476 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Fri, 8 Jul 2016 20:48:09 -0700 Subject: [PATCH 6/8] Add RDRAND feature --- Cargo.toml | 1 + src/lib.rs | 37 +++++++++++++++++++++++-------------- src/os.rs | 41 ++++++++++++++++++++++++++++++++++++----- 3 files changed, 60 insertions(+), 19 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f20328e164f..be5ac7aedc0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ default = ["std"] std = ["libc"] box = [] # enable use of Box on not(std), requires alloc crate and feature vec = [] # enable use of Vec on not(std), requires collections crate and feature +rdrand = [] [dev-dependencies] log = "0.3.0" diff --git a/src/lib.rs b/src/lib.rs index 56e68c32538..7890c236d53 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -244,6 +244,7 @@ #![cfg_attr(not(feature="std"),no_std)] #![cfg_attr(all(feature="box",not(feature="std")),feature(alloc))] #![cfg_attr(all(feature="vec",not(feature="std")),feature(collections))] +#![cfg_attr(feature="rdrand",feature(asm))] #[cfg(test)] #[macro_use] extern crate log; @@ -252,16 +253,16 @@ #[cfg(all(feature="box",not(feature="std")))] extern crate alloc; #[cfg(all(feature="vec",not(feature="std")))] extern crate collections; -#[cfg(feature="std")] use core::cell::RefCell; +#[cfg(all(feature="std",not(feature="rdrand")))] use core::cell::RefCell; use core::marker; use core::mem; #[cfg(feature="std")] use std::io; -#[cfg(feature="std")] use std::rc::Rc; +#[cfg(all(feature="std",not(feature="rdrand")))] use std::rc::Rc; use core::num::Wrapping as w; #[cfg(all(feature="box",not(feature="std")))] use alloc::boxed::Box; #[cfg(all(feature="vec",not(feature="std")))] use collections::vec::Vec; -#[cfg(feature="std")] pub use os::OsRng; +#[cfg(any(feature="std",feature="rdrand"))] pub use os::OsRng; pub use isaac::{IsaacRng, Isaac64Rng}; pub use chacha::ChaChaRng; @@ -279,7 +280,7 @@ pub mod isaac; pub mod chacha; pub mod reseeding; mod rand_impls; -#[cfg(feature="std")] pub mod os; +#[cfg(any(feature="std",feature="rdrand"))] pub mod os; #[cfg(any(feature="std",feature="core_io"))] pub mod read; #[allow(bad_style)] @@ -822,7 +823,7 @@ impl StdRng { /// /// Reading the randomness from the OS may fail, and any error is /// propagated via the `io::Result` return value. - #[cfg(feature="std")] + #[cfg(any(feature="std",feature="rdrand"))] pub fn new() -> io::Result { OsRng::new().map(|mut r| StdRng { rng: r.gen() }) } @@ -861,7 +862,7 @@ impl<'a> SeedableRng<&'a [usize]> for StdRng { /// /// This will read randomness from the operating system to seed the /// generator. -#[cfg(feature="std")] +#[cfg(any(feature="std",feature="rdrand"))] pub fn weak_rng() -> XorShiftRng { match OsRng::new() { Ok(mut r) => r.gen(), @@ -870,10 +871,10 @@ pub fn weak_rng() -> XorShiftRng { } /// Controls how the thread-local RNG is reseeded. -#[cfg(feature="std")] +#[cfg(all(feature="std",not(feature="rdrand")))] struct ThreadRngReseeder; -#[cfg(feature="std")] +#[cfg(all(feature="std",not(feature="rdrand")))] impl reseeding::Reseeder for ThreadRngReseeder { fn reseed(&mut self, rng: &mut StdRng) { *rng = match StdRng::new() { @@ -882,14 +883,14 @@ impl reseeding::Reseeder for ThreadRngReseeder { } } } -#[cfg(feature="std")] +#[cfg(all(feature="std",not(feature="rdrand")))] const THREAD_RNG_RESEED_THRESHOLD: u64 = 32_768; -#[cfg(feature="std")] +#[cfg(all(feature="std",not(feature="rdrand")))] type ThreadRngInner = reseeding::ReseedingRng; /// The thread-local RNG. +#[cfg(all(feature="std",not(feature="rdrand")))] #[derive(Clone)] -#[cfg(feature="std")] pub struct ThreadRng { rng: Rc>, } @@ -905,7 +906,7 @@ pub struct ThreadRng { /// if the operating system random number generator is rigged to give /// the same sequence always. If absolute consistency is required, /// explicitly select an RNG, e.g. `IsaacRng` or `Isaac64Rng`. -#[cfg(feature="std")] +#[cfg(all(feature="std",not(feature="rdrand")))] pub fn thread_rng() -> ThreadRng { // used to make space in TLS for a random number generator thread_local!(static THREAD_RNG_KEY: Rc> = { @@ -922,7 +923,7 @@ pub fn thread_rng() -> ThreadRng { ThreadRng { rng: THREAD_RNG_KEY.with(|t| t.clone()) } } -#[cfg(feature="std")] +#[cfg(all(feature="std",not(feature="rdrand")))] impl Rng for ThreadRng { fn next_u32(&mut self) -> u32 { self.rng.borrow_mut().next_u32() @@ -938,6 +939,14 @@ impl Rng for ThreadRng { } } +#[cfg(feature="rdrand")] +pub use os::OsRng as ThreadRng; + +#[cfg(feature="rdrand")] +pub fn thread_rng() -> ThreadRng { + OsRng::new().unwrap() +} + /// Generates a random value using the thread-local random number generator. /// /// `random()` can generate various types of random things, and so may require @@ -980,7 +989,7 @@ impl Rng for ThreadRng { /// *x = rng.gen(); /// } /// ``` -#[cfg(feature="std")] +#[cfg(any(feature="std",feature="rdrand"))] #[inline] pub fn random() -> T { thread_rng().gen() diff --git a/src/os.rs b/src/os.rs index fc36012b827..4105b670bef 100644 --- a/src/os.rs +++ b/src/os.rs @@ -11,7 +11,8 @@ //! Interfaces to the operating system provided random number //! generators. -use std::io; +#[cfg(not(feature="std"))] use io; +#[cfg(feature="std")] use std::io; use Rng; /// A random number generator that retrieves randomness straight from @@ -41,7 +42,7 @@ impl Rng for OsRng { } #[cfg(all(unix, not(target_os = "ios"), - not(target_os = "nacl")))] + not(target_os = "nacl"), not(feature = "rdrand")))] mod imp { extern crate libc; @@ -198,7 +199,7 @@ mod imp { } } -#[cfg(target_os = "ios")] +#[cfg(all(target_os = "ios", not(feature = "rdrand")))] mod imp { extern crate libc; @@ -248,7 +249,7 @@ mod imp { } } -#[cfg(windows)] +#[cfg(all(windows, not(feature = "rdrand")))] mod imp { use std::io; use std::mem; @@ -339,7 +340,7 @@ mod imp { } } -#[cfg(target_os = "nacl")] +#[cfg(all(target_os = "nacl", not(feature = "rdrand")))] mod imp { extern crate libc; @@ -417,6 +418,36 @@ mod imp { } +#[cfg(feature = "rdrand")] +mod imp { + #[cfg(not(feature="std"))] use io; + #[cfg(feature="std")] use std::io; + + use Rng; + + pub struct OsRng; + + impl OsRng { + pub fn new() -> io::Result { + Ok(OsRng) + } + } + + impl Rng for OsRng { + fn next_u32(&mut self) -> u32 { + let ret; + unsafe{asm!("rdrand $0":"=r"(ret):::"volatile")}; + ret + } + #[cfg(target_arch="x86_64")] + fn next_u64(&mut self) -> u64 { + let ret; + unsafe{asm!("rdrand $0":"=r"(ret):::"volatile")}; + ret + } + } +} + #[cfg(test)] mod test { use std::sync::mpsc::channel; From 03fc4e0cb047eb095dcbcea02c5fe766d93eb6d1 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Fri, 8 Jul 2016 23:08:50 -0700 Subject: [PATCH 7/8] Check for RDRAND failure --- src/os.rs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/os.rs b/src/os.rs index 4105b670bef..ec19b3661d9 100644 --- a/src/os.rs +++ b/src/os.rs @@ -436,13 +436,31 @@ mod imp { impl Rng for OsRng { fn next_u32(&mut self) -> u32 { let ret; - unsafe{asm!("rdrand $0":"=r"(ret):::"volatile")}; + let mut retry=10; + unsafe{asm!(" +1: + rdrand $0 + jc 2f + dec $1 + jnz 1b +2: + ":"=r"(ret),"=r"(retry):"1"(retry)::"volatile")}; + if retry==0 { panic!("RDRAND failure") } ret } #[cfg(target_arch="x86_64")] fn next_u64(&mut self) -> u64 { let ret; - unsafe{asm!("rdrand $0":"=r"(ret):::"volatile")}; + let mut retry=10; + unsafe{asm!(" +1: + rdrand $0 + jc 2f + dec $1 + jnz 1b +2: + ":"=r"(ret),"=r"(retry):"1"(retry)::"volatile")}; + if retry==0 { panic!("RDRAND failure") } ret } } From b052c17960b8e8ead7af61acc07fbbc2b7458792 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Sat, 9 Jul 2016 13:28:43 -0700 Subject: [PATCH 8/8] Add warning about core_io --- Cargo.toml | 2 +- src/lib.rs | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index be5ac7aedc0..e81de35779c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ default = ["std"] std = ["libc"] box = [] # enable use of Box on not(std), requires alloc crate and feature vec = [] # enable use of Vec on not(std), requires collections crate and feature -rdrand = [] +rdrand = [] # with not(std), requires core_io [dev-dependencies] log = "0.3.0" diff --git a/src/lib.rs b/src/lib.rs index 7890c236d53..3e3d7b4e014 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -253,6 +253,9 @@ #[cfg(all(feature="box",not(feature="std")))] extern crate alloc; #[cfg(all(feature="vec",not(feature="std")))] extern crate collections; +#[cfg(all(not(feature="std"),feature="rdrand",not(feature="core_io")))] +use using::rdrand::feature::without::std::feature::requires::core_io::feature; + #[cfg(all(feature="std",not(feature="rdrand")))] use core::cell::RefCell; use core::marker; use core::mem;