Bug 1409444 - Update rand to 0.3.17. r?Manishearth draft
authorXidorn Quan <me@upsuper.org>
Mon, 23 Oct 2017 15:52:44 +1100
changeset 684578 4a034387d4bd1a9fc94f9b275b30545339e86d47
parent 684577 bf492ded9c7e18117aa7813795a81437a9dc2af2
child 736896 acd4d5f04f93395b7be08152e26a4822911d3d77
push id85651
push userxquan@mozilla.com
push dateMon, 23 Oct 2017 04:57:23 +0000
reviewersManishearth
bugs1409444
milestone58.0a1
Bug 1409444 - Update rand to 0.3.17. r?Manishearth MozReview-Commit-ID: DjCEQV9t2hi
testing/geckodriver/Cargo.lock
third_party/rust/fuchsia-zircon-sys/.cargo-checksum.json
third_party/rust/fuchsia-zircon-sys/.cargo-ok
third_party/rust/fuchsia-zircon-sys/BUILD.gn
third_party/rust/fuchsia-zircon-sys/Cargo.toml
third_party/rust/fuchsia-zircon-sys/examples/hello.rs
third_party/rust/fuchsia-zircon-sys/src/definitions.rs
third_party/rust/fuchsia-zircon-sys/src/lib.rs
third_party/rust/fuchsia-zircon/.cargo-checksum.json
third_party/rust/fuchsia-zircon/.cargo-ok
third_party/rust/fuchsia-zircon/BUILD.gn
third_party/rust/fuchsia-zircon/Cargo.toml
third_party/rust/fuchsia-zircon/LICENSE
third_party/rust/fuchsia-zircon/README.md
third_party/rust/fuchsia-zircon/examples/BUILD.gn
third_party/rust/fuchsia-zircon/src/channel.rs
third_party/rust/fuchsia-zircon/src/event.rs
third_party/rust/fuchsia-zircon/src/eventpair.rs
third_party/rust/fuchsia-zircon/src/fifo.rs
third_party/rust/fuchsia-zircon/src/job.rs
third_party/rust/fuchsia-zircon/src/lib.rs
third_party/rust/fuchsia-zircon/src/port.rs
third_party/rust/fuchsia-zircon/src/process.rs
third_party/rust/fuchsia-zircon/src/socket.rs
third_party/rust/fuchsia-zircon/src/thread.rs
third_party/rust/fuchsia-zircon/src/timer.rs
third_party/rust/fuchsia-zircon/src/vmo.rs
third_party/rust/fuchsia-zircon/tools/BUILD.gn
third_party/rust/fuchsia-zircon/tools/README.md
third_party/rust/fuchsia-zircon/tools/clang_wrapper.cc
third_party/rust/fuchsia-zircon/tools/gen_status.py
third_party/rust/rand/.cargo-checksum.json
third_party/rust/rand/.travis.yml
third_party/rust/rand/Cargo.toml
third_party/rust/rand/README.md
third_party/rust/rand/appveyor.yml
third_party/rust/rand/benches/bench.rs
third_party/rust/rand/src/chacha.rs
third_party/rust/rand/src/distributions/exponential.rs
third_party/rust/rand/src/distributions/gamma.rs
third_party/rust/rand/src/distributions/mod.rs
third_party/rust/rand/src/distributions/normal.rs
third_party/rust/rand/src/distributions/range.rs
third_party/rust/rand/src/isaac.rs
third_party/rust/rand/src/lib.rs
third_party/rust/rand/src/os.rs
third_party/rust/rand/src/rand_impls.rs
third_party/rust/rand/src/read.rs
third_party/rust/rand/src/reseeding.rs
toolkit/library/gtest/rust/Cargo.lock
toolkit/library/rust/Cargo.lock
--- a/testing/geckodriver/Cargo.lock
+++ b/testing/geckodriver/Cargo.lock
@@ -66,16 +66,21 @@ name = "base64"
 version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "bitflags"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "bitflags"
 version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "byteorder"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
@@ -151,16 +156,32 @@ name = "flate2"
 version = "0.2.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "fuchsia-zircon"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "fuchsia-zircon-sys"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "gcc"
 version = "0.3.42"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "httparse"
 version = "1.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -371,19 +392,20 @@ source = "registry+https://github.com/ru
 
 [[package]]
 name = "podio"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "rand"
-version = "0.3.15"
+version = "0.3.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
+ "fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "redox_syscall"
 version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
@@ -510,17 +532,17 @@ name = "strsim"
 version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "tempdir"
 version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "term_size"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -621,17 +643,17 @@ name = "utf8-ranges"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "uuid"
 version = "0.1.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "vec_map"
 version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
@@ -689,27 +711,30 @@ dependencies = [
 ]
 
 [metadata]
 "checksum advapi32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "307c92332867e586720c0222ee9d890bbe8431711efed8a1b06bc5b40fc66bd7"
 "checksum aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0638fd549427caa90c499814196d1b9e3725eb4d15d7339d6de073a680ed0ca2"
 "checksum backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72f9b4182546f4b04ebc4ab7f84948953a118bd6021a1b6a6c909e3e94f6be76"
 "checksum backtrace-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d192fd129132fbc97497c1f2ec2c2c5174e376b95f535199ef4fe0a293d33842"
 "checksum base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30e93c03064e7590d0466209155251b90c22e37fab1daf2771582598b5827557"
+"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
 "checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4"
 "checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8"
 "checksum bzip2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3eafc42c44e0d827de6b1c131175098fe7fb53b8ce8a47e65cb3ea94688be24"
 "checksum bzip2-sys 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "98ce3fff84d4e90011f464bbdf48e3428f04270439f703868fd489d2aaedfc30"
 "checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
 "checksum chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9213f7cd7c27e95c2b57c49f0e69b1ea65b27138da84a170133fd21b07659c00"
 "checksum clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b8f69e518f967224e628896b54e41ff6acfb4dcfefc5076325c36525dac900f"
 "checksum cookie 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a54aa6d675d62b2f95b56b331b5222a520149a54f23a2d21974dfcc69caf0a9d"
 "checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97"
 "checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
 "checksum flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "36df0166e856739905cd3d7e0b210fe818592211a008862599845e012d8d304c"
+"checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159"
+"checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82"
 "checksum gcc 0.3.42 (registry+https://github.com/rust-lang/crates.io-index)" = "291055c78f59ca3d84c99026c9501c469413d386bb46be1e1cf1d285cd1db3b0"
 "checksum httparse 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77f756bed9ee3a83ce98774f4155b42a31b787029013f3a7d83eca714e500e21"
 "checksum hyper 0.10.10 (registry+https://github.com/rust-lang/crates.io-index)" = "36e108e0b1fa2d17491cbaac4bc460dc0956029d10ccf83c913dd0e5db3e7f07"
 "checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d"
 "checksum isatty 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fa500db770a99afe2a0f2229be2a3d09c7ed9d7e4e8440bf71253141994e240f"
 "checksum kernel32-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e014dab1082fd9d80ea1fa6fcb261b47ed3eb511612a14198bb507701add083e"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
 "checksum ktmw32-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f9313a869ff779ae08dd990b75a92dc06aa16d771f41305f7286649cd39a0ee"
@@ -728,17 +753,17 @@ dependencies = [
 "checksum msdos_time 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "65ba9d75bcea84e07812618fedf284a64776c2f2ea0cad6bca7f69739695a958"
 "checksum num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "98b15ba84e910ea7a1973bccd3df7b31ae282bf9d8bd2897779950c9b8303d40"
 "checksum num-integer 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "21e4df1098d1d797d27ef0c69c178c3fab64941559b290fcae198e0825c9c8b5"
 "checksum num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d1891bd7b936f12349b7d1403761c8a0b85a18b148e9da4429d5d102c1a41e"
 "checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99"
 "checksum num_cpus 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a225d1e2717567599c24f88e49f00856c6e825a12125181ee42c4257e3688d39"
 "checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356"
 "checksum podio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e5422a1ee1bc57cc47ae717b0137314258138f38fd5f3cea083f43a9725383a0"
-"checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"
+"checksum rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "61efcbcd9fa8d8fbb07c84e34a8af18a1ff177b449689ad38a6e9457ecc7b2ae"
 "checksum redox_syscall 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd35cc9a8bdec562c757e3d43c1526b5c6d2653e23e2315065bc25556550753"
 "checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01"
 "checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457"
 "checksum rust-ini 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "06d4e8b0b50e7e7f827d609fa9746e1cf6371a1fa15404a1a0a86152a801079f"
 "checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95"
 "checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b"
 "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084"
 "checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon-sys/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","BUILD.gn":"862eccf06f706db5af1e0041b10b6b637dbc77257b6c4f536a72fc7d21d3dfb9","Cargo.toml":"d05607413136805977463d1c2b979e7692ea1ac06e051d598de440c64603e886","examples/hello.rs":"66c6a147b98b913fef8e7a7da6387fb735f7f1e2c00abc8794a32a8cf0320851","src/definitions.rs":"0b13b741cad9ba42c1da5b654c6d60f03183a7c79a5843e7734a95b4f934d81f","src/lib.rs":"83c8b96c64b442d72a7b87455f182e6ffef6bf2cd7aa2c0c88db992ac9060bda"},"package":"43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82"}
