Skip to content

Commit d5e2e5f

Browse files
committed
Auto merge of #31738 - seanmonstar:sys-rand, r=alexcrichton
2 parents 15611f7 + 34dfc39 commit d5e2e5f

File tree

5 files changed

+167
-168
lines changed

5 files changed

+167
-168
lines changed

src/libstd/rand/mod.rs

Lines changed: 93 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ use cell::RefCell;
6262
use io;
6363
use mem;
6464
use rc::Rc;
65+
use sys;
6566

6667
#[cfg(target_pointer_width = "32")]
6768
use core_rand::IsaacRng as IsaacWordRng;
@@ -71,9 +72,7 @@ use core_rand::Isaac64Rng as IsaacWordRng;
7172
pub use core_rand::{Rand, Rng, SeedableRng};
7273
pub use core_rand::{XorShiftRng, IsaacRng, Isaac64Rng};
7374
pub use core_rand::reseeding;
74-
pub use rand::os::OsRng;
7575

76-
pub mod os;
7776
pub mod reader;
7877

7978
/// The standard RNG. This is designed to be efficient on the current
@@ -185,3 +184,95 @@ impl Rng for ThreadRng {
185184
self.rng.borrow_mut().fill_bytes(bytes)
186185
}
187186
}
187+
188+
/// A random number generator that retrieves randomness straight from
189+
/// the operating system. Platform sources:
190+
///
191+
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
192+
/// `/dev/urandom`, or from `getrandom(2)` system call if available.
193+
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
194+
/// service provider with the `PROV_RSA_FULL` type.
195+
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
196+
/// - OpenBSD: uses the `getentropy(2)` system call.
197+
///
198+
/// This does not block.
199+
pub struct OsRng(sys::rand::OsRng);
200+
201+
impl OsRng {
202+
/// Create a new `OsRng`.
203+
pub fn new() -> io::Result<OsRng> {
204+
sys::rand::OsRng::new().map(OsRng)
205+
}
206+
}
207+
208+
impl Rng for OsRng {
209+
#[inline]
210+
fn next_u32(&mut self) -> u32 {
211+
self.0.next_u32()
212+
}
213+
214+
#[inline]
215+
fn next_u64(&mut self) -> u64 {
216+
self.0.next_u64()
217+
}
218+
219+
#[inline]
220+
fn fill_bytes(&mut self, bytes: &mut [u8]) {
221+
self.0.fill_bytes(bytes)
222+
}
223+
}
224+
225+
226+
#[cfg(test)]
227+
mod tests {
228+
use sync::mpsc::channel;
229+
use rand::Rng;
230+
use super::OsRng;
231+
use thread;
232+
233+
#[test]
234+
fn test_os_rng() {
235+
let mut r = OsRng::new().unwrap();
236+
237+
r.next_u32();
238+
r.next_u64();
239+
240+
let mut v = [0; 1000];
241+
r.fill_bytes(&mut v);
242+
}
243+
244+
#[test]
245+
fn test_os_rng_tasks() {
246+
247+
let mut txs = vec!();
248+
for _ in 0..20 {
249+
let (tx, rx) = channel();
250+
txs.push(tx);
251+
252+
thread::spawn(move|| {
253+
// wait until all the threads are ready to go.
254+
rx.recv().unwrap();
255+
256+
// deschedule to attempt to interleave things as much
257+
// as possible (XXX: is this a good test?)
258+
let mut r = OsRng::new().unwrap();
259+
thread::yield_now();
260+
let mut v = [0; 1000];
261+
262+
for _ in 0..100 {
263+
r.next_u32();
264+
thread::yield_now();
265+
r.next_u64();
266+
thread::yield_now();
267+
r.fill_bytes(&mut v);
268+
thread::yield_now();
269+
}
270+
});
271+
}
272+
273+
// start all the threads
274+
for tx in &txs {
275+
tx.send(()).unwrap();
276+
}
277+
}
278+
}

src/libstd/sys/unix/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ pub mod os;
4242
pub mod os_str;
4343
pub mod pipe;
4444
pub mod process;
45+
pub mod rand;
4546
pub mod rwlock;
4647
pub mod stack_overflow;
4748
pub mod thread;

src/libstd/rand/os.rs renamed to src/libstd/sys/unix/rand.rs

Lines changed: 0 additions & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
//! Interfaces to the operating system provided random number
12-
//! generators.
13-
1411
pub use self::imp::OsRng;
1512

1613
#[cfg(all(unix, not(target_os = "ios"), not(target_os = "openbsd")))]
@@ -125,17 +122,6 @@ mod imp {
125122
target_arch = "powerpc64"))))]
126123
fn is_getrandom_available() -> bool { false }
127124

