Merge pull request #160 from tkilbourn/master

Implement rand for Fuchsia
diff --git a/Cargo.toml b/Cargo.toml
index 51ff34a..e7dd0f4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "rand"
-version = "0.3.15"
+version = "0.3.16"
 authors = ["The Rust Project Developers"]
 license = "MIT/Apache-2.0"
 readme = "README.md"
@@ -25,3 +25,6 @@
 
 [workspace]
 members = ["rand-derive"]
+
+[target.'cfg(target_os = "fuchsia")'.dependencies]
+magenta = "^0.1.1"
diff --git a/src/os.rs b/src/os.rs
index 7f24119..82a09ad 100644
--- a/src/os.rs
+++ b/src/os.rs
@@ -68,6 +68,7 @@
 #[cfg(all(unix, not(target_os = "ios"),
           not(target_os = "nacl"),
           not(target_os = "freebsd"),
+          not(target_os = "fuchsia"),
           not(target_os = "openbsd"),
           not(target_os = "redox")))]
 mod imp {
@@ -380,6 +381,45 @@
     }
 }
 
+#[cfg(target_os = "fuchsia")]
+mod imp {
+    extern crate magenta;
+
+    use std::io;
+    use Rng;
+
+    use super::{next_u32, next_u64};
+
+    #[derive(Debug)]
+    pub struct OsRng;
+
+    impl OsRng {
+        pub fn new() -> io::Result<OsRng> {
+            Ok(OsRng)
+        }
+    }
+
+    impl Rng for OsRng {
+        fn next_u32(&mut self) -> u32 {
+            next_u32(&mut |v| self.fill_bytes(v))
+        }
+        fn next_u64(&mut self) -> u64 {
+            next_u64(&mut |v| self.fill_bytes(v))
+        }
+        fn fill_bytes(&mut self, v: &mut [u8]) {
+            for s in v.chunks_mut(magenta::MX_CPRNG_DRAW_MAX_LEN) {
+                let mut filled = 0;
+                while filled < s.len() {
+                    match magenta::cprng_draw(&mut s[filled..]) {
+                        Ok(actual) => filled += actual,
+                        Err(e) => panic!("cprng_draw failed: {:?}", e),
+                    };
+                }
+            }
+        }
+    }
+}
+
 #[cfg(windows)]
 mod imp {
     use std::io;