diff --git a/src/libcollections/deque.rs b/src/libcollections/deque.rs index 9c1427d0225..6c1391e7ca8 100644 --- a/src/libcollections/deque.rs +++ b/src/libcollections/deque.rs @@ -52,7 +52,7 @@ pub mod bench { map: &mut M, bh: &mut BenchHarness) { // setup - let mut rng = rand::XorShiftRng::new(); + let mut rng = rand::weak_rng(); map.clear(); for _ in range(0, n) { @@ -89,7 +89,7 @@ pub mod bench { map: &mut M, bh: &mut BenchHarness) { // setup - let mut rng = rand::XorShiftRng::new(); + let mut rng = rand::weak_rng(); let mut keys = slice::from_fn(n, |_| rng.gen::() % n); for k in keys.iter() { diff --git a/src/libgreen/sched.rs b/src/libgreen/sched.rs index adfd5908de2..683df846d62 100644 --- a/src/libgreen/sched.rs +++ b/src/libgreen/sched.rs @@ -967,7 +967,12 @@ impl ClosureConverter for UnsafeTaskReceiver { // worry there. #[cfg(windows)] fn new_sched_rng() -> XorShiftRng { - XorShiftRng::new() + match XorShiftRng::new() { + Ok(r) => r, + Err(e) => { + rtabort!("sched: failed to create seeded RNG: {}", e) + } + } } #[cfg(unix)] fn new_sched_rng() -> XorShiftRng { diff --git a/src/libnative/io/addrinfo.rs b/src/libnative/io/addrinfo.rs index ff617e5a230..bca564870e2 100644 --- a/src/libnative/io/addrinfo.rs +++ b/src/libnative/io/addrinfo.rs @@ -96,10 +96,8 @@ extern "system" { #[cfg(windows)] fn get_error(_: c_int) -> IoError { - use super::translate_error; - unsafe { - translate_error(WSAGetLastError() as i32, true) + IoError::from_errno(WSAGetLastError() as uint, true) } } diff --git a/src/libnative/io/mod.rs b/src/libnative/io/mod.rs index e6e9cbb7ce3..34843102456 100644 --- a/src/libnative/io/mod.rs +++ b/src/libnative/io/mod.rs @@ -86,73 +86,10 @@ fn unimpl() -> IoError { } } -fn translate_error(errno: i32, detail: bool) -> IoError { - #[cfg(windows)] - fn get_err(errno: i32) -> (io::IoErrorKind, &'static str) { - match errno { - libc::EOF => (io::EndOfFile, "end of file"), - libc::ERROR_NO_DATA => (io::BrokenPipe, "the pipe is being closed"), - libc::ERROR_FILE_NOT_FOUND => (io::FileNotFound, "file not found"), - libc::ERROR_INVALID_NAME => (io::InvalidInput, "invalid file name"), - libc::WSAECONNREFUSED => (io::ConnectionRefused, "connection refused"), - libc::WSAECONNRESET => (io::ConnectionReset, "connection reset"), - libc::WSAEACCES => (io::PermissionDenied, "permission denied"), - libc::WSAEWOULDBLOCK => { - (io::ResourceUnavailable, "resource temporarily unavailable") - } - libc::WSAENOTCONN => (io::NotConnected, "not connected"), - libc::WSAECONNABORTED => (io::ConnectionAborted, "connection aborted"), - libc::WSAEADDRNOTAVAIL => (io::ConnectionRefused, "address not available"), - libc::WSAEADDRINUSE => (io::ConnectionRefused, "address in use"), - libc::ERROR_BROKEN_PIPE => (io::EndOfFile, "the pipe has ended"), - - // libuv maps this error code to EISDIR. we do too. if it is found - // to be incorrect, we can add in some more machinery to only - // return this message when ERROR_INVALID_FUNCTION after certain - // win32 calls. - libc::ERROR_INVALID_FUNCTION => (io::InvalidInput, - "illegal operation on a directory"), - - _ => (io::OtherIoError, "unknown error") - } - } - - #[cfg(not(windows))] - fn get_err(errno: i32) -> (io::IoErrorKind, &'static str) { - // FIXME: this should probably be a bit more descriptive... - match errno { - libc::EOF => (io::EndOfFile, "end of file"), - libc::ECONNREFUSED => (io::ConnectionRefused, "connection refused"), - libc::ECONNRESET => (io::ConnectionReset, "connection reset"), - libc::EPERM | libc::EACCES => - (io::PermissionDenied, "permission denied"), - libc::EPIPE => (io::BrokenPipe, "broken pipe"), - libc::ENOTCONN => (io::NotConnected, "not connected"), - libc::ECONNABORTED => (io::ConnectionAborted, "connection aborted"), - libc::EADDRNOTAVAIL => (io::ConnectionRefused, "address not available"), - libc::EADDRINUSE => (io::ConnectionRefused, "address in use"), - libc::ENOENT => (io::FileNotFound, "no such file or directory"), - libc::EISDIR => (io::InvalidInput, "illegal operation on a directory"), - - // These two constants can have the same value on some systems, but - // different values on others, so we can't use a match clause - x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => - (io::ResourceUnavailable, "resource temporarily unavailable"), - - _ => (io::OtherIoError, "unknown error") - } - } - - let (kind, desc) = get_err(errno); - IoError { - kind: kind, - desc: desc, - detail: if detail {Some(os::last_os_error())} else {None}, - } +fn last_error() -> IoError { + IoError::last_error() } -fn last_error() -> IoError { translate_error(os::errno() as i32, true) } - // unix has nonzero values as errors fn mkerr_libc(ret: libc::c_int) -> IoResult<()> { if ret != 0 { diff --git a/src/libnative/io/net.rs b/src/libnative/io/net.rs index bf751be1f7f..6ddd69eb019 100644 --- a/src/libnative/io/net.rs +++ b/src/libnative/io/net.rs @@ -120,7 +120,7 @@ fn last_error() -> io::IoError { extern "system" { fn WSAGetLastError() -> libc::c_int; } - super::translate_error(unsafe { WSAGetLastError() }, true) + io::IoError::from_errno(unsafe { WSAGetLastError() } as uint, true) } #[cfg(not(windows))] diff --git a/src/libnative/io/process.rs b/src/libnative/io/process.rs index c729473eecd..d2e2db63c1b 100644 --- a/src/libnative/io/process.rs +++ b/src/libnative/io/process.rs @@ -481,7 +481,7 @@ fn spawn_process_os(config: p::ProcessConfig, (bytes[1] << 16) as i32 | (bytes[2] << 8) as i32 | (bytes[3] << 0) as i32; - Err(super::translate_error(errno, false)) + Err(io::IoError::from_errno(errno as uint, false)) } Err(e) => { assert!(e.kind == io::BrokenPipe || diff --git a/src/librand/distributions/exponential.rs b/src/librand/distributions/exponential.rs index 5a6b925c53f..5cd53ca88a9 100644 --- a/src/librand/distributions/exponential.rs +++ b/src/librand/distributions/exponential.rs @@ -126,7 +126,7 @@ mod bench { #[bench] fn rand_exp(bh: &mut BenchHarness) { - let mut rng = XorShiftRng::new(); + let mut rng = XorShiftRng::new().unwrap(); let mut exp = Exp::new(2.71828 * 3.14159); bh.iter(|| { diff --git a/src/librand/distributions/gamma.rs b/src/librand/distributions/gamma.rs index 1e9b5cbe99e..a1557b84212 100644 --- a/src/librand/distributions/gamma.rs +++ b/src/librand/distributions/gamma.rs @@ -370,14 +370,14 @@ mod bench { use self::test::BenchHarness; use std::mem::size_of; use distributions::IndependentSample; - use {StdRng, RAND_BENCH_N}; + use {XorShiftRng, RAND_BENCH_N}; use super::Gamma; #[bench] fn bench_gamma_large_shape(bh: &mut BenchHarness) { let gamma = Gamma::new(10., 1.0); - let mut rng = StdRng::new(); + let mut rng = XorShiftRng::new().unwrap(); bh.iter(|| { for _ in range(0, RAND_BENCH_N) { @@ -390,7 +390,7 @@ mod bench { #[bench] fn bench_gamma_small_shape(bh: &mut BenchHarness) { let gamma = Gamma::new(0.1, 1.0); - let mut rng = StdRng::new(); + let mut rng = XorShiftRng::new().unwrap(); bh.iter(|| { for _ in range(0, RAND_BENCH_N) { diff --git a/src/librand/distributions/normal.rs b/src/librand/distributions/normal.rs index 42fb76ad4eb..7340d00929e 100644 --- a/src/librand/distributions/normal.rs +++ b/src/librand/distributions/normal.rs @@ -193,7 +193,7 @@ mod bench { #[bench] fn rand_normal(bh: &mut BenchHarness) { - let mut rng = XorShiftRng::new(); + let mut rng = XorShiftRng::new().unwrap(); let mut normal = Normal::new(-2.71828, 3.14159); bh.iter(|| { diff --git a/src/librand/isaac.rs b/src/librand/isaac.rs index 5c14d2c9f5b..de3d471c7bd 100644 --- a/src/librand/isaac.rs +++ b/src/librand/isaac.rs @@ -11,6 +11,7 @@ //! The ISAAC random number generator. use {Rng, SeedableRng, OSRng}; +use std::io::IoResult; use std::iter::{range_step, Repeat}; use std::slice::raw; use std::mem; @@ -44,19 +45,23 @@ static EMPTY: IsaacRng = IsaacRng { impl IsaacRng { /// Create an ISAAC random number generator with a random seed. - pub fn new() -> IsaacRng { + /// + /// This reads randomness from the operating system (via `OSRng`) + /// which may fail, any error is propagated via the `IoResult` + /// return value. + pub fn new() -> IoResult { let mut rng = EMPTY; - + let mut os_rng = try!(OSRng::new()); unsafe { let ptr = rng.rsl.as_mut_ptr(); raw::mut_buf_as_slice(ptr as *mut u8, mem::size_of_val(&rng.rsl), |slice| { - OSRng::new().fill_bytes(slice); + os_rng.fill_bytes(slice); }) } rng.init(true); - rng + Ok(rng) } /// Create an ISAAC random number generator using the default @@ -249,19 +254,24 @@ static EMPTY_64: Isaac64Rng = Isaac64Rng { impl Isaac64Rng { /// Create a 64-bit ISAAC random number generator with a random /// seed. - pub fn new() -> Isaac64Rng { + /// + /// This reads randomness from the operating system (via `OSRng`) + /// which may fail, any error is propagated via the `IoResult` + /// return value. + pub fn new() -> IoResult { let mut rng = EMPTY_64; + let mut os_rng = try!(OSRng::new()); unsafe { let ptr = rng.rsl.as_mut_ptr(); raw::mut_buf_as_slice(ptr as *mut u8, mem::size_of_val(&rng.rsl), |slice| { - OSRng::new().fill_bytes(slice); + os_rng.fill_bytes(slice); }) } rng.init(true); - rng + Ok(rng) } /// Create a 64-bit ISAAC random number generator using the @@ -430,19 +440,19 @@ impl<'a> SeedableRng<&'a [u64]> for Isaac64Rng { #[cfg(test)] mod test { use super::{IsaacRng, Isaac64Rng}; - use {Rng, SeedableRng, OSRng}; + use {Rng, SeedableRng, task_rng}; use std::slice; #[test] fn test_rng_32_rand_seeded() { - let s = OSRng::new().gen_vec::(256); + let s = task_rng().gen_vec::(256); let mut ra: IsaacRng = SeedableRng::from_seed(s.as_slice()); let mut rb: IsaacRng = SeedableRng::from_seed(s.as_slice()); assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u)); } #[test] fn test_rng_64_rand_seeded() { - let s = OSRng::new().gen_vec::(256); + let s = task_rng().gen_vec::(256); let mut ra: Isaac64Rng = SeedableRng::from_seed(s.as_slice()); let mut rb: Isaac64Rng = SeedableRng::from_seed(s.as_slice()); assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u)); @@ -465,7 +475,7 @@ mod test { #[test] fn test_rng_32_reseed() { - let s = OSRng::new().gen_vec::(256); + let s = task_rng().gen_vec::(256); let mut r: IsaacRng = SeedableRng::from_seed(s.as_slice()); let string1 = r.gen_ascii_str(100); @@ -476,7 +486,7 @@ mod test { } #[test] fn test_rng_64_reseed() { - let s = OSRng::new().gen_vec::(256); + let s = task_rng().gen_vec::(256); let mut r: Isaac64Rng = SeedableRng::from_seed(s.as_slice()); let string1 = r.gen_ascii_str(100); diff --git a/src/librand/lib.rs b/src/librand/lib.rs index d9920501ab0..56d52e78466 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -78,6 +78,7 @@ println!("{:?}", tuple_ptr) #[phase(syntax, link)] extern crate log; use std::cast; +use std::io::IoResult; use std::kinds::marker; use std::local_data; use std::str; @@ -403,7 +404,7 @@ pub trait SeedableRng: Rng { /// appropriate. #[deprecated="use `task_rng` or `StdRng::new`"] pub fn rng() -> StdRng { - StdRng::new() + StdRng::new().unwrap() } /// The standard RNG. This is designed to be efficient on the current @@ -425,9 +426,12 @@ impl StdRng { /// number of random numbers, or doesn't need the utmost speed for /// generating each number, `task_rng` and/or `random` may be more /// appropriate. + /// + /// Reading the randomness from the OS may fail, and any error is + /// propagated via the `IoResult` return value. #[cfg(not(target_word_size="64"))] - pub fn new() -> StdRng { - StdRng { rng: IsaacRng::new() } + pub fn new() -> IoResult { + IsaacRng::new().map(|r| StdRng { rng: r }) } /// Create a randomly seeded instance of `StdRng`. /// @@ -437,9 +441,12 @@ impl StdRng { /// number of random numbers, or doesn't need the utmost speed for /// generating each number, `task_rng` and/or `random` may be more /// appropriate. + /// + /// Reading the randomness from the OS may fail, and any error is + /// propagated via the `IoResult` return value. #[cfg(target_word_size="64")] - pub fn new() -> StdRng { - StdRng { rng: Isaac64Rng::new() } + pub fn new() -> IoResult { + Isaac64Rng::new().map(|r| StdRng { rng: r }) } } @@ -477,7 +484,10 @@ impl<'a> SeedableRng<&'a [uint]> for StdRng { /// This will read randomness from the operating system to seed the /// generator. pub fn weak_rng() -> XorShiftRng { - XorShiftRng::new() + match XorShiftRng::new() { + Ok(r) => r, + Err(e) => fail!("weak_rng: failed to create seeded RNG: {}", e) + } } /// An Xorshift[1] random number @@ -539,10 +549,10 @@ impl SeedableRng<[u32, .. 4]> for XorShiftRng { impl XorShiftRng { /// Create an xor shift random number generator with a random seed. - pub fn new() -> XorShiftRng { + pub fn new() -> IoResult { let mut s = [0u8, ..16]; + let mut r = try!(OSRng::new()); loop { - let mut r = OSRng::new(); r.fill_bytes(s); if !s.iter().all(|x| *x == 0) { @@ -550,7 +560,7 @@ impl XorShiftRng { } } let s: [u32, ..4] = unsafe { cast::transmute(s) }; - SeedableRng::from_seed(s) + Ok(SeedableRng::from_seed(s)) } } @@ -559,7 +569,10 @@ struct TaskRngReseeder; impl reseeding::Reseeder for TaskRngReseeder { fn reseed(&mut self, rng: &mut StdRng) { - *rng = StdRng::new(); + *rng = match StdRng::new() { + Ok(r) => r, + Err(e) => fail!("could not reseed task_rng: {}", e) + } } } static TASK_RNG_RESEED_THRESHOLD: uint = 32_768; @@ -596,7 +609,11 @@ local_data_key!(TASK_RNG_KEY: ~TaskRngInner) pub fn task_rng() -> TaskRng { local_data::get_mut(TASK_RNG_KEY, |rng| match rng { None => { - let mut rng = ~reseeding::ReseedingRng::new(StdRng::new(), + let r = match StdRng::new() { + Ok(r) => r, + Err(e) => fail!("could not initialize task_rng: {}", e) + }; + let mut rng = ~reseeding::ReseedingRng::new(r, TASK_RNG_RESEED_THRESHOLD, TaskRngReseeder); let ptr = &mut *rng as *mut TaskRngInner; @@ -679,7 +696,7 @@ pub struct Closed01(F); #[cfg(test)] mod test { use std::slice; - use super::{Rng, task_rng, random, OSRng, SeedableRng, StdRng}; + use super::{Rng, task_rng, random, SeedableRng, StdRng}; struct ConstRng { i: u64 } impl Rng for ConstRng { @@ -841,7 +858,7 @@ mod test { #[test] fn test_std_rng_seeded() { - let s = OSRng::new().gen_vec::(256); + let s = task_rng().gen_vec::(256); let mut ra: StdRng = SeedableRng::from_seed(s.as_slice()); let mut rb: StdRng = SeedableRng::from_seed(s.as_slice()); assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u)); @@ -849,7 +866,7 @@ mod test { #[test] fn test_std_rng_reseed() { - let s = OSRng::new().gen_vec::(256); + let s = task_rng().gen_vec::(256); let mut r: StdRng = SeedableRng::from_seed(s.as_slice()); let string1 = r.gen_ascii_str(100); @@ -872,7 +889,7 @@ mod bench { #[bench] fn rand_xorshift(bh: &mut BenchHarness) { - let mut rng = XorShiftRng::new(); + let mut rng = XorShiftRng::new().unwrap(); bh.iter(|| { for _ in range(0, RAND_BENCH_N) { rng.gen::(); @@ -883,7 +900,7 @@ mod bench { #[bench] fn rand_isaac(bh: &mut BenchHarness) { - let mut rng = IsaacRng::new(); + let mut rng = IsaacRng::new().unwrap(); bh.iter(|| { for _ in range(0, RAND_BENCH_N) { rng.gen::(); @@ -894,7 +911,7 @@ mod bench { #[bench] fn rand_isaac64(bh: &mut BenchHarness) { - let mut rng = Isaac64Rng::new(); + let mut rng = Isaac64Rng::new().unwrap(); bh.iter(|| { for _ in range(0, RAND_BENCH_N) { rng.gen::(); @@ -905,7 +922,7 @@ mod bench { #[bench] fn rand_std(bh: &mut BenchHarness) { - let mut rng = StdRng::new(); + let mut rng = StdRng::new().unwrap(); bh.iter(|| { for _ in range(0, RAND_BENCH_N) { rng.gen::(); @@ -916,7 +933,7 @@ mod bench { #[bench] fn rand_shuffle_100(bh: &mut BenchHarness) { - let mut rng = XorShiftRng::new(); + let mut rng = XorShiftRng::new().unwrap(); let x : &mut[uint] = [1,..100]; bh.iter(|| { rng.shuffle_mut(x); diff --git a/src/librand/os.rs b/src/librand/os.rs index 6ba919a7e65..86960af7a4d 100644 --- a/src/librand/os.rs +++ b/src/librand/os.rs @@ -17,7 +17,7 @@ pub use self::imp::OSRng; mod imp { use Rng; use reader::ReaderRng; - use std::io::File; + use std::io::{IoResult, File}; /// A random number generator that retrieves randomness straight from /// the operating system. Platform sources: @@ -35,12 +35,11 @@ mod imp { impl OSRng { /// Create a new `OSRng`. - pub fn new() -> OSRng { - let reader = File::open(&Path::new("/dev/urandom")); - let reader = reader.ok().expect("Error opening /dev/urandom"); + pub fn new() -> IoResult { + let reader = try!(File::open(&Path::new("/dev/urandom"))); let reader_rng = ReaderRng::new(reader); - OSRng { inner: reader_rng } + Ok(OSRng { inner: reader_rng }) } } @@ -61,6 +60,7 @@ mod imp { mod imp { use Rng; use std::cast; + use std::io::{IoResult, IoError}; use std::libc::{c_ulong, DWORD, BYTE, LPCSTR, BOOL}; use std::os; use std::rt::stack; @@ -99,7 +99,7 @@ mod imp { impl OSRng { /// Create a new `OSRng`. - pub fn new() -> OSRng { + pub fn new() -> IoResult { let mut hcp = 0; let mut ret = unsafe { CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR, @@ -143,9 +143,10 @@ mod imp { } if ret == 0 { - fail!("couldn't create context: {}", os::last_os_error()); + Err(IoError::last_error()) + } else { + Ok(OSRng { hcryptprov: hcp }) } - OSRng { hcryptprov: hcp } } } @@ -191,7 +192,7 @@ mod test { #[test] fn test_os_rng() { - let mut r = OSRng::new(); + let mut r = OSRng::new().unwrap(); r.next_u32(); r.next_u64(); @@ -213,7 +214,7 @@ mod test { // deschedule to attempt to interleave things as much // as possible (XXX: is this a good test?) - let mut r = OSRng::new(); + let mut r = OSRng::new().unwrap(); task::deschedule(); let mut v = [0u8, .. 1000]; diff --git a/src/librand/reseeding.rs b/src/librand/reseeding.rs index 70108d76b56..c069c7389c2 100644 --- a/src/librand/reseeding.rs +++ b/src/librand/reseeding.rs @@ -100,12 +100,12 @@ impl, Rsdr: Reseeder> /// # Example /// /// ```rust -/// use rand::{Rng, SeedableRng}; +/// use rand::{Rng, SeedableRng, StdRng}; /// use rand::reseeding::{Reseeder, ReseedingRng}; /// /// struct TickTockReseeder { tick: bool } -/// impl Reseeder for TickTockReseeder { -/// fn reseed(&mut self, rng: &mut rand::StdRng) { +/// impl Reseeder for TickTockReseeder { +/// fn reseed(&mut self, rng: &mut StdRng) { /// let val = if self.tick {0} else {1}; /// rng.reseed(&[val]); /// self.tick = !self.tick; @@ -113,7 +113,9 @@ impl, Rsdr: Reseeder> /// } /// fn main() { /// let rsdr = TickTockReseeder { tick: true }; -/// let mut rng = ReseedingRng::new(rand::StdRng::new(), 10, rsdr); +/// +/// let inner = StdRng::new().unwrap(); +/// let mut rng = ReseedingRng::new(inner, 10, rsdr); /// /// // this will repeat, because it gets reseeded very regularly. /// println!("{}", rng.gen_ascii_str(100)); diff --git a/src/libstd/fmt/num.rs b/src/libstd/fmt/num.rs index b10a9584df9..4d1d08551a6 100644 --- a/src/libstd/fmt/num.rs +++ b/src/libstd/fmt/num.rs @@ -400,31 +400,31 @@ mod bench { #[bench] fn format_bin(bh: &mut BenchHarness) { - let mut rng = XorShiftRng::new(); + let mut rng = XorShiftRng::new().unwrap(); bh.iter(|| { format!("{:t}", rng.gen::()); }) } #[bench] fn format_oct(bh: &mut BenchHarness) { - let mut rng = XorShiftRng::new(); + let mut rng = XorShiftRng::new().unwrap(); bh.iter(|| { format!("{:o}", rng.gen::()); }) } #[bench] fn format_dec(bh: &mut BenchHarness) { - let mut rng = XorShiftRng::new(); + let mut rng = XorShiftRng::new().unwrap(); bh.iter(|| { format!("{:u}", rng.gen::()); }) } #[bench] fn format_hex(bh: &mut BenchHarness) { - let mut rng = XorShiftRng::new(); + let mut rng = XorShiftRng::new().unwrap(); bh.iter(|| { format!("{:x}", rng.gen::()); }) } #[bench] fn format_base_36(bh: &mut BenchHarness) { - let mut rng = XorShiftRng::new(); + let mut rng = XorShiftRng::new().unwrap(); bh.iter(|| { format!("{}", radix(rng.gen::(), 36)); }) } } @@ -436,31 +436,31 @@ mod bench { #[bench] fn format_bin(bh: &mut BenchHarness) { - let mut rng = XorShiftRng::new(); + let mut rng = XorShiftRng::new().unwrap(); bh.iter(|| { format!("{:t}", rng.gen::()); }) } #[bench] fn format_oct(bh: &mut BenchHarness) { - let mut rng = XorShiftRng::new(); + let mut rng = XorShiftRng::new().unwrap(); bh.iter(|| { format!("{:o}", rng.gen::()); }) } #[bench] fn format_dec(bh: &mut BenchHarness) { - let mut rng = XorShiftRng::new(); + let mut rng = XorShiftRng::new().unwrap(); bh.iter(|| { format!("{:d}", rng.gen::()); }) } #[bench] fn format_hex(bh: &mut BenchHarness) { - let mut rng = XorShiftRng::new(); + let mut rng = XorShiftRng::new().unwrap(); bh.iter(|| { format!("{:x}", rng.gen::()); }) } #[bench] fn format_base_36(bh: &mut BenchHarness) { - let mut rng = XorShiftRng::new(); + let mut rng = XorShiftRng::new().unwrap(); bh.iter(|| { format!("{}", radix(rng.gen::(), 36)); }) } } diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs index b6efdfad9d3..410b841545e 100644 --- a/src/libstd/io/fs.rs +++ b/src/libstd/io/fs.rs @@ -1286,7 +1286,7 @@ mod test { use rand::{StdRng, Rng}; let mut bytes = [0, ..1024]; - StdRng::new().fill_bytes(bytes); + StdRng::new().unwrap().fill_bytes(bytes); let tmpdir = tmpdir(); diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 50f8b0b28c4..403e0e48fd5 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -216,6 +216,8 @@ use container::Container; use fmt; use int; use iter::Iterator; +use libc; +use os; use option::{Option, Some, None}; use path::Path; use result::{Ok, Err, Result}; @@ -290,6 +292,88 @@ pub struct IoError { pub detail: Option<~str> } +impl IoError { + /// Convert an `errno` value into an `IoError`. + /// + /// If `detail` is `true`, the `detail` field of the `IoError` + /// struct is filled with an allocated string describing the error + /// in more detail, retrieved from the operating system. + pub fn from_errno(errno: uint, detail: bool) -> IoError { + #[cfg(windows)] + fn get_err(errno: i32) -> (IoErrorKind, &'static str) { + match errno { + libc::EOF => (EndOfFile, "end of file"), + libc::ERROR_NO_DATA => (BrokenPipe, "the pipe is being closed"), + libc::ERROR_FILE_NOT_FOUND => (FileNotFound, "file not found"), + libc::ERROR_INVALID_NAME => (InvalidInput, "invalid file name"), + libc::WSAECONNREFUSED => (ConnectionRefused, "connection refused"), + libc::WSAECONNRESET => (ConnectionReset, "connection reset"), + libc::WSAEACCES => (PermissionDenied, "permission denied"), + libc::WSAEWOULDBLOCK => { + (ResourceUnavailable, "resource temporarily unavailable") + } + libc::WSAENOTCONN => (NotConnected, "not connected"), + libc::WSAECONNABORTED => (ConnectionAborted, "connection aborted"), + libc::WSAEADDRNOTAVAIL => (ConnectionRefused, "address not available"), + libc::WSAEADDRINUSE => (ConnectionRefused, "address in use"), + libc::ERROR_BROKEN_PIPE => (EndOfFile, "the pipe has ended"), + + // libuv maps this error code to EISDIR. we do too. if it is found + // to be incorrect, we can add in some more machinery to only + // return this message when ERROR_INVALID_FUNCTION after certain + // win32 calls. + libc::ERROR_INVALID_FUNCTION => (InvalidInput, + "illegal operation on a directory"), + + _ => (OtherIoError, "unknown error") + } + } + + #[cfg(not(windows))] + fn get_err(errno: i32) -> (IoErrorKind, &'static str) { + // FIXME: this should probably be a bit more descriptive... + match errno { + libc::EOF => (EndOfFile, "end of file"), + libc::ECONNREFUSED => (ConnectionRefused, "connection refused"), + libc::ECONNRESET => (ConnectionReset, "connection reset"), + libc::EPERM | libc::EACCES => + (PermissionDenied, "permission denied"), + libc::EPIPE => (BrokenPipe, "broken pipe"), + libc::ENOTCONN => (NotConnected, "not connected"), + libc::ECONNABORTED => (ConnectionAborted, "connection aborted"), + libc::EADDRNOTAVAIL => (ConnectionRefused, "address not available"), + libc::EADDRINUSE => (ConnectionRefused, "address in use"), + libc::ENOENT => (FileNotFound, "no such file or directory"), + libc::EISDIR => (InvalidInput, "illegal operation on a directory"), + + // These two constants can have the same value on some systems, but + // different values on others, so we can't use a match clause + x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => + (ResourceUnavailable, "resource temporarily unavailable"), + + _ => (OtherIoError, "unknown error") + } + } + + let (kind, desc) = get_err(errno as i32); + IoError { + kind: kind, + desc: desc, + detail: if detail {Some(os::error_string(errno))} else {None}, + } + } + + /// Retrieve the last error to occur as a (detailed) IoError. + /// + /// This uses the OS `errno`, and so there should not be any task + /// descheduling or migration (other than that performed by the + /// operating system) between the call(s) for which errors are + /// being checked and the call of this function. + pub fn last_error() -> IoError { + IoError::from_errno(os::errno() as uint, true) + } +} + impl fmt::Show for IoError { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { try!(fmt.buf.write_str(self.desc)); diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index dc49da415a4..15c7b251fa7 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -821,31 +821,31 @@ mod bench { #[bench] fn to_str_bin(bh: &mut BenchHarness) { - let mut rng = XorShiftRng::new(); + let mut rng = XorShiftRng::new().unwrap(); bh.iter(|| { rng.gen::().to_str_radix(2); }) } #[bench] fn to_str_oct(bh: &mut BenchHarness) { - let mut rng = XorShiftRng::new(); + let mut rng = XorShiftRng::new().unwrap(); bh.iter(|| { rng.gen::().to_str_radix(8); }) } #[bench] fn to_str_dec(bh: &mut BenchHarness) { - let mut rng = XorShiftRng::new(); + let mut rng = XorShiftRng::new().unwrap(); bh.iter(|| { rng.gen::().to_str_radix(10); }) } #[bench] fn to_str_hex(bh: &mut BenchHarness) { - let mut rng = XorShiftRng::new(); + let mut rng = XorShiftRng::new().unwrap(); bh.iter(|| { rng.gen::().to_str_radix(16); }) } #[bench] fn to_str_base_36(bh: &mut BenchHarness) { - let mut rng = XorShiftRng::new(); + let mut rng = XorShiftRng::new().unwrap(); bh.iter(|| { rng.gen::().to_str_radix(36); }) } } @@ -857,31 +857,31 @@ mod bench { #[bench] fn to_str_bin(bh: &mut BenchHarness) { - let mut rng = XorShiftRng::new(); + let mut rng = XorShiftRng::new().unwrap(); bh.iter(|| { rng.gen::().to_str_radix(2); }) } #[bench] fn to_str_oct(bh: &mut BenchHarness) { - let mut rng = XorShiftRng::new(); + let mut rng = XorShiftRng::new().unwrap(); bh.iter(|| { rng.gen::().to_str_radix(8); }) } #[bench] fn to_str_dec(bh: &mut BenchHarness) { - let mut rng = XorShiftRng::new(); + let mut rng = XorShiftRng::new().unwrap(); bh.iter(|| { rng.gen::().to_str_radix(10); }) } #[bench] fn to_str_hex(bh: &mut BenchHarness) { - let mut rng = XorShiftRng::new(); + let mut rng = XorShiftRng::new().unwrap(); bh.iter(|| { rng.gen::().to_str_radix(16); }) } #[bench] fn to_str_base_36(bh: &mut BenchHarness) { - let mut rng = XorShiftRng::new(); + let mut rng = XorShiftRng::new().unwrap(); bh.iter(|| { rng.gen::().to_str_radix(36); }) } } @@ -893,7 +893,7 @@ mod bench { #[bench] fn float_to_str(bh: &mut BenchHarness) { - let mut rng = XorShiftRng::new(); + let mut rng = XorShiftRng::new().unwrap(); bh.iter(|| { f64::to_str(rng.gen()); }) } } diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 5485aaec085..a5583afb31d 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -663,10 +663,12 @@ pub fn errno() -> uint { } } -/// Get a string representing the platform-dependent last error -pub fn last_os_error() -> ~str { +/// Return the string corresponding to an `errno()` value of `errnum`. +pub fn error_string(errnum: uint) -> ~str { + return strerror(errnum); + #[cfg(unix)] - fn strerror() -> ~str { + fn strerror(errnum: uint) -> ~str { #[cfg(target_os = "macos")] #[cfg(target_os = "android")] #[cfg(target_os = "freebsd")] @@ -702,7 +704,7 @@ pub fn last_os_error() -> ~str { let p = buf.as_mut_ptr(); unsafe { - if strerror_r(errno() as c_int, p, buf.len() as libc::size_t) < 0 { + if strerror_r(errnum as c_int, p, buf.len() as libc::size_t) < 0 { fail!("strerror_r failure"); } @@ -711,7 +713,7 @@ pub fn last_os_error() -> ~str { } #[cfg(windows)] - fn strerror() -> ~str { + fn strerror(errnum: uint) -> ~str { use libc::types::os::arch::extra::DWORD; use libc::types::os::arch::extra::LPWSTR; use libc::types::os::arch::extra::LPVOID; @@ -735,7 +737,6 @@ pub fn last_os_error() -> ~str { // This value is calculated from the macro // MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT) let langId = 0x0800 as DWORD; - let err = errno() as DWORD; let mut buf = [0 as WCHAR, ..TMPBUF_SZ]; @@ -743,7 +744,7 @@ pub fn last_os_error() -> ~str { let res = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, ptr::mut_null(), - err, + errnum as DWORD, langId, buf.as_mut_ptr(), buf.len() as DWORD, @@ -751,18 +752,21 @@ pub fn last_os_error() -> ~str { if res == 0 { // Sometimes FormatMessageW can fail e.g. system doesn't like langId, let fm_err = errno(); - return format!("OS Error {} (FormatMessageW() returned error {})", err, fm_err); + return format!("OS Error {} (FormatMessageW() returned error {})", errnum, fm_err); } let msg = str::from_utf16(str::truncate_utf16_at_nul(buf)); match msg { - Some(msg) => format!("OS Error {}: {}", err, msg), - None => format!("OS Error {} (FormatMessageW() returned invalid UTF-16)", err), + Some(msg) => format!("OS Error {}: {}", errnum, msg), + None => format!("OS Error {} (FormatMessageW() returned invalid UTF-16)", errnum), } } } +} - strerror() +/// Get a string representing the platform-dependent last error +pub fn last_os_error() -> ~str { + error_string(errno() as uint) } static mut EXIT_STATUS: AtomicInt = INIT_ATOMIC_INT; diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs index d9700ea9980..0f90135512c 100644 --- a/src/libstd/rt/task.rs +++ b/src/libstd/rt/task.rs @@ -435,7 +435,7 @@ mod test { #[test] fn rng() { use rand::{StdRng, Rng}; - let mut r = StdRng::new(); + let mut r = StdRng::new().unwrap(); let _ = r.next_u32(); } diff --git a/src/test/bench/noise.rs b/src/test/bench/noise.rs index 4954f083b36..babf3f737fb 100644 --- a/src/test/bench/noise.rs +++ b/src/test/bench/noise.rs @@ -41,7 +41,7 @@ struct Noise2DContext { impl Noise2DContext { fn new() -> Noise2DContext { - let mut rng = StdRng::new(); + let mut rng = StdRng::new().unwrap(); let mut rgradients = [Vec2 { x: 0.0, y: 0.0 }, ..256]; for x in rgradients.mut_iter() {