128-
/// A random number generator that retrieves randomness straight from
129-
/// the operating system. Platform sources:
130-
///
131-
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
132-
/// `/dev/urandom`, or from `getrandom(2)` system call if available.
133-
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
134-
/// service provider with the `PROV_RSA_FULL` type.
135-
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
136-
/// - OpenBSD: uses the `getentropy(2)` system call.
137-
///
138-
/// This does not block.
139125
pub struct OsRng {
140126
inner: OsRngInner,
141127
}
@@ -189,17 +175,6 @@ mod imp {
189175
use sys::os::errno;
190176
use rand::Rng;
191177

192-
/// A random number generator that retrieves randomness straight from
193-
/// the operating system. Platform sources:
194-
///
195-
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
196-
/// `/dev/urandom`, or from `getrandom(2)` system call if available.
197-
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
198-
/// service provider with the `PROV_RSA_FULL` type.
199-
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
200-
/// - OpenBSD: uses the `getentropy(2)` system call.
201-
///
202-
/// This does not block.
203178
pub struct OsRng {
204179
// dummy field to ensure that this struct cannot be constructed outside
205180
// of this module
@@ -246,17 +221,6 @@ mod imp {
246221
use rand::Rng;
247222
use libc::{c_int, size_t};
248223

249-
/// A random number generator that retrieves randomness straight from
250-
/// the operating system. Platform sources:
251-
///
252-
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
253-
/// `/dev/urandom`, or from `getrandom(2)` system call if available.
254-
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
255-
/// service provider with the `PROV_RSA_FULL` type.
256-
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
257-
/// - OpenBSD: uses the `getentropy(2)` system call.
258-
///
259-
/// This does not block.
260224
pub struct OsRng {
261225
// dummy field to ensure that this struct cannot be constructed outside
262226
// of this module
@@ -307,133 +271,3 @@ mod imp {
307271
}
308272
}
309273
}
310-
311-
#[cfg(windows)]
312-
mod imp {
313-
use io;
314-
use mem;
315-
use rand::Rng;
316-
use sys::c;
317-
318-
/// A random number generator that retrieves randomness straight from
319-
/// the operating system. Platform sources:
320-
///
321-
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
322-
/// `/dev/urandom`, or from `getrandom(2)` system call if available.
323-
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
324-
/// service provider with the `PROV_RSA_FULL` type.
325-
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
326-
/// - OpenBSD: uses the `getentropy(2)` system call.
327-
///
328-
/// This does not block.
329-
pub struct OsRng {
330-
hcryptprov: c::HCRYPTPROV
331-
}
332-
333-
impl OsRng {
334-
/// Create a new `OsRng`.
335-
pub fn new() -> io::Result<OsRng> {
336-
let mut hcp = 0;
337-
let ret = unsafe {
338-
c::CryptAcquireContextA(&mut hcp, 0 as c::LPCSTR, 0 as c::LPCSTR,
339-
c::PROV_RSA_FULL,
340-
c::CRYPT_VERIFYCONTEXT | c::CRYPT_SILENT)
341-
};
342-
343-
if ret == 0 {
344-
Err(io::Error::last_os_error())
345-
} else {
346-
Ok(OsRng { hcryptprov: hcp })
347-
}
348-
}
349-
}
350-
351-
impl Rng for OsRng {
352-
fn next_u32(&mut self) -> u32 {
353-
let mut v = [0; 4];
354-
self.fill_bytes(&mut v);
355-
unsafe { mem::transmute(v) }
356-
}
357-
fn next_u64(&mut self) -> u64 {
358-
let mut v = [0; 8];
359-
self.fill_bytes(&mut v);
360-
unsafe { mem::transmute(v) }
361-
}
362-
fn fill_bytes(&mut self, v: &mut [u8]) {
363-
let ret = unsafe {
364-
c::CryptGenRandom(self.hcryptprov, v.len() as c::DWORD,
365-
v.as_mut_ptr())
366-
};
367-
if ret == 0 {
368-
panic!("couldn't generate random bytes: {}",
369-
io::Error::last_os_error());
370-
}
371-
}
372-
}
373-
374-
impl Drop for OsRng {
375-
fn drop(&mut self) {
376-
let ret = unsafe {
377-
c::CryptReleaseContext(self.hcryptprov, 0)
378-
};
379-
if ret == 0 {
380-
panic!("couldn't release context: {}",
381-
io::Error::last_os_error());
382-
}
383-
}
384-
}
385-
}
386-
387-
#[cfg(test)]
388-
mod tests {
389-
use sync::mpsc::channel;
390-
use rand::Rng;
391-
use super::OsRng;
392-
use thread;
393-
394-
#[test]
395-
fn test_os_rng() {
396-
let mut r = OsRng::new().unwrap();
397-
398-
r.next_u32();
399-
r.next_u64();
400-
401-
let mut v = [0; 1000];
402-
r.fill_bytes(&mut v);
403-
}
404-
405-
#[test]
406-
fn test_os_rng_tasks() {
407-
408-
let mut txs = vec!();
409-
for _ in 0..20 {
410-
let (tx, rx) = channel();
411-
txs.push(tx);
412-
413-
thread::spawn(move|| {
414-
// wait until all the threads are ready to go.
415-
rx.recv().unwrap();
416-
417-
// deschedule to attempt to interleave things as much
418-
// as possible (XXX: is this a good test?)
419-
let mut r = OsRng::new().unwrap();
420-
thread::yield_now();
421-
let mut v = [0; 1000];
422-
423-
for _ in 0..100 {
424-
r.next_u32();
425-
thread::yield_now();
426-
r.next_u64();
427-
thread::yield_now();
428-
r.fill_bytes(&mut v);
429-
thread::yield_now();
430-
}
431-
});
432-
}
433-
434-
// start all the threads
435-
for tx in &txs {
436-
tx.send(()).unwrap();
437-
}
438-
}
439-
}

src/libstd/sys/windows/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ pub mod os;
3333
pub mod os_str;
3434
pub mod pipe;
3535
pub mod process;
36+
pub mod rand;
3637
pub mod rwlock;
3738
pub mod stack_overflow;
3839
pub mod thread;

0 commit comments

Comments
 (0)