diff --git a/Cargo.toml b/Cargo.toml index 851b1ca2128..f20328e164f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,14 @@ Random number generators and other randomness functionality. keywords = ["random", "rng"] [dependencies] -libc = "0.2" +libc = { version = "0.2", optional = true } +core_io = { version = "0.1", optional = true } # enable use of read module on not(std) + +[features] +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/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..c70a24c6e41 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(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; -pub mod gamma; -pub mod normal; -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> { } } -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,6 +218,7 @@ mod ziggurat_tables; // the perf improvement (25-50%) is definitely worth the extra code // size from force-inlining. +#[cfg(feature="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..56e68c32538 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -241,16 +241,27 @@ html_favicon_url = "https://www.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/rand/")] +#![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; -use std::cell::RefCell; -use std::marker; -use std::mem; -use std::io; -use std::rc::Rc; -use std::num::Wrapping as w; +#[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(feature="std")] use core::cell::RefCell; +use core::marker; +use core::mem; +#[cfg(feature="std")] use std::io; +#[cfg(feature="std")] 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; -pub use os::OsRng; +#[cfg(feature="std")] pub use os::OsRng; pub use isaac::{IsaacRng, Isaac64Rng}; pub use chacha::ChaChaRng; @@ -268,8 +279,8 @@ pub mod isaac; pub mod chacha; pub mod reseeding; mod rand_impls; -pub mod os; -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; @@ -576,6 +587,7 @@ impl<'a, R: ?Sized> Rng for &'a mut R where R: Rng { } } +#[cfg(any(feature="box",feature="std"))] impl Rng for Box where R: Rng { fn next_u32(&mut self) -> u32 { (**self).next_u32() @@ -810,6 +822,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")] pub fn new() -> io::Result { OsRng::new().map(|mut r| StdRng { rng: r.gen() }) } @@ -848,6 +861,7 @@ impl<'a> SeedableRng<&'a [usize]> for StdRng { /// /// This will read randomness from the operating system to seed the /// generator. +#[cfg(feature="std")] pub fn weak_rng() -> XorShiftRng { match OsRng::new() { Ok(mut r) => r.gen(), @@ -856,8 +870,10 @@ pub fn weak_rng() -> XorShiftRng { } /// Controls how the thread-local RNG is reseeded. +#[cfg(feature="std")] struct ThreadRngReseeder; +#[cfg(feature="std")] impl reseeding::Reseeder for ThreadRngReseeder { fn reseed(&mut self, rng: &mut StdRng) { *rng = match StdRng::new() { @@ -866,11 +882,14 @@ impl reseeding::Reseeder for ThreadRngReseeder { } } } +#[cfg(feature="std")] const THREAD_RNG_RESEED_THRESHOLD: u64 = 32_768; +#[cfg(feature="std")] type ThreadRngInner = reseeding::ReseedingRng; /// The thread-local RNG. #[derive(Clone)] +#[cfg(feature="std")] pub struct ThreadRng { rng: Rc>, } @@ -886,6 +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(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> = { @@ -902,6 +922,7 @@ pub fn thread_rng() -> ThreadRng { ThreadRng { rng: THREAD_RNG_KEY.with(|t| t.clone()) } } +#[cfg(feature="std")] impl Rng for ThreadRng { fn next_u32(&mut self) -> u32 { self.rng.borrow_mut().next_u32() @@ -959,6 +980,7 @@ impl Rng for ThreadRng { /// *x = rng.gen(); /// } /// ``` +#[cfg(feature="std")] #[inline] pub fn random() -> T { thread_rng().gen() @@ -975,6 +997,7 @@ pub fn random() -> T { /// let sample = sample(&mut rng, 1..100, 5); /// println!("{:?}", sample); /// ``` +#[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/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..ad78fab6fe7 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="std"))] use io::{self, Read}; +#[cfg(feature="std")] use std::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};