Skip to content

Commit 6ca4943

Browse files
author
Jethro Beekman
committed
Add RDRAND feature
1 parent 76bf777 commit 6ca4943

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
@@ -22,6 +22,7 @@ default = ["libc"]
2222
no_std = []
2323
box = [] # enable use of Box on no_std, requires alloc crate and feature
2424
vec = [] # enable use of Vec on no_std, requires collections crate and feature
25+
rdrand = []
2526

2627
[dev-dependencies]
2728
log = "0.3.0"

src/lib.rs

+23-14
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@
244244
#![cfg_attr(feature="no_std",no_std)]
245245
#![cfg_attr(feature="box",feature(alloc))]
246246
#![cfg_attr(feature="vec",feature(collections))]
247+
#![cfg_attr(feature="rdrand",feature(asm))]
247248

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

@@ -252,16 +253,16 @@
252253
#[cfg(feature="box")] extern crate alloc;
253254
#[cfg(feature="vec")] extern crate collections;
254255

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

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

266267
pub use isaac::{IsaacRng, Isaac64Rng};
267268
pub use chacha::ChaChaRng;
@@ -279,7 +280,7 @@ pub mod isaac;
279280
pub mod chacha;
280281
pub mod reseeding;
281282
mod rand_impls;
282-
#[cfg(not(feature="no_std"))] pub mod os;
283+
#[cfg(any(not(feature="no_std"),feature="rdrand"))] pub mod os;
283284
#[cfg(any(not(feature="no_std"),feature="core_io"))] pub mod read;
284285

285286
#[allow(bad_style)]
@@ -816,7 +817,7 @@ impl StdRng {
816817
///
817818
/// Reading the randomness from the OS may fail, and any error is
818819
/// propagated via the `io::Result` return value.
819-
#[cfg(not(feature="no_std"))]
820+
#[cfg(any(not(feature="no_std"),feature="rdrand"))]
820821
pub fn new() -> io::Result<StdRng> {
821822
OsRng::new().map(|mut r| StdRng { rng: r.gen() })
822823
}
@@ -855,7 +856,7 @@ impl<'a> SeedableRng<&'a [usize]> for StdRng {
855856
///
856857
/// This will read randomness from the operating system to seed the
857858
/// generator.
858-
#[cfg(not(feature="no_std"))]
859+
#[cfg(any(not(feature="no_std"),feature="rdrand"))]
859860
pub fn weak_rng() -> XorShiftRng {
860861
match OsRng::new() {
861862
Ok(mut r) => r.gen(),
@@ -864,10 +865,10 @@ pub fn weak_rng() -> XorShiftRng {
864865
}
865866

866867
/// Controls how the thread-local RNG is reseeded.
867-
#[cfg(not(feature="no_std"))]
868+
#[cfg(all(not(feature="no_std"),not(feature="rdrand")))]
868869
struct ThreadRngReseeder;
869870

870-
#[cfg(not(feature="no_std"))]
871+
#[cfg(all(not(feature="no_std"),not(feature="rdrand")))]
871872
impl reseeding::Reseeder<StdRng> for ThreadRngReseeder {
872873
fn reseed(&mut self, rng: &mut StdRng) {
873874
*rng = match StdRng::new() {
@@ -876,14 +877,14 @@ impl reseeding::Reseeder<StdRng> for ThreadRngReseeder {
876877
}
877878
}
878879
}
879-
#[cfg(not(feature="no_std"))]
880+
#[cfg(all(not(feature="no_std"),not(feature="rdrand")))]
880881
const THREAD_RNG_RESEED_THRESHOLD: u64 = 32_768;
881-
#[cfg(not(feature="no_std"))]
882+
#[cfg(all(not(feature="no_std"),not(feature="rdrand")))]
882883
type ThreadRngInner = reseeding::ReseedingRng<StdRng, ThreadRngReseeder>;
883884

884885
/// The thread-local RNG.
886+
#[cfg(all(not(feature="no_std"),not(feature="rdrand")))]
885887
#[derive(Clone)]
886-
#[cfg(not(feature="no_std"))]
887888
pub struct ThreadRng {
888889
rng: Rc<RefCell<ThreadRngInner>>,
889890
}
@@ -899,7 +900,7 @@ pub struct ThreadRng {
899900
/// if the operating system random number generator is rigged to give
900901
/// the same sequence always. If absolute consistency is required,
901902
/// explicitly select an RNG, e.g. `IsaacRng` or `Isaac64Rng`.
902-
#[cfg(not(feature="no_std"))]
903+
#[cfg(all(not(feature="no_std"),not(feature="rdrand")))]
903904
pub fn thread_rng() -> ThreadRng {
904905
// used to make space in TLS for a random number generator
905906
thread_local!(static THREAD_RNG_KEY: Rc<RefCell<ThreadRngInner>> = {
@@ -916,7 +917,7 @@ pub fn thread_rng() -> ThreadRng {
916917
ThreadRng { rng: THREAD_RNG_KEY.with(|t| t.clone()) }
917918
}
918919

919-
#[cfg(not(feature="no_std"))]
920+
#[cfg(all(not(feature="no_std"),not(feature="rdrand")))]
920921
impl Rng for ThreadRng {
921922
fn next_u32(&mut self) -> u32 {
922923
self.rng.borrow_mut().next_u32()
@@ -932,6 +933,14 @@ impl Rng for ThreadRng {
932933
}
933934
}
934935

936+
#[cfg(feature="rdrand")]
937+
pub use os::OsRng as ThreadRng;
938+
939+
#[cfg(feature="rdrand")]
940+
pub fn thread_rng() -> ThreadRng {
941+
OsRng::new().unwrap()
942+
}
943+
935944
/// Generates a random value using the thread-local random number generator.
936945
///
937946
/// `random()` can generate various types of random things, and so may require
@@ -974,7 +983,7 @@ impl Rng for ThreadRng {
974983
/// *x = rng.gen();
975984
/// }
976985
/// ```
977-
#[cfg(not(feature="no_std"))]
986+
#[cfg(any(not(feature="no_std"),feature="rdrand"))]
978987
#[inline]
979988
pub fn random<T: Rand>() -> T {
980989
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)