Skip to content

Commit cf78054

Browse files
author
Jethro Beekman
committed
Add RDRAND feature
1 parent 2c97416 commit cf78054

File tree

3 files changed

+60
-19
lines changed

3 files changed

+60
-19
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ core_io = { version = "0.0", optional = true }
2020
[features]
2121
default = ["libc"]
2222
no_std = ["core_io"]
23+
rdrand = []
2324

2425
[dev-dependencies]
2526
log = "0.3.0"

src/lib.rs

+23-14
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@
243243

244244
#![cfg_attr(feature="no_std",no_std)]
245245
#![cfg_attr(feature="no_std",feature(alloc,collections))]
246+
#![cfg_attr(feature="rdrand",feature(asm))]
246247

247248
#[cfg(test)] #[macro_use] extern crate log;
248249

@@ -251,16 +252,16 @@
251252
#[cfg(feature="no_std")] extern crate alloc;
252253
#[cfg(feature="no_std")] extern crate collections;
253254

254-
#[cfg(not(feature="no_std"))] use core::cell::RefCell;
255+
#[cfg(all(not(feature="no_std"),not(feature="rdrand")))] use core::cell::RefCell;
255256
use core::marker;
256257
use core::mem;
257258
#[cfg(not(feature="no_std"))] use std::io;
258-
#[cfg(not(feature="no_std"))] use std::rc::Rc;
259+
#[cfg(all(not(feature="no_std"),not(feature="rdrand")))] use std::rc::Rc;
259260
use core::num::Wrapping as w;
260261
#[cfg(feature="no_std")] use alloc::boxed::Box;
261262
#[cfg(feature="no_std")] use collections::vec::Vec;
262263

263-
#[cfg(not(feature="no_std"))] pub use os::OsRng;
264+
#[cfg(any(not(feature="no_std"),feature="rdrand"))] pub use os::OsRng;
264265

265266
pub use isaac::{IsaacRng, Isaac64Rng};
266267
pub use chacha::ChaChaRng;
@@ -278,7 +279,7 @@ pub mod isaac;
278279
pub mod chacha;
279280
pub mod reseeding;
280281
mod rand_impls;
281-
#[cfg(not(feature="no_std"))] pub mod os;
282+
#[cfg(any(not(feature="no_std"),feature="rdrand"))] pub mod os;
282283
pub mod read;
283284

