Merge pull request #181 from cpeterso/cpeterso-weak_rng-seed

 Seed weak_rng with the current time if OsRng fails
diff --git a/src/lib.rs b/src/lib.rs
index cd856d1..3c7d2cc 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -254,6 +254,7 @@
 use std::io;
 use std::rc::Rc;
 use std::num::Wrapping as w;
+use std::time;
 
 pub use os::OsRng;
 
@@ -891,13 +892,9 @@
 /// seeded `Rng` for consistency over time you should pick one algorithm and
 /// create the `Rng` yourself.
 ///
-/// This will read randomness from the operating system to seed the
-/// generator.
+/// This will seed the generator with randomness from thread_rng.
 pub fn weak_rng() -> XorShiftRng {
-    match OsRng::new() {
-        Ok(mut r) => r.gen(),
-        Err(e) => panic!("weak_rng: failed to create seeded RNG: {:?}", e)
-    }
+    thread_rng().gen()
 }
 
 /// Controls how the thread-local RNG is reseeded.
@@ -906,9 +903,9 @@
 
 impl reseeding::Reseeder<StdRng> for ThreadRngReseeder {
     fn reseed(&mut self, rng: &mut StdRng) {
-        *rng = match StdRng::new() {
-            Ok(r) => r,
-            Err(e) => panic!("could not reseed thread_rng: {}", e)
+        match StdRng::new() {
+            Ok(r) => *rng = r,
+            Err(_) => rng.reseed(&weak_seed())
         }
     }
 }
@@ -925,8 +922,9 @@
 /// generator, seeded by the system. Intended to be used in method
 /// chaining style, e.g. `thread_rng().gen::<i32>()`.
 ///
-/// The RNG provided will reseed itself from the operating system
-/// after generating a certain amount of randomness.
+/// After generating a certain amount of randomness, the RNG will reseed itself
+/// from the operating system or, if the operating system RNG returns an error,
+/// a seed based on the current system time.
 ///
 /// The internal RNG used is platform and architecture dependent, even
 /// if the operating system random number generator is rigged to give
@@ -937,7 +935,7 @@
     thread_local!(static THREAD_RNG_KEY: Rc<RefCell<ThreadRngInner>> = {
         let r = match StdRng::new() {
             Ok(r) => r,
-            Err(e) => panic!("could not initialize thread_rng: {}", e)
+            Err(_) => StdRng::from_seed(&weak_seed())
         };
         let rng = reseeding::ReseedingRng::new(r,
                                                THREAD_RNG_RESEED_THRESHOLD,
@@ -948,6 +946,14 @@
     ThreadRng { rng: THREAD_RNG_KEY.with(|t| t.clone()) }
 }
 
+fn weak_seed() -> [usize; 2] {
+    let now = time::SystemTime::now();
+    let unix_time = now.duration_since(time::UNIX_EPOCH).unwrap();
+    let seconds = unix_time.as_secs() as usize;
+    let nanoseconds = unix_time.subsec_nanos() as usize;
+    [seconds, nanoseconds]
+}
+
 impl Rng for ThreadRng {
     fn next_u32(&mut self) -> u32 {
         self.rng.borrow_mut().next_u32()
@@ -1042,7 +1048,8 @@
 
 #[cfg(test)]
 mod test {
-    use super::{Rng, thread_rng, random, SeedableRng, StdRng, sample};
+    use super::{Rng, thread_rng, random, SeedableRng, StdRng, sample,
+                weak_rng};
     use std::iter::repeat;
 
     pub struct MyRng<R> { inner: R }
@@ -1286,4 +1293,13 @@
         let string2 = r.gen_ascii_chars().take(100).collect::<String>();
         assert_eq!(string1, string2);
     }
+
+    #[test]
+    fn test_weak_rng() {
+        let s = weak_rng().gen_iter::<usize>().take(256).collect::<Vec<usize>>();
+        let mut ra: StdRng = SeedableRng::from_seed(&s[..]);
+        let mut rb: StdRng = SeedableRng::from_seed(&s[..]);
+        assert!(iter_eq(ra.gen_ascii_chars().take(100),
+                        rb.gen_ascii_chars().take(100)));
+    }
 }