Skip to content

Commit f69bfef

Browse files
author
Jethro Beekman
committed
Add RDRAND feature
1 parent 6896e25 commit f69bfef

File tree

3 files changed

+60
-19
lines changed

3 files changed

+60
-19
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ default = ["std"]
2222
std = ["libc"]
2323
box = [] # enable use of Box on not(std), requires alloc crate and feature
2424
vec = [] # enable use of Vec on not(std), requires collections crate and feature
25+
rdrand = []
2526

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

src/lib.rs

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@
244244
#![cfg_attr(not(feature="std"),no_std)]
245245
#![cfg_attr(all(feature="box",not(feature="std")),feature(alloc))]
246246
#![cfg_attr(all(feature="vec",not(feature="std")),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(all(feature="box",not(feature="std")))] extern crate alloc;
253254
#[cfg(all(feature="vec",not(feature="std")))] extern crate collections;
254255

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

264-
#[cfg(feature="std")] pub use os::OsRng;
265+
#[cfg(any(feature="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(feature="std")] pub mod os;
283+
#[cfg(any(feature="std",feature="rdrand"))] pub mod os;
283284
#[cfg(any(feature="std",feature="core_io"))] pub mod read;
284285

285286
#[allow(bad_style)]
@@ -822,7 +823,7 @@ impl StdRng {
822823
///
823824
/// Reading the randomness from the OS may fail, and any error is
824825
/// propagated via the `io::Result` return value.
825-
#[cfg(feature="std")]
826+
#[cfg(any(feature="std",feature="rdrand"))]
826827
pub fn new() -> io::Result<StdRng> {
827828
OsRng::new().map(|mut r| StdRng { rng: r.gen() })
828829
}
@@ -861,7 +862,7 @@ impl<'a> SeedableRng<&'a [usize]> for StdRng {
861862
///
862863
/// This will read randomness from the operating system to seed the
863864
/// generator.
864-
#[cfg(feature="std")]
865+
#[cfg(any(feature="std",feature="rdrand"))]
865866
pub fn weak_rng() -> XorShiftRng {
866867
match OsRng::new() {
867868
Ok(mut r) => r.gen(),
@@ -870,10 +871,10 @@ pub fn weak_rng() -> XorShiftRng {
870871
}
871872

872873
/// Controls how the thread-local RNG is reseeded.
873-
#[cfg(feature="std")]
874+
#[cfg(all(feature="std",not(feature="rdrand")))]
874875
struct ThreadRngReseeder;
875876

876-
#[cfg(feature="std")]
877+
#[cfg(all(feature="std",not(feature="rdrand")))]
877878
impl reseeding::Reseeder<StdRng> for ThreadRngReseeder {
878879
fn reseed(&mut self, rng: &mut StdRng) {
879880
*rng = match StdRng::new() {
@@ -882,14 +883,14 @@ impl reseeding::Reseeder<StdRng> for ThreadRngReseeder {
882883
}
883884
}
884885
}
885-
#[cfg(feature="std")]
886+
#[cfg(all(feature="std",not(feature="rdrand")))]
886887
const THREAD_RNG_RESEED_THRESHOLD: u64 = 32_768;
887-
#[cfg(feature="std")]
888+
#[cfg(all(feature="std",not(feature="rdrand")))]
888889
type ThreadRngInner = reseeding::ReseedingRng<StdRng, ThreadRngReseeder>;
889890

890891
/// The thread-local RNG.
892+
#[cfg(all(feature="std",not(feature="rdrand")))]
891893
#[derive(Clone)]
892-
#[cfg(feature="std")]
893894
pub struct ThreadRng {
894895
rng: Rc<RefCell<ThreadRngInner>>,
895896
}
@@ -905,7 +906,7 @@ pub struct ThreadRng {
905906
/// if the operating system random number generator is rigged to give
906907
/// the same sequence always. If absolute consistency is required,
907908
/// explicitly select an RNG, e.g. `IsaacRng` or `Isaac64Rng`.
908-
#[cfg(feature="std")]
909+
#[cfg(all(feature="std",not(feature="rdrand")))]
909910
pub fn thread_rng() -> ThreadRng {
910911
// used to make space in TLS for a random number generator
911912
thread_local!(static THREAD_RNG_KEY: Rc<RefCell<ThreadRngInner>> = {
@@ -922,7 +923,7 @@ pub fn thread_rng() -> ThreadRng {
922923
ThreadRng { rng: THREAD_RNG_KEY.with(|t| t.clone()) }
923924
}
924925

925-
#[cfg(feature="std")]
926+
#[cfg(all(feature="std",not(feature="rdrand")))]
926927
impl Rng for ThreadRng {
927928
fn next_u32(&mut self) -> u32 {
928929
self.rng.borrow_mut().next_u32()
@@ -938,6 +939,14 @@ impl Rng for ThreadRng {
938939
}
939940
}
940941

942+
#[cfg(feature="rdrand")]
943+
pub use os::OsRng as ThreadRng;
944+
945+
#[cfg(feature="rdrand")]
946+
pub fn thread_rng() -> ThreadRng {
947+
OsRng::new().unwrap()
948+
}
949+
941950
/// Generates a random value using the thread-local random number generator.
942951
///
943952
/// `random()` can generate various types of random things, and so may require
@@ -980,7 +989,7 @@ impl Rng for ThreadRng {
980989
/// *x = rng.gen();
981990
/// }
982991
/// ```
983-
#[cfg(feature="std")]
992+
#[cfg(any(feature="std",feature="rdrand"))]
984993
#[inline]
985994
pub fn random<T: Rand>() -> T {
986995
thread_rng().gen()

src/os.rs

Lines changed: 36 additions & 5 deletions
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="std"))] use io;
15+
#[cfg(feature="std")] use std::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="std"))] use io;
424+
#[cfg(feature="std")] use std::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)