284285
#[allow(bad_style)]
@@ -814,7 +815,7 @@ impl StdRng {
814815
///
815816
/// Reading the randomness from the OS may fail, and any error is
816817
/// propagated via the `io::Result` return value.
817-
#[cfg(not(feature="no_std"))]
818+
#[cfg(any(not(feature="no_std"),feature="rdrand"))]
818819
pub fn new() -> io::Result<StdRng> {
819820
OsRng::new().map(|mut r| StdRng { rng: r.gen() })
820821
}
@@ -853,7 +854,7 @@ impl<'a> SeedableRng<&'a [usize]> for StdRng {
853854
///
854855
/// This will read randomness from the operating system to seed the
855856
/// generator.
856-
#[cfg(not(feature="no_std"))]
857+
#[cfg(any(not(feature="no_std"),feature="rdrand"))]
857858
pub fn weak_rng() -> XorShiftRng {
858859
match OsRng::new() {
859860
Ok(mut r) => r.gen(),
@@ -862,10 +863,10 @@ pub fn weak_rng() -> XorShiftRng {
862863
}
863864

864865
/// Controls how the thread-local RNG is reseeded.
865-
#[cfg(not(feature="no_std"))]
866+
#[cfg(all(not(feature="no_std"),not(feature="rdrand")))]
866867
struct ThreadRngReseeder;
867868

868-
#[cfg(not(feature="no_std"))]
869+
#[cfg(all(not(feature="no_std"),not(feature="rdrand")))]
869870
impl reseeding::Reseeder<StdRng> for ThreadRngReseeder {
870871
fn reseed(&mut self, rng: &mut StdRng) {
871872
*rng = match StdRng::new() {
@@ -874,14 +875,14 @@ impl reseeding::Reseeder<StdRng> for ThreadRngReseeder {
874875
}
875876
}
876877
}
877-
#[cfg(not(feature="no_std"))]
878+
#[cfg(all(not(feature="no_std"),not(feature="rdrand")))]
878879
const THREAD_RNG_RESEED_THRESHOLD: u64 = 32_768;
879-
#[cfg(not(feature="no_std"))]
880+
#[cfg(all(not(feature="no_std"),not(feature="rdrand")))]
880881
type ThreadRngInner = reseeding::ReseedingRng<StdRng, ThreadRngReseeder>;
881882

882883
/// The thread-local RNG.
884+
#[cfg(all(not(feature="no_std"),not(feature="rdrand")))]
883885
#[derive(Clone)]
884-
#[cfg(not(feature="no_std"))]
885886
pub struct ThreadRng {
886887
rng: Rc<RefCell<ThreadRngInner>>,
887888
}
@@ -897,7 +898,7 @@ pub struct ThreadRng {
897898
/// if the operating system random number generator is rigged to give
898899
/// the same sequence always. If absolute consistency is required,
899900
/// explicitly select an RNG, e.g. `IsaacRng` or `Isaac64Rng`.
900-
#[cfg(not(feature="no_std"))]
901+
#[cfg(all(not(feature="no_std"),not(feature="rdrand")))]
901902
pub fn thread_rng() -> ThreadRng {
902903
// used to make space in TLS for a random number generator
903904
thread_local!(static THREAD_RNG_KEY: Rc<RefCell<ThreadRngInner>> = {
@@ -914,7 +915,7 @@ pub fn thread_rng() -> ThreadRng {
914915
ThreadRng { rng: THREAD_RNG_KEY.with(|t| t.clone()) }
915916
}
916917

917-
#[cfg(not(feature="no_std"))]
918+
#[cfg(all(not(feature="no_std"),not(feature="rdrand")))]
918919
impl Rng for ThreadRng {
919920
fn next_u32(&mut self) -> u32 {
920921
self.rng.borrow_mut().next_u32()
@@ -930,6 +931,14 @@ impl Rng for ThreadRng {
930931
}
931932
}
932933

934+
#[cfg(feature="rdrand")]
935+
pub use os::OsRng as ThreadRng;
936+
937+
#[cfg(feature="rdrand")]
938+
pub fn thread_rng() -> ThreadRng {
939+
OsRng::new().unwrap()
940+
}
941+
933942
/// Generates a random value using the thread-local random number generator.
934943
///
935944
/// `random()` can generate various types of random things, and so may require
@@ -972,7 +981,7 @@ impl Rng for ThreadRng {
972981
/// *x = rng.gen();
973982
/// }
974983
/// ```
975-
#[cfg(not(feature="no_std"))]
984+
#[cfg(any(not(feature="no_std"),feature="rdrand"))]
976985
#[inline]
977986
pub fn random<T: Rand>() -> T {
978987
thread_rng().gen()

src/os.rs

+36-5
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
//! Interfaces to the operating system provided random number
1212
//! generators.
1313
14-
use std::io;
14+
#[cfg(not(feature="no_std"))] use std::io;
15+
#[cfg(feature="no_std")] use io;
1516
use Rng;
1617

1718
/// A random number generator that retrieves randomness straight from
@@ -41,7 +42,7 @@ impl Rng for OsRng {
4142
}
4243

4344
#[cfg(all(unix, not(target_os = "ios"),
44-
not(target_os = "nacl")))]
45+
not(target_os = "nacl"), not(feature = "rdrand")))]
4546
mod imp {
4647
extern crate libc;
4748

@@ -198,7 +199,7 @@ mod imp {
198199
}
199200
}
200201

201-
#[cfg(target_os = "ios")]
202+
#[cfg(all(target_os = "ios", not(feature = "rdrand")))]
202203
mod imp {
203204
extern crate libc;
204205

@@ -248,7 +249,7 @@ mod imp {
248249
}
249250
}
250251

251-
#[cfg(windows)]
252+
#[cfg(all(windows, not(feature = "rdrand")))]
252253
mod imp {
253254
use std::io;
254255
use std::mem;
@@ -339,7 +340,7 @@ mod imp {
339340
}
340341
}
341342

342-
#[cfg(target_os = "nacl")]
343+
#[cfg(all(target_os = "nacl", not(feature = "rdrand")))]
343344
mod imp {
344345
extern crate libc;
345346

@@ -417,6 +418,36 @@ mod imp {
417418
}
418419

419420

421+
#[cfg(feature = "rdrand")]
422+
mod imp {
423+
#[cfg(not(feature="no_std"))] use std::io;
424+
#[cfg(feature="no_std")] use io;
425+
426+
use Rng;
427+
428+
pub struct OsRng;
429+
430+
impl OsRng {
431+
pub fn new() -> io::Result<OsRng> {
432+
Ok(OsRng)
433+
}
434+
}
435+
436+
impl Rng for OsRng {
437+
fn next_u32(&mut self) -> u32 {
438+
let ret;
439+
unsafe{asm!("rdrand $0":"=r"(ret):::"volatile")};
440+
ret
441+
}
442+
#[cfg(target_arch="x86_64")]
443+
fn next_u64(&mut self) -> u64 {
444+
let ret;
445+
unsafe{asm!("rdrand $0":"=r"(ret):::"volatile")};
446+
ret
447+
}
448+
}
449+
}
450+
420451
#[cfg(test)]
421452
mod test {
422453
use std::sync::mpsc::channel;

0 commit comments

Comments
 (0)