\ No newline at end of file
new file mode 100644
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon-sys/BUILD.gn
@@ -0,0 +1,11 @@
+# Copyright 2017 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/rust/rust_library.gni")
+
+rust_library("fuchsia-zircon-sys") {
+  deps = [
+    "//third_party/rust-crates:bitflags-0.7.0",
+  ]
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon-sys/Cargo.toml
@@ -0,0 +1,21 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "fuchsia-zircon-sys"
+version = "0.2.0"
+authors = ["Raph Levien <raph@google.com>"]
+description = "Low-level Rust bindings for the Zircon kernel"
+license = "BSD-3-Clause"
+repository = "https://fuchsia.googlesource.com/garnet/"
+[dependencies.bitflags]
+version = "0.7.0"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon-sys/examples/hello.rs
@@ -0,0 +1,14 @@
+// Copyright 2016 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+extern crate fuchsia_zircon_sys as zircon_sys;
+
+pub fn main() {
+    let time = unsafe { zircon_sys::zx_time_get(zircon_sys::ZX_CLOCK_MONOTONIC) };
+    println!("before sleep, time = {}", time);
+    unsafe { zircon_sys::zx_nanosleep(zircon_sys::zx_deadline_after(1000_000_000)); }
+    let time = unsafe { zircon_sys::zx_time_get(zircon_sys::ZX_CLOCK_MONOTONIC) };
+    println!("after sleep, time = {}", time);
+}
+
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon-sys/src/definitions.rs
@@ -0,0 +1,903 @@
+// Copyright 2017 The Fuchsia Authors. All rights reserved.
+// This is a GENERATED file, see //zircon/system/host/sysgen.
+// The license governing this file can be found in the LICENSE file.
+
+#[link(name = "zircon")]
+extern {
+    pub fn zx_time_get(
+        clock_id: u32
+        ) -> zx_time_t;
+
+    pub fn zx_nanosleep(
+        deadline: zx_time_t
+        ) -> zx_status_t;
+
+    pub fn zx_ticks_get(
+        ) -> u64;
+
+    pub fn zx_ticks_per_second(
+        ) -> u64;
+
+    pub fn zx_deadline_after(
+        nanoseconds: zx_duration_t
+        ) -> zx_time_t;
+
+    pub fn zx_clock_adjust(
+        handle: zx_handle_t,
+        clock_id: u32,
+        offset: i64
+        ) -> zx_status_t;
+
+    pub fn zx_system_get_num_cpus(
+        ) -> u32;
+
+    pub fn zx_system_get_version(
+        version: *mut u8,
+        version_len: u32
+        ) -> zx_status_t;
+
+    pub fn zx_system_get_physmem(
+        ) -> u64;
+
+    pub fn zx_cache_flush(
+        addr: *const u8,
+        len: usize,
+        options: u32
+        ) -> zx_status_t;
+
+    pub fn zx_handle_close(
+        handle: zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_handle_duplicate(
+        handle: zx_handle_t,
+        rights: zx_rights_t,
+        out: *mut zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_handle_replace(
+        handle: zx_handle_t,
+        rights: zx_rights_t,
+        out: *mut zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_object_wait_one(
+        handle: zx_handle_t,
+        waitfor: zx_signals_t,
+        deadline: zx_time_t,
+        observed: *mut zx_signals_t
+        ) -> zx_status_t;
+
+    pub fn zx_object_wait_many(
+        items: *mut zx_wait_item_t,
+        count: u32,
+        deadline: zx_time_t
+        ) -> zx_status_t;
+
+    pub fn zx_object_wait_async(
+        handle: zx_handle_t,
+        port_handle: zx_handle_t,
+        key: u64,
+        signals: zx_signals_t,
+        options: u32
+        ) -> zx_status_t;
+
+    pub fn zx_object_signal(
+        handle: zx_handle_t,
+        clear_mask: u32,
+        set_mask: u32
+        ) -> zx_status_t;
+
+    pub fn zx_object_signal_peer(
+        handle: zx_handle_t,
+        clear_mask: u32,
+        set_mask: u32
+        ) -> zx_status_t;
+
+    pub fn zx_object_get_property(
+        handle: zx_handle_t,
+        property: u32,
+        value: *mut u8,
+        size: usize
+        ) -> zx_status_t;
+
+    pub fn zx_object_set_property(
+        handle: zx_handle_t,
+        property: u32,
+        value: *const u8,
+        size: usize
+        ) -> zx_status_t;
+
+    pub fn zx_object_set_cookie(
+        handle: zx_handle_t,
+        scope: zx_handle_t,
+        cookie: u64
+        ) -> zx_status_t;
+
+    pub fn zx_object_get_cookie(
+        handle: zx_handle_t,
+        scope: zx_handle_t,
+        cookie: *mut u64
+        ) -> zx_status_t;
+
+    pub fn zx_object_get_info(
+        handle: zx_handle_t,
+        topic: u32,
+        buffer: *mut u8,
+        buffer_size: usize,
+        actual_count: *mut usize,
+        avail_count: *mut usize
+        ) -> zx_status_t;
+
+    pub fn zx_object_get_child(
+        handle: zx_handle_t,
+        koid: u64,
+        rights: zx_rights_t,
+        out: *mut zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_channel_create(
+        options: u32,
+        out0: *mut zx_handle_t,
+        out1: *mut zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_channel_read(
+        handle: zx_handle_t,
+        options: u32,
+        bytes: *mut u8,
+        handles: *mut zx_handle_t,
+        num_bytes: u32,
+        num_handles: u32,
+        actual_bytes: *mut u32,
+        actual_handles: *mut u32
+        ) -> zx_status_t;
+
+    pub fn zx_channel_write(
+        handle: zx_handle_t,
+        options: u32,
+        bytes: *const u8,
+        num_bytes: u32,
+        handles: *const zx_handle_t,
+        num_handles: u32
+        ) -> zx_status_t;
+
+    pub fn zx_channel_call_noretry(
+        handle: zx_handle_t,
+        options: u32,
+        deadline: zx_time_t,
+        args: *const zx_channel_call_args_t,
+        actual_bytes: *mut u32,
+        actual_handles: *mut u32,
+        read_status: *mut zx_status_t
+        ) -> zx_status_t;
+
+    pub fn zx_channel_call_finish(
+        deadline: zx_time_t,
+        args: *const zx_channel_call_args_t,
+        actual_bytes: *mut u32,
+        actual_handles: *mut u32,
+        read_status: *mut zx_status_t
+        ) -> zx_status_t;
+
+    pub fn zx_channel_call(
+        handle: zx_handle_t,
+        options: u32,
+        deadline: zx_time_t,
+        args: *const zx_channel_call_args_t,
+        actual_bytes: *mut u32,
+        actual_handles: *mut u32,
+        read_status: *mut zx_status_t
+        ) -> zx_status_t;
+
+    pub fn zx_socket_create(
+        options: u32,
+        out0: *mut zx_handle_t,
+        out1: *mut zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_socket_write(
+        handle: zx_handle_t,
+        options: u32,
+        buffer: *const u8,
+        size: usize,
+        actual: *mut usize
+        ) -> zx_status_t;
+
+    pub fn zx_socket_read(
+        handle: zx_handle_t,
+        options: u32,
+        buffer: *mut u8,
+        size: usize,
+        actual: *mut usize
+        ) -> zx_status_t;
+
+    pub fn zx_thread_exit(
+        );
+
+    pub fn zx_thread_create(
+        process: zx_handle_t,
+        name: *const u8,
+        name_len: u32,
+        options: u32,
+        out: *mut zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_thread_start(
+        handle: zx_handle_t,
+        thread_entry: usize,
+        stack: usize,
+        arg1: usize,
+        arg2: usize
+        ) -> zx_status_t;
+
+    pub fn zx_thread_read_state(
+        handle: zx_handle_t,
+        kind: u32,
+        buffer: *mut u8,
+        len: u32,
+        actual: *mut u32
+        ) -> zx_status_t;
+
+    pub fn zx_thread_write_state(
+        handle: zx_handle_t,
+        kind: u32,
+        buffer: *const u8,
+        buffer_len: u32
+        ) -> zx_status_t;
+
+    pub fn zx_thread_set_priority(
+        prio: i32
+        ) -> zx_status_t;
+
+    pub fn zx_process_exit(
+        retcode: isize
+        );
+
+    pub fn zx_process_create(
+        job: zx_handle_t,
+        name: *const u8,
+        name_len: u32,
+        options: u32,
+        proc_handle: *mut zx_handle_t,
+        vmar_handle: *mut zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_process_start(
+        process_handle: zx_handle_t,
+        thread_handle: zx_handle_t,
+        entry: usize,
+        stack: usize,
+        arg_handle: zx_handle_t,
+        arg2: usize
+        ) -> zx_status_t;
+
+    pub fn zx_process_read_memory(
+        proc_: zx_handle_t,
+        vaddr: usize,
+        buffer: *mut u8,
+        len: usize,
+        actual: *mut usize
+        ) -> zx_status_t;
+
+    pub fn zx_process_write_memory(
+        proc_: zx_handle_t,
+        vaddr: usize,
+        buffer: *const u8,
+        len: usize,
+        actual: *mut usize
+        ) -> zx_status_t;
+
+    pub fn zx_job_create(
+        parent_job: zx_handle_t,
+        options: u32,
+        out: *mut zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_job_set_policy(
+        job: zx_handle_t,
+        options: u32,
+        topic: u32,
+        policy: *const u8,
+        count: u32
+        ) -> zx_status_t;
+
+    pub fn zx_task_bind_exception_port(
+        object: zx_handle_t,
+        eport: zx_handle_t,
+        key: u64,
+        options: u32
+        ) -> zx_status_t;
+
+    pub fn zx_task_suspend(
+        task_handle: zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_task_resume(
+        task_handle: zx_handle_t,
+        options: u32
+        ) -> zx_status_t;
+
+    pub fn zx_task_kill(
+        task_handle: zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_event_create(
+        options: u32,
+        out: *mut zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_eventpair_create(
+        options: u32,
+        out0: *mut zx_handle_t,
+        out1: *mut zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_futex_wait(
+        value_ptr: *mut zx_futex_t,
+        current_value: isize,
+        deadline: zx_time_t
+        ) -> zx_status_t;
+
+    pub fn zx_futex_wake(
+        value_ptr: *const zx_futex_t,
+        count: u32
+        ) -> zx_status_t;
+
+    pub fn zx_futex_requeue(
+        wake_ptr: *mut zx_futex_t,
+        wake_count: u32,
+        current_value: isize,
+        requeue_ptr: *mut zx_futex_t,
+        requeue_count: u32
+        ) -> zx_status_t;
+
+    pub fn zx_port_create(
+        options: u32,
+        out: *mut zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_port_queue(
+        handle: zx_handle_t,
+        packet: *const u8,
+        size: usize
+        ) -> zx_status_t;
+
+    pub fn zx_port_wait(
+        handle: zx_handle_t,
+        deadline: zx_time_t,
+        packet: *mut u8,
+        size: usize
+        ) -> zx_status_t;
+
+    pub fn zx_port_cancel(
+        handle: zx_handle_t,
+        source: zx_handle_t,
+        key: u64
+        ) -> zx_status_t;
+
+    pub fn zx_timer_create(
+        options: u32,
+        clock_id: u32,
+        out: *mut zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_timer_set(
+        handle: zx_handle_t,
+        deadline: zx_time_t,
+        slack: zx_duration_t
+        ) -> zx_status_t;
+
+    pub fn zx_timer_cancel(
+        handle: zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_vmo_create(
+        size: u64,
+        options: u32,
+        out: *mut zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_vmo_read(
+        handle: zx_handle_t,
+        data: *mut u8,
+        offset: u64,
+        len: usize,
+        actual: *mut usize
+        ) -> zx_status_t;
+
+    pub fn zx_vmo_write(
+        handle: zx_handle_t,
+        data: *const u8,
+        offset: u64,
+        len: usize,
+        actual: *mut usize
+        ) -> zx_status_t;
+
+    pub fn zx_vmo_get_size(
+        handle: zx_handle_t,
+        size: *mut u64
+        ) -> zx_status_t;
+
+    pub fn zx_vmo_set_size(
+        handle: zx_handle_t,
+        size: u64
+        ) -> zx_status_t;
+
+    pub fn zx_vmo_op_range(
+        handle: zx_handle_t,
+        op: u32,
+        offset: u64,
+        size: u64,
+        buffer: *mut u8,
+        buffer_size: usize
+        ) -> zx_status_t;
+
+    pub fn zx_vmo_clone(
+        handle: zx_handle_t,
+        options: u32,
+        offset: u64,
+        size: u64,
+        out: *mut zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_vmo_set_cache_policy(
+        handle: zx_handle_t,
+        cache_policy: u32
+        ) -> zx_status_t;
+
+    pub fn zx_vmar_allocate(
+        parent_vmar_handle: zx_handle_t,
+        offset: usize,
+        size: usize,
+        map_flags: u32,
+        child_vmar: *mut zx_handle_t,
+        child_addr: *mut usize
+        ) -> zx_status_t;
+
+    pub fn zx_vmar_destroy(
+        vmar_handle: zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_vmar_map(
+        vmar_handle: zx_handle_t,
+        vmar_offset: usize,
+        vmo_handle: zx_handle_t,
+        vmo_offset: u64,
+        len: usize,
+        map_flags: u32,
+        mapped_addr: *mut usize
+        ) -> zx_status_t;
+
+    pub fn zx_vmar_unmap(
+        vmar_handle: zx_handle_t,
+        addr: usize,
+        len: usize
+        ) -> zx_status_t;
+
+    pub fn zx_vmar_protect(
+        vmar_handle: zx_handle_t,
+        addr: usize,
+        len: usize,
+        prot_flags: u32
+        ) -> zx_status_t;
+
+    pub fn zx_vmar_root_self() -> zx_handle_t;
+
+    pub fn zx_cprng_draw(
+        buffer: *mut u8,
+        len: usize,
+        actual: *mut usize
+        ) -> zx_status_t;
+
+    pub fn zx_cprng_add_entropy(
+        buffer: *const u8,
+        len: usize
+        ) -> zx_status_t;
+
+    pub fn zx_fifo_create(
+        elem_count: u32,
+        elem_size: u32,
+        options: u32,
+        out0: *mut zx_handle_t,
+        out1: *mut zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_fifo_read(
+        handle: zx_handle_t,
+        data: *mut u8,
+        len: usize,
+        num_written: *mut u32
+        ) -> zx_status_t;
+
+    pub fn zx_fifo_write(
+        handle: zx_handle_t,
+        data: *const u8,
+        len: usize,
+        num_written: *mut u32
+        ) -> zx_status_t;
+
+    pub fn zx_vmar_unmap_handle_close_thread_exit(
+        vmar_handle: zx_handle_t,
+        addr: usize,
+        len: usize,
+        handle: zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_futex_wake_handle_close_thread_exit(
+        value_ptr: *const zx_futex_t,
+        count: u32,
+        new_value: isize,
+        handle: zx_handle_t
+        );
+
+    pub fn zx_log_create(
+        options: u32,
+        out: *mut zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_log_write(
+        handle: zx_handle_t,
+        len: u32,
+        buffer: *const u8,
+        options: u32
+        ) -> zx_status_t;
+
+    pub fn zx_log_read(
+        handle: zx_handle_t,
+        len: u32,
+        buffer: *mut u8,
+        options: u32
+        ) -> zx_status_t;
+
+    pub fn zx_ktrace_read(
+        handle: zx_handle_t,
+        data: *mut u8,
+        offset: u32,
+        len: u32,
+        actual: *mut u32
+        ) -> zx_status_t;
+
+    pub fn zx_ktrace_control(
+        handle: zx_handle_t,
+        action: u32,
+        options: u32,
+        ptr: *mut u8
+        ) -> zx_status_t;
+
+    pub fn zx_ktrace_write(
+        handle: zx_handle_t,
+        id: u32,
+        arg0: u32,
+        arg1: u32
+        ) -> zx_status_t;
+
+    pub fn zx_mtrace_control(
+        handle: zx_handle_t,
+        kind: u32,
+        action: u32,
+        options: u32,
+        ptr: *mut u8,
+        size: u32
+        ) -> zx_status_t;
+
+    pub fn zx_debug_read(
+        handle: zx_handle_t,
+        buffer: *mut u8,
+        length: u32
+        ) -> zx_status_t;
+
+    pub fn zx_debug_write(
+        buffer: *const u8,
+        length: u32
+        ) -> zx_status_t;
+
+    pub fn zx_debug_send_command(
+        resource_handle: zx_handle_t,
+        buffer: *const u8,
+        length: u32
+        ) -> zx_status_t;
+
+    pub fn zx_interrupt_create(
+        handle: zx_handle_t,
+        vector: u32,
+        options: u32,
+        out_handle: *mut zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_interrupt_complete(
+        handle: zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_interrupt_wait(
+        handle: zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_interrupt_signal(
+        handle: zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_mmap_device_io(
+        handle: zx_handle_t,
+        io_addr: u32,
+        len: u32
+        ) -> zx_status_t;
+
+    pub fn zx_vmo_create_contiguous(
+        rsrc_handle: zx_handle_t,
+        size: usize,
+        alignment_log2: u32,
+        out: *mut zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_vmo_create_physical(
+        rsrc_handle: zx_handle_t,
+        paddr: zx_paddr_t,
+        size: usize,
+        out: *mut zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_bootloader_fb_get_info(
+        format: *mut u32,
+        width: *mut u32,
+        height: *mut u32,
+        stride: *mut u32
+        ) -> zx_status_t;
+
+    pub fn zx_set_framebuffer(
+        handle: zx_handle_t,
+        vaddr: *mut u8,
+        len: u32,
+        format: u32,
+        width: u32,
+        height: u32,
+        stride: u32
+        ) -> zx_status_t;
+
+    pub fn zx_set_framebuffer_vmo(
+        handle: zx_handle_t,
+        vmo: zx_handle_t,
+        len: u32,
+        format: u32,
+        width: u32,
+        height: u32,
+        stride: u32
+        ) -> zx_status_t;
+
+    pub fn zx_pci_get_nth_device(
+        handle: zx_handle_t,
+        index: u32,
+        out_info: *mut zx_pcie_device_info_t,
+        out_handle: *mut zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_pci_enable_bus_master(
+        handle: zx_handle_t,
+        enable: bool
+        ) -> zx_status_t;
+
+    pub fn zx_pci_enable_pio(
+        handle: zx_handle_t,
+        enable: bool
+        ) -> zx_status_t;
+
+    pub fn zx_pci_reset_device(
+        handle: zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_pci_cfg_pio_rw(
+        handle: zx_handle_t,
+        bus: u8,
+        dev: u8,
+        func: u8,
+        offset: u8,
+        val: *mut u32,
+        width: usize,
+        write: bool
+        ) -> zx_status_t;
+
+    pub fn zx_pci_get_bar(
+        handle: zx_handle_t,
+        bar_num: u32,
+        out_bar: *mut zx_pci_resource_t
+        ) -> zx_status_t;
+
+    pub fn zx_pci_get_config(
+        handle: zx_handle_t,
+        out_config: *mut zx_pci_resource_t
+        ) -> zx_status_t;
+
+    pub fn zx_pci_io_write(
+        handle: zx_handle_t,
+        bar_num: u32,
+        offset: u32,
+        len: u32,
+        value: u32
+        ) -> zx_status_t;
+
+    pub fn zx_pci_io_read(
+        handle: zx_handle_t,
+        bar_num: u32,
+        offset: u32,
+        len: u32,
+        out_value: *mut u32
+        ) -> zx_status_t;
+
+    pub fn zx_pci_map_interrupt(
+        handle: zx_handle_t,
+        which_irq: i32,
+        out_handle: *mut zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_pci_query_irq_mode_caps(
+        handle: zx_handle_t,
+        mode: u32,
+        out_max_irqs: *mut u32
+        ) -> zx_status_t;
+
+    pub fn zx_pci_set_irq_mode(
+        handle: zx_handle_t,
+        mode: u32,
+        requested_irq_count: u32
+        ) -> zx_status_t;
+
+    pub fn zx_pci_init(
+        handle: zx_handle_t,
+        init_buf: *const zx_pci_init_arg_t,
+        len: u32
+        ) -> zx_status_t;
+
+    pub fn zx_pci_add_subtract_io_range(
+        handle: zx_handle_t,
+        mmio: bool,
+        base: u64,
+        len: u64,
+        add: bool
+        ) -> zx_status_t;
+
+    pub fn zx_acpi_uefi_rsdp(
+        handle: zx_handle_t
+        ) -> u64;
+
+    pub fn zx_acpi_cache_flush(
+        handle: zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_resource_create(
+        parent_handle: zx_handle_t,
+        kind: u32,
+        low: u64,
+        high: u64,
+        resource_out: *mut zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_guest_create(
+        resource: zx_handle_t,
+        options: u32,
+        physmem_vmo: zx_handle_t,
+        out: *mut zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_guest_set_trap(
+        guest: zx_handle_t,
+        kind: u32,
+        addr: zx_vaddr_t,
+        len: usize,
+        fifo: zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_vcpu_create(
+        guest: zx_handle_t,
+        options: u32,
+        args: *const zx_vcpu_create_args_t,
+        out: *mut zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_vcpu_resume(
+        vcpu: zx_handle_t,
+        packet: *mut zx_guest_packet_t
+        ) -> zx_status_t;
+
+    pub fn zx_vcpu_interrupt(
+        vcpu: zx_handle_t,
+        vector: u32
+        ) -> zx_status_t;
+
+    pub fn zx_vcpu_read_state(
+        vcpu: zx_handle_t,
+        kind: u32,
+        buffer: *mut u8,
+        len: u32
+        ) -> zx_status_t;
+
+    pub fn zx_vcpu_write_state(
+        vcpu: zx_handle_t,
+        kind: u32,
+        buffer: *const u8,
+        len: u32
+        ) -> zx_status_t;
+
+    pub fn zx_system_mexec(
+        kernel: zx_handle_t,
+        bootimage: zx_handle_t,
+        cmdline: *const u8,
+        cmdline_len: u32
+        ) -> zx_status_t;
+
+    pub fn zx_job_set_relative_importance(
+        root_resource: zx_handle_t,
+        job: zx_handle_t,
+        less_important_job: zx_handle_t
+        ) -> zx_status_t;
+
+    pub fn zx_syscall_test_0(
+        ) -> zx_status_t;
+
+    pub fn zx_syscall_test_1(
+        a: isize
+        ) -> zx_status_t;
+
+    pub fn zx_syscall_test_2(
+        a: isize,
+        b: isize
+        ) -> zx_status_t;
+
+    pub fn zx_syscall_test_3(
+        a: isize,
+        b: isize,
+        c: isize
+        ) -> zx_status_t;
+
+    pub fn zx_syscall_test_4(
+        a: isize,
+        b: isize,
+        c: isize,
+        d: isize
+        ) -> zx_status_t;
+
+    pub fn zx_syscall_test_5(
+        a: isize,
+        b: isize,
+        c: isize,
+        d: isize,
+        e: isize
+        ) -> zx_status_t;
+
+    pub fn zx_syscall_test_6(
+        a: isize,
+        b: isize,
+        c: isize,
+        d: isize,
+        e: isize,
+        f: isize
+        ) -> zx_status_t;
+
+    pub fn zx_syscall_test_7(
+        a: isize,
+        b: isize,
+        c: isize,
+        d: isize,
+        e: isize,
+        f: isize,
+        g: isize
+        ) -> zx_status_t;
+
+    pub fn zx_syscall_test_8(
+        a: isize,
+        b: isize,
+        c: isize,
+        d: isize,
+        e: isize,
+        f: isize,
+        g: isize,
+        h: isize
+        ) -> zx_status_t;
+
+    pub fn zx_syscall_test_wrapper(
+        a: isize,
+        b: isize,
+        c: isize
+        ) -> zx_status_t;
+
+
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon-sys/src/lib.rs
@@ -0,0 +1,460 @@
+// Copyright 2016 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#![allow(non_camel_case_types)]
+
+#[macro_use]
+extern crate bitflags;
+
+use std::{cmp, fmt};
+
+pub type zx_handle_t = i32;
+
+pub type zx_status_t = i32;
+
+pub type zx_futex_t = isize;
+pub type zx_addr_t = usize;
+pub type zx_paddr_t = usize;
+pub type zx_vaddr_t = usize;
+pub type zx_off_t = u64;
+
+// Auto-generated using tools/gen_status.py
+pub const ZX_OK                    : zx_status_t = 0;
+pub const ZX_ERR_INTERNAL          : zx_status_t = -1;
+pub const ZX_ERR_NOT_SUPPORTED     : zx_status_t = -2;
+pub const ZX_ERR_NO_RESOURCES      : zx_status_t = -3;
+pub const ZX_ERR_NO_MEMORY         : zx_status_t = -4;
+pub const ZX_ERR_CALL_FAILED       : zx_status_t = -5;
+pub const ZX_ERR_INTERRUPTED_RETRY : zx_status_t = -6;
+pub const ZX_ERR_INVALID_ARGS      : zx_status_t = -10;
+pub const ZX_ERR_BAD_HANDLE        : zx_status_t = -11;
+pub const ZX_ERR_WRONG_TYPE        : zx_status_t = -12;
+pub const ZX_ERR_BAD_SYSCALL       : zx_status_t = -13;
+pub const ZX_ERR_OUT_OF_RANGE      : zx_status_t = -14;
+pub const ZX_ERR_BUFFER_TOO_SMALL  : zx_status_t = -15;
+pub const ZX_ERR_BAD_STATE         : zx_status_t = -20;
+pub const ZX_ERR_TIMED_OUT         : zx_status_t = -21;
+pub const ZX_ERR_SHOULD_WAIT       : zx_status_t = -22;
+pub const ZX_ERR_CANCELED          : zx_status_t = -23;
+pub const ZX_ERR_PEER_CLOSED       : zx_status_t = -24;
+pub const ZX_ERR_NOT_FOUND         : zx_status_t = -25;
+pub const ZX_ERR_ALREADY_EXISTS    : zx_status_t = -26;
+pub const ZX_ERR_ALREADY_BOUND     : zx_status_t = -27;
+pub const ZX_ERR_UNAVAILABLE       : zx_status_t = -28;
+pub const ZX_ERR_ACCESS_DENIED     : zx_status_t = -30;
+pub const ZX_ERR_IO                : zx_status_t = -40;
+pub const ZX_ERR_IO_REFUSED        : zx_status_t = -41;
+pub const ZX_ERR_IO_DATA_INTEGRITY : zx_status_t = -42;
+pub const ZX_ERR_IO_DATA_LOSS      : zx_status_t = -43;
+pub const ZX_ERR_BAD_PATH          : zx_status_t = -50;
+pub const ZX_ERR_NOT_DIR           : zx_status_t = -51;
+pub const ZX_ERR_NOT_FILE          : zx_status_t = -52;
+pub const ZX_ERR_FILE_BIG          : zx_status_t = -53;
+pub const ZX_ERR_NO_SPACE          : zx_status_t = -54;
+pub const ZX_ERR_STOP              : zx_status_t = -60;
+pub const ZX_ERR_NEXT              : zx_status_t = -61;
+
+pub type zx_time_t = u64;
+pub type zx_duration_t = u64;
+pub const ZX_TIME_INFINITE : zx_time_t = ::std::u64::MAX;
+
+bitflags! {
+    #[repr(C)]
+    pub flags zx_signals_t: u32 {
+        const ZX_SIGNAL_NONE              = 0,
+        const ZX_OBJECT_SIGNAL_ALL        = 0x00ffffff,
+        const ZX_USER_SIGNAL_ALL          = 0xff000000,
+        const ZX_OBJECT_SIGNAL_0          = 1 << 0,
+        const ZX_OBJECT_SIGNAL_1          = 1 << 1,
+        const ZX_OBJECT_SIGNAL_2          = 1 << 2,
+        const ZX_OBJECT_SIGNAL_3          = 1 << 3,
+        const ZX_OBJECT_SIGNAL_4          = 1 << 4,
+        const ZX_OBJECT_SIGNAL_5          = 1 << 5,
+        const ZX_OBJECT_SIGNAL_6          = 1 << 6,
+        const ZX_OBJECT_SIGNAL_7          = 1 << 7,
+        const ZX_OBJECT_SIGNAL_8          = 1 << 8,
+        const ZX_OBJECT_SIGNAL_9          = 1 << 9,
+        const ZX_OBJECT_SIGNAL_10         = 1 << 10,
+        const ZX_OBJECT_SIGNAL_11         = 1 << 11,
+        const ZX_OBJECT_SIGNAL_12         = 1 << 12,
+        const ZX_OBJECT_SIGNAL_13         = 1 << 13,
+        const ZX_OBJECT_SIGNAL_14         = 1 << 14,
+        const ZX_OBJECT_SIGNAL_15         = 1 << 15,
+        const ZX_OBJECT_SIGNAL_16         = 1 << 16,
+        const ZX_OBJECT_SIGNAL_17         = 1 << 17,
+        const ZX_OBJECT_SIGNAL_18         = 1 << 18,
+        const ZX_OBJECT_SIGNAL_19         = 1 << 19,
+        const ZX_OBJECT_SIGNAL_20         = 1 << 20,
+        const ZX_OBJECT_SIGNAL_21         = 1 << 21,
+        const ZX_OBJECT_LAST_HANDLE       = 1 << 22,
+        const ZX_OBJECT_HANDLE_CLOSED     = 1 << 23,
+        const ZX_USER_SIGNAL_0            = 1 << 24,
+        const ZX_USER_SIGNAL_1            = 1 << 25,
+        const ZX_USER_SIGNAL_2            = 1 << 26,
+        const ZX_USER_SIGNAL_3            = 1 << 27,
+        const ZX_USER_SIGNAL_4            = 1 << 28,
+        const ZX_USER_SIGNAL_5            = 1 << 29,
+        const ZX_USER_SIGNAL_6            = 1 << 30,
+        const ZX_USER_SIGNAL_7            = 1 << 31,
+
+        const ZX_OBJECT_READABLE          = ZX_OBJECT_SIGNAL_0.bits,
+        const ZX_OBJECT_WRITABLE          = ZX_OBJECT_SIGNAL_1.bits,
+        const ZX_OBJECT_PEER_CLOSED       = ZX_OBJECT_SIGNAL_2.bits,
+
+        // Cancelation (handle was closed while waiting with it)
+        const ZX_SIGNAL_HANDLE_CLOSED     = ZX_OBJECT_HANDLE_CLOSED.bits,
+
+        // Only one user-more reference (handle) to the object exists.
+        const ZX_SIGNAL_LAST_HANDLE       = ZX_OBJECT_LAST_HANDLE.bits,
+
+        // Event
+        const ZX_EVENT_SIGNALED           = ZX_OBJECT_SIGNAL_3.bits,
+
+        // EventPair
+        const ZX_EPAIR_SIGNALED           = ZX_OBJECT_SIGNAL_3.bits,
+        const ZX_EPAIR_CLOSED             = ZX_OBJECT_SIGNAL_2.bits,
+
+        // Task signals (process, thread, job)
+        const ZX_TASK_TERMINATED          = ZX_OBJECT_SIGNAL_3.bits,
+
+        // Channel
+        const ZX_CHANNEL_READABLE         = ZX_OBJECT_SIGNAL_0.bits,
+        const ZX_CHANNEL_WRITABLE         = ZX_OBJECT_SIGNAL_1.bits,
+        const ZX_CHANNEL_PEER_CLOSED      = ZX_OBJECT_SIGNAL_2.bits,
+
+        // Socket
+        const ZX_SOCKET_READABLE          = ZX_OBJECT_SIGNAL_0.bits,
+        const ZX_SOCKET_WRITABLE          = ZX_OBJECT_SIGNAL_1.bits,
+        const ZX_SOCKET_PEER_CLOSED       = ZX_OBJECT_SIGNAL_2.bits,
+
+        // Port
+        const ZX_PORT_READABLE            = ZX_OBJECT_READABLE.bits,
+
+        // Resource
+        const ZX_RESOURCE_DESTROYED       = ZX_OBJECT_SIGNAL_3.bits,
+        const ZX_RESOURCE_READABLE        = ZX_OBJECT_READABLE.bits,
+        const ZX_RESOURCE_WRITABLE        = ZX_OBJECT_WRITABLE.bits,
+        const ZX_RESOURCE_CHILD_ADDED     = ZX_OBJECT_SIGNAL_4.bits,
+
+        // Fifo
+        const ZX_FIFO_READABLE            = ZX_OBJECT_READABLE.bits,
+        const ZX_FIFO_WRITABLE            = ZX_OBJECT_WRITABLE.bits,
+        const ZX_FIFO_PEER_CLOSED         = ZX_OBJECT_PEER_CLOSED.bits,
+
+        // Job
+        const ZX_JOB_NO_PROCESSES         = ZX_OBJECT_SIGNAL_3.bits,
+        const ZX_JOB_NO_JOBS              = ZX_OBJECT_SIGNAL_4.bits,
+
+        // Process
+        const ZX_PROCESS_TERMINATED       = ZX_OBJECT_SIGNAL_3.bits,
+
+        // Thread
+        const ZX_THREAD_TERMINATED        = ZX_OBJECT_SIGNAL_3.bits,
+
+        // Log
+        const ZX_LOG_READABLE             = ZX_OBJECT_READABLE.bits,
+        const ZX_LOG_WRITABLE             = ZX_OBJECT_WRITABLE.bits,
+
+        // Timer
+        const ZX_TIMER_SIGNALED           = ZX_OBJECT_SIGNAL_3.bits,
+    }
+}
+
+pub type zx_size_t = usize;
+pub type zx_ssize_t = isize;
+
+bitflags! {
+    #[repr(C)]
+    pub flags zx_rights_t: u32 {
+        const ZX_RIGHT_NONE         = 0,
+        const ZX_RIGHT_DUPLICATE    = 1 << 0,
+        const ZX_RIGHT_TRANSFER     = 1 << 1,
+        const ZX_RIGHT_READ         = 1 << 2,
+        const ZX_RIGHT_WRITE        = 1 << 3,
+        const ZX_RIGHT_EXECUTE      = 1 << 4,
+        const ZX_RIGHT_MAP          = 1 << 5,
+        const ZX_RIGHT_GET_PROPERTY = 1 << 6,
+        const ZX_RIGHT_SET_PROPERTY = 1 << 7,
+        const ZX_RIGHT_DEBUG        = 1 << 8,
+        const ZX_RIGHT_SAME_RIGHTS  = 1 << 31,
+    }
+}
+
+// clock ids
+pub const ZX_CLOCK_MONOTONIC: u32 = 0;
+
+// Buffer size limits on the cprng syscalls
+pub const ZX_CPRNG_DRAW_MAX_LEN: usize = 256;
+pub const ZX_CPRNG_ADD_ENTROPY_MAX_LEN: usize = 256;
+
+// Socket flags and limits.
+pub const ZX_SOCKET_HALF_CLOSE: u32 = 1;
+
+// VM Object opcodes
+pub const ZX_VMO_OP_COMMIT: u32 = 1;
+pub const ZX_VMO_OP_DECOMMIT: u32 = 2;
+pub const ZX_VMO_OP_LOCK: u32 = 3;
+pub const ZX_VMO_OP_UNLOCK: u32 = 4;
+pub const ZX_VMO_OP_LOOKUP: u32 = 5;
+pub const ZX_VMO_OP_CACHE_SYNC: u32 = 6;
+pub const ZX_VMO_OP_CACHE_INVALIDATE: u32 = 7;
+pub const ZX_VMO_OP_CACHE_CLEAN: u32 = 8;
+pub const ZX_VMO_OP_CACHE_CLEAN_INVALIDATE: u32 = 9;
+
+// VM Object clone flags
+pub const ZX_VMO_CLONE_COPY_ON_WRITE: u32 = 1;
+
+// Mapping flags to vmar routines
+bitflags! {
+    #[repr(C)]
+    pub flags zx_vmar_flags_t: u32 {
+    // flags to vmar routines
+        const ZX_VM_FLAG_PERM_READ          = 1  << 0,
+        const ZX_VM_FLAG_PERM_WRITE         = 1  << 1,
+        const ZX_VM_FLAG_PERM_EXECUTE       = 1  << 2,
+        const ZX_VM_FLAG_COMPACT            = 1  << 3,
+        const ZX_VM_FLAG_SPECIFIC           = 1  << 4,
+        const ZX_VM_FLAG_SPECIFIC_OVERWRITE = 1  << 5,
+        const ZX_VM_FLAG_CAN_MAP_SPECIFIC   = 1  << 6,
+        const ZX_VM_FLAG_CAN_MAP_READ       = 1  << 7,
+        const ZX_VM_FLAG_CAN_MAP_WRITE      = 1  << 8,
+        const ZX_VM_FLAG_CAN_MAP_EXECUTE    = 1  << 9,
+    }
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum zx_cache_policy_t {
+    ZX_CACHE_POLICY_CACHED = 0,
+    ZX_CACHE_POLICY_UNCACHED = 1,
+    ZX_CACHE_POLICY_UNCACHED_DEVICE = 2,
+    ZX_CACHE_POLICY_WRITE_COMBINING = 3,
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub struct zx_wait_item_t {
+    pub handle: zx_handle_t,
+    pub waitfor: zx_signals_t,
+    pub pending: zx_signals_t,
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub struct zx_waitset_result_t {
+    pub cookie: u64,
+    pub status: zx_status_t,
+    pub observed: zx_signals_t,
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub struct zx_channel_call_args_t {
+    pub wr_bytes: *const u8,
+    pub wr_handles: *const zx_handle_t,
+    pub rd_bytes: *mut u8,
+    pub rd_handles: *mut zx_handle_t,
+    pub wr_num_bytes: u32,
+    pub wr_num_handles: u32,
+    pub rd_num_bytes: u32,
+    pub rd_num_handles: u32,
+}
+
+pub type zx_pci_irq_swizzle_lut_t = [[[u32; 4]; 8]; 32];
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub struct zx_pci_init_arg_t {
+    pub dev_pin_to_global_irq: zx_pci_irq_swizzle_lut_t,
+    pub num_irqs: u32,
+    pub irqs: [zx_irq_t; 32],
+    pub ecam_window_count: u32,
+    // Note: the ecam_windows field is actually a variable size array.
+    // We use a fixed size array to match the C repr.
+    pub ecam_windows: [zx_ecam_window_t; 1],
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub struct zx_irq_t {
+    pub global_irq: u32,
+    pub level_triggered: bool,
+    pub active_high: bool,
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub struct zx_ecam_window_t {
+    pub base: u64,
+    pub size: usize,
+    pub bus_start: u8,
+    pub bus_end: u8,
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub struct zx_pcie_device_info_t {
+    pub vendor_id: u16,
+    pub device_id: u16,
+    pub base_class: u8,
+    pub sub_class: u8,
+    pub program_interface: u8,
+    pub revision_id: u8,
+    pub bus_id: u8,
+    pub dev_id: u8,
+    pub func_id: u8,
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub struct zx_pci_resource_t {
+    pub type_: u32,
+    pub size: usize,
+    // TODO: Actually a union
+    pub pio_addr: usize,
+}
+
+// TODO: Actually a union
+pub type zx_rrec_t = [u8; 64];
+
+// Ports V2
+#[repr(u32)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum zx_packet_type_t {
+    ZX_PKT_TYPE_USER = 0,
+    ZX_PKT_TYPE_SIGNAL_ONE = 1,
+    ZX_PKT_TYPE_SIGNAL_REP = 2,
+}
+
+impl Default for zx_packet_type_t {
+    fn default() -> Self {
+        zx_packet_type_t::ZX_PKT_TYPE_USER
+    }
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct zx_packet_signal_t {
+    pub trigger: zx_signals_t,
+    pub observed: zx_signals_t,
+    pub count: u64,
+}
+
+pub const ZX_WAIT_ASYNC_ONCE: u32 = 0;
+pub const ZX_WAIT_ASYNC_REPEATING: u32 = 1;
+
+// Actually a union of different integer types, but this should be good enough.
+pub type zx_packet_user_t = [u8; 32];
+
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
+pub struct zx_port_packet_t {
+    pub key: u64,
+    pub packet_type: zx_packet_type_t,
+    pub status: i32,
+    pub union: [u8; 32],
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub struct zx_guest_io_t {
+    port: u16,
+    access_size: u8,
+    input: bool,
+    // TODO: Actually a union
+    data: [u8; 4],
+}
+
+#[cfg(target_arch="aarch64")]
+#[repr(C)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub struct zx_guest_memory_t {
+    addr: zx_vaddr_t,
+    inst: u32,
+}
+
+pub const X86_MAX_INST_LEN: usize = 15;
+
+#[cfg(target_arch="x86_64")]
+#[repr(C)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub struct zx_guest_memory_t {
+    addr: zx_vaddr_t,
+    inst_len: u8,
+    inst_buf: [u8; X86_MAX_INST_LEN],
+}
+
+#[repr(u8)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum zx_guest_packet_t_type {
+    ZX_GUEST_PKT_MEMORY = 1,
+    ZX_GUEST_PKT_IO = 2,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub union zx_guest_packet_t_union {
+    // ZX_GUEST_PKT_MEMORY
+    memory: zx_guest_memory_t,
+    // ZX_GUEST_PKT_IO
+    io: zx_guest_io_t,
+}
+
+// Note: values of this type must maintain the invariant that
+// `packet_type` correctly indicates the type of `contents`.
+// Failure to do so will result in unsafety.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct zx_guest_packet_t {
+    packet_type: zx_guest_packet_t_type,
+    contents: zx_guest_packet_t_union,
+}
+
+impl fmt::Debug for zx_guest_packet_t {
+    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+        write!(f, "zx_guest_packet_t {{ packet_type: {:?}, contents: ", self.packet_type)?;
+        match self.packet_type {
+            zx_guest_packet_t_type::ZX_GUEST_PKT_MEMORY =>
+                write!(f, "zx_guest_packet_t_union {{ memory: {:?} }} }}",
+                    unsafe { self.contents.memory }
+                ),
+            zx_guest_packet_t_type::ZX_GUEST_PKT_IO =>
+                write!(f, "zx_guest_packet_t_union {{ io: {:?} }} }}",
+                    unsafe { self.contents.io }
+                ),
+        }
+    }
+}
+
+impl cmp::PartialEq for zx_guest_packet_t {
+    fn eq(&self, other: &Self) -> bool {
+        (self.packet_type == other.packet_type) &&
+        match self.packet_type {
+            zx_guest_packet_t_type::ZX_GUEST_PKT_MEMORY =>
+                unsafe { self.contents.memory == other.contents.memory },
+            zx_guest_packet_t_type::ZX_GUEST_PKT_IO =>
+                unsafe { self.contents.io == other.contents.io },
+        }
+    }
+}
+
+impl cmp::Eq for zx_guest_packet_t {}
+
+#[cfg(target_arch="x86_64")]
+#[repr(C)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub struct zx_vcpu_create_args_t {
+    pub ip: zx_vaddr_t,
+    pub cr3: zx_vaddr_t,
+    pub apic_vmo: zx_handle_t,
+}
+
+#[cfg(not(target_arch="x86_64"))]
+#[repr(C)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub struct zx_vcpu_create_args_t {
+    pub ip: zx_vaddr_t,
+}
+
+include!("definitions.rs");
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","BUILD.gn":"1d49d75a432f5b4587b59a50a9b86a21e2a3faf1fff60876b4e486e43cffca35","Cargo.toml":"263dce41c44c34a70fb9803acbfb77c1801ff2b23f0fa46bb2c90f14f33f0ac9","LICENSE":"f82f9062a6dff28145c185f90f94c485eebdc2bb4c6f1c840513709e6d228453","README.md":"f4bff6efc5d888460e2d1eaf62fa0eaca8afe7b51df528ad7829340ec397b32c","examples/BUILD.gn":"fb7a491a26e5f3d48b8796db80d475be2d361bada7311213363dcce4efa9d4fc","src/channel.rs":"0b3c3761a831c9211e327f5332e58becc287cf2444b44164a4f680dc5bdded50","src/event.rs":"9b11c6c0c9fcdbe4e45c03f4a671ef66c31a1be540d3f50a5d0602314fdc1294","src/eventpair.rs":"aca1c6a15450badbfe71c33e287bab8aa05d6fff5968513b191436b853929ca8","src/fifo.rs":"ecc49463cc28713c1375ecafc8008b806767417da72fcc8685b42078ec0308df","src/job.rs":"827db2e4ea1bbf5ecabec9fb279f2721792032e4223b6bd15b56922d80c7ac01","src/lib.rs":"5bc01f9c7d1f3316826bf86cc5c8488523ca7f2ad2a58a8b539c3b49aed3f1a2","src/port.rs":"695aa7114d88d476954fde689180502f22ea6b70339855ebff89dce6694abb9e","src/process.rs":"0b5e42c4eb79b2a7fff9c70f0d99c8b805cefab99285e94fabf2542290b4b990","src/socket.rs":"6e8b799a8f605d42681660129989c9c6427b9039b83de9954c61aa351596218f","src/thread.rs":"d703414c440b5fa597dbafe7b8be925a94d1fe0cf8b47366c786b45eaaec4c60","src/timer.rs":"8fc50736e6a928cabccf78b18aec3e57ac7e5a57c1c519a1cd34158f59e1ff65","src/vmo.rs":"0f219777d5abffcfbc49a43f7eff3ef92b854d1d964579dc9a01d33ba57341c1","tools/BUILD.gn":"f4ce07b2906e6cde15a9d2ec253c58fbfe88ea1819083f864c154a0f1c50c14f","tools/README.md":"0217d58913c32b7e8aa231da852d96307d8387f99e2352a026196150cb180d07","tools/clang_wrapper.cc":"c62dcc1f71cab03f7e215c8800d798bd05af56fa7510ea8d59d6b15dce2b6a6f","tools/gen_status.py":"a2330db86564e12412af2dce60d4c605c0ab203fcdea8039d5c6a8e7f218a3c3"},"package":"f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159"}
\ No newline at end of file
new file mode 100644
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon/BUILD.gn
@@ -0,0 +1,13 @@
+# Copyright 2017 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/rust/rust_library.gni")
+
+rust_library("fuchsia-zircon") {
+  deps = [
+    "//garnet/public/rust/crates/fuchsia-zircon/fuchsia-zircon-sys",
+  ]
+
+  with_tests = true
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon/Cargo.toml
@@ -0,0 +1,21 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "fuchsia-zircon"
+version = "0.2.1"
+authors = ["Raph Levien <raph@google.com>"]
+description = "Rust bindings for the Zircon kernel"
+license = "BSD-3-Clause"
+repository = "https://fuchsia.googlesource.com/garnet/"
+[dependencies.fuchsia-zircon-sys]
+version = "0.2.0"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon/LICENSE
@@ -0,0 +1,27 @@
+// Copyright 2016 The Fuchsia Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon/README.md
@@ -0,0 +1,12 @@
+Rust bindings for Zircon kernel
+================================
+
+This repository contains Rust language bindings for Zircon kernel syscalls. The
+main crate contains type-safe wrappers, while the inner "sys" crate contains the
+raw types and FFI declarations.
+
+There are two ways to build Rust artifacts targeting Fuchsia; using the
+[Fargo](https://fuchsia.googlesource.com/fargo/) cross compiling tool or
+including your [artifact in the GN
+build](https://fuchsia.googlesource.com/docs/+/master/rust.md). Of the two,
+Fargo is likely better for exploration and experimentation.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon/examples/BUILD.gn
@@ -0,0 +1,9 @@
+# Copyright 2017 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+group("examples") {
+  deps = [
+    "//garnet/public/rust/crates/fuchsia-zircon/examples/zx_toy",
+  ]
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon/src/channel.rs
@@ -0,0 +1,380 @@
+// Copyright 2017 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//! Type-safe bindings for Zircon channel objects.
+
+use {AsHandleRef, HandleBased, Handle, HandleRef, INVALID_HANDLE, Peered, Status, Time, usize_into_u32, size_to_u32_sat};
+use {sys, handle_drop, into_result};
+use std::mem;
+
+/// An object representing a Zircon
+/// [channel](https://fuchsia.googlesource.com/zircon/+/master/docs/objects/channel.md).
+///
+/// As essentially a subtype of `Handle`, it can be freely interconverted.
+#[derive(Debug, Eq, PartialEq)]
+pub struct Channel(Handle);
+impl_handle_based!(Channel);
+impl Peered for Channel {}
+
+impl Channel {
+    /// Create a channel, resulting an a pair of `Channel` objects representing both
+    /// sides of the channel. Messages written into one maybe read from the opposite.
+    ///
+    /// Wraps the
+    /// [zx_channel_create](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/channel_create.md)
+    /// syscall.
+    pub fn create(opts: ChannelOpts) -> Result<(Channel, Channel), Status> {
+        unsafe {
+            let mut handle0 = 0;
+            let mut handle1 = 0;
+            let status = sys::zx_channel_create(opts as u32, &mut handle0, &mut handle1);
+            into_result(status, ||
+                (Self::from(Handle(handle0)),
+                    Self::from(Handle(handle1))))
+        }
+    }
+
+    /// Read a message from a channel. Wraps the
+    /// [zx_channel_read](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/channel_read.md)
+    /// syscall.
+    ///
+    /// If the `MessageBuf` lacks the capacity to hold the pending message,
+    /// returns an `Err` with the number of bytes and number of handles needed.
+    /// Otherwise returns an `Ok` with the result as usual.
+    pub fn read_raw(&self, opts: u32, buf: &mut MessageBuf)
+        -> Result<Result<(), Status>, (usize, usize)>
+    {
+        unsafe {
+            buf.reset_handles();
+            let raw_handle = self.raw_handle();
+            let mut num_bytes: u32 = size_to_u32_sat(buf.bytes.capacity());
+            let mut num_handles: u32 = size_to_u32_sat(buf.handles.capacity());
+            let status = sys::zx_channel_read(raw_handle, opts,
+                buf.bytes.as_mut_ptr(), buf.handles.as_mut_ptr(),
+                num_bytes, num_handles, &mut num_bytes, &mut num_handles);
+            if status == sys::ZX_ERR_BUFFER_TOO_SMALL {
+                Err((num_bytes as usize, num_handles as usize))
+            } else {
+                Ok(into_result(status, || {
+                    buf.bytes.set_len(num_bytes as usize);
+                    buf.handles.set_len(num_handles as usize);
+                }))
+            }
+        }
+    }
+
+    /// Read a message from a channel.
+    ///
+    /// Note that this method can cause internal reallocations in the `MessageBuf`
+    /// if it is lacks capacity to hold the full message. If such reallocations
+    /// are not desirable, use `read_raw` instead.
+    pub fn read(&self, opts: u32, buf: &mut MessageBuf) -> Result<(), Status> {
+        loop {
+            match self.read_raw(opts, buf) {
+                Ok(result) => return result,
+                Err((num_bytes, num_handles)) => {
+                    buf.ensure_capacity_bytes(num_bytes);
+                    buf.ensure_capacity_handles(num_handles);
+                }
+            }
+        }
+    }
+
+    /// Write a message to a channel. Wraps the
+    /// [zx_channel_write](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/channel_write.md)
+    /// syscall.
+    pub fn write(&self, bytes: &[u8], handles: &mut Vec<Handle>, opts: u32)
+            -> Result<(), Status>
+    {
+        let n_bytes = try!(usize_into_u32(bytes.len()).map_err(|_| Status::ErrOutOfRange));
+        let n_handles = try!(usize_into_u32(handles.len()).map_err(|_| Status::ErrOutOfRange));
+        unsafe {
+            let status = sys::zx_channel_write(self.raw_handle(), opts, bytes.as_ptr(), n_bytes,
+                handles.as_ptr() as *const sys::zx_handle_t, n_handles);
+            into_result(status, || {
+                // Handles were successfully transferred, forget them on sender side
+                handles.set_len(0);
+            })
+        }
+    }
+
+    /// Send a message consisting of the given bytes and handles to a channel and await a reply. The
+    /// bytes should start with a four byte 'txid' which is used to identify the matching reply.
+    ///
+    /// Wraps the
+    /// [zx_channel_call](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/channel_call.md)
+    /// syscall.
+    ///
+    /// Note that unlike [`read`][read], the caller must ensure that the MessageBuf has enough
+    /// capacity for the bytes and handles which will be received, as replies which are too large
+    /// are discarded.
+    ///
+    /// On failure returns the both the main and read status.
+    ///
+    /// [read]: struct.Channel.html#method.read
+    pub fn call(&self, options: u32, timeout: Time, bytes: &[u8], handles: &mut Vec<Handle>,
+        buf: &mut MessageBuf) -> Result<(), (Status, Status)>
+    {
+        let write_num_bytes = try!(usize_into_u32(bytes.len()).map_err(
+            |_| (Status::ErrOutOfRange, Status::NoError)));
+        let write_num_handles = try!(usize_into_u32(handles.len()).map_err(
+            |_| (Status::ErrOutOfRange, Status::NoError)));
+        buf.reset_handles();
+        let read_num_bytes: u32 = size_to_u32_sat(buf.bytes.capacity());
+        let read_num_handles: u32 = size_to_u32_sat(buf.handles.capacity());
+        let args = sys::zx_channel_call_args_t {
+            wr_bytes: bytes.as_ptr(),
+            wr_handles: handles.as_ptr() as *const sys::zx_handle_t,
+            rd_bytes: buf.bytes.as_mut_ptr(),
+            rd_handles: buf.handles.as_mut_ptr(),
+            wr_num_bytes: write_num_bytes,
+            wr_num_handles: write_num_handles,
+            rd_num_bytes: read_num_bytes,
+            rd_num_handles: read_num_handles,
+        };
+        let mut actual_read_bytes: u32 = 0;
+        let mut actual_read_handles: u32 = 0;
+        let mut read_status = sys::ZX_OK;
+        let status = unsafe {
+            sys::zx_channel_call(self.raw_handle(), options, timeout, &args, &mut actual_read_bytes,
+                &mut actual_read_handles, &mut read_status)
+        };
+        if status == sys::ZX_OK || status == sys::ZX_ERR_TIMED_OUT || status == sys::ZX_ERR_CALL_FAILED
+        {
+            // Handles were successfully transferred, even if we didn't get a response, so forget
+            // them on the sender side.
+            unsafe { handles.set_len(0); }
+        }
+        unsafe {
+            buf.bytes.set_len(actual_read_bytes as usize);
+            buf.handles.set_len(actual_read_handles as usize);
+        }
+        if status == sys::ZX_OK {
+            Ok(())
+        } else {
+            Err((Status::from_raw(status), Status::from_raw(read_status)))
+        }
+    }
+}
+
+/// Options for creating a channel.
+#[repr(u32)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum ChannelOpts {
+    /// A normal channel.
+    Normal = 0,
+}
+
+impl Default for ChannelOpts {
+    fn default() -> Self {
+        ChannelOpts::Normal
+    }
+}
+
+/// A buffer for _receiving_ messages from a channel.
+///
+/// A `MessageBuf` is essentially a byte buffer and a vector of
+/// handles, but move semantics for "taking" handles requires special handling.
+///
+/// Note that for sending messages to a channel, the caller manages the buffers,
+/// using a plain byte slice and `Vec<Handle>`.
+#[derive(Default)]
+#[derive(Debug)]
+pub struct MessageBuf {
+    bytes: Vec<u8>,
+    handles: Vec<sys::zx_handle_t>,
+}
+
+impl MessageBuf {
+    /// Create a new, empty, message buffer.
+    pub fn new() -> Self {
+        Default::default()
+    }
+
+    /// Ensure that the buffer has the capacity to hold at least `n_bytes` bytes.
+    pub fn ensure_capacity_bytes(&mut self, n_bytes: usize) {
+        ensure_capacity(&mut self.bytes, n_bytes);
+    }
+
+    /// Ensure that the buffer has the capacity to hold at least `n_handles` handles.
+    pub fn ensure_capacity_handles(&mut self, n_handles: usize) {
+        ensure_capacity(&mut self.handles, n_handles);
+    }
+
+    /// Get a reference to the bytes of the message buffer, as a `&[u8]` slice.
+    pub fn bytes(&self) -> &[u8] {
+        self.bytes.as_slice()
+    }
+
+    /// The number of handles in the message buffer. Note this counts the number
+    /// available when the message was received; `take_handle` does not affect
+    /// the count.
+    pub fn n_handles(&self) -> usize {
+        self.handles.len()
+    }
+
+    /// Take the handle at the specified index from the message buffer. If the
+    /// method is called again with the same index, it will return `None`, as
+    /// will happen if the index exceeds the number of handles available.
+    pub fn take_handle(&mut self, index: usize) -> Option<Handle> {
+        self.handles.get_mut(index).and_then(|handleref|
+            if *handleref == INVALID_HANDLE {
+                None
+            } else {
+                Some(Handle(mem::replace(handleref, INVALID_HANDLE)))
+            }
+        )
+    }
+
+    fn drop_handles(&mut self) {
+        for &handle in &self.handles {
+            if handle != 0 {
+                handle_drop(handle);
+            }
+        }
+    }
+
+    fn reset_handles(&mut self) {
+        self.drop_handles();
+        self.handles.clear();
+    }
+}
+
+impl Drop for MessageBuf {
+    fn drop(&mut self) {
+        self.drop_handles();
+    }
+}
+
+fn ensure_capacity<T>(vec: &mut Vec<T>, size: usize) {
+    let len = vec.len();
+    if size > len {
+        vec.reserve(size - len);
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use {Duration, ZX_CHANNEL_READABLE, ZX_CHANNEL_WRITABLE, ZX_RIGHT_SAME_RIGHTS, ZX_SIGNAL_LAST_HANDLE, Vmo, VmoOpts};
+    use deadline_after;
+    use std::thread;
+
+    #[test]
+    fn channel_basic() {
+        let (p1, p2) = Channel::create(ChannelOpts::Normal).unwrap();
+
+        let mut empty = vec![];
+        assert!(p1.write(b"hello", &mut empty, 0).is_ok());
+
+        let mut buf = MessageBuf::new();
+        assert!(p2.read(0, &mut buf).is_ok());
+        assert_eq!(buf.bytes(), b"hello");
+    }
+
+    #[test]
+    fn channel_read_raw_too_small() {
+        let (p1, p2) = Channel::create(ChannelOpts::Normal).unwrap();
+
+        let mut empty = vec![];
+        assert!(p1.write(b"hello", &mut empty, 0).is_ok());
+
+        let mut buf = MessageBuf::new();
+        let result = p2.read_raw(0, &mut buf);
+        assert_eq!(result, Err((5, 0)));
+        assert_eq!(buf.bytes(), b"");
+    }
+
+    #[test]
+    fn channel_send_handle() {
+        let hello_length: usize = 5;
+
+        // Create a pair of channels and a virtual memory object.
+        let (p1, p2) = Channel::create(ChannelOpts::Normal).unwrap();
+        let vmo = Vmo::create(hello_length as u64, VmoOpts::Default).unwrap();
+
+        // Duplicate VMO handle and send it down the channel.
+        let duplicate_vmo_handle = vmo.duplicate_handle(ZX_RIGHT_SAME_RIGHTS).unwrap().into();
+        let mut handles_to_send: Vec<Handle> = vec![duplicate_vmo_handle];
+        assert!(p1.write(b"", &mut handles_to_send, 0).is_ok());
+        // Handle should be removed from vector.
+        assert!(handles_to_send.is_empty());
+
+        // Read the handle from the receiving channel.
+        let mut buf = MessageBuf::new();
+        assert!(p2.read(0, &mut buf).is_ok());
+        assert_eq!(buf.n_handles(), 1);
+        // Take the handle from the buffer.
+        let received_handle = buf.take_handle(0).unwrap();
+        // Should not affect number of handles.
+        assert_eq!(buf.n_handles(), 1);
+        // Trying to take it again should fail.
+        assert!(buf.take_handle(0).is_none());
+
+        // Now to test that we got the right handle, try writing something to it...
+        let received_vmo = Vmo::from(received_handle);
+        assert_eq!(received_vmo.write(b"hello", 0).unwrap(), hello_length);
+
+        // ... and reading it back from the original VMO.
+        let mut read_vec = vec![0; hello_length];
+        assert_eq!(vmo.read(&mut read_vec, 0).unwrap(), hello_length);
+        assert_eq!(read_vec, b"hello");
+    }
+
+    #[test]
+    fn channel_call_timeout() {
+        let ten_ms: Duration = 10_000_000;
+
+        // Create a pair of channels and a virtual memory object.
+        let (p1, p2) = Channel::create(ChannelOpts::Normal).unwrap();
+        let vmo = Vmo::create(0 as u64, VmoOpts::Default).unwrap();
+
+        // Duplicate VMO handle and send it along with the call.
+        let duplicate_vmo_handle = vmo.duplicate_handle(ZX_RIGHT_SAME_RIGHTS).unwrap().into();
+        let mut handles_to_send: Vec<Handle> = vec![duplicate_vmo_handle];
+        let mut buf = MessageBuf::new();
+        assert_eq!(p1.call(0, deadline_after(ten_ms), b"call", &mut handles_to_send, &mut buf),
+            Err((Status::ErrTimedOut, Status::NoError)));
+        // Handle should be removed from vector even though we didn't get a response, as it was
+        // still sent over the channel.
+        assert!(handles_to_send.is_empty());
+
+        // Should be able to read call even though it timed out waiting for a response.
+        let mut buf = MessageBuf::new();
+        assert!(p2.read(0, &mut buf).is_ok());
+        assert_eq!(buf.bytes(), b"call");
+        assert_eq!(buf.n_handles(), 1);
+    }
+
+    #[test]
+    fn channel_call() {
+        let hundred_ms: Duration = 100_000_000;
+
+        // Create a pair of channels
+        let (p1, p2) = Channel::create(ChannelOpts::Normal).unwrap();
+
+        // Start a new thread to respond to the call.
+        let server = thread::spawn(move || {
+            assert_eq!(p2.wait_handle(ZX_CHANNEL_READABLE, deadline_after(hundred_ms)),
+                Ok(ZX_CHANNEL_READABLE | ZX_CHANNEL_WRITABLE | ZX_SIGNAL_LAST_HANDLE));
+            let mut buf = MessageBuf::new();
+            assert_eq!(p2.read(0, &mut buf), Ok(()));
+            assert_eq!(buf.bytes(), b"txidcall");
+            assert_eq!(buf.n_handles(), 0);
+            let mut empty = vec![];
+            assert_eq!(p2.write(b"txidresponse", &mut empty, 0), Ok(()));
+        });
+
+        // Make the call.
+        let mut empty = vec![];
+        let mut buf = MessageBuf::new();
+        buf.ensure_capacity_bytes(12);
+        assert_eq!(p1.call(0, deadline_after(hundred_ms), b"txidcall", &mut empty, &mut buf),
+            Ok(()));
+        assert_eq!(buf.bytes(), b"txidresponse");
+        assert_eq!(buf.n_handles(), 0);
+
+        assert!(server.join().is_ok());
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon/src/event.rs
@@ -0,0 +1,42 @@
+// Copyright 2017 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//! Type-safe bindings for Zircon event objects.
+
+use {AsHandleRef, Cookied, HandleBased, Handle, HandleRef, Status};
+use {sys, into_result};
+
+/// An object representing a Zircon
+/// [event object](https://fuchsia.googlesource.com/zircon/+/master/docs/objects/event.md).
+///
+/// As essentially a subtype of `Handle`, it can be freely interconverted.
+#[derive(Debug, Eq, PartialEq)]
+pub struct Event(Handle);
+impl_handle_based!(Event);
+impl Cookied for Event {}
+
+impl Event {
+    /// Create an event object, an object which is signalable but nothing else. Wraps the
+    /// [zx_event_create](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/event_create.md)
+    /// syscall.
+    pub fn create(options: EventOpts) -> Result<Event, Status> {
+        let mut out = 0;
+        let status = unsafe { sys::zx_event_create(options as u32, &mut out) };
+        into_result(status, || Self::from(Handle(out)))
+    }
+}
+
+/// Options for creating an event object.
+#[repr(u32)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum EventOpts {
+    /// Default options.
+    Default = 0,
+}
+
+impl Default for EventOpts {
+    fn default() -> Self {
+        EventOpts::Default
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon/src/eventpair.rs
@@ -0,0 +1,75 @@
+// Copyright 2016 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//! Type-safe bindings for Zircon event pairs.
+
+use {AsHandleRef, Cookied, HandleBased, Handle, HandleRef, Peered, Status};
+use {sys, into_result};
+
+/// An object representing a Zircon
+/// [event pair](https://fuchsia.googlesource.com/zircon/+/master/docs/concepts.md#Other-IPC_Events_Event-Pairs_and-User-Signals).
+///
+/// As essentially a subtype of `Handle`, it can be freely interconverted.
+#[derive(Debug, Eq, PartialEq)]
+pub struct EventPair(Handle);
+impl_handle_based!(EventPair);
+impl Peered for EventPair {}
+impl Cookied for EventPair {}
+
+impl EventPair {
+    /// Create an event pair, a pair of objects which can signal each other. Wraps the
+    /// [zx_eventpair_create](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/eventpair_create.md)
+    /// syscall.
+    pub fn create(options: EventPairOpts) -> Result<(EventPair, EventPair), Status> {
+        let mut out0 = 0;
+        let mut out1 = 0;
+        let status = unsafe { sys::zx_eventpair_create(options as u32, &mut out0, &mut out1) };
+        into_result(status, ||
+            (Self::from(Handle(out0)),
+                Self::from(Handle(out1))))
+    }
+}
+
+/// Options for creating an event pair.
+#[repr(u32)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum EventPairOpts {
+    /// Default options.
+    Default = 0,
+}
+
+impl Default for EventPairOpts {
+    fn default() -> Self {
+        EventPairOpts::Default
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use {Duration, ZX_SIGNAL_LAST_HANDLE, ZX_SIGNAL_NONE, ZX_USER_SIGNAL_0};
+    use deadline_after;
+
+    #[test]
+    fn wait_and_signal_peer() {
+        let (p1, p2) = EventPair::create(EventPairOpts::Default).unwrap();
+        let eighty_ms: Duration = 80_000_000;
+
+        // Waiting on one without setting any signal should time out.
+        assert_eq!(p2.wait_handle(ZX_USER_SIGNAL_0, deadline_after(eighty_ms)), Err(Status::ErrTimedOut));
+
+        // If we set a signal, we should be able to wait for it.
+        assert!(p1.signal_peer(ZX_SIGNAL_NONE, ZX_USER_SIGNAL_0).is_ok());
+        assert_eq!(p2.wait_handle(ZX_USER_SIGNAL_0, deadline_after(eighty_ms)).unwrap(),
+            ZX_USER_SIGNAL_0 | ZX_SIGNAL_LAST_HANDLE);
+
+        // Should still work, signals aren't automatically cleared.
+        assert_eq!(p2.wait_handle(ZX_USER_SIGNAL_0, deadline_after(eighty_ms)).unwrap(),
+            ZX_USER_SIGNAL_0 | ZX_SIGNAL_LAST_HANDLE);
+
+        // Now clear it, and waiting should time out again.
+        assert!(p1.signal_peer(ZX_USER_SIGNAL_0, ZX_SIGNAL_NONE).is_ok());
+        assert_eq!(p2.wait_handle(ZX_USER_SIGNAL_0, deadline_after(eighty_ms)), Err(Status::ErrTimedOut));
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon/src/fifo.rs
@@ -0,0 +1,107 @@
+// Copyright 2017 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//! Type-safe bindings for Zircon fifo objects.
+
+use {AsHandleRef, HandleBased, Handle, HandleRef, Status};
+use {sys, into_result};
+
+/// An object representing a Zircon fifo.
+///
+/// As essentially a subtype of `Handle`, it can be freely interconverted.
+#[derive(Debug, Eq, PartialEq)]
+pub struct Fifo(Handle);
+impl_handle_based!(Fifo);
+
+impl Fifo {
+    /// Create a pair of fifos and return their endpoints. Writing to one endpoint enqueues an
+    /// element into the fifo from which the opposing endpoint reads. Wraps the
+    /// [zx_fifo_create](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/fifo_create.md)
+    /// syscall.
+    pub fn create(elem_count: u32, elem_size: u32, options: FifoOpts)
+        -> Result<(Fifo, Fifo), Status>
+    {
+        let mut out0 = 0;
+        let mut out1 = 0;
+        let status = unsafe {
+            sys::zx_fifo_create(elem_count, elem_size, options as u32, &mut out0, &mut out1)
+        };
+        into_result(status, || (Self::from(Handle(out0)), Self::from(Handle(out1))))
+    }
+
+    /// Attempts to write some number of elements into the fifo. The number of bytes written will be
+    /// rounded down to a multiple of the fifo's element size.
+    /// Return value (on success) is number of elements actually written.
+    ///
+    /// Wraps
+    /// [zx_fifo_write](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/fifo_write.md).
+    pub fn write(&self, bytes: &[u8]) -> Result<u32, Status> {
+        let mut num_entries_written = 0;
+        let status = unsafe {
+            sys::zx_fifo_write(self.raw_handle(), bytes.as_ptr(), bytes.len(),
+                &mut num_entries_written)
+        };
+        into_result(status, || num_entries_written)
+    }
+
+    /// Attempts to read some number of elements out of the fifo. The number of bytes read will
+    /// always be a multiple of the fifo's element size.
+    /// Return value (on success) is number of elements actually read.
+    ///
+    /// Wraps
+    /// [zx_fifo_read](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/fifo_read.md).
+    pub fn read(&self, bytes: &mut [u8]) -> Result<u32, Status> {
+        let mut num_entries_read = 0;
+        let status = unsafe {
+            sys::zx_fifo_read(self.raw_handle(), bytes.as_mut_ptr(), bytes.len(),
+                &mut num_entries_read)
+        };
+        into_result(status, || num_entries_read)
+    }
+}
+
+/// Options for creating a fifo pair.
+#[repr(u32)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum FifoOpts {
+    /// Default options.
+    Default = 0,
+}
+
+impl Default for FifoOpts {
+    fn default() -> Self {
+        FifoOpts::Default
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn fifo_basic() {
+        let (fifo1, fifo2) = Fifo::create(4, 2, FifoOpts::Default).unwrap();
+
+        // Trying to write less than one element should fail.
+        assert_eq!(fifo1.write(b""), Err(Status::ErrOutOfRange));
+        assert_eq!(fifo1.write(b"h"), Err(Status::ErrOutOfRange));
+
+        // Should write one element "he" and ignore the last half-element as it rounds down.
+        assert_eq!(fifo1.write(b"hex").unwrap(), 1);
+
+        // Should write three elements "ll" "o " "wo" and drop the rest as it is full.
+        assert_eq!(fifo1.write(b"llo worlds").unwrap(), 3);
+
+        // Now that the fifo is full any further attempts to write should fail.
+        assert_eq!(fifo1.write(b"blah blah"), Err(Status::ErrShouldWait));
+
+        // Read all 4 entries from the other end.
+        let mut read_vec = vec![0; 8];
+        assert_eq!(fifo2.read(&mut read_vec).unwrap(), 4);
+        assert_eq!(read_vec, b"hello wo");
+
+        // Reading again should fail as the fifo is empty.
+        assert_eq!(fifo2.read(&mut read_vec), Err(Status::ErrShouldWait));
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon/src/job.rs
@@ -0,0 +1,14 @@
+// Copyright 2017 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//! Type-safe bindings for Zircon job.
+
+use {AsHandleRef, HandleBased, Handle, HandleRef};
+
+/// An object representing a Zircon job.
+///
+/// As essentially a subtype of `Handle`, it can be freely interconverted.
+#[derive(Debug, Eq, PartialEq)]
+pub struct Job(Handle);
+impl_handle_based!(Job);
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon/src/lib.rs
@@ -0,0 +1,911 @@
+// Copyright 2016 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//! Type-safe bindings for Zircon kernel
+//! [syscalls](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls.md).
+
+extern crate fuchsia_zircon_sys as zircon_sys;
+
+use std::io;
+use std::marker::PhantomData;
+
+macro_rules! impl_handle_based {
+    ($type_name:path) => {
+        impl AsHandleRef for $type_name {
+            fn as_handle_ref(&self) -> HandleRef {
+                self.0.as_handle_ref()
+            }
+        }
+
+        impl From<Handle> for $type_name {
+            fn from(handle: Handle) -> Self {
+                $type_name(handle)
+            }
+        }
+
+        impl From<$type_name> for Handle {
+            fn from(x: $type_name) -> Handle {
+                x.0
+            }
+        }
+
+        impl HandleBased for $type_name {}
+    }
+}
+
+mod channel;
+mod event;
+mod eventpair;
+mod fifo;
+mod job;
+mod port;
+mod process;
+mod socket;
+mod timer;
+mod thread;
+mod vmo;
+
+pub use channel::{Channel, ChannelOpts, MessageBuf};
+pub use event::{Event, EventOpts};
+pub use eventpair::{EventPair, EventPairOpts};
+pub use fifo::{Fifo, FifoOpts};
+pub use job::Job;
+pub use port::{Packet, PacketContents, Port, PortOpts, SignalPacket, UserPacket, WaitAsyncOpts};
+pub use process::Process;
+pub use socket::{Socket, SocketOpts, SocketReadOpts, SocketWriteOpts};
+pub use timer::{Timer, TimerOpts};
+pub use thread::Thread;
+pub use vmo::{Vmo, VmoCloneOpts, VmoOp, VmoOpts};
+
+use zircon_sys as sys;
+
+type Duration = sys::zx_duration_t;
+type Time = sys::zx_time_t;
+pub use zircon_sys::ZX_TIME_INFINITE;
+
+// A placeholder value used for handles that have been taken from the message buf.
+// We rely on the kernel never to produce any actual handles with this value.
+const INVALID_HANDLE: sys::zx_handle_t = 0;
+
+/// A status code returned from the Zircon kernel.
+///
+/// See
+/// [errors.md](https://fuchsia.googlesource.com/zircon/+/master/docs/errors.md)
+/// in the Zircon documentation for more information about the meaning of these
+/// codes.
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+#[repr(i32)]
+// Auto-generated using tools/gen_status.py
+pub enum Status {
+    NoError = 0,
+    ErrInternal = -1,
+    ErrNotSupported = -2,
+    ErrNoResources = -3,
+    ErrNoMemory = -4,
+    ErrCallFailed = -5,
+    ErrInterruptedRetry = -6,
+    ErrInvalidArgs = -10,
+    ErrBadHandle = -11,
+    ErrWrongType = -12,
+    ErrBadSyscall = -13,
+    ErrOutOfRange = -14,
+    ErrBufferTooSmall = -15,
+    ErrBadState = -20,
+    ErrTimedOut = -21,
+    ErrShouldWait = -22,
+    ErrCanceled = -23,
+    ErrPeerClosed = -24,
+    ErrNotFound = -25,
+    ErrAlreadyExists = -26,
+    ErrAlreadyBound = -27,
+    ErrUnavailable = -28,
+    ErrAccessDenied = -30,
+    ErrIo = -40,
+    ErrIoRefused = -41,
+    ErrIoDataIntegrity = -42,
+    ErrIoDataLoss = -43,
+    ErrBadPath = -50,
+    ErrNotDir = -51,
+    ErrNotFile = -52,
+    ErrFileBig = -53,
+    ErrNoSpace = -54,
+    ErrStop = -60,
+    ErrNext = -61,
+
+    /// Any zx_status_t not in the set above will map to the following:
+    UnknownOther = -32768,
+
+    // used to prevent exhaustive matching
+    #[doc(hidden)]
+    __Nonexhaustive = -32787,
+}
+
+impl Status {
+    pub fn from_raw(raw: sys::zx_status_t) -> Self {
+        match raw {
+            // Auto-generated using tools/gen_status.py
+            sys::ZX_OK => Status::NoError,
+            sys::ZX_ERR_INTERNAL => Status::ErrInternal,
+            sys::ZX_ERR_NOT_SUPPORTED => Status::ErrNotSupported,
+            sys::ZX_ERR_NO_RESOURCES => Status::ErrNoResources,
+            sys::ZX_ERR_NO_MEMORY => Status::ErrNoMemory,
+            sys::ZX_ERR_CALL_FAILED => Status::ErrCallFailed,
+            sys::ZX_ERR_INTERRUPTED_RETRY => Status::ErrInterruptedRetry,
+            sys::ZX_ERR_INVALID_ARGS => Status::ErrInvalidArgs,
+            sys::ZX_ERR_BAD_HANDLE => Status::ErrBadHandle,
+            sys::ZX_ERR_WRONG_TYPE => Status::ErrWrongType,
+            sys::ZX_ERR_BAD_SYSCALL => Status::ErrBadSyscall,
+            sys::ZX_ERR_OUT_OF_RANGE => Status::ErrOutOfRange,
+            sys::ZX_ERR_BUFFER_TOO_SMALL => Status::ErrBufferTooSmall,
+            sys::ZX_ERR_BAD_STATE => Status::ErrBadState,
+            sys::ZX_ERR_TIMED_OUT => Status::ErrTimedOut,
+            sys::ZX_ERR_SHOULD_WAIT => Status::ErrShouldWait,
+            sys::ZX_ERR_CANCELED => Status::ErrCanceled,
+            sys::ZX_ERR_PEER_CLOSED => Status::ErrPeerClosed,
+            sys::ZX_ERR_NOT_FOUND => Status::ErrNotFound,
+            sys::ZX_ERR_ALREADY_EXISTS => Status::ErrAlreadyExists,
+            sys::ZX_ERR_ALREADY_BOUND => Status::ErrAlreadyBound,
+            sys::ZX_ERR_UNAVAILABLE => Status::ErrUnavailable,
+            sys::ZX_ERR_ACCESS_DENIED => Status::ErrAccessDenied,
+            sys::ZX_ERR_IO => Status::ErrIo,
+            sys::ZX_ERR_IO_REFUSED => Status::ErrIoRefused,
+            sys::ZX_ERR_IO_DATA_INTEGRITY => Status::ErrIoDataIntegrity,
+            sys::ZX_ERR_IO_DATA_LOSS => Status::ErrIoDataLoss,
+            sys::ZX_ERR_BAD_PATH => Status::ErrBadPath,
+            sys::ZX_ERR_NOT_DIR => Status::ErrNotDir,
+            sys::ZX_ERR_NOT_FILE => Status::ErrNotFile,
+            sys::ZX_ERR_FILE_BIG => Status::ErrFileBig,
+            sys::ZX_ERR_NO_SPACE => Status::ErrNoSpace,
+            sys::ZX_ERR_STOP => Status::ErrStop,
+            sys::ZX_ERR_NEXT => Status::ErrNext,
+            _ => Status::UnknownOther,
+        }
+    }
+
+    pub fn into_io_err(self) -> io::Error {
+        self.into()
+    }
+
+    // Note: no to_raw, even though it's easy to implement, partly because
+    // handling of UnknownOther would be tricky.
+}
+
+impl From<io::ErrorKind> for Status {
+    fn from(kind: io::ErrorKind) -> Self {
+        use io::ErrorKind::*;
+        use Status::*;
+
+        match kind {
+            NotFound => ErrNotFound,
+            PermissionDenied => ErrAccessDenied,
+            ConnectionRefused => ErrIoRefused,
+            ConnectionAborted => ErrPeerClosed,
+            AddrInUse => ErrAlreadyBound,
+            AddrNotAvailable => ErrUnavailable,
+            BrokenPipe => ErrPeerClosed,
+            AlreadyExists => ErrAlreadyExists,
+            WouldBlock => ErrShouldWait,
+            InvalidInput => ErrInvalidArgs,
+            TimedOut => ErrTimedOut,
+            Interrupted => ErrInterruptedRetry,
+
+            UnexpectedEof |
+            WriteZero |
+            ConnectionReset |
+            NotConnected |
+            Other | _ => ErrIo,
+        }
+    }
+}
+
+impl From<Status> for io::ErrorKind {
+    fn from(status: Status) -> io::ErrorKind {
+        use io::ErrorKind::*;
+        use Status::*;
+
+        match status {
+            ErrInterruptedRetry => Interrupted,
+            ErrBadHandle => BrokenPipe,
+            ErrTimedOut => TimedOut,
+            ErrShouldWait => WouldBlock,
+            ErrPeerClosed => ConnectionAborted,
+            ErrNotFound => NotFound,
+            ErrAlreadyExists => AlreadyExists,
+            ErrAlreadyBound => AlreadyExists,
+            ErrUnavailable => AddrNotAvailable,
+            ErrAccessDenied => PermissionDenied,
+            ErrIoRefused => ConnectionRefused,
+            ErrIoDataIntegrity => InvalidData,
+
+            ErrBadPath |
+            ErrInvalidArgs |
+            ErrOutOfRange |
+            ErrWrongType => InvalidInput,
+
+            Status::__Nonexhaustive |
+            UnknownOther |
+            NoError |
+            ErrNext |
+            ErrStop |
+            ErrNoSpace |
+            ErrFileBig |
+            ErrNotFile |
+            ErrNotDir |
+            ErrIoDataLoss |
+            ErrIo |
+            ErrCanceled |
+            ErrBadState |
+            ErrBufferTooSmall |
+            ErrBadSyscall |
+            ErrInternal |
+            ErrNotSupported |
+            ErrNoResources |
+            ErrNoMemory |
+            ErrCallFailed => Other,
+        }
+    }
+}
+
+impl From<io::Error> for Status {
+    fn from(err: io::Error) -> Status {
+        err.kind().into()
+    }
+}
+
+impl From<Status> for io::Error {
+    fn from(status: Status) -> io::Error {
+        io::Error::from(io::ErrorKind::from(status))
+    }
+}
+
+/// Rights associated with a handle.
+///
+/// See [rights.md](https://fuchsia.googlesource.com/zircon/+/master/docs/rights.md)
+/// for more information.
+pub type Rights = sys::zx_rights_t;
+pub use zircon_sys::{
+    ZX_RIGHT_NONE,
+    ZX_RIGHT_DUPLICATE,
+    ZX_RIGHT_TRANSFER,
+    ZX_RIGHT_READ,
+    ZX_RIGHT_WRITE,
+    ZX_RIGHT_EXECUTE,
+    ZX_RIGHT_MAP,
+    ZX_RIGHT_GET_PROPERTY,
+    ZX_RIGHT_SET_PROPERTY,
+    ZX_RIGHT_DEBUG,
+    ZX_RIGHT_SAME_RIGHTS,
+};
+
+/// Signals that can be waited upon.
+///
+/// See
+/// [Objects and signals](https://fuchsia.googlesource.com/zircon/+/master/docs/concepts.md#Objects-and-Signals)
+/// in the Zircon kernel documentation. Note: the names of signals are still in flux.
+pub type Signals = sys::zx_signals_t;
+
+pub use zircon_sys::{
+        ZX_SIGNAL_NONE,
+
+        ZX_SIGNAL_HANDLE_CLOSED,
+        ZX_SIGNAL_LAST_HANDLE,
+
+        ZX_USER_SIGNAL_0,
+        ZX_USER_SIGNAL_1,
+        ZX_USER_SIGNAL_2,
+        ZX_USER_SIGNAL_3,
+        ZX_USER_SIGNAL_4,
+        ZX_USER_SIGNAL_5,
+        ZX_USER_SIGNAL_6,
+        ZX_USER_SIGNAL_7,
+
+        // Event
+        ZX_EVENT_SIGNALED,
+
+        // EventPair
+        ZX_EPAIR_SIGNALED,
+        ZX_EPAIR_CLOSED,
+
+        // Task signals (process, thread, job)
+        ZX_TASK_TERMINATED,
+
+        // Channel
+        ZX_CHANNEL_READABLE,
+        ZX_CHANNEL_WRITABLE,
+        ZX_CHANNEL_PEER_CLOSED,
+
+        // Socket
+        ZX_SOCKET_READABLE,
+        ZX_SOCKET_WRITABLE,
+        ZX_SOCKET_PEER_CLOSED,
+
+        // Timer
+        ZX_TIMER_SIGNALED,
+};
+
+/// A "wait item" containing a handle reference and information about what signals
+/// to wait on, and, on return from `object_wait_many`, which are pending.
+#[repr(C)]
+#[derive(Debug)]
+pub struct WaitItem<'a> {
+    /// The handle to wait on.
+    pub handle: HandleRef<'a>,
+    /// A set of signals to wait for.
+    pub waitfor: Signals,
+    /// The set of signals pending, on return of `object_wait_many`.
+    pub pending: Signals,
+}
+
+
+/// An identifier to select a particular clock. See
+/// [zx_time_get](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/time_get.md)
+/// for more information about the possible values.
+#[repr(u32)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum ClockId {
+    /// The number of nanoseconds since the system was powered on. Corresponds to
+    /// `ZX_CLOCK_MONOTONIC`.
+    Monotonic = 0,
+    /// The number of wall clock nanoseconds since the Unix epoch (midnight on January 1 1970) in
+    /// UTC. Corresponds to ZX_CLOCK_UTC.
+    UTC = 1,
+    /// The number of nanoseconds the current thread has been running for. Corresponds to
+    /// ZX_CLOCK_THREAD.
+    Thread = 2,
+}
+
+/// Get the current time, from the specific clock id.
+///
+/// Wraps the
+/// [zx_time_get](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/time_get.md)
+/// syscall.
+pub fn time_get(clock_id: ClockId) -> Time {
+    unsafe { sys::zx_time_get(clock_id as u32) }
+}
+
+/// Read the number of high-precision timer ticks since boot. These ticks may be processor cycles,
+/// high speed timer, profiling timer, etc. They are not guaranteed to continue advancing when the
+/// system is asleep.
+///
+/// Wraps the
+/// [zx_ticks_get](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/ticks_get.md)
+/// syscall.
+pub fn ticks_get() -> u64 {
+    unsafe { sys::zx_ticks_get() }
+}
+
+/// Compute a deadline for the time in the future that is the given `Duration` away.
+///
+/// Wraps the
+/// [zx_deadline_after](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/deadline_after.md)
+/// syscall.
+pub fn deadline_after(nanos: Duration) -> Time {
+    unsafe { sys::zx_deadline_after(nanos) }
+}
+
+/// Sleep until the given deadline.
+///
+/// Wraps the
+/// [zx_nanosleep](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/nanosleep.md)
+/// syscall.
+pub fn nanosleep(deadline: Time) {
+    unsafe { sys::zx_nanosleep(deadline); }
+}
+
+/// Return the number of high-precision timer ticks in a second.
+///
+/// Wraps the
+/// [zx_ticks_per_second](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/ticks_per_second.md)
+/// syscall.
+pub fn ticks_per_second() -> u64 {
+    unsafe { sys::zx_ticks_per_second() }
+}
+
+pub use zircon_sys::{
+    ZX_CPRNG_DRAW_MAX_LEN,
+    ZX_CPRNG_ADD_ENTROPY_MAX_LEN,
+};
+
+/// Draw random bytes from the kernel's CPRNG to fill the given buffer. Returns the actual number of
+/// bytes drawn, which may sometimes be less than the size of the buffer provided.
+///
+/// The buffer must have length less than `ZX_CPRNG_DRAW_MAX_LEN`.
+///
+/// Wraps the
+/// [zx_cprng_draw](https://fuchsia.googlesource.com/zircon/+/HEAD/docs/syscalls/cprng_draw.md)
+/// syscall.
+pub fn cprng_draw(buffer: &mut [u8]) -> Result<usize, Status> {
+    let mut actual = 0;
+    let status = unsafe { sys::zx_cprng_draw(buffer.as_mut_ptr(), buffer.len(), &mut actual) };
+    into_result(status, || actual)
+}
+
+/// Mix the given entropy into the kernel CPRNG.
+///
+/// The buffer must have length less than `ZX_CPRNG_ADD_ENTROPY_MAX_LEN`.
+///
+/// Wraps the
+/// [zx_cprng_add_entropy](https://fuchsia.googlesource.com/zircon/+/HEAD/docs/syscalls/cprng_add_entropy.md)
+/// syscall.
+pub fn cprng_add_entropy(buffer: &[u8]) -> Result<(), Status> {
+    let status = unsafe { sys::zx_cprng_add_entropy(buffer.as_ptr(), buffer.len()) };
+    into_result(status, || ())
+}
+
+fn into_result<T, F>(status: sys::zx_status_t, f: F) -> Result<T, Status>
+    where F: FnOnce() -> T {
+    // All non-negative values are assumed successful. Note: calls that don't try
+    // to multiplex success values into status return could be more strict here.
+    if status >= 0 {
+        Ok(f())
+    } else {
+        Err(Status::from_raw(status))
+    }
+}
+
+// Handles
+
+/// A borrowed reference to a `Handle`.
+///
+/// Mostly useful as part of a `WaitItem`.
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+pub struct HandleRef<'a> {
+    handle: sys::zx_handle_t,
+    phantom: PhantomData<&'a sys::zx_handle_t>,
+}
+
+impl<'a> HandleRef<'a> {
+    pub fn raw_handle(&self) -> sys::zx_handle_t {
+        self.handle
+    }
+
+    pub fn duplicate(&self, rights: Rights) -> Result<Handle, Status> {
+        let handle = self.handle;
+        let mut out = 0;
+        let status = unsafe { sys::zx_handle_duplicate(handle, rights, &mut out) };
+        into_result(status, || Handle(out))
+    }
+
+    pub fn signal(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
+        let handle = self.handle;
+        let status = unsafe { sys::zx_object_signal(handle, clear_mask.bits(), set_mask.bits()) };
+        into_result(status, || ())
+    }
+
+    pub fn wait(&self, signals: Signals, deadline: Time) -> Result<Signals, Status> {
+        let handle = self.handle;
+        let mut pending = sys::zx_signals_t::empty();
+        let status = unsafe {
+            sys::zx_object_wait_one(handle, signals, deadline, &mut pending)
+        };
+        into_result(status, || pending)
+    }
+
+    pub fn wait_async(&self, port: &Port, key: u64, signals: Signals, options: WaitAsyncOpts)
+        -> Result<(), Status>
+    {
+        let handle = self.handle;
+        let status = unsafe {
+            sys::zx_object_wait_async(handle, port.raw_handle(), key, signals, options as u32)
+        };
+        into_result(status, || ())
+    }
+}
+
+/// A trait to get a reference to the underlying handle of an object.
+pub trait AsHandleRef {
+    /// Get a reference to the handle. One important use of such a reference is
+    /// for `object_wait_many`.
+    fn as_handle_ref(&self) -> HandleRef;
+
+    /// Interpret the reference as a raw handle (an integer type). Two distinct
+    /// handles will have different raw values (so it can perhaps be used as a
+    /// key in a data structure).
+    fn raw_handle(&self) -> sys::zx_handle_t {
+        self.as_handle_ref().raw_handle()
+    }
+
+    /// Set and clear userspace-accessible signal bits on an object. Wraps the
+    /// [zx_object_signal](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_signal.md)
+    /// syscall.
+    fn signal_handle(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
+        self.as_handle_ref().signal(clear_mask, set_mask)
+    }
+
+    /// Waits on a handle. Wraps the
+    /// [zx_object_wait_one](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_wait_one.md)
+    /// syscall.
+    fn wait_handle(&self, signals: Signals, deadline: Time) -> Result<Signals, Status> {
+        self.as_handle_ref().wait(signals, deadline)
+    }
+
+    /// Causes packet delivery on the given port when the object changes state and matches signals.
+    /// [zx_object_wait_async](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_wait_async.md)
+    /// syscall.
+    fn wait_async_handle(&self, port: &Port, key: u64, signals: Signals, options: WaitAsyncOpts)
+        -> Result<(), Status>
+    {
+        self.as_handle_ref().wait_async(port, key, signals, options)
+    }
+}
+
+impl<'a> AsHandleRef for HandleRef<'a> {
+    fn as_handle_ref(&self) -> HandleRef { *self }
+}
+
+/// A trait implemented by all handle-based types.
+///
+/// Note: it is reasonable for user-defined objects wrapping a handle to implement
+/// this trait. For example, a specific interface in some protocol might be
+/// represented as a newtype of `Channel`, and implement the `as_handle_ref`
+/// method and the `From<Handle>` trait to facilitate conversion from and to the
+/// interface.
+pub trait HandleBased: AsHandleRef + From<Handle> + Into<Handle> {
+    /// Duplicate a handle, possibly reducing the rights available. Wraps the
+    /// [zx_handle_duplicate](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/handle_duplicate.md)
+    /// syscall.
+    fn duplicate_handle(&self, rights: Rights) -> Result<Self, Status> {
+        self.as_handle_ref().duplicate(rights).map(|handle| Self::from(handle))
+    }
+
+    /// Create a replacement for a handle, possibly reducing the rights available. This invalidates
+    /// the original handle. Wraps the
+    /// [zx_handle_replace](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/handle_replace.md)
+    /// syscall.
+    fn replace_handle(self, rights: Rights) -> Result<Self, Status> {
+        <Self as Into<Handle>>::into(self)
+            .replace(rights).map(|handle| Self::from(handle))
+    }
+
+    /// Converts the value into its inner handle.
+    ///
+    /// This is a convenience function which simply forwards to the `Into` trait.
+    fn into_handle(self) -> Handle {
+        self.into()
+    }
+
+    /// Creates an instance of this type from a handle.
+    ///
+    /// This is a convenience function which simply forwards to the `From` trait.
+    fn from_handle(handle: Handle) -> Self {
+        Self::from(handle)
+    }
+
+    /// Creates an instance of another handle-based type from this value's inner handle.
+    fn into_handle_based<H: HandleBased>(self) -> H {
+        H::from_handle(self.into_handle())
+    }
+
+    /// Creates an instance of this type from the inner handle of another
+    /// handle-based type.
+    fn from_handle_based<H: HandleBased>(h: H) -> Self {
+        Self::from_handle(h.into_handle())
+    }
+}
+
+/// A trait implemented by all handles for objects which have a peer.
+pub trait Peered: HandleBased {
+    /// Set and clear userspace-accessible signal bits on the object's peer. Wraps the
+    /// [zx_object_signal_peer](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_signal.md)
+    /// syscall.
+    fn signal_peer(&self, clear_mask: Signals, set_mask: Signals) -> Result<(), Status> {
+        let handle = self.as_handle_ref().handle;
+        let status = unsafe {
+            sys::zx_object_signal_peer(handle, clear_mask.bits(), set_mask.bits())
+        };
+        into_result(status, || ())
+    }
+}
+
+/// A trait implemented by all handles for objects which can have a cookie attached.
+pub trait Cookied: HandleBased {
+    /// Get the cookie attached to this object, if any. Wraps the
+    /// [zx_object_get_cookie](https://fuchsia.googlesource.com/zircon/+/HEAD/docs/syscalls/object_get_cookie.md)
+    /// syscall.
+    fn get_cookie(&self, scope: &HandleRef) -> Result<u64, Status> {
+        let handle = self.as_handle_ref().handle;
+        let mut cookie = 0;
+        let status = unsafe { sys::zx_object_get_cookie(handle, scope.handle, &mut cookie) };
+        into_result(status, || cookie)
+    }
+
+    /// Attach an opaque cookie to this object with the given scope. The cookie may be read or
+    /// changed in future only with the same scope. Wraps the
+    /// [zx_object_set_cookie](https://fuchsia.googlesource.com/zircon/+/HEAD/docs/syscalls/object_set_cookie.md)
+    /// syscall.
+    fn set_cookie(&self, scope: &HandleRef, cookie: u64) -> Result<(), Status> {
+        let handle = self.as_handle_ref().handle;
+        let status = unsafe { sys::zx_object_set_cookie(handle, scope.handle, cookie) };
+        into_result(status, || ())
+    }
+}
+
+fn handle_drop(handle: sys::zx_handle_t) {
+    let _ = unsafe { sys::zx_handle_close(handle) };
+}
+
+/// Wait on multiple handles.
+/// The success return value is a bool indicating whether one or more of the
+/// provided handle references was closed during the wait.
+///
+/// Wraps the
+/// [zx_object_wait_many](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/object_wait_many.md)
+/// syscall.
+pub fn object_wait_many(items: &mut [WaitItem], deadline: Time) -> Result<bool, Status>
+{
+    let len = try!(usize_into_u32(items.len()).map_err(|_| Status::ErrOutOfRange));
+    let items_ptr = items.as_mut_ptr() as *mut sys::zx_wait_item_t;
+    let status = unsafe { sys::zx_object_wait_many( items_ptr, len, deadline) };
+    if status == sys::ZX_ERR_CANCELED {
+        return Ok((true))
+    }
+    into_result(status, || false)
+}
+
+// An untyped handle
+
+/// An object representing a Zircon
+/// [handle](https://fuchsia.googlesource.com/zircon/+/master/docs/handles.md).
+///
+/// Internally, it is represented as a 32-bit integer, but this wrapper enforces
+/// strict ownership semantics. The `Drop` implementation closes the handle.
+///
+/// This type represents the most general reference to a kernel object, and can
+/// be interconverted to and from more specific types. Those conversions are not
+/// enforced in the type system; attempting to use them will result in errors
+/// returned by the kernel. These conversions don't change the underlying
+/// representation, but do change the type and thus what operations are available.
+#[derive(Debug, Eq, PartialEq, Hash)]
+pub struct Handle(sys::zx_handle_t);
+
+impl AsHandleRef for Handle {
+    fn as_handle_ref(&self) -> HandleRef {
+        HandleRef { handle: self.0, phantom: Default::default() }
+    }
+}
+
+impl HandleBased for Handle {}
+
+impl Drop for Handle {
+    fn drop(&mut self) {
+        handle_drop(self.0)
+    }
+}
+
+impl Handle {
+    /// If a raw handle is obtained from some other source, this method converts
+    /// it into a type-safe owned handle.
+    pub unsafe fn from_raw(raw: sys::zx_handle_t) -> Handle {
+        Handle(raw)
+    }
+
+    pub fn replace(self, rights: Rights) -> Result<Handle, Status> {
+        let handle = self.0;
+        let mut out = 0;
+        let status = unsafe { sys::zx_handle_replace(handle, rights, &mut out) };
+        into_result(status, || Handle(out))
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn monotonic_time_increases() {
+        let time1 = time_get(ClockId::Monotonic);
+        nanosleep(deadline_after(1_000));
+        let time2 = time_get(ClockId::Monotonic);
+        assert!(time2 > time1);
+    }
+
+    #[test]
+    fn utc_time_increases() {
+        let time1 = time_get(ClockId::UTC);
+        nanosleep(deadline_after(1_000));
+        let time2 = time_get(ClockId::UTC);
+        assert!(time2 > time1);
+    }
+
+    #[test]
+    fn thread_time_increases() {
+        let time1 = time_get(ClockId::Thread);
+        nanosleep(deadline_after(1_000));
+        let time2 = time_get(ClockId::Thread);
+        assert!(time2 > time1);
+    }
+
+    #[test]
+    fn ticks_increases() {
+        let ticks1 = ticks_get();
+        nanosleep(deadline_after(1_000));
+        let ticks2 = ticks_get();
+        assert!(ticks2 > ticks1);
+    }
+
+    #[test]
+    fn tick_length() {
+        let sleep_ns = 1_000_000;  // 1ms
+        let one_second_ns = 1_000_000_000; // 1 second in ns
+        let ticks1 = ticks_get();
+        nanosleep(deadline_after(sleep_ns));
+        let ticks2 = ticks_get();
+        // The number of ticks should have increased by at least 1 ms worth
+        assert!(ticks2 > ticks1 + sleep_ns * ticks_per_second() / one_second_ns);
+    }
+
+    #[test]
+    fn sleep() {
+        let sleep_ns = 1_000_000;  // 1ms
+        let time1 = time_get(ClockId::Monotonic);
+        nanosleep(deadline_after(sleep_ns));
+        let time2 = time_get(ClockId::Monotonic);
+        assert!(time2 > time1 + sleep_ns);
+    }
+
+    /// Test duplication by means of a VMO
+    #[test]
+    fn duplicate() {
+        let hello_length: usize = 5;
+
+        // Create a VMO and write some data to it.
+        let vmo = Vmo::create(hello_length as u64, VmoOpts::Default).unwrap();
+        assert!(vmo.write(b"hello", 0).is_ok());
+
+        // Replace, reducing rights to read.
+        let readonly_vmo = vmo.duplicate_handle(ZX_RIGHT_READ).unwrap();
+        // Make sure we can read but not write.
+        let mut read_vec = vec![0; hello_length];
+        assert_eq!(readonly_vmo.read(&mut read_vec, 0).unwrap(), hello_length);
+        assert_eq!(read_vec, b"hello");
+        assert_eq!(readonly_vmo.write(b"", 0), Err(Status::ErrAccessDenied));
+
+        // Write new data to the original handle, and read it from the new handle
+        assert!(vmo.write(b"bye", 0).is_ok());
+        assert_eq!(readonly_vmo.read(&mut read_vec, 0).unwrap(), hello_length);
+        assert_eq!(read_vec, b"byelo");
+    }
+
+    // Test replace by means of a VMO
+    #[test]
+    fn replace() {
+        let hello_length: usize = 5;
+
+        // Create a VMO and write some data to it.
+        let vmo = Vmo::create(hello_length as u64, VmoOpts::Default).unwrap();
+        assert!(vmo.write(b"hello", 0).is_ok());
+
+        // Replace, reducing rights to read.
+        let readonly_vmo = vmo.replace_handle(ZX_RIGHT_READ).unwrap();
+        // Make sure we can read but not write.
+        let mut read_vec = vec![0; hello_length];
+        assert_eq!(readonly_vmo.read(&mut read_vec, 0).unwrap(), hello_length);
+        assert_eq!(read_vec, b"hello");
+        assert_eq!(readonly_vmo.write(b"", 0), Err(Status::ErrAccessDenied));
+    }
+
+    #[test]
+    fn wait_and_signal() {
+        let event = Event::create(EventOpts::Default).unwrap();
+        let ten_ms: Duration = 10_000_000;
+
+        // Waiting on it without setting any signal should time out.
+        assert_eq!(event.wait_handle(
+            ZX_USER_SIGNAL_0, deadline_after(ten_ms)), Err(Status::ErrTimedOut));
+
+        // If we set a signal, we should be able to wait for it.
+        assert!(event.signal_handle(ZX_SIGNAL_NONE, ZX_USER_SIGNAL_0).is_ok());
+        assert_eq!(event.wait_handle(ZX_USER_SIGNAL_0, deadline_after(ten_ms)).unwrap(),
+            ZX_USER_SIGNAL_0 | ZX_SIGNAL_LAST_HANDLE);
+
+        // Should still work, signals aren't automatically cleared.
+        assert_eq!(event.wait_handle(ZX_USER_SIGNAL_0, deadline_after(ten_ms)).unwrap(),
+            ZX_USER_SIGNAL_0 | ZX_SIGNAL_LAST_HANDLE);
+
+        // Now clear it, and waiting should time out again.
+        assert!(event.signal_handle(ZX_USER_SIGNAL_0, ZX_SIGNAL_NONE).is_ok());
+        assert_eq!(event.wait_handle(
+            ZX_USER_SIGNAL_0, deadline_after(ten_ms)), Err(Status::ErrTimedOut));
+    }
+
+    #[test]
+    fn wait_many_and_signal() {
+        let ten_ms: Duration = 10_000_000;
+        let e1 = Event::create(EventOpts::Default).unwrap();
+        let e2 = Event::create(EventOpts::Default).unwrap();
+
+        // Waiting on them now should time out.
+        let mut items = vec![
+          WaitItem { handle: e1.as_handle_ref(), waitfor: ZX_USER_SIGNAL_0, pending: ZX_SIGNAL_NONE },
+          WaitItem { handle: e2.as_handle_ref(), waitfor: ZX_USER_SIGNAL_1, pending: ZX_SIGNAL_NONE },
+        ];
+        assert_eq!(object_wait_many(&mut items, deadline_after(ten_ms)), Err(Status::ErrTimedOut));
+        assert_eq!(items[0].pending, ZX_SIGNAL_LAST_HANDLE);
+        assert_eq!(items[1].pending, ZX_SIGNAL_LAST_HANDLE);
+
+        // Signal one object and it should return success.
+        assert!(e1.signal_handle(ZX_SIGNAL_NONE, ZX_USER_SIGNAL_0).is_ok());
+        assert!(object_wait_many(&mut items, deadline_after(ten_ms)).is_ok());
+        assert_eq!(items[0].pending, ZX_USER_SIGNAL_0 | ZX_SIGNAL_LAST_HANDLE);
+        assert_eq!(items[1].pending, ZX_SIGNAL_LAST_HANDLE);
+
+        // Signal the other and it should return both.
+        assert!(e2.signal_handle(ZX_SIGNAL_NONE, ZX_USER_SIGNAL_1).is_ok());
+        assert!(object_wait_many(&mut items, deadline_after(ten_ms)).is_ok());
+        assert_eq!(items[0].pending, ZX_USER_SIGNAL_0 | ZX_SIGNAL_LAST_HANDLE);
+        assert_eq!(items[1].pending, ZX_USER_SIGNAL_1 | ZX_SIGNAL_LAST_HANDLE);
+
+        // Clear signals on both; now it should time out again.
+        assert!(e1.signal_handle(ZX_USER_SIGNAL_0, ZX_SIGNAL_NONE).is_ok());
+        assert!(e2.signal_handle(ZX_USER_SIGNAL_1, ZX_SIGNAL_NONE).is_ok());
+        assert_eq!(object_wait_many(&mut items, deadline_after(ten_ms)), Err(Status::ErrTimedOut));
+        assert_eq!(items[0].pending, ZX_SIGNAL_LAST_HANDLE);
+        assert_eq!(items[1].pending, ZX_SIGNAL_LAST_HANDLE);
+    }
+
+    #[test]
+    fn cookies() {
+        let event = Event::create(EventOpts::Default).unwrap();
+        let scope = Event::create(EventOpts::Default).unwrap();
+
+        // Getting a cookie when none has been set should fail.
+        assert_eq!(event.get_cookie(&scope.as_handle_ref()), Err(Status::ErrAccessDenied));
+
+        // Set a cookie.
+        assert_eq!(event.set_cookie(&scope.as_handle_ref(), 42), Ok(()));
+
+        // Should get it back....
+        assert_eq!(event.get_cookie(&scope.as_handle_ref()), Ok(42));
+
+        // but not with the wrong scope!
+        assert_eq!(event.get_cookie(&event.as_handle_ref()), Err(Status::ErrAccessDenied));
+
+        // Can change it, with the same scope...
+        assert_eq!(event.set_cookie(&scope.as_handle_ref(), 123), Ok(()));
+
+        // but not with a different scope.
+        assert_eq!(event.set_cookie(&event.as_handle_ref(), 123), Err(Status::ErrAccessDenied));
+    }
+
+    #[test]
+    fn cprng() {
+        let mut buffer = [0; 20];
+        assert_eq!(cprng_draw(&mut buffer), Ok(20));
+        assert_ne!(buffer[0], 0);
+        assert_ne!(buffer[19], 0);
+    }
+
+    #[test]
+    fn cprng_too_large() {
+        let mut buffer = [0; ZX_CPRNG_DRAW_MAX_LEN + 1];
+        assert_eq!(cprng_draw(&mut buffer), Err(Status::ErrInvalidArgs));
+
+        for mut s in buffer.chunks_mut(ZX_CPRNG_DRAW_MAX_LEN) {
+            assert_eq!(cprng_draw(&mut s), Ok(s.len()));
+        }
+    }
+
+    #[test]
+    fn cprng_add() {
+        let buffer = [0, 1, 2];
+        assert_eq!(cprng_add_entropy(&buffer), Ok(()));
+    }
+}
+
+pub fn usize_into_u32(n: usize) -> Result<u32, ()> {
+    if n > ::std::u32::MAX as usize || n < ::std::u32::MIN as usize {
+        return Err(())
+    }
+    Ok(n as u32)
+}
+
+pub fn size_to_u32_sat(n: usize) -> u32 {
+    if n > ::std::u32::MAX as usize {
+        return ::std::u32::MAX;
+    }
+    if n < ::std::u32::MIN as usize {
+        return ::std::u32::MIN;
+    }
+    n as u32
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon/src/port.rs
@@ -0,0 +1,354 @@
+// Copyright 2017 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//! Type-safe bindings for Zircon port objects.
+
+use std::mem;
+
+use {AsHandleRef, HandleBased, Handle, HandleRef, Signals, Status, Time};
+use {sys, into_result};
+
+/// An object representing a Zircon
+/// [port](https://fuchsia.googlesource.com/zircon/+/master/docs/objects/port.md).
+///
+/// As essentially a subtype of `Handle`, it can be freely interconverted.
+#[derive(Debug, Eq, PartialEq)]
+pub struct Port(Handle);
+impl_handle_based!(Port);
+
+/// A packet sent through a port. This is a type-safe wrapper for
+/// [zx_port_packet_t](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/port_wait2.md).
+#[derive(PartialEq, Eq, Debug)]
+pub struct Packet(sys::zx_port_packet_t);
+
+/// The contents of a `Packet`.
+#[derive(Debug, Copy, Clone)]
+pub enum PacketContents {
+    /// A user-generated packet.
+    User(UserPacket),
+    /// A one-shot signal packet generated via `object_wait_async`.
+    SignalOne(SignalPacket),
+    /// A repeating signal packet generated via `object_wait_async`.
+    SignalRep(SignalPacket),
+}
+
+/// Contents of a user packet (one sent by `port_queue`). This is a type-safe wrapper for
+/// [zx_packet_user_t](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/port_wait2.md).
+#[derive(Debug, Copy, Clone)]
+pub struct UserPacket(sys::zx_packet_user_t);
+
+/// Contents of a signal packet (one generated by the kernel). This is a type-safe wrapper for
+/// [zx_packet_signal_t](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/port_wait2.md).
+#[derive(Debug, Copy, Clone)]
+pub struct SignalPacket(sys::zx_packet_signal_t);
+
+impl Packet {
+    /// Creates a new packet with `UserPacket` data.
+    pub fn from_user_packet(key: u64, status: i32, user: UserPacket) -> Packet {
+        Packet(
+            sys::zx_port_packet_t {
+                key: key,
+                packet_type: sys::zx_packet_type_t::ZX_PKT_TYPE_USER,
+                status: status,
+                union: user.0,
+            }
+        )
+    }
+
+    /// The packet's key.
+    pub fn key(&self) -> u64 {
+        self.0.key
+    }
+
+    /// The packet's status.
+    // TODO: should this type be wrapped?
+    pub fn status(&self) -> i32 {
+        self.0.status
+    }
+
+    /// The contents of the packet.
+    pub fn contents(&self) -> PacketContents {
+        if self.0.packet_type == sys::zx_packet_type_t::ZX_PKT_TYPE_USER {
+            PacketContents::User(UserPacket(self.0.union))
+        } else if self.0.packet_type == sys::zx_packet_type_t::ZX_PKT_TYPE_SIGNAL_ONE {
+            PacketContents::SignalOne(SignalPacket(unsafe { mem::transmute_copy(&self.0.union) }))
+        } else if self.0.packet_type == sys::zx_packet_type_t::ZX_PKT_TYPE_SIGNAL_REP {
+            PacketContents::SignalRep(SignalPacket(unsafe { mem::transmute_copy(&self.0.union) }))
+        } else {
+            panic!("unexpected packet type");
+        }
+    }
+}
+
+impl UserPacket {
+    pub fn from_u8_array(val: [u8; 32]) -> UserPacket {
+        UserPacket(val)
+    }
+
+    pub fn as_u8_array(&self) -> &[u8; 32] {
+        &self.0
+    }
+
+    pub fn as_mut_u8_array(&mut self) -> &mut [u8; 32] {
+        &mut self.0
+    }
+}
+
+impl SignalPacket {
+    /// The signals used in the call to `object_wait_async`.
+    pub fn trigger(&self) -> Signals {
+        self.0.trigger
+    }
+
+    /// The observed signals.
+    pub fn observed(&self) -> Signals {
+        self.0.observed
+    }
+
+    /// A per object count of pending operations.
+    pub fn count(&self) -> u64 {
+        self.0.count
+    }
+}
+
+impl Port {
+    /// Create an IO port, allowing IO packets to be read and enqueued.
+    ///
+    /// Wraps the
+    /// [zx_port_create](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/port_create.md)
+    /// syscall.
+    pub fn create(opts: PortOpts) -> Result<Port, Status> {
+        unsafe {
+            let mut handle = 0;
+            let status = sys::zx_port_create(opts as u32, &mut handle);
+            into_result(status, || Self::from(Handle(handle)))
+        }
+    }
+
+    /// Attempt to queue a user packet to the IO port.
+    ///
+    /// Wraps the
+    /// [zx_port_queue](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/port_queue.md)
+    /// syscall.
+    pub fn queue(&self, packet: &Packet) -> Result<(), Status> {
+        let status = unsafe {
+            sys::zx_port_queue(self.raw_handle(),
+                &packet.0 as *const sys::zx_port_packet_t as *const u8, 0)
+        };
+        into_result(status, || ())
+    }
+
+    /// Wait for a packet to arrive on a (V2) port.
+    ///
+    /// Wraps the
+    /// [zx_port_wait](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/port_wait2.md)
+    /// syscall.
+    pub fn wait(&self, deadline: Time) -> Result<Packet, Status> {
+        let mut packet = Default::default();
+        let status = unsafe {
+            sys::zx_port_wait(self.raw_handle(), deadline,
+                &mut packet as *mut sys::zx_port_packet_t as *mut u8, 0)
+        };
+        into_result(status, || Packet(packet))
+    }
+
+    /// Cancel pending wait_async calls for an object with the given key.
+    ///
+    /// Wraps the
+    /// [zx_port_cancel](https://fuchsia.googlesource.com/zircon/+/HEAD/docs/syscalls/port_cancel.md)
+    /// syscall.
+    pub fn cancel<H>(&self, source: &H, key: u64) -> Result<(), Status> where H: HandleBased {
+        let status = unsafe {
+            sys::zx_port_cancel(self.raw_handle(), source.raw_handle(), key)
+        };
+        into_result(status, || ())
+    }
+}
+
+/// Options for creating a port.
+#[repr(u32)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum PortOpts {
+    /// Default options.
+    Default = 0,
+}
+
+impl Default for PortOpts {
+    fn default() -> Self {
+        PortOpts::Default
+    }
+}
+
+/// Options for wait_async.
+#[repr(u32)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum WaitAsyncOpts {
+    Once = sys::ZX_WAIT_ASYNC_ONCE,
+    Repeating = sys::ZX_WAIT_ASYNC_REPEATING,
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use {Duration, Event, EventOpts};
+    use {ZX_SIGNAL_LAST_HANDLE, ZX_SIGNAL_NONE, ZX_USER_SIGNAL_0, ZX_USER_SIGNAL_1};
+    use deadline_after;
+
+    #[test]
+    fn port_basic() {
+        let ten_ms: Duration = 10_000_000;
+
+        let port = Port::create(PortOpts::Default).unwrap();
+
+        // Waiting now should time out.
+        assert_eq!(port.wait(deadline_after(ten_ms)), Err(Status::ErrTimedOut));
+
+        // Send a valid packet.
+        let packet = Packet::from_user_packet(
+            42,
+            123,
+            UserPacket::from_u8_array([13; 32]),
+        );
+        assert!(port.queue(&packet).is_ok());
+
+        // Waiting should succeed this time. We should get back the packet we sent.
+        let read_packet = port.wait(deadline_after(ten_ms)).unwrap();
+        assert_eq!(read_packet, packet);
+    }
+
+    #[test]
+    fn wait_async_once() {
+        let ten_ms: Duration = 10_000_000;
+        let key = 42;
+
+        let port = Port::create(PortOpts::Default).unwrap();
+        let event = Event::create(EventOpts::Default).unwrap();
+
+        assert!(event.wait_async_handle(&port, key, ZX_USER_SIGNAL_0 | ZX_USER_SIGNAL_1,
+            WaitAsyncOpts::Once).is_ok());
+
+        // Waiting without setting any signal should time out.
+        assert_eq!(port.wait(deadline_after(ten_ms)), Err(Status::ErrTimedOut));
+
+        // If we set a signal, we should be able to wait for it.
+        assert!(event.signal_handle(ZX_SIGNAL_NONE, ZX_USER_SIGNAL_0).is_ok());
+        let read_packet = port.wait(deadline_after(ten_ms)).unwrap();
+        assert_eq!(read_packet.key(), key);
+        assert_eq!(read_packet.status(), 0);
+        match read_packet.contents() {
+            PacketContents::SignalOne(sig) => {
+                assert_eq!(sig.trigger(), ZX_USER_SIGNAL_0 | ZX_USER_SIGNAL_1);
+                assert_eq!(sig.observed(), ZX_USER_SIGNAL_0 | ZX_SIGNAL_LAST_HANDLE);
+                assert_eq!(sig.count(), 1);
+            }
+            _ => panic!("wrong packet type"),
+        }
+
+        // Shouldn't get any more packets.
+        assert_eq!(port.wait(deadline_after(ten_ms)), Err(Status::ErrTimedOut));
+
+        // Calling wait_async again should result in another packet.
+        assert!(event.wait_async_handle(&port, key, ZX_USER_SIGNAL_0, WaitAsyncOpts::Once).is_ok());
+        let read_packet = port.wait(deadline_after(ten_ms)).unwrap();
+        assert_eq!(read_packet.key(), key);
+        assert_eq!(read_packet.status(), 0);
+        match read_packet.contents() {
+            PacketContents::SignalOne(sig) => {
+                assert_eq!(sig.trigger(), ZX_USER_SIGNAL_0);
+                assert_eq!(sig.observed(), ZX_USER_SIGNAL_0 | ZX_SIGNAL_LAST_HANDLE);
+                assert_eq!(sig.count(), 1);
+            }
+            _ => panic!("wrong packet type"),
+        }
+
+        // Calling wait_async_handle then cancel, we should not get a packet as cancel will
+        // remove it from  the queue.
+        assert!(event.wait_async_handle(&port, key, ZX_USER_SIGNAL_0, WaitAsyncOpts::Once).is_ok());
+        assert!(port.cancel(&event, key).is_ok());
+        assert_eq!(port.wait(deadline_after(ten_ms)), Err(Status::ErrTimedOut));
+
+        // If the event is signalled after the cancel, we also shouldn't get a packet.
+        assert!(event.signal_handle(ZX_USER_SIGNAL_0, ZX_SIGNAL_NONE).is_ok());  // clear signal
+        assert!(event.wait_async_handle(&port, key, ZX_USER_SIGNAL_0, WaitAsyncOpts::Once).is_ok());
+        assert!(port.cancel(&event, key).is_ok());
+        assert!(event.signal_handle(ZX_SIGNAL_NONE, ZX_USER_SIGNAL_0).is_ok());
+        assert_eq!(port.wait(deadline_after(ten_ms)), Err(Status::ErrTimedOut));
+    }
+
+    #[test]
+    fn wait_async_repeating() {
+        let ten_ms: Duration = 10_000_000;
+        let key = 42;
+
+        let port = Port::create(PortOpts::Default).unwrap();
+        let event = Event::create(EventOpts::Default).unwrap();
+
+        assert!(event.wait_async_handle(&port, key, ZX_USER_SIGNAL_0 | ZX_USER_SIGNAL_1,
+            WaitAsyncOpts::Repeating).is_ok());
+
+        // Waiting without setting any signal should time out.
+        assert_eq!(port.wait(deadline_after(ten_ms)), Err(Status::ErrTimedOut));
+
+        // If we set a signal, we should be able to wait for it.
+        assert!(event.signal_handle(ZX_SIGNAL_NONE, ZX_USER_SIGNAL_0).is_ok());
+        let read_packet = port.wait(deadline_after(ten_ms)).unwrap();
+        assert_eq!(read_packet.key(), key);
+        assert_eq!(read_packet.status(), 0);
+        match read_packet.contents() {
+            PacketContents::SignalRep(sig) => {
+                assert_eq!(sig.trigger(), ZX_USER_SIGNAL_0 | ZX_USER_SIGNAL_1);
+                assert_eq!(sig.observed(), ZX_USER_SIGNAL_0 | ZX_SIGNAL_LAST_HANDLE);
+                assert_eq!(sig.count(), 1);
+            }
+            _ => panic!("wrong packet type"),
+        }
+
+        // Should not get any more packets, as ZX_WAIT_ASYNC_REPEATING is edge triggered rather than
+        // level triggered.
+        assert_eq!(port.wait(deadline_after(ten_ms)), Err(Status::ErrTimedOut));
+
+        // If we clear and resignal, we should get the same packet again,
+        // even though we didn't call event.wait_async again.
+        assert!(event.signal_handle(ZX_USER_SIGNAL_0, ZX_SIGNAL_NONE).is_ok());  // clear signal
+        assert!(event.signal_handle(ZX_SIGNAL_NONE, ZX_USER_SIGNAL_0).is_ok());
+        let read_packet = port.wait(deadline_after(ten_ms)).unwrap();
+        assert_eq!(read_packet.key(), key);
+        assert_eq!(read_packet.status(), 0);
+        match read_packet.contents() {
+            PacketContents::SignalRep(sig) => {
+                assert_eq!(sig.trigger(), ZX_USER_SIGNAL_0 | ZX_USER_SIGNAL_1);
+                assert_eq!(sig.observed(), ZX_USER_SIGNAL_0 | ZX_SIGNAL_LAST_HANDLE);
+                assert_eq!(sig.count(), 1);
+            }
+            _ => panic!("wrong packet type"),
+        }
+
+        // Cancelling the wait should stop us getting packets...
+        assert!(port.cancel(&event, key).is_ok());
+        assert_eq!(port.wait(deadline_after(ten_ms)), Err(Status::ErrTimedOut));
+        // ... even if we clear and resignal
+        assert!(event.signal_handle(ZX_USER_SIGNAL_0, ZX_SIGNAL_NONE).is_ok());  // clear signal
+        assert!(event.signal_handle(ZX_SIGNAL_NONE, ZX_USER_SIGNAL_0).is_ok());
+        assert_eq!(port.wait(deadline_after(ten_ms)), Err(Status::ErrTimedOut));
+
+        // Calling wait_async again should result in another packet.
+        assert!(event.wait_async_handle(
+            &port, key, ZX_USER_SIGNAL_0, WaitAsyncOpts::Repeating).is_ok());
+        let read_packet = port.wait(deadline_after(ten_ms)).unwrap();
+        assert_eq!(read_packet.key(), key);
+        assert_eq!(read_packet.status(), 0);
+        match read_packet.contents() {
+            PacketContents::SignalRep(sig) => {
+                assert_eq!(sig.trigger(), ZX_USER_SIGNAL_0);
+                assert_eq!(sig.observed(), ZX_USER_SIGNAL_0 | ZX_SIGNAL_LAST_HANDLE);
+                assert_eq!(sig.count(), 1);
+            }
+            _ => panic!("wrong packet type"),
+        }
+
+        // Closing the handle should stop us getting packets.
+        drop(event);
+        assert_eq!(port.wait(deadline_after(ten_ms)), Err(Status::ErrTimedOut));
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon/src/process.rs
@@ -0,0 +1,14 @@
+// Copyright 2017 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//! Type-safe bindings for Zircon process.
+
+use {AsHandleRef, HandleBased, Handle, HandleRef};
+
+/// An object representing a Zircon process.
+///
+/// As essentially a subtype of `Handle`, it can be freely interconverted.
+#[derive(Debug, Eq, PartialEq)]
+pub struct Process(Handle);
+impl_handle_based!(Process);
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon/src/socket.rs
@@ -0,0 +1,162 @@
+// Copyright 2016 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//! Type-safe bindings for Zircon sockets.
+
+use {AsHandleRef, HandleBased, Handle, HandleRef, Peered};
+use {sys, Status, into_result};
+
+use std::ptr;
+
+/// An object representing a Zircon
+/// [socket](https://fuchsia.googlesource.com/zircon/+/master/docs/concepts.md#Message-Passing_Sockets-and-Channels).
+///
+/// As essentially a subtype of `Handle`, it can be freely interconverted.
+#[derive(Debug, Eq, PartialEq)]
+pub struct Socket(Handle);
+impl_handle_based!(Socket);
+impl Peered for Socket {}
+
+/// Options for creating a socket pair.
+#[repr(u32)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum SocketOpts {
+    /// Default options.
+    Default = 0,
+}
+
+impl Default for SocketOpts {
+    fn default() -> Self {
+        SocketOpts::Default
+    }
+}
+
+/// Options for writing into a socket.
+#[repr(u32)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum SocketWriteOpts {
+    /// Default options.
+    Default = 0,
+}
+
+impl Default for SocketWriteOpts {
+    fn default() -> Self {
+        SocketWriteOpts::Default
+    }
+}
+
+/// Options for reading from a socket.
+#[repr(u32)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum SocketReadOpts {
+    /// Default options.
+    Default = 0,
+}
+
+impl Default for SocketReadOpts {
+    fn default() -> Self {
+        SocketReadOpts::Default
+    }
+}
+
+
+impl Socket {
+    /// Create a socket, accessed through a pair of endpoints. Data written
+    /// into one may be read from the other.
+    ///
+    /// Wraps
+    /// [zx_socket_create](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/socket_create.md).
+    pub fn create(opts: SocketOpts) -> Result<(Socket, Socket), Status> {
+        unsafe {
+            let mut out0 = 0;
+            let mut out1 = 0;
+            let status = sys::zx_socket_create(opts as u32, &mut out0, &mut out1);
+            into_result(status, ||
+                (Self::from(Handle(out0)),
+                    Self::from(Handle(out1))))
+        }
+    }
+
+    /// Write the given bytes into the socket.
+    /// Return value (on success) is number of bytes actually written.
+    ///
+    /// Wraps
+    /// [zx_socket_write](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/socket_write.md).
+    pub fn write(&self, opts: SocketWriteOpts, bytes: &[u8]) -> Result<usize, Status> {
+        let mut actual = 0;
+        let status = unsafe {
+            sys::zx_socket_write(self.raw_handle(), opts as u32, bytes.as_ptr(), bytes.len(),
+                &mut actual)
+        };
+        into_result(status, || actual)
+    }
+
+    /// Read the given bytes from the socket.
+    /// Return value (on success) is number of bytes actually read.
+    ///
+    /// Wraps
+    /// [zx_socket_read](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/socket_read.md).
+    pub fn read(&self, opts: SocketReadOpts, bytes: &mut [u8]) -> Result<usize, Status> {
+        let mut actual = 0;
+        let status = unsafe {
+            sys::zx_socket_read(self.raw_handle(), opts as u32, bytes.as_mut_ptr(),
+                bytes.len(), &mut actual)
+        };
+        if status != sys::ZX_OK {
+            // If an error is returned then actual is undefined, so to be safe we set it to 0 and
+            // ignore any data that is set in bytes.
+            actual = 0;
+        }
+        into_result(status, || actual)
+    }
+
+    /// Close half of the socket, so attempts by the other side to write will fail.
+    ///
+    /// Implements the `ZX_SOCKET_HALF_CLOSE` option of
+    /// [zx_socket_write](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/socket_write.md).
+    pub fn half_close(&self) -> Result<(), Status> {
+        let status = unsafe { sys::zx_socket_write(self.raw_handle(), sys::ZX_SOCKET_HALF_CLOSE,
+            ptr::null(), 0, ptr::null_mut()) };
+        into_result(status, || ())
+    }
+
+    pub fn outstanding_read_bytes(&self) -> Result<usize, Status> {
+        let mut outstanding = 0;
+        let status = unsafe {
+            sys::zx_socket_read(self.raw_handle(), 0, ptr::null_mut(), 0, &mut outstanding)
+        };
+        into_result(status, || outstanding)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn socket_basic() {
+        let (s1, s2) = Socket::create(SocketOpts::Default).unwrap();
+
+        // Write in one end and read it back out the other.
+        assert_eq!(s1.write(SocketWriteOpts::Default, b"hello").unwrap(), 5);
+
+        let mut read_vec = vec![0; 8];
+        assert_eq!(s2.read(SocketReadOpts::Default, &mut read_vec).unwrap(), 5);
+        assert_eq!(&read_vec[0..5], b"hello");
+
+        // Try reading when there is nothing to read.
+        assert_eq!(s2.read(SocketReadOpts::Default, &mut read_vec), Err(Status::ErrShouldWait));
+
+        // Close the socket from one end.
+        assert!(s1.half_close().is_ok());
+        assert_eq!(s2.read(SocketReadOpts::Default, &mut read_vec), Err(Status::ErrBadState));
+        assert_eq!(s1.write(SocketWriteOpts::Default, b"fail"), Err(Status::ErrBadState));
+
+        // Writing in the other direction should still work.
+        assert_eq!(s1.read(SocketReadOpts::Default, &mut read_vec), Err(Status::ErrShouldWait));
+        assert_eq!(s2.write(SocketWriteOpts::Default, b"back").unwrap(), 4);
+        assert_eq!(s1.read(SocketReadOpts::Default, &mut read_vec).unwrap(), 4);
+        assert_eq!(&read_vec[0..4], b"back");
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon/src/thread.rs
@@ -0,0 +1,14 @@
+// Copyright 2017 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//! Type-safe bindings for Zircon thread.
+
+use {AsHandleRef, HandleBased, Handle, HandleRef};
+
+/// An object representing a Zircon thread.
+///
+/// As essentially a subtype of `Handle`, it can be freely interconverted.
+#[derive(Debug, Eq, PartialEq)]
+pub struct Thread(Handle);
+impl_handle_based!(Thread);
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon/src/timer.rs
@@ -0,0 +1,92 @@
+// Copyright 2016 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//! Type-safe bindings for Zircon timer objects.
+
+use {AsHandleRef, ClockId, Duration, HandleBased, Handle, HandleRef, Status, Time};
+use {sys, into_result};
+
+/// An object representing a Zircon
+/// [event pair](https://fuchsia.googlesource.com/zircon/+/master/docs/concepts.md#Other-IPC_Events_Event-Pairs_and-User-Signals).
+///
+/// As essentially a subtype of `Handle`, it can be freely interconverted.
+#[derive(Debug, Eq, PartialEq)]
+pub struct Timer(Handle);
+impl_handle_based!(Timer);
+
+impl Timer {
+    /// Create a timer, an object that can signal when a specified point in time has been reached.
+    /// Wraps the
+    /// [zx_timer_create](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/timer_create.md)
+    /// syscall.
+    pub fn create(options: TimerOpts, clock_id: ClockId) -> Result<Timer, Status> {
+        let mut out = 0;
+        let status = unsafe { sys::zx_timer_create(options as u32, clock_id as u32, &mut out) };
+        into_result(status, || Self::from(Handle(out)))
+    }
+
+    /// Start a one-shot timer that will fire when `deadline` passes. Wraps the
+    /// [zx_timer_set](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/timer_set.md)
+    /// syscall.
+    pub fn set(&self, deadline: Time, slack: Duration) -> Result<(), Status> {
+        let status = unsafe { sys::zx_timer_set(self.raw_handle(), deadline, slack) };
+        into_result(status, || ())
+    }
+
+    /// Cancels a pending timer that was started with start(). Wraps the
+    /// [zx_timer_cancel](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/timer_cancel.md)
+    /// syscall.
+    pub fn cancel(&self) -> Result<(), Status> {
+        let status = unsafe { sys::zx_timer_cancel(self.raw_handle()) };
+        into_result(status, || ())
+    }
+}
+
+/// Options for creating a timer.
+#[repr(u32)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum TimerOpts {
+    /// Default options.
+    Default = 0,
+}
+
+impl Default for TimerOpts {
+    fn default() -> Self {
+        TimerOpts::Default
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use {Duration, ZX_SIGNAL_LAST_HANDLE, ZX_TIMER_SIGNALED};
+    use deadline_after;
+
+    #[test]
+    fn create_timer_invalid_clock() {
+        assert_eq!(Timer::create(TimerOpts::Default, ClockId::UTC).unwrap_err(), Status::ErrInvalidArgs);
+        assert_eq!(Timer::create(TimerOpts::Default, ClockId::Thread), Err(Status::ErrInvalidArgs));
+    }
+
+    #[test]
+    fn timer_basic() {
+        let ten_ms: Duration = 10_000_000;
+        let twenty_ms: Duration = 20_000_000;
+
+        // Create a timer
+        let timer = Timer::create(TimerOpts::Default, ClockId::Monotonic).unwrap();
+
+        // Should not signal yet.
+        assert_eq!(timer.wait_handle(ZX_TIMER_SIGNALED, deadline_after(ten_ms)), Err(Status::ErrTimedOut));
+
+        // Set it, and soon it should signal.
+        assert_eq!(timer.set(ten_ms, 0), Ok(()));
+        assert_eq!(timer.wait_handle(ZX_TIMER_SIGNALED, deadline_after(twenty_ms)).unwrap(),
+            ZX_TIMER_SIGNALED | ZX_SIGNAL_LAST_HANDLE);
+
+        // Cancel it, and it should stop signalling.
+        assert_eq!(timer.cancel(), Ok(()));
+        assert_eq!(timer.wait_handle(ZX_TIMER_SIGNALED, deadline_after(ten_ms)), Err(Status::ErrTimedOut));
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon/src/vmo.rs
@@ -0,0 +1,273 @@
+// Copyright 2017 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//! Type-safe bindings for Zircon vmo objects.
+
+use {AsHandleRef, Cookied, HandleBased, Handle, HandleRef, Status};
+use {sys, into_result};
+use std::{mem, ptr};
+
+/// An object representing a Zircon
+/// [virtual memory object](https://fuchsia.googlesource.com/zircon/+/master/docs/objects/vm_object.md).
+///
+/// As essentially a subtype of `Handle`, it can be freely interconverted.
+#[derive(Debug, Eq, PartialEq)]
+pub struct Vmo(Handle);
+impl_handle_based!(Vmo);
+impl Cookied for Vmo {}
+
+impl Vmo {
+    /// Create a virtual memory object.
+    ///
+    /// Wraps the
+    /// `zx_vmo_create`
+    /// syscall. See the
+    /// [Shared Memory: Virtual Memory Objects (VMOs)](https://fuchsia.googlesource.com/zircon/+/master/docs/concepts.md#Shared-Memory_Virtual-Memory-Objects-VMOs)
+    /// for more information.
+    pub fn create(size: u64, options: VmoOpts) -> Result<Vmo, Status> {
+        let mut handle = 0;
+        let status = unsafe { sys::zx_vmo_create(size, options as u32, &mut handle) };
+        into_result(status, ||
+            Vmo::from(Handle(handle)))
+    }
+
+    /// Read from a virtual memory object.
+    ///
+    /// Wraps the `zx_vmo_read` syscall.
+    pub fn read(&self, data: &mut [u8], offset: u64) -> Result<usize, Status> {
+        unsafe {
+            let mut actual = 0;
+            let status = sys::zx_vmo_read(self.raw_handle(), data.as_mut_ptr(),
+                offset, data.len(), &mut actual);
+            into_result(status, || actual)
+        }
+    }
+
+    /// Write to a virtual memory object.
+    ///
+    /// Wraps the `zx_vmo_write` syscall.
+    pub fn write(&self, data: &[u8], offset: u64) -> Result<usize, Status> {
+        unsafe {
+            let mut actual = 0;
+            let status = sys::zx_vmo_write(self.raw_handle(), data.as_ptr(),
+                offset, data.len(), &mut actual);
+            into_result(status, || actual)
+        }
+    }
+
+    /// Get the size of a virtual memory object.
+    ///
+    /// Wraps the `zx_vmo_get_size` syscall.
+    pub fn get_size(&self) -> Result<u64, Status> {
+        let mut size = 0;
+        let status = unsafe { sys::zx_vmo_get_size(self.raw_handle(), &mut size) };
+        into_result(status, || size)
+    }
+
+    /// Attempt to change the size of a virtual memory object.
+    ///
+    /// Wraps the `zx_vmo_set_size` syscall.
+    pub fn set_size(&self, size: u64) -> Result<(), Status> {
+        let status = unsafe { sys::zx_vmo_set_size(self.raw_handle(), size) };
+        into_result(status, || ())
+    }
+
+    /// Perform an operation on a range of a virtual memory object.
+    ///
+    /// Wraps the
+    /// [zx_vmo_op_range](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/vmo_op_range.md)
+    /// syscall.
+    pub fn op_range(&self, op: VmoOp, offset: u64, size: u64) -> Result<(), Status> {
+        let status = unsafe {
+            sys::zx_vmo_op_range(self.raw_handle(), op as u32, offset, size, ptr::null_mut(), 0)
+        };
+        into_result(status, || ())
+    }
+
+    /// Look up a list of physical addresses corresponding to the pages held by the VMO from
+    /// `offset` to `offset`+`size`, and store them in `buffer`.
+    ///
+    /// Wraps the
+    /// [zx_vmo_op_range](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/vmo_op_range.md)
+    /// syscall with ZX_VMO_OP_LOOKUP.
+    pub fn lookup(&self, offset: u64, size: u64, buffer: &mut [sys::zx_paddr_t])
+        -> Result<(), Status>
+    {
+        let status = unsafe {
+            sys::zx_vmo_op_range(self.raw_handle(), sys::ZX_VMO_OP_LOOKUP, offset, size,
+                buffer.as_mut_ptr() as *mut u8, buffer.len() * mem::size_of::<sys::zx_paddr_t>())
+        };
+        into_result(status, || ())
+    }
+
+    /// Create a new virtual memory object that clones a range of this one.
+    ///
+    /// Wraps the
+    /// [zx_vmo_clone](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/vmo_clone.md)
+    /// syscall.
+    pub fn clone(&self, options: VmoCloneOpts, offset: u64, size: u64) -> Result<Vmo, Status> {
+        let mut out = 0;
+        let status = unsafe {
+            sys::zx_vmo_clone(self.raw_handle(), options as u32, offset, size, &mut out)
+        };
+        into_result(status, || Vmo::from(Handle(out)))
+    }
+}
+
+/// Options for creating virtual memory objects. None supported yet.
+#[repr(u32)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum VmoOpts {
+    /// Default options.
+    Default = 0,
+}
+
+impl Default for VmoOpts {
+    fn default() -> Self {
+        VmoOpts::Default
+    }
+}
+
+#[repr(u32)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum VmoOp {
+    /// Commit `size` bytes worth of pages starting at byte `offset` for the VMO.
+    Commit = sys::ZX_VMO_OP_COMMIT,
+    /// Release a range of pages previously committed to the VMO from `offset` to `offset`+`size`.
+    Decommit = sys::ZX_VMO_OP_DECOMMIT,
+    // Presently unsupported.
+    Lock = sys::ZX_VMO_OP_LOCK,
+    // Presently unsupported.
+    Unlock = sys::ZX_VMO_OP_UNLOCK,
+    /// Perform a cache sync operation.
+    CacheSync = sys::ZX_VMO_OP_CACHE_SYNC,
+    /// Perform a cache invalidation operation.
+    CacheInvalidate = sys::ZX_VMO_OP_CACHE_INVALIDATE,
+    /// Perform a cache clean operation.
+    CacheClean = sys::ZX_VMO_OP_CACHE_CLEAN,
+    /// Perform cache clean and invalidation operations together.
+    CacheCleanInvalidate = sys::ZX_VMO_OP_CACHE_CLEAN_INVALIDATE,
+}
+
+#[repr(u32)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum VmoCloneOpts {
+    /// Create a copy-on-write clone.
+    CopyOnWrite = sys::ZX_VMO_CLONE_COPY_ON_WRITE,
+}
+
+impl Default for VmoCloneOpts {
+    fn default() -> Self {
+        VmoCloneOpts::CopyOnWrite
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn vmo_get_size() {
+        let size = 16 * 1024 * 1024;
+        let vmo = Vmo::create(size, VmoOpts::Default).unwrap();
+        assert_eq!(size, vmo.get_size().unwrap());
+    }
+
+    #[test]
+    fn vmo_set_size() {
+        let start_size = 12;
+        let vmo = Vmo::create(start_size, VmoOpts::Default).unwrap();
+        assert_eq!(start_size, vmo.get_size().unwrap());
+
+        // Change the size and make sure the new size is reported
+        let new_size = 23;
+        assert!(vmo.set_size(new_size).is_ok());
+        assert_eq!(new_size, vmo.get_size().unwrap());
+    }
+
+    #[test]
+    fn vmo_read_write() {
+        let mut vec1 = vec![0; 16];
+        let vmo = Vmo::create(vec1.len() as u64, VmoOpts::Default).unwrap();
+        assert_eq!(vmo.write(b"abcdef", 0), Ok(6));
+        assert_eq!(16, vmo.read(&mut vec1, 0).unwrap());
+        assert_eq!(b"abcdef", &vec1[0..6]);
+        assert_eq!(vmo.write(b"123", 2), Ok(3));
+        assert_eq!(16, vmo.read(&mut vec1, 0).unwrap());
+        assert_eq!(b"ab123f", &vec1[0..6]);
+        assert_eq!(15, vmo.read(&mut vec1, 1).unwrap());
+        assert_eq!(b"b123f", &vec1[0..5]);
+    }
+
+    #[test]
+    fn vmo_op_range_unsupported() {
+        let vmo = Vmo::create(12, VmoOpts::Default).unwrap();
+        assert_eq!(vmo.op_range(VmoOp::Lock, 0, 1), Err(Status::ErrNotSupported));
+        assert_eq!(vmo.op_range(VmoOp::Unlock, 0, 1), Err(Status::ErrNotSupported));
+    }
+
+    #[test]
+    fn vmo_lookup() {
+        let vmo = Vmo::create(12, VmoOpts::Default).unwrap();
+        let mut buffer = vec![0; 2];
+
+        // Lookup will fail as it is not committed yet.
+        assert_eq!(vmo.lookup(0, 12, &mut buffer), Err(Status::ErrNoMemory));
+
+        // Commit and try again.
+        assert_eq!(vmo.op_range(VmoOp::Commit, 0, 12), Ok(()));
+        assert_eq!(vmo.lookup(0, 12, &mut buffer), Ok(()));
+        assert_ne!(buffer[0], 0);
+        assert_eq!(buffer[1], 0);
+
+        // If we decommit then lookup should go back to failing.
+        assert_eq!(vmo.op_range(VmoOp::Decommit, 0, 12), Ok(()));
+        assert_eq!(vmo.lookup(0, 12, &mut buffer), Err(Status::ErrNoMemory));
+    }
+
+    #[test]
+    fn vmo_cache() {
+        let vmo = Vmo::create(12, VmoOpts::Default).unwrap();
+
+        // Cache operations should all succeed.
+        assert_eq!(vmo.op_range(VmoOp::CacheSync, 0, 12), Ok(()));
+        assert_eq!(vmo.op_range(VmoOp::CacheInvalidate, 0, 12), Ok(()));
+        assert_eq!(vmo.op_range(VmoOp::CacheClean, 0, 12), Ok(()));
+        assert_eq!(vmo.op_range(VmoOp::CacheCleanInvalidate, 0, 12), Ok(()));
+    }
+
+    #[test]
+    fn vmo_clone() {
+        let original = Vmo::create(12, VmoOpts::Default).unwrap();
+        assert_eq!(original.write(b"one", 0), Ok(3));
+
+        // Clone the VMO, and make sure it contains what we expect.
+        let clone = original.clone(VmoCloneOpts::CopyOnWrite, 0, 10).unwrap();
+        let mut read_buffer = vec![0; 16];
+        assert_eq!(clone.read(&mut read_buffer, 0), Ok(10));
+        assert_eq!(&read_buffer[0..3], b"one");
+
+        // Writing to the original will affect the clone too, surprisingly.
+        assert_eq!(original.write(b"two", 0), Ok(3));
+        assert_eq!(original.read(&mut read_buffer, 0), Ok(12));
+        assert_eq!(&read_buffer[0..3], b"two");
+        assert_eq!(clone.read(&mut read_buffer, 0), Ok(10));
+        assert_eq!(&read_buffer[0..3], b"two");
+
+        // However, writing to the clone will not affect the original
+        assert_eq!(clone.write(b"three", 0), Ok(5));
+        assert_eq!(original.read(&mut read_buffer, 0), Ok(12));
+        assert_eq!(&read_buffer[0..3], b"two");
+        assert_eq!(clone.read(&mut read_buffer, 0), Ok(10));
+        assert_eq!(&read_buffer[0..5], b"three");
+
+        // And now that the copy-on-write has happened, writing to the original will not affect the
+        // clone. How bizarre.
+        assert_eq!(original.write(b"four", 0), Ok(4));
+        assert_eq!(original.read(&mut read_buffer, 0), Ok(12));
+        assert_eq!(&read_buffer[0..4], b"four");
+        assert_eq!(clone.read(&mut read_buffer, 0), Ok(10));
+        assert_eq!(&read_buffer[0..5], b"three");
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon/tools/BUILD.gn
@@ -0,0 +1,51 @@
+# Copyright 2017 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+group("clang_wrapper") {
+  deps = [
+    ":arm64_wrapper",
+    ":x64_wrapper",
+  ]
+}
+
+executable("clang_wrapper_bin") {
+  output_name = "rust_clang_wrapper"
+
+  sources = [
+    "clang_wrapper.cc",
+  ]
+
+  if (is_linux) {
+    ldflags = [
+      "-pthread",
+    ]
+  }
+}
+
+template("copy_wrapper") {
+
+  arch = invoker.arch
+
+  copy(target_name) {
+    sources = [
+      "$root_out_dir/rust_clang_wrapper",
+    ]
+
+    outputs = [
+      "$root_out_dir/$arch-unknown-fuchsia-cc",
+    ]
+
+    deps = [
+      ":clang_wrapper_bin",
+    ]
+  }
+}
+
+copy_wrapper("arm64_wrapper") {
+  arch = "aarch64"
+}
+
+copy_wrapper("x64_wrapper") {
+  arch = "x86_64"
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon/tools/README.md
@@ -0,0 +1,26 @@
+Build tools for Rust on Fuchsia
+===============================
+
+This directory contains a wrapper so that clang can be invoked using a
+target-specific command line (as is typically done using Gnu tools for
+cross-compiling).
+
+To compile standalone (not part of a build system):
+
+```
+clang++ -O --std=c++11 clang_wrapper.cc -o clang_wrapper
+ln -s clang_wrapper x86-64-unknown-fuchsia-ar
+ln -s clang_wrapper x86-64-unknown-fuchsia-cc
+ln -s clang_wrapper aarch64-unknown-fuchsia-ar
+ln -s clang_wrapper aarch64-unknown-fuchsia-cc
+```
+
+The resulting binaries (`x86-64-unknown-fuchsia-cc` and the like) must be
+placed somewhere under the root of the fuchsia tree.
+
+The wrapper sets the target triple appropriately, and also finds the
+appropriate sysroot for the given target (necessary for linking).
+
+Note: this wrapper is provisional, hopefully to be supplanted by a more
+general config mechanism in LLVM
+(see [relevant LLVM patch](https://reviews.llvm.org/D24933)).
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon/tools/clang_wrapper.cc
@@ -0,0 +1,205 @@
+// Copyright 2016 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Wrap the clang toolchain to supply triple-specific configuration parameters
+// as arguments.
+
+// Gnu-style toolchains encode the target triple in the executable name (each
+// executable is specialized to a single triple), and each toolchain also knows
+// how to find the corresponding sysroot. By contrast, clang uses a single
+// binary, and the target is specified as a command line argument. In addition,
+// in the Fuchsia world, the sysroot is not bundled with the compiler.
+//
+// This wrapper infers the relevant configuration parameters from the command
+// name used to invoke the wrapper, and also finds the sysroot at a known
+// location relative to the jiri root, then invokes clang with the additional
+// arguments.
+
+#include <map>
+#include <string>
+#include <vector>
+#include <iostream>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/utsname.h>
+#include <unistd.h>
+#include <string.h>
+#include <algorithm>
+
+using std::map;
+using std::string;
+using std::vector;
+
+// Get the real path of this executable, resolving symbolic links.
+string GetPath(const char* argv0) {
+  char* path_c = realpath(argv0, nullptr);
+  string path = string(path_c);
+  free(path_c);
+  return path;
+}
+
+// Return path of Jiri root, or empty string if not found.
+string FindJiriRoot(const string& self_path) {
+  string path = self_path;
+  while (true) {
+    size_t pos = path.rfind('/');
+    if (pos == string::npos) {
+      return "";
+    }
+    string basedir = path.substr(0, pos + 1);
+    string trial = basedir + ".jiri_root";
+    struct stat stat_buf;
+    int status = stat(trial.c_str(), &stat_buf);
+    if (status == 0) {
+      return basedir;
+    }
+    path = path.substr(0, pos);
+  }
+}
+
+// Get the basename of the command used to invoke this wrapper.
+// Typical return value: "x86-64-unknown-fuchsia-cc"
+string GetCmd(const char* argv0) {
+  string cmd = argv0;
+  size_t pos = cmd.rfind('/');
+  if (pos != string::npos) {
+    cmd = cmd.substr(pos + 1);
+  }
+  return cmd;
+}
+
+// Given the command basename, get the llvm target triple. Empty string on failure.
+// Typical return value: "x86_64-unknown-fuchsia"
+string TargetTriple(const string& cmd) {
+  size_t pos = cmd.rfind('-');
+  if (pos == string::npos) {
+    return "";
+  }
+  string triple = cmd.substr(0, pos);
+  if (triple.find("x86-64") == 0) {
+    triple[3] = '_';
+  }
+  return triple;
+}
+
+// Given the path to the command, calculate the matching sysroot
+string SysrootPath(const string& triple, const string& self_path) {
+  const string out_dir_name = "out/";
+  size_t pos = self_path.find(out_dir_name);
+  if (pos != string::npos) {
+    string out_path = self_path.substr(0, pos + out_dir_name.length());
+    string zircon_name = triple == "x86_64-unknown-fuchsia" ?
+      "build-zircon-pc-x86-64" : "build-zircon-qemu-arm64";
+    string sysroot_path = out_path + "build-zircon/" + zircon_name + "/sysroot";
+    struct stat stat_buf;
+    int status = stat(sysroot_path.c_str(), &stat_buf);
+    if (status == 0) {
+      return sysroot_path;
+    }
+  }
+  return "";
+}
+
+// Detect the host, get the host identifier (used to select a prebuilt toolchain).
+// Empty string on failure.
+// Typical return value: "mac-x64"
+string HostDouble() {
+  struct utsname name;
+  int status = uname(&name);
+  if (status != 0) {
+    return "";
+  }
+  map<string, string> cpumap = {
+    {"aarch64", "arm64"},
+    {"x86_64", "x64"}
+  };
+  map<string, string> osmap = {
+    {"Linux", "linux"},
+    {"Darwin", "mac"}
+  };
+  return osmap[name.sysname] + "-" + cpumap[name.machine];
+}
+
+// Given the command baseline, get the llvm binary to invoke.
+// Note: the "llvm-ar" special case should probably go away, as Rust no longer
+// invokes an external "ar" tool, and the llvm-ar one probably wouldn't work.
+// Typical return value: "clang"
+string InferTool(const string& cmd) {
+  size_t pos = cmd.rfind('-');
+  string base;
+  if (pos != string::npos) {
+    base = cmd.substr(pos + 1);
+  } else {
+    base = cmd;
+  }
+  if (base == "cc" || base == "gcc") {
+    return "clang";
+  } else if (base == "ar") {
+    return "llvm-ar";
+  }
+  return base;
+}
+
+// Collect C-style argc/argv into a vector of strings.
+vector<string> CollectArgs(int argc, char** argv) {
+  vector<string> result;
+  for (int i = 0; i < argc; i++) {
+    result.push_back(argv[i]);
+  }
+  return result;
+}
+
+// Do "execv" given command path as a string and args as a vector of strings.
+int DoExecv(const string& cmd, vector<string>& args) {
+  vector<const char*> argvec;
+  for (auto& it : args) {
+    argvec.push_back(it.c_str());
+  }
+  argvec.push_back(nullptr);
+  char* const* argv = const_cast<char* const*>(argvec.data());
+  return execv(cmd.c_str(), argv);
+}
+
+void Die(const string& message) {
+  std::cerr << message << std::endl;
+  exit(1);
+}
+
+int main(int argc, char** argv) {
+  string self_path = GetPath(argv[0]);
+  string root = FindJiriRoot(self_path);
+  if (root.empty()) {
+    Die("Can't find .jiri_root in any parent of " + self_path);
+  }
+  string host = HostDouble();
+  if (host.empty()) {
+    Die("Can't detect host (uname failed)");
+  }
+  string cmd = GetCmd(argv[0]);
+  string tool = InferTool(cmd);
+  string triple = TargetTriple(cmd);
+  vector<string> args = CollectArgs(argc, argv);
+
+  string newcmd = root + "buildtools/" + host + "/clang/bin/" + tool;
+  string sysroot = SysrootPath(triple, self_path);
+  if (sysroot.empty()) {
+    Die("Can't find sysroot from wrapper path");
+  }
+  vector<string> newargs;
+  newargs.push_back(newcmd);
+  if (tool != "llvm-ar") {
+    newargs.push_back("-target");
+    newargs.push_back(triple);
+    newargs.push_back("--sysroot=" + sysroot);
+  }
+  for (auto it = args.begin() + 1; it != args.end(); ++it) {
+    newargs.push_back(*it);
+  }
+  int status = DoExecv(newcmd, newargs);
+  if (status != 0) {
+    Die("error invoking " + newcmd + ": " + strerror(errno));
+  }
+  return 0;
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/fuchsia-zircon/tools/gen_status.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+# Copyright 2016 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# A tool for autogenerating the mapping between Status and zx_status_t
+# Usage: python gen_status.py zircon/system/public/zircon/errors.h {sys,enum,match}
+import re
+import sys
+
+status_re = re.compile('#define\s+(ZX_\w+)\s+\((\-?\d+)\)$')
+
+def parse(in_filename):
+    result = []
+    for line in file(in_filename):
+        m = status_re.match(line)
+        if m:
+            result.append((m.group(1), int(m.group(2))))
+    return result
+
+def to_snake_case(name):
+    result = []
+    for element in name.split('_'):
+        result.append(element[0] + element[1:].lower())
+    return ''.join(result)
+
+def out(style, l):
+    print('// Auto-generated using tools/gen_status.py')
+    longest = max(len(name) for (name, num) in l)
+    if style == 'sys':
+        for (name, num) in l:
+            print('pub const %s : zx_status_t = %d;' % (name.ljust(longest), num))
+    if style == 'enum':
+        print('pub enum Status {')
+        for (name, num) in l:
+            print('    %s = %d,' % (to_snake_case(name[3:]), num))
+        print('');
+        print('    /// Any zx_status_t not in the set above will map to the following:')
+        print('    UnknownOther = -32768,')
+        print('}')
+    if style == 'match':
+        for (name, num) in l:
+            print('            sys::%s => Status::%s,' % (name, to_snake_case(name[3:])))
+        print('            _ => Status::UnknownOther,')
+
+
+l = parse(sys.argv[1])
+out(sys.argv[2], l)
--- a/third_party/rust/rand/.cargo-checksum.json
+++ b/third_party/rust/rand/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".travis.yml":"977ae778ea9d60b5abec3674cec33720b9db33c1e3da255ccaa58ad6a70b4c7f","Cargo.toml":"f000bcadb1b0f90fea9defd4d650a5d7bb3f15fb2705be5e96788fa59eedf6cc","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"969ef4c906eb704377d99bb69125f3aa3c523daa5b410d426ac5dcdd107b008d","appveyor.yml":"3a74394c3e3ef3b2c7d9458f526e47587977e98d026b63f00be29479075ff597","benches/bench.rs":"e6adfb15146d3176164a345a6d978071cb71aa3f9761000702e798cb53fde2b5","benches/distributions/exponential.rs":"99cb59c013a0b6bb390d34c5649b341fc3b88ea7df0caf2470bdda8798f9fe3d","benches/distributions/gamma.rs":"3533f311e4b55d743c5b01a7eb6529c94fd97726ef6702a6372f914f5f33666b","benches/distributions/mod.rs":"0028f1cb96f61152ed5b49a4fe91227d809ef6d19035592c36032a538af7f95e","benches/distributions/normal.rs":"4e10c18cb583ccb96301ea953c8e0aa9ee3b6662060271d1b8d19ca23364dc6b","src/chacha.rs":"ed43d7966192f265a22fe6913b799e081703b42c1ba7b1214128f42b70aaab3a","src/distributions/exponential.rs":"a63bfb1ec564408697ab587da3bd85417983405b2af4fd14a185e6f21cfe2723","src/distributions/gamma.rs":"26edf7055f31c12d31fc89d2da9357723693c1358cd343089df2cf6f58355d5c","src/distributions/mod.rs":"696f4f2edd0d1a26916fbe6ab330971d810d60bbcb2c06cf6f179a5c27038bbd","src/distributions/normal.rs":"414806b102d77707c9a4e03df65e059f487c463a85db80c33ef8f5ef7c40ca8c","src/distributions/range.rs":"9fac31b9d8dfc258be725a83c60f97e71efbbca725830e053d8f53c508b3e288","src/distributions/ziggurat_tables.rs":"4eacf94fc352c91c455a6623de6a721e53842e1690f13a5662b6a79c7fbb73de","src/isaac.rs":"8426fa913a163c13c1c81d166204c9748f79d3e47d83fd14319c3499eac4fcb3","src/lib.rs":"d4ad3ceb63b735ab41e0cc5f500363196918a553a53af493de3173246a49dc98","src/os.rs":"355f0cee9643442d521851460af6bb593d690f29f1cb9144dc6e7b484edb3fd9","src/rand_impls.rs":"6bafe095c291c1718cc880a830beca46eb26a257a4fe44e4087245bbdca0656b","src/read.rs":"bdad8df5687fd90180bc602967d66248d3f051a11b4459aedcd3f21dbfa93f9b","src/reseeding.rs":"9f0d154e4d0fcc3024622adc386ead8ce222dac56761e9a6d92c4fb3c6e0d47b"},"package":"022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".travis.yml":"c5edd03cb5679918a6d85f64c0a634ed83022ff85ea78f440f39fd281bd29c02","Cargo.toml":"e7efa66cdfb551389cc7485818a776cb289f248079df2247eece7f57b30c3abe","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"51831128477b9c9db0ec632ed6b6164f4e70e2d5f21eb5b3a391ecb9ab35e727","appveyor.yml":"6bf2f0c8f17d2dc4957dd39aba9a88ced3130200cf847a76d47b6c8fdcc2cbd8","benches/bench.rs":"2d3481c524841c532b9b9705073b223fd4b308c86ed7c9188b7fcd8e595ad459","benches/distributions/exponential.rs":"99cb59c013a0b6bb390d34c5649b341fc3b88ea7df0caf2470bdda8798f9fe3d","benches/distributions/gamma.rs":"3533f311e4b55d743c5b01a7eb6529c94fd97726ef6702a6372f914f5f33666b","benches/distributions/mod.rs":"0028f1cb96f61152ed5b49a4fe91227d809ef6d19035592c36032a538af7f95e","benches/distributions/normal.rs":"4e10c18cb583ccb96301ea953c8e0aa9ee3b6662060271d1b8d19ca23364dc6b","src/chacha.rs":"529c20ca1eff845da4cdca9ac995bcb8e698e48a61fbae91f09e3b4600ac57c3","src/distributions/exponential.rs":"103c8412c8a581b71835f1c00e40f6370e7702adf9d499243933a793d132d4e7","src/distributions/gamma.rs":"8403bce8e78a42eda20578329d4f5e7ccbb86139a39d6efbd2d37b698d36e946","src/distributions/mod.rs":"2c042ad7d0d53f9c54c02d11e1e623bca8906785cf4264ad708fa05420724f52","src/distributions/normal.rs":"1562b43f80e4d5f83a8deb5af18de5a18dfeeeeda11fefc577da26672b14c949","src/distributions/range.rs":"c0ac6858d6a3979de7996feca22d190fde0bfb6f758d43030efa04a1a0fdcc17","src/distributions/ziggurat_tables.rs":"4eacf94fc352c91c455a6623de6a721e53842e1690f13a5662b6a79c7fbb73de","src/isaac.rs":"1725114b2d63c6fe4c0f4f7e0c36fc993a47f0322350d13abc631b0806bb71ed","src/lib.rs":"e3470f49b8ba85b590bd4375ff0d90874916cf0296637a6639a22c2a4301c3bf","src/os.rs":"ea6c5eb1a2ac8f41269d45b55655704a0ec1b8dd49d3a0a6644263c0acbad0fe","src/rand_impls.rs":"cf411028341f67fd196ccde6200eea563c993f59d360a030b3d7d3ee15447a7d","src/read.rs":"bd0eb508a6b659dc578d546fc2f231484aed80c73cfe8c475e0d65c8d699a769","src/reseeding.rs":"73b2539b86b4cb8068e54716c7fd53e0d70b6c0de787a0749431b17019c9d826"},"package":"61efcbcd9fa8d8fbb07c84e34a8af18a1ff177b449689ad38a6e9457ecc7b2ae"}
\ No newline at end of file
--- a/third_party/rust/rand/.travis.yml
+++ b/third_party/rust/rand/.travis.yml
@@ -1,24 +1,30 @@
 language: rust
-rust:
-  - 1.0.0
-  - stable
-  - beta
-  - nightly
 sudo: false
 before_script:
   - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH
+
+matrix:
+  include:
+    - rust: 1.15.0
+    - rust: stable
+    - rust: stable
+      os: osx
+    - rust: beta
+    - rust: nightly
+      script:
+        - cargo test
+        - cargo test --features nightly
+        - cargo test --manifest-path rand-derive/Cargo.toml
+        - cargo doc --no-deps --features nightly
 script:
-  - cargo build --verbose
-  - cargo test --verbose
-  - cargo doc --no-deps
+  - cargo test
+  - cargo test --manifest-path rand-derive/Cargo.toml
 after_success:
   - travis-cargo --only nightly doc-upload
 env:
   global:
     secure: "BdDntVHSompN+Qxz5Rz45VI4ZqhD72r6aPl166FADlnkIwS6N6FLWdqs51O7G5CpoMXEDvyYrjmRMZe/GYLIG9cmqmn/wUrWPO+PauGiIuG/D2dmfuUNvSTRcIe7UQLXrfP3yyfZPgqsH6pSnNEVopquQKy3KjzqepgriOJtbyY="
 
-
-
 notifications:
   email:
     on_success: never
--- a/third_party/rust/rand/Cargo.toml
+++ b/third_party/rust/rand/Cargo.toml
@@ -1,20 +1,34 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
 [package]
-
 name = "rand"
-version = "0.3.15"
+version = "0.3.17"
 authors = ["The Rust Project Developers"]
-license = "MIT/Apache-2.0"
+description = "Random number generators and other randomness functionality.\n"
+homepage = "https://github.com/rust-lang-nursery/rand"
+documentation = "https://docs.rs/rand"
 readme = "README.md"
-repository = "https://github.com/rust-lang/rand"
-documentation = "https://doc.rust-lang.org/rand"
-homepage = "https://github.com/rust-lang/rand"
-description = """
-Random number generators and other randomness functionality.
-"""
 keywords = ["random", "rng"]
+categories = ["algorithms"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/rust-lang-nursery/rand"
+[dependencies.libc]
+version = "0.2"
+[dev-dependencies.log]
+version = "0.3.0"
 
-[dependencies]
-libc = "0.2"
-
-[dev-dependencies]
-log = "0.3.0"
+[features]
+nightly = ["i128_support"]
+i128_support = []
+[target."cfg(target_os = \"fuchsia\")".dependencies.fuchsia-zircon]
+version = "^0.2.1"
--- a/third_party/rust/rand/README.md
+++ b/third_party/rust/rand/README.md
@@ -1,17 +1,17 @@
 rand
 ====
 
 A Rust library for random number generators and other randomness functionality.
 
 [![Build Status](https://travis-ci.org/rust-lang-nursery/rand.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/rand)
 [![Build status](https://ci.appveyor.com/api/projects/status/rm5c9o33k3jhchbw?svg=true)](https://ci.appveyor.com/project/alexcrichton/rand)
 
-[Documentation](https://doc.rust-lang.org/rand)
+[Documentation](https://docs.rs/rand)
 
 ## Usage
 
 Add this to your `Cargo.toml`:
 
 ```toml
 [dependencies]
 rand = "0.3"
@@ -45,8 +45,43 @@ It is also possible to use other RNG typ
 
 ```rust
 use rand::{Rng, ChaChaRng};
 
 let mut rng = rand::ChaChaRng::new_unseeded();
 println!("i32: {}, u32: {}", rng.gen::<i32>(), rng.gen::<u32>())
 ```
 
+# `derive(Rand)`
+
+You can derive the `Rand` trait for your custom type via the `#[derive(Rand)]`
+directive. To use this first add this to your Cargo.toml:
+
+```toml
+rand = "0.3"
+rand_derive = "0.3"
+```
+
+Next in your crate:
+
+```rust
+extern crate rand;
+#[macro_use]
+extern crate rand_derive;
+
+#[derive(Rand, Debug)]
+struct MyStruct {
+    a: i32,
+    b: u32,
+}
+
+fn main() {
+    println!("{:?}", rand::random::<MyStruct>());
+}
+```
+
+
+# License
+
+`rand` is primarily distributed under the terms of both the MIT
+license and the Apache License (Version 2.0).
+
+See LICENSE-APACHE, and LICENSE-MIT for details.
--- a/third_party/rust/rand/appveyor.yml
+++ b/third_party/rust/rand/appveyor.yml
@@ -1,17 +1,37 @@
 environment:
+
+  # At the time this was added AppVeyor was having troubles with checking
+  # revocation of SSL certificates of sites like static.rust-lang.org and what
+  # we think is crates.io. The libcurl HTTP client by default checks for
+  # revocation on Windows and according to a mailing list [1] this can be
+  # disabled.
+  #
+  # The `CARGO_HTTP_CHECK_REVOKE` env var here tells cargo to disable SSL
+  # revocation checking on Windows in libcurl. Note, though, that rustup, which
+  # we're using to download Rust here, also uses libcurl as the default backend.
+  # Unlike Cargo, however, rustup doesn't have a mechanism to disable revocation
+  # checking. To get rustup working we set `RUSTUP_USE_HYPER` which forces it to
+  # use the Hyper instead of libcurl backend. Both Hyper and libcurl use
+  # schannel on Windows but it appears that Hyper configures it slightly
+  # differently such that revocation checking isn't turned on by default.
+  #
+  # [1]: https://curl.haxx.se/mail/lib-2016-03/0202.html
+  RUSTUP_USE_HYPER: 1
+  CARGO_HTTP_CHECK_REVOKE: false
+
   matrix:
   - TARGET: x86_64-pc-windows-msvc
   - TARGET: i686-pc-windows-msvc
-  - TARGET: i686-pc-windows-gnu
 install:
-  - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe"
-  - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
-  - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin
-  - SET PATH=%PATH%;C:\MinGW\bin
+  - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
+  - rustup-init.exe -y --default-host %TARGET% --default-toolchain nightly
+  - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin
   - rustc -V
   - cargo -V
 
 build: false
 
 test_script:
-  - cargo test --verbose --target %TARGET%
+  - cargo test
+  - cargo test --features nightly
+  - cargo test --manifest-path rand-derive/Cargo.toml
--- a/third_party/rust/rand/benches/bench.rs
+++ b/third_party/rust/rand/benches/bench.rs
@@ -5,17 +5,17 @@ extern crate rand;
 
 const RAND_BENCH_N: u64 = 1000;
 
 mod distributions;
 
 use std::mem::size_of;
 use test::{black_box, Bencher};
 use rand::{XorShiftRng, StdRng, IsaacRng, Isaac64Rng, Rng};
-use rand::{OsRng, weak_rng};
+use rand::{OsRng, sample, weak_rng};
 
 #[bench]
 fn rand_xorshift(b: &mut Bencher) {
     let mut rng: XorShiftRng = OsRng::new().unwrap().gen();
     b.iter(|| {
         for _ in 0..RAND_BENCH_N {
             black_box(rng.gen::<usize>());
         }
@@ -81,8 +81,17 @@ fn rand_f64(b: &mut Bencher) {
 #[bench]
 fn rand_shuffle_100(b: &mut Bencher) {
     let mut rng = weak_rng();
     let x : &mut [usize] = &mut [1; 100];
     b.iter(|| {
         rng.shuffle(x);
     })
 }
+
+#[bench]
+fn rand_sample_10_of_100(b: &mut Bencher) {
+    let mut rng = weak_rng();
+    let x : &[usize] = &[1; 100];
+    b.iter(|| {
+        sample(&mut rng, x, 10);
+    })
+}
--- a/third_party/rust/rand/src/chacha.rs
+++ b/third_party/rust/rand/src/chacha.rs
@@ -21,17 +21,17 @@ const CHACHA_ROUNDS: u32 = 20; // Crypto
 ///
 /// The ChaCha algorithm is widely accepted as suitable for
 /// cryptographic purposes, but this implementation has not been
 /// verified as such. Prefer a generator like `OsRng` that defers to
 /// the operating system for cases that need high security.
 ///
 /// [1]: D. J. Bernstein, [*ChaCha, a variant of
 /// Salsa20*](http://cr.yp.to/chacha.html)
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
 pub struct ChaChaRng {
     buffer:  [w32; STATE_WORDS], // Internal buffer of output
     state:   [w32; STATE_WORDS], // Initial state
     index:   usize,                 // Index into state
 }
 
 static EMPTY: ChaChaRng = ChaChaRng {
     buffer:  [w(0); STATE_WORDS],
--- a/third_party/rust/rand/src/distributions/exponential.rs
+++ b/third_party/rust/rand/src/distributions/exponential.rs
@@ -29,17 +29,17 @@ use distributions::{ziggurat, ziggurat_t
 /// # Example
 ///
 /// ```rust
 /// use rand::distributions::exponential::Exp1;
 ///
 /// let Exp1(x) = rand::random();
 /// println!("{}", x);
 /// ```
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 pub struct Exp1(pub f64);
 
 // This could be done via `-rng.gen::<f64>().ln()` but that is slower.
 impl Rand for Exp1 {
     #[inline]
     fn rand<R:Rng>(rng: &mut R) -> Exp1 {
         #[inline]
         fn pdf(x: f64) -> f64 {
@@ -66,17 +66,17 @@ impl Rand for Exp1 {
 ///
 /// ```rust
 /// use rand::distributions::{Exp, IndependentSample};
 ///
 /// let exp = Exp::new(2.0);
 /// let v = exp.ind_sample(&mut rand::thread_rng());
 /// println!("{} is from a Exp(2) distribution", v);
 /// ```
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 pub struct Exp {
     /// `lambda` stored as `1/lambda`, since this is what we scale by.
     lambda_inverse: f64
 }
 
 impl Exp {
     /// Construct a new `Exp` with the given shape parameter
     /// `lambda`. Panics if `lambda <= 0`.
--- a/third_party/rust/rand/src/distributions/gamma.rs
+++ b/third_party/rust/rand/src/distributions/gamma.rs
@@ -44,22 +44,22 @@ use super::{IndependentSample, Sample, E
 /// let v = gamma.ind_sample(&mut rand::thread_rng());
 /// println!("{} is from a Gamma(2, 5) distribution", v);
 /// ```
 ///
 /// [1]: George Marsaglia and Wai Wan Tsang. 2000. "A Simple Method
 /// for Generating Gamma Variables" *ACM Trans. Math. Softw.* 26, 3
 /// (September 2000),
 /// 363-372. DOI:[10.1145/358407.358414](http://doi.acm.org/10.1145/358407.358414)
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 pub struct Gamma {
     repr: GammaRepr,
 }
 
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 enum GammaRepr {
     Large(GammaLargeShape),
     One(Exp),
     Small(GammaSmallShape)
 }
 
 // These two helpers could be made public, but saving the
 // match-on-Gamma-enum branch from using them directly (e.g. if one
@@ -70,47 +70,49 @@ enum GammaRepr {
 ///
 /// Note, samples from this require a compulsory floating-point `pow`
 /// call, which makes it significantly slower than sampling from a
 /// gamma distribution where the shape parameter is greater than or
 /// equal to 1.
 ///
 /// See `Gamma` for sampling from a Gamma distribution with general
 /// shape parameters.
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 struct GammaSmallShape {
     inv_shape: f64,
     large_shape: GammaLargeShape
 }
 
 /// Gamma distribution where the shape parameter is larger than 1.
 ///
 /// See `Gamma` for sampling from a Gamma distribution with general
 /// shape parameters.
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 struct GammaLargeShape {
     scale: f64,
     c: f64,
     d: f64
 }
 
 impl Gamma {
     /// Construct an object representing the `Gamma(shape, scale)`
     /// distribution.
     ///
     /// Panics if `shape <= 0` or `scale <= 0`.
     #[inline]
     pub fn new(shape: f64, scale: f64) -> Gamma {
         assert!(shape > 0.0, "Gamma::new called with shape <= 0");
         assert!(scale > 0.0, "Gamma::new called with scale <= 0");
 
-        let repr = match shape {
-            1.0         => One(Exp::new(1.0 / scale)),
-            0.0 ... 1.0 => Small(GammaSmallShape::new_raw(shape, scale)),
-            _           => Large(GammaLargeShape::new_raw(shape, scale))
+        let repr = if shape == 1.0 {
+            One(Exp::new(1.0 / scale))
+        } else if shape < 1.0 {
+            Small(GammaSmallShape::new_raw(shape, scale))
+        } else {
+            Large(GammaLargeShape::new_raw(shape, scale))
         };
         Gamma { repr: repr }
     }
 }
 
 impl GammaSmallShape {
     fn new_raw(shape: f64, scale: f64) -> GammaSmallShape {
         GammaSmallShape {
@@ -190,22 +192,22 @@ impl IndependentSample<f64> for GammaLar
 ///
 /// ```rust
 /// use rand::distributions::{ChiSquared, IndependentSample};
 ///
 /// let chi = ChiSquared::new(11.0);
 /// let v = chi.ind_sample(&mut rand::thread_rng());
 /// println!("{} is from a χ²(11) distribution", v)
 /// ```
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 pub struct ChiSquared {
     repr: ChiSquaredRepr,
 }
 
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 enum ChiSquaredRepr {
     // k == 1, Gamma(alpha, ..) is particularly slow for alpha < 1,
     // e.g. when alpha = 1/2 as it would be for this case, so special-
     // casing and using the definition of N(0,1)^2 is faster.
     DoFExactlyOne,
     DoFAnythingElse(Gamma),
 }
 
@@ -248,17 +250,17 @@ impl IndependentSample<f64> for ChiSquar
 ///
 /// ```rust
 /// use rand::distributions::{FisherF, IndependentSample};
 ///
 /// let f = FisherF::new(2.0, 32.0);
 /// let v = f.ind_sample(&mut rand::thread_rng());
 /// println!("{} is from an F(2, 32) distribution", v)
 /// ```
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 pub struct FisherF {
     numer: ChiSquared,
     denom: ChiSquared,
     // denom_dof / numer_dof so that this can just be a straight
     // multiplication, rather than a division.
     dof_ratio: f64,
 }
 
@@ -292,17 +294,17 @@ impl IndependentSample<f64> for FisherF 
 ///
 /// ```rust
 /// use rand::distributions::{StudentT, IndependentSample};
 ///
 /// let t = StudentT::new(11.0);
 /// let v = t.ind_sample(&mut rand::thread_rng());
 /// println!("{} is from a t(11) distribution", v)
 /// ```
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 pub struct StudentT {
     chi: ChiSquared,
     dof: f64
 }
 
 impl StudentT {
     /// Create a new Student t distribution with `n` degrees of
     /// freedom. Panics if `n <= 0`.
--- a/third_party/rust/rand/src/distributions/mod.rs
+++ b/third_party/rust/rand/src/distributions/mod.rs
@@ -48,16 +48,17 @@ pub trait Sample<Support> {
 // trait called `Sample` and the other should be `DependentSample`.
 pub trait IndependentSample<Support>: Sample<Support> {
     /// Generate a random value.
     fn ind_sample<R: Rng>(&self, &mut R) -> Support;
 }
 
 /// A wrapper for generating types that implement `Rand` via the
 /// `Sample` & `IndependentSample` traits.
+#[derive(Debug)]
 pub struct RandSample<Sup> {
     _marker: marker::PhantomData<fn() -> Sup>,
 }
 
 impl<Sup> Copy for RandSample<Sup> {}
 impl<Sup> Clone for RandSample<Sup> {
     fn clone(&self) -> Self { *self }
 }
@@ -74,18 +75,17 @@ impl<Sup: Rand> IndependentSample<Sup> f
 
 impl<Sup> RandSample<Sup> {
     pub fn new() -> RandSample<Sup> {
         RandSample { _marker: marker::PhantomData }
     }
 }
 
 /// A value with a particular weight for use with `WeightedChoice`.
-#[derive(Copy)]
-#[derive(Clone)]
+#[derive(Copy, Clone, Debug)]
 pub struct Weighted<T> {
     /// The numerical weight of this item
     pub weight: u32,
     /// The actual item which is being weighted
     pub item: T,
 }
 
 /// A distribution that selects from a finite collection of weighted items.
@@ -108,16 +108,17 @@ pub struct Weighted<T> {
 ///                      Weighted { weight: 1, item: 'c' });
 /// let wc = WeightedChoice::new(&mut items);
 /// let mut rng = rand::thread_rng();
 /// for _ in 0..16 {
 ///      // on average prints 'a' 4 times, 'b' 8 and 'c' twice.
 ///      println!("{}", wc.ind_sample(&mut rng));
 /// }
 /// ```
+#[derive(Debug)]
 pub struct WeightedChoice<'a, T:'a> {
     items: &'a mut [Weighted<T>],
     weight_range: Range<u32>
 }
 
 impl<'a, T: Clone> WeightedChoice<'a, T> {
     /// Create a new `WeightedChoice`.
     ///
--- a/third_party/rust/rand/src/distributions/normal.rs
+++ b/third_party/rust/rand/src/distributions/normal.rs
@@ -28,17 +28,17 @@ use distributions::{ziggurat, ziggurat_t
 /// # Example
 ///
 /// ```rust
 /// use rand::distributions::normal::StandardNormal;
 ///
 /// let StandardNormal(x) = rand::random();
 /// println!("{}", x);
 /// ```
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 pub struct StandardNormal(pub f64);
 
 impl Rand for StandardNormal {
     fn rand<R:Rng>(rng: &mut R) -> StandardNormal {
         #[inline]
         fn pdf(x: f64) -> f64 {
             (-x*x/2.0).exp()
         }
@@ -83,17 +83,17 @@ impl Rand for StandardNormal {
 /// ```rust
 /// use rand::distributions::{Normal, IndependentSample};
 ///
 /// // mean 2, standard deviation 3
 /// let normal = Normal::new(2.0, 3.0);
 /// let v = normal.ind_sample(&mut rand::thread_rng());
 /// println!("{} is from a N(2, 9) distribution", v)
 /// ```
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 pub struct Normal {
     mean: f64,
     std_dev: f64,
 }
 
 impl Normal {
     /// Construct a new `Normal` distribution with the given mean and
     /// standard deviation.
@@ -131,17 +131,17 @@ impl IndependentSample<f64> for Normal {
 /// ```rust
 /// use rand::distributions::{LogNormal, IndependentSample};
 ///
 /// // mean 2, standard deviation 3
 /// let log_normal = LogNormal::new(2.0, 3.0);
 /// let v = log_normal.ind_sample(&mut rand::thread_rng());
 /// println!("{} is from an ln N(2, 9) distribution", v)
 /// ```
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 pub struct LogNormal {
     norm: Normal
 }
 
 impl LogNormal {
     /// Construct a new `LogNormal` distribution with the given mean
     /// and standard deviation.
     ///
--- a/third_party/rust/rand/src/distributions/range.rs
+++ b/third_party/rust/rand/src/distributions/range.rs
@@ -41,17 +41,17 @@ use distributions::{Sample, IndependentS
 ///     let mut rng = rand::thread_rng();
 ///     let mut sum = 0;
 ///     for _ in 0..1000 {
 ///         sum += between.ind_sample(&mut rng);
 ///     }
 ///     println!("{}", sum);
 /// }
 /// ```
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 pub struct Range<X> {
     low: X,
     range: X,
     accept_zone: X
 }
 
 impl<X: SampleRange + PartialOrd> Range<X> {
     /// Create a new `Range` instance that samples uniformly from
@@ -91,32 +91,34 @@ macro_rules! integer_impl {
     ($ty:ty, $unsigned:ident) => {
         impl SampleRange for $ty {
             // we play free and fast with unsigned vs signed here
             // (when $ty is signed), but that's fine, since the
             // contract of this macro is for $ty and $unsigned to be
             // "bit-equal", so casting between them is a no-op & a
             // bijection.
 
+            #[inline]
             fn construct_range(low: $ty, high: $ty) -> Range<$ty> {
                 let range = (w(high as $unsigned) - w(low as $unsigned)).0;
                 let unsigned_max: $unsigned = ::std::$unsigned::MAX;
 
                 // this is the largest number that fits into $unsigned
                 // that `range` divides evenly, so, if we've sampled
                 // `n` uniformly from this region, then `n % range` is
                 // uniform in [0, range)
                 let zone = unsigned_max - unsigned_max % range;
 
                 Range {
                     low: low,
                     range: range as $ty,
                     accept_zone: zone as $ty
                 }
             }
+
             #[inline]
             fn sample_range<R: Rng>(r: &Range<$ty>, rng: &mut R) -> $ty {
                 loop {
                     // rejection sample
                     let v = rng.gen::<$unsigned>();
                     // until we find something that fits into the
                     // region which r.range evenly divides (this will
                     // be uniformly distributed)
--- a/third_party/rust/rand/src/isaac.rs
+++ b/third_party/rust/rand/src/isaac.rs
@@ -10,16 +10,17 @@
 
 //! The ISAAC random number generator.
 
 #![allow(non_camel_case_types)]
 
 use std::slice;
 use std::iter::repeat;
 use std::num::Wrapping as w;
+use std::fmt;
 
 use {Rng, SeedableRng, Rand, w32, w64};
 
 const RAND_SIZE_LEN: usize = 8;
 const RAND_SIZE: u32 = 1 << RAND_SIZE_LEN;
 const RAND_SIZE_USIZE: usize = 1 << RAND_SIZE_LEN;
 
 /// A random number generator that uses the ISAAC algorithm[1].
@@ -255,16 +256,22 @@ impl Rand for IsaacRng {
         ret.b = w(0);
         ret.c = w(0);
 
         ret.init(true);
         return ret;
     }
 }
 
+impl fmt::Debug for IsaacRng {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "IsaacRng {{}}")
+    }
+}
+
 const RAND_SIZE_64_LEN: usize = 8;
 const RAND_SIZE_64: usize = 1 << RAND_SIZE_64_LEN;
 
 /// A random number generator that uses ISAAC-64[1], the 64-bit
 /// variant of the ISAAC algorithm.
 ///
 /// The ISAAC algorithm is generally accepted as suitable for
 /// cryptographic purposes, but this implementation has not be
@@ -498,16 +505,21 @@ impl Rand for Isaac64Rng {
         ret.b = w(0);
         ret.c = w(0);
 
         ret.init(true);
         return ret;
     }
 }
 
+impl fmt::Debug for Isaac64Rng {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "Isaac64Rng {{}}")
+    }
+}
 
 #[cfg(test)]
 mod test {
     use {Rng, SeedableRng};
     use super::{IsaacRng, Isaac64Rng};
 
     #[test]
     fn test_rng_32_rand_seeded() {
--- a/third_party/rust/rand/src/lib.rs
+++ b/third_party/rust/rand/src/lib.rs
@@ -234,20 +234,25 @@
 //!              switch_wins as f32 / total_switches as f32);
 //!     println!("Estimated chance to win if we don't: {}",
 //!              keep_wins as f32 / total_keeps as f32);
 //! }
 //! ```
 
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
        html_favicon_url = "https://www.rust-lang.org/favicon.ico",
-       html_root_url = "https://doc.rust-lang.org/rand/")]
+       html_root_url = "https://docs.rs/rand/0.3")]
+
+#![deny(missing_debug_implementations)]
+
+#![cfg_attr(feature = "i128_support", feature(i128_type))]
 
 #[cfg(test)] #[macro_use] extern crate log;
 
+
 use std::cell::RefCell;
 use std::marker;
 use std::mem;
 use std::io;
 use std::rc::Rc;
 use std::num::Wrapping as w;
 
 pub use os::OsRng;
@@ -272,29 +277,61 @@ pub mod os;
 pub mod read;
 
 #[allow(bad_style)]
 type w64 = w<u64>;
 #[allow(bad_style)]
 type w32 = w<u32>;
 
 /// A type that can be randomly generated using an `Rng`.
+///
+/// ## Built-in Implementations
+///
+/// This crate implements `Rand` for various primitive types.  Assuming the
+/// provided `Rng` is well-behaved, these implementations generate values with
+/// the following ranges and distributions:
+///
+/// * Integers (`i32`, `u32`, `isize`, `usize`, etc.): Uniformly distributed
+///   over all values of the type.
+/// * `char`: Uniformly distributed over all Unicode scalar values, i.e. all
+///   code points in the range `0...0x10_FFFF`, except for the range
+///   `0xD800...0xDFFF` (the surrogate code points).  This includes
+///   unassigned/reserved code points.
+/// * `bool`: Generates `false` or `true`, each with probability 0.5.
+/// * Floating point types (`f32` and `f64`): Uniformly distributed in the
+///   half-open range `[0, 1)`.  (The [`Open01`], [`Closed01`], [`Exp1`], and
+///   [`StandardNormal`] wrapper types produce floating point numbers with
+///   alternative ranges or distributions.)
+///
+/// [`Open01`]: struct.Open01.html
+/// [`Closed01`]: struct.Closed01.html
+/// [`Exp1`]: struct.Exp1.html
+/// [`StandardNormal`]: struct.StandardNormal.html
+///
+/// The following aggregate types also implement `Rand` as long as their
+/// component types implement it:
+///
+/// * Tuples and arrays: Each element of the tuple or array is generated
+///   independently, using its own `Rand` implementation.
+/// * `Option<T>`: Returns `None` with probability 0.5; otherwise generates a
+///   random `T` and returns `Some(T)`.
+
 pub trait Rand : Sized {
     /// Generates a random instance of this type using the specified source of
     /// randomness.
     fn rand<R: Rng>(rng: &mut R) -> Self;
 }
 
 /// A random number generator.
 pub trait Rng {
     /// Return the next random u32.
     ///
     /// This rarely needs to be called directly, prefer `r.gen()` to
     /// `r.next_u32()`.
-    // FIXME #7771: Should be implemented in terms of next_u64
+    // FIXME #rust-lang/rfcs#628: Should be implemented in terms of next_u64
     fn next_u32(&mut self) -> u32;
 
     /// Return the next random u64.
     ///
     /// By default this is implemented in terms of `next_u32`. An
     /// implementation of this trait must provide at least one of
     /// these two methods. Similarly to `next_u32`, this rarely needs
     /// to be called directly, prefer `r.gen()` to `r.next_u64()`.
@@ -526,16 +563,19 @@ pub trait Rng {
         } else {
             let len = values.len();
             Some(&mut values[self.gen_range(0, len)])
         }
     }
 
     /// Shuffle a mutable slice in place.
     ///
+    /// This applies Durstenfeld's algorithm for the [Fisher–Yates shuffle](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm)
+    /// which produces an unbiased permutation.
+    ///
     /// # Example
     ///
     /// ```rust
     /// use rand::{thread_rng, Rng};
     ///
     /// let mut rng = thread_rng();
     /// let mut y = [1, 2, 3];
     /// rng.shuffle(&mut y);
@@ -599,16 +639,17 @@ impl<R: ?Sized> Rng for Box<R> where R: 
 }
 
 /// Iterator which will generate a stream of random items.
 ///
 /// This iterator is created via the [`gen_iter`] method on [`Rng`].
 ///
 /// [`gen_iter`]: trait.Rng.html#method.gen_iter
 /// [`Rng`]: trait.Rng.html
+#[derive(Debug)]
 pub struct Generator<'a, T, R:'a> {
     rng: &'a mut R,
     _marker: marker::PhantomData<fn() -> T>,
 }
 
 impl<'a, T: Rand, R: Rng> Iterator for Generator<'a, T, R> {
     type Item = T;
 
@@ -618,16 +659,17 @@ impl<'a, T: Rand, R: Rng> Iterator for G
 }
 
 /// Iterator which will continuously generate random ascii characters.
 ///
 /// This iterator is created via the [`gen_ascii_chars`] method on [`Rng`].
 ///
 /// [`gen_ascii_chars`]: trait.Rng.html#method.gen_ascii_chars
 /// [`Rng`]: trait.Rng.html
+#[derive(Debug)]
 pub struct AsciiGenerator<'a, R:'a> {
     rng: &'a mut R,
 }
 
 impl<'a, R: Rng> Iterator for AsciiGenerator<'a, R> {
     type Item = char;
 
     fn next(&mut self) -> Option<char> {
@@ -677,17 +719,17 @@ pub trait SeedableRng<Seed>: Rng {
 /// The Xorshift algorithm is not suitable for cryptographic purposes
 /// but is very fast. If you do not know for sure that it fits your
 /// requirements, use a more secure one such as `IsaacRng` or `OsRng`.
 ///
 /// [1]: Marsaglia, George (July 2003). ["Xorshift
 /// RNGs"](http://www.jstatsoft.org/v08/i14/paper). *Journal of
 /// Statistical Software*. Vol. 8 (Issue 14).
 #[allow(missing_copy_implementations)]
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub struct XorShiftRng {
     x: w32,
     y: w32,
     z: w32,
     w: w32,
 }
 
 impl XorShiftRng {
@@ -767,16 +809,17 @@ impl Rand for XorShiftRng {
 ///
 /// # Example
 /// ```rust
 /// use rand::{random, Open01};
 ///
 /// let Open01(val) = random::<Open01<f32>>();
 /// println!("f32 from (0,1): {}", val);
 /// ```
+#[derive(Debug)]
 pub struct Open01<F>(pub F);
 
 /// A wrapper for generating floating point numbers uniformly in the
 /// closed interval `[0,1]` (including both endpoints).
 ///
 /// Use `Open01` for the closed interval `(0,1)`, and the default
 /// `Rand` implementation of `f32` and `f64` for the half-open
 /// `[0,1)`.
@@ -784,21 +827,22 @@ pub struct Open01<F>(pub F);
 /// # Example
 ///
 /// ```rust
 /// use rand::{random, Closed01};
 ///
 /// let Closed01(val) = random::<Closed01<f32>>();
 /// println!("f32 from [0,1]: {}", val);
 /// ```
+#[derive(Debug)]
 pub struct Closed01<F>(pub F);
 
 /// The standard RNG. This is designed to be efficient on the current
 /// platform.
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
 pub struct StdRng {
     rng: IsaacWordRng,
 }
 
 impl StdRng {
     /// Create a randomly seeded instance of `StdRng`.
     ///
     /// This is a very expensive operation as it has to read
@@ -851,31 +895,32 @@ impl<'a> SeedableRng<&'a [usize]> for St
 pub fn weak_rng() -> XorShiftRng {
     match OsRng::new() {
         Ok(mut r) => r.gen(),
         Err(e) => panic!("weak_rng: failed to create seeded RNG: {:?}", e)
     }
 }
 
 /// Controls how the thread-local RNG is reseeded.
+#[derive(Debug)]
 struct ThreadRngReseeder;
 
 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)
         }
     }
 }
 const THREAD_RNG_RESEED_THRESHOLD: u64 = 32_768;
 type ThreadRngInner = reseeding::ReseedingRng<StdRng, ThreadRngReseeder>;
 
 /// The thread-local RNG.
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub struct ThreadRng {
     rng: Rc<RefCell<ThreadRngInner>>,
 }
 
 /// Retrieve the lazily-initialized thread-local random number
 /// generator, seeded by the system. Intended to be used in method
 /// chaining style, e.g. `thread_rng().gen::<i32>()`.
 ///
@@ -959,17 +1004,18 @@ impl Rng for ThreadRng {
 ///     *x = rng.gen();
 /// }
 /// ```
 #[inline]
 pub fn random<T: Rand>() -> T {
     thread_rng().gen()
 }
 
-/// Randomly sample up to `amount` elements from an iterator.
+/// Randomly sample up to `amount` elements from a finite iterator.
+/// The order of elements in the sample is not random.
 ///
 /// # Example
 ///
 /// ```rust
 /// use rand::{thread_rng, sample};
 ///
 /// let mut rng = thread_rng();
 /// let sample = sample(&mut rng, 1..100, 5);
--- a/third_party/rust/rand/src/os.rs
+++ b/third_party/rust/rand/src/os.rs
@@ -6,62 +6,74 @@
 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
 //! Interfaces to the operating system provided random number
 //! generators.
 
-use std::{io, mem};
+use std::{io, mem, fmt};
 use Rng;
 
 /// A random number generator that retrieves randomness straight from
 /// the operating system. Platform sources:
 ///
 /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
 ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
 /// - OpenBSD: calls `getentropy(2)`
 /// - FreeBSD: uses the `kern.arandom` `sysctl(2)` mib
-/// - Windows: calls `CryptGenRandom`, using the default cryptographic
-///   service provider with the `PROV_RSA_FULL` type.
+/// - Windows: calls `RtlGenRandom`, exported from `advapi32.dll` as
+///   `SystemFunction036`.
 /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
 /// - PNaCl: calls into the `nacl-irt-random-0.1` IRT interface.
 ///
-/// This does not block.
+/// This usually does not block. On some systems (e.g. FreeBSD, OpenBSD,
+/// Max OS X, and modern Linux) this may block very early in the init
+/// process, if the CSPRNG has not been seeded yet.[1]
+///
+/// [1] See https://www.python.org/dev/peps/pep-0524/ for a more in-depth
+///     discussion.
 pub struct OsRng(imp::OsRng);
 
 impl OsRng {
     /// Create a new `OsRng`.
     pub fn new() -> io::Result<OsRng> {
         imp::OsRng::new().map(OsRng)
     }
 }
 
 impl Rng for OsRng {
     fn next_u32(&mut self) -> u32 { self.0.next_u32() }
     fn next_u64(&mut self) -> u64 { self.0.next_u64() }
     fn fill_bytes(&mut self, v: &mut [u8]) { self.0.fill_bytes(v) }
 }
 
+impl fmt::Debug for OsRng {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "OsRng {{}}")
+    }
+}
+
 fn next_u32(mut fill_buf: &mut FnMut(&mut [u8])) -> u32 {
     let mut buf: [u8; 4] = [0; 4];
     fill_buf(&mut buf);
     unsafe { mem::transmute::<[u8; 4], u32>(buf) }
 }
 
 fn next_u64(mut fill_buf: &mut FnMut(&mut [u8])) -> u64 {
     let mut buf: [u8; 8] = [0; 8];
     fill_buf(&mut buf);
     unsafe { mem::transmute::<[u8; 8], u64>(buf) }
 }
 
 #[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 {
     extern crate libc;
 
     use super::{next_u32, next_u64};
     use self::OsRngInner::*;
 
@@ -208,16 +220,17 @@ mod imp {
     extern crate libc;
 
     use super::{next_u32, next_u64};
 
     use std::io;
     use Rng;
     use self::libc::{c_int, size_t};
 
+    #[derive(Debug)]
     pub struct OsRng;
 
     enum SecRandom {}
 
     #[allow(non_upper_case_globals)]
     const kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;
 
     #[link(name = "Security", kind = "framework")]
@@ -254,16 +267,17 @@ mod imp {
 mod imp {
     extern crate libc;
 
     use std::{io, ptr};
     use Rng;
 
     use super::{next_u32, next_u64};
 
+    #[derive(Debug)]
     pub struct OsRng;
 
     impl OsRng {
         pub fn new() -> io::Result<OsRng> {
             Ok(OsRng)
         }
     }
 
@@ -297,16 +311,17 @@ mod imp {
 mod imp {
     extern crate libc;
 
     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)
         }
     }
 
@@ -334,16 +349,17 @@ mod imp {
 
 #[cfg(target_os = "redox")]
 mod imp {
     use std::io;
     use std::fs::File;
     use Rng;
     use read::ReadRng;
 
+    #[derive(Debug)]
     pub struct OsRng {
         inner: ReadRng<File>,
     }
 
     impl OsRng {
         pub fn new() -> io::Result<OsRng> {
             let reader = try!(File::open("rand:"));
             let reader_rng = ReadRng::new(reader);
@@ -360,114 +376,114 @@ mod imp {
             self.inner.next_u64()
         }
         fn fill_bytes(&mut self, v: &mut [u8]) {
             self.inner.fill_bytes(v)
         }
     }
 }
 
-#[cfg(windows)]
+#[cfg(target_os = "fuchsia")]
 mod imp {
+    extern crate fuchsia_zircon;
+
     use std::io;
-    use std::ptr;
     use Rng;
 
     use super::{next_u32, next_u64};
 
-    type BOOL = i32;
-    type LPCSTR = *const i8;
-    type DWORD = u32;
-    type HCRYPTPROV = usize;
-    type BYTE = u8;
-
-    const PROV_RSA_FULL: DWORD = 1;
-    const CRYPT_SILENT: DWORD = 0x00000040;
-    const CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;
-
-    #[link(name = "advapi32")]
-    extern "system" {
-        fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
-                                szContainer: LPCSTR,
-                                szProvider: LPCSTR,
-                                dwProvType: DWORD,
-                                dwFlags: DWORD) -> BOOL;
-        fn CryptGenRandom(hProv: HCRYPTPROV,
-                          dwLen: DWORD,
-                          pbBuffer: *mut BYTE) -> BOOL;
-        fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
-    }
-
-    pub struct OsRng {
-        hcryptprov: HCRYPTPROV
-    }
+    #[derive(Debug)]
+    pub struct OsRng;
 
     impl OsRng {
         pub fn new() -> io::Result<OsRng> {
-            let mut hcp = 0;
-            let ret = unsafe {
-                CryptAcquireContextA(&mut hcp, ptr::null(), ptr::null(),
-                                     PROV_RSA_FULL,
-                                     CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
-            };
-
-            if ret == 0 {
-                Err(io::Error::last_os_error())
-            } else {
-                Ok(OsRng { hcryptprov: hcp })
-            }
+            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]) {
-            // CryptGenRandom takes a DWORD (u32) for the length so we need to
+            for s in v.chunks_mut(fuchsia_zircon::ZX_CPRNG_DRAW_MAX_LEN) {
+                let mut filled = 0;
+                while filled < s.len() {
+                    match fuchsia_zircon::cprng_draw(&mut s[filled..]) {
+                        Ok(actual) => filled += actual,
+                        Err(e) => panic!("cprng_draw failed: {:?}", e),
+                    };
+                }
+            }
+        }
+    }
+}
+
+#[cfg(windows)]
+mod imp {
+    use std::io;
+    use Rng;
+
+    use super::{next_u32, next_u64};
+
+    type BOOLEAN = u8;
+    type ULONG = u32;
+
+    #[link(name = "advapi32")]
+    extern "system" {
+        // This function's real name is `RtlGenRandom`.
+        fn SystemFunction036(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN;
+    }
+
+    #[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]) {
+            // RtlGenRandom takes an ULONG (u32) for the length so we need to
             // split up the buffer.
-            for slice in v.chunks_mut(<DWORD>::max_value() as usize) {
+            for slice in v.chunks_mut(<ULONG>::max_value() as usize) {
                 let ret = unsafe {
-                    CryptGenRandom(self.hcryptprov, slice.len() as DWORD,
-                                   slice.as_mut_ptr())
+                    SystemFunction036(slice.as_mut_ptr(), slice.len() as ULONG)
                 };
                 if ret == 0 {
                     panic!("couldn't generate random bytes: {}",
                            io::Error::last_os_error());
                 }
             }
         }
     }
-
-    impl Drop for OsRng {
-        fn drop(&mut self) {
-            let ret = unsafe {
-                CryptReleaseContext(self.hcryptprov, 0)
-            };
-            if ret == 0 {
-                panic!("couldn't release context: {}",
-                       io::Error::last_os_error());
-            }
-        }
-    }
 }
 
 #[cfg(target_os = "nacl")]
 mod imp {
     extern crate libc;
 
     use std::io;
     use std::mem;
     use Rng;
 
     use super::{next_u32, next_u64};
 
+    #[derive(Debug)]
     pub struct OsRng(extern fn(dest: *mut libc::c_void,
                                bytes: libc::size_t,
                                read: *mut libc::size_t) -> libc::c_int);
 
     extern {
         fn nacl_interface_query(name: *const libc::c_char,
                                 table: *mut libc::c_void,
                                 table_size: libc::size_t) -> libc::size_t;
--- a/third_party/rust/rand/src/rand_impls.rs
+++ b/third_party/rust/rand/src/rand_impls.rs
@@ -49,16 +49,24 @@ impl Rand for i32 {
 
 impl Rand for i64 {
     #[inline]
     fn rand<R: Rng>(rng: &mut R) -> i64 {
         rng.next_u64() as i64
     }
 }
 
+#[cfg(feature = "i128_support")]
+impl Rand for i128 {
+    #[inline]
+    fn rand<R: Rng>(rng: &mut R) -> i128 {
+        rng.gen::<u128>() as i128
+    }
+}
+
 impl Rand for usize {
     #[inline]
     fn rand<R: Rng>(rng: &mut R) -> usize {
         if mem::size_of::<usize>() == 4 {
             rng.gen::<u32>() as usize
         } else {
             rng.gen::<u64>() as usize
         }
@@ -88,16 +96,25 @@ impl Rand for u32 {
 
 impl Rand for u64 {
     #[inline]
     fn rand<R: Rng>(rng: &mut R) -> u64 {
         rng.next_u64()
     }
 }
 
+#[cfg(feature = "i128_support")]
+impl Rand for u128 {
+    #[inline]
+    fn rand<R: Rng>(rng: &mut R) -> u128 {
+        ((rng.next_u64() as u128) << 64) | (rng.next_u64() as u128)
+    }
+}
+
+
 macro_rules! float_impls {
     ($mod_name:ident, $ty:ty, $mantissa_bits:expr, $method_name:ident) => {
         mod $mod_name {
             use {Rand, Rng, Open01, Closed01};
 
             const SCALE: $ty = (1u64 << $mantissa_bits) as $ty;
 
             impl Rand for $ty {
--- a/third_party/rust/rand/src/read.rs
+++ b/third_party/rust/rand/src/read.rs
@@ -25,16 +25,17 @@ use Rng;
 ///
 /// ```rust
 /// use rand::{read, Rng};
 ///
 /// let data = vec![1, 2, 3, 4, 5, 6, 7, 8];
 /// let mut rng = read::ReadRng::new(&data[..]);
 /// println!("{:x}", rng.gen::<u32>());
 /// ```
+#[derive(Debug)]
 pub struct ReadRng<R> {
     reader: R
 }
 
 impl<R: Read> ReadRng<R> {
     /// Create a new `ReadRng` from a `Read`.
     pub fn new(r: R) -> ReadRng<R> {
         ReadRng {
--- a/third_party/rust/rand/src/reseeding.rs
+++ b/third_party/rust/rand/src/reseeding.rs
@@ -16,16 +16,17 @@ use std::default::Default;
 use {Rng, SeedableRng};
 
 /// How many bytes of entropy the underling RNG is allowed to generate
 /// before it is reseeded
 const DEFAULT_GENERATION_THRESHOLD: u64 = 32 * 1024;
 
 /// A wrapper around any RNG which reseeds the underlying RNG after it
 /// has generated a certain number of random bytes.
+#[derive(Debug)]
 pub struct ReseedingRng<R, Rsdr> {
     rng: R,
     generation_threshold: u64,
     bytes_generated: u64,
     /// Controls the behaviour when reseeding the RNG.
     pub reseeder: Rsdr,
 }
 
@@ -127,17 +128,17 @@ impl<S, R: SeedableRng<S>, Rsdr: Reseede
 /// ```
 pub trait Reseeder<R> {
     /// Reseed the given RNG.
     fn reseed(&mut self, rng: &mut R);
 }
 
 /// Reseed an RNG using a `Default` instance. This reseeds by
 /// replacing the RNG with the result of a `Default::default` call.
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 pub struct ReseedWithDefault;
 
 impl<R: Rng + Default> Reseeder<R> for ReseedWithDefault {
     fn reseed(&mut self, rng: &mut R) {
         *rng = Default::default();
     }
 }
 impl Default for ReseedWithDefault {
--- a/toolkit/library/gtest/rust/Cargo.lock
+++ b/toolkit/library/gtest/rust/Cargo.lock
@@ -495,16 +495,32 @@ version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "fuchsia-zircon"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "fuchsia-zircon-sys"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "futures"
 version = "0.1.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "fxhash"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -945,17 +961,17 @@ dependencies = [
 
 [[package]]
 name = "parking_lot_core"
 version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "peeking_take_while"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -983,17 +999,17 @@ dependencies = [
 ]
 
 [[package]]
 name = "phf_generator"
 version = "0.7.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "phf_shared"
 version = "0.7.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "siphasher 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1062,19 +1078,20 @@ dependencies = [
 
 [[package]]
 name = "quote"
 version = "0.3.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "rand"
-version = "0.3.15"
+version = "0.3.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
+ "fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rayon"
 version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -1086,17 +1103,17 @@ name = "rayon-core"
 version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "redox_syscall"
 version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -1464,17 +1481,17 @@ name = "u2fhid"
 version = "0.1.0"
 dependencies = [
  "boxfnonce 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "libudev 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "runloop 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "unicode-bidi"
 version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1672,16 +1689,18 @@ dependencies = [
 "checksum encoding_c 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "93ec52324ca72f423237a413ca0e1c60654c8b3d0934fcd5fd888508dfcc4ba7"
 "checksum encoding_rs 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f5215aabf22b83153be3ee44dfe3f940214541b2ce13d419c55e7a115c8c51a9"
 "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b"
 "checksum error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8"
 "checksum euclid 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "50c9e4c3b53de731815135191f0b77969bea953211b8bbd3cc3083a7b10e190e"
 "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344"
 "checksum freetype 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "398b8a11884898184d55aca9806f002b3cf68f0e860e0cbb4586f834ee39b0e7"
 "checksum fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ab76cfd2aaa59b7bf6688ad9ba15bbae64bff97f04ea02144cfd3443e5c2866"
+"checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159"
+"checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82"
 "checksum futures 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "55f0008e13fc853f79ea8fc86e931486860d4c4c156cdffb59fa5f7fa833660a"
 "checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
 "checksum gamma-lut 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dd65074503368cef99b98844012adfed8d7f99ff3e1e6d05e9055232f2d59dc9"
 "checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518"
 "checksum gl_generator 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0940975a4ca12b088d32b5d5134826c47d2e73de4b0b459b05244c01503eccbb"
 "checksum gleam 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "bf887141f0c2a83eae026cbf3fba74f0a5cb0f01d20e5cdfcd8c4ad39295be1e"
 "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
 "checksum heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4c7593b1522161003928c959c20a2ca421c68e940d63d75573316a009e48a6d4"
@@ -1724,17 +1743,17 @@ dependencies = [
 "checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2"
 "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
 "checksum plane-split 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e57800a97ca52c556db6b6184a3201f05366ad5e11876f7d17e234589ca2fa26"
 "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 "checksum procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9f566249236c6ca4340f7ca78968271f0ed2b0f234007a61b66f9ecd0af09260"
 "checksum quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18c45c4854d6d1cf5d531db97c75880feb91c958b0720f4ec1057135fec358b3"
 "checksum quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9e25fa23c044c1803f43ca59c98dac608976dd04ce799411edd58ece776d4"
 "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
-"checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"
+"checksum rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "61efcbcd9fa8d8fbb07c84e34a8af18a1ff177b449689ad38a6e9457ecc7b2ae"
 "checksum rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b614fe08b6665cb9a231d07ac1364b0ef3cb3698f1239ee0c4c3a88a524f54c8"
 "checksum rayon-core 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2c21a92a5dca958fb030787c1158446c6deb7f976399b72fa8074603f169e2a"
 "checksum redox_syscall 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd35cc9a8bdec562c757e3d43c1526b5c6d2653e23e2315065bc25556550753"
 "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b"
 "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
 "checksum runloop 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d79b4b604167921892e84afbbaad9d5ad74e091bf6c511d9dbfb0593f09fabd"
 "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
 "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
--- a/toolkit/library/rust/Cargo.lock
+++ b/toolkit/library/rust/Cargo.lock
@@ -494,16 +494,32 @@ version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "fuchsia-zircon"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "fuchsia-zircon-sys"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "futures"
 version = "0.1.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "fxhash"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -933,17 +949,17 @@ dependencies = [
 
 [[package]]
 name = "parking_lot_core"
 version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "peeking_take_while"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -971,17 +987,17 @@ dependencies = [
 ]
 
 [[package]]
 name = "phf_generator"
 version = "0.7.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "phf_shared"
 version = "0.7.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "siphasher 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1050,19 +1066,20 @@ dependencies = [
 
 [[package]]
 name = "quote"
 version = "0.3.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "rand"
-version = "0.3.15"
+version = "0.3.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
+ "fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rayon"
 version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -1074,17 +1091,17 @@ name = "rayon-core"
 version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "redox_syscall"
 version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -1476,17 +1493,17 @@ name = "u2fhid"
 version = "0.1.0"
 dependencies = [
  "boxfnonce 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "libudev 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "runloop 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "unicode-bidi"
 version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1684,16 +1701,18 @@ dependencies = [
 "checksum encoding_c 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "93ec52324ca72f423237a413ca0e1c60654c8b3d0934fcd5fd888508dfcc4ba7"
 "checksum encoding_rs 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f5215aabf22b83153be3ee44dfe3f940214541b2ce13d419c55e7a115c8c51a9"
 "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b"
 "checksum error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8"
 "checksum euclid 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "50c9e4c3b53de731815135191f0b77969bea953211b8bbd3cc3083a7b10e190e"
 "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344"
 "checksum freetype 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "398b8a11884898184d55aca9806f002b3cf68f0e860e0cbb4586f834ee39b0e7"
 "checksum fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ab76cfd2aaa59b7bf6688ad9ba15bbae64bff97f04ea02144cfd3443e5c2866"
+"checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159"
+"checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82"
 "checksum futures 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "55f0008e13fc853f79ea8fc86e931486860d4c4c156cdffb59fa5f7fa833660a"
 "checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
 "checksum gamma-lut 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dd65074503368cef99b98844012adfed8d7f99ff3e1e6d05e9055232f2d59dc9"
 "checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518"
 "checksum gl_generator 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0940975a4ca12b088d32b5d5134826c47d2e73de4b0b459b05244c01503eccbb"
 "checksum gleam 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "bf887141f0c2a83eae026cbf3fba74f0a5cb0f01d20e5cdfcd8c4ad39295be1e"
 "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
 "checksum heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4c7593b1522161003928c959c20a2ca421c68e940d63d75573316a009e48a6d4"
@@ -1736,17 +1755,17 @@ dependencies = [
 "checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2"
 "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
 "checksum plane-split 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e57800a97ca52c556db6b6184a3201f05366ad5e11876f7d17e234589ca2fa26"
 "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 "checksum procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9f566249236c6ca4340f7ca78968271f0ed2b0f234007a61b66f9ecd0af09260"
 "checksum quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18c45c4854d6d1cf5d531db97c75880feb91c958b0720f4ec1057135fec358b3"
 "checksum quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9e25fa23c044c1803f43ca59c98dac608976dd04ce799411edd58ece776d4"
 "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
-"checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"
+"checksum rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "61efcbcd9fa8d8fbb07c84e34a8af18a1ff177b449689ad38a6e9457ecc7b2ae"
 "checksum rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b614fe08b6665cb9a231d07ac1364b0ef3cb3698f1239ee0c4c3a88a524f54c8"
 "checksum rayon-core 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2c21a92a5dca958fb030787c1158446c6deb7f976399b72fa8074603f169e2a"
 "checksum redox_syscall 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd35cc9a8bdec562c757e3d43c1526b5c6d2653e23e2315065bc25556550753"
 "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b"
 "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
 "checksum runloop 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d79b4b604167921892e84afbbaad9d5ad74e091bf6c511d9dbfb0593f09fabd"
 "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
 "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"