Bug 1445451 - vendor rkv r=froydnj
☠☠ backed out by 6d19dd7ed3e5 ☠ ☠
authorMyk Melez <myk@mykzilla.org>
Wed, 08 Aug 2018 20:59:21 +0000
changeset 430574 08fa47a24e89697e4e43177860b55cc28298bbff
parent 430573 aa72fd1d53db7e6ef515cf847a55471d58b6b5f8
child 430575 e367443dd417aed7d28eb6eed8288c6361a50d6f
push id34409
push usertoros@mozilla.com
push dateThu, 09 Aug 2018 10:00:05 +0000
treeherdermozilla-central@eb9ff7de69ef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1445451
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1445451 - vendor rkv r=froydnj Differential Revision: https://phabricator.services.mozilla.com/D2246
Cargo.lock
gfx/webrender_bindings/Cargo.toml
gfx/webrender_bindings/src/program_cache.rs
testing/geckodriver/Cargo.toml
third_party/rust/arrayref/.cargo-checksum.json
third_party/rust/arrayref/.travis.yml
third_party/rust/arrayref/Cargo.toml
third_party/rust/arrayref/LICENSE
third_party/rust/arrayref/README.md
third_party/rust/arrayref/examples/array_refs.rs
third_party/rust/arrayref/examples/array_refs_with_const.rs
third_party/rust/arrayref/examples/simple-case.rs
third_party/rust/arrayref/src/lib.rs
third_party/rust/failure/.cargo-checksum.json
third_party/rust/failure/.gitlab-ci.yml
third_party/rust/failure/.travis.yml
third_party/rust/failure/CODE_OF_CONDUCT.md
third_party/rust/failure/Cargo.toml
third_party/rust/failure/LICENSE-APACHE
third_party/rust/failure/LICENSE-MIT
third_party/rust/failure/Makefile
third_party/rust/failure/README.md
third_party/rust/failure/RELEASES.md
third_party/rust/failure/book/src/SUMMARY.md
third_party/rust/failure/book/src/bail-and-ensure.md
third_party/rust/failure/book/src/custom-fail.md
third_party/rust/failure/book/src/derive-fail.md
third_party/rust/failure/book/src/error-errorkind.md
third_party/rust/failure/book/src/error-msg.md
third_party/rust/failure/book/src/error.md
third_party/rust/failure/book/src/fail.md
third_party/rust/failure/book/src/guidance.md
third_party/rust/failure/book/src/howto.md
third_party/rust/failure/book/src/intro.md
third_party/rust/failure/book/src/use-error.md
third_party/rust/failure/build-docs.sh
third_party/rust/failure/examples/bail_ensure.rs
third_party/rust/failure/examples/simple.rs
third_party/rust/failure/src/backtrace/internal.rs
third_party/rust/failure/src/backtrace/mod.rs
third_party/rust/failure/src/box_std.rs
third_party/rust/failure/src/compat.rs
third_party/rust/failure/src/context.rs
third_party/rust/failure/src/error/error_impl.rs
third_party/rust/failure/src/error/error_impl_small.rs
third_party/rust/failure/src/error/mod.rs
third_party/rust/failure/src/error_message.rs
third_party/rust/failure/src/lib.rs
third_party/rust/failure/src/macros.rs
third_party/rust/failure/src/result_ext.rs
third_party/rust/failure/src/small_error.rs
third_party/rust/failure/src/sync_failure.rs
third_party/rust/failure/travis.sh
third_party/rust/failure_derive/.cargo-checksum.json
third_party/rust/failure_derive/Cargo.toml
third_party/rust/failure_derive/build.rs
third_party/rust/failure_derive/src/lib.rs
third_party/rust/failure_derive/tests/backtrace.rs
third_party/rust/failure_derive/tests/custom_type_bounds.rs
third_party/rust/failure_derive/tests/no_derive_display.rs
third_party/rust/failure_derive/tests/tests.rs
third_party/rust/failure_derive/tests/wraps.rs
third_party/rust/lmdb-rkv/.appveyor.yml
third_party/rust/lmdb-rkv/.cargo-checksum.json
third_party/rust/lmdb-rkv/.gitmodules
third_party/rust/lmdb-rkv/.rustfmt.toml
third_party/rust/lmdb-rkv/.travis.yml
third_party/rust/lmdb-rkv/Cargo.toml
third_party/rust/lmdb-rkv/LICENSE
third_party/rust/lmdb-rkv/README.md
third_party/rust/lmdb-rkv/src/cursor.rs
third_party/rust/lmdb-rkv/src/database.rs
third_party/rust/lmdb-rkv/src/environment.rs
third_party/rust/lmdb-rkv/src/error.rs
third_party/rust/lmdb-rkv/src/flags.rs
third_party/rust/lmdb-rkv/src/lib.rs
third_party/rust/lmdb-rkv/src/transaction.rs
third_party/rust/lmdb-sys/.cargo-checksum.json
third_party/rust/lmdb-sys/Cargo.toml
third_party/rust/lmdb-sys/build.rs
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/CHANGES
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/COPYRIGHT
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/Doxyfile
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/LICENSE
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/Makefile
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/intro.doc
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/lmdb.h
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/mdb.c
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/mdb_copy.1
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/mdb_copy.c
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/mdb_dump.1
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/mdb_dump.c
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/mdb_load.1
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/mdb_load.c
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/mdb_stat.1
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/mdb_stat.c
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/midl.c
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/midl.h
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/mtest.c
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/mtest2.c
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/mtest3.c
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/mtest4.c
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/mtest5.c
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/mtest6.c
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/sample-bdb.txt
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/sample-mdb.txt
third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/tooltag
third_party/rust/lmdb-sys/src/constants.rs
third_party/rust/lmdb-sys/src/ffi.rs
third_party/rust/lmdb-sys/src/lib.rs
third_party/rust/proc-macro2/.cargo-checksum.json
third_party/rust/proc-macro2/Cargo.toml
third_party/rust/proc-macro2/src/lib.rs
third_party/rust/proc-macro2/src/unstable.rs
third_party/rust/proc-macro2/tests/test.rs
third_party/rust/rkv/.appveyor.yml
third_party/rust/rkv/.cargo-checksum.json
third_party/rust/rkv/.rustfmt.toml
third_party/rust/rkv/.travis.yml
third_party/rust/rkv/Cargo.toml
third_party/rust/rkv/LICENSE
third_party/rust/rkv/README.md
third_party/rust/rkv/examples/README.md
third_party/rust/rkv/examples/iterator.rs
third_party/rust/rkv/examples/simple-store.rs
third_party/rust/rkv/run-all-examples.sh
third_party/rust/rkv/src/env.rs
third_party/rust/rkv/src/error.rs
third_party/rust/rkv/src/integer.rs
third_party/rust/rkv/src/lib.rs
third_party/rust/rkv/src/manager.rs
third_party/rust/rkv/src/readwrite.rs
third_party/rust/rkv/src/value.rs
third_party/rust/rkv/tests/manager.rs
third_party/rust/syn/.cargo-checksum.json
third_party/rust/syn/Cargo.toml
third_party/rust/syn/src/attr.rs
third_party/rust/syn/src/buffer.rs
third_party/rust/syn/src/data.rs
third_party/rust/syn/src/derive.rs
third_party/rust/syn/src/expr.rs
third_party/rust/syn/src/gen/fold.rs
third_party/rust/syn/src/gen/visit.rs
third_party/rust/syn/src/gen/visit_mut.rs
third_party/rust/syn/src/generics.rs
third_party/rust/syn/src/item.rs
third_party/rust/syn/src/lib.rs
third_party/rust/syn/src/lifetime.rs
third_party/rust/syn/src/macros.rs
third_party/rust/syn/src/parsers.rs
third_party/rust/syn/src/path.rs
third_party/rust/syn/src/punctuated.rs
third_party/rust/syn/src/synom.rs
third_party/rust/syn/src/token.rs
third_party/rust/syn/src/ty.rs
third_party/rust/syn/src/verbatim.rs
third_party/rust/synstructure-0.8.1/.cargo-checksum.json
third_party/rust/synstructure-0.8.1/Cargo.toml
third_party/rust/synstructure-0.8.1/LICENSE
third_party/rust/synstructure-0.8.1/README.md
third_party/rust/synstructure-0.8.1/src/lib.rs
third_party/rust/synstructure-0.8.1/src/macros.rs
third_party/rust/synstructure/.cargo-checksum.json
third_party/rust/synstructure/Cargo.toml
third_party/rust/synstructure/README.md
third_party/rust/synstructure/src/lib.rs
third_party/rust/synstructure/src/macros.rs
third_party/rust/uuid/.cargo-checksum.json
third_party/rust/uuid/.travis.yml
third_party/rust/uuid/Cargo.toml
third_party/rust/uuid/README.md
third_party/rust/uuid/src/lib.rs
third_party/rust/uuid/src/rustc_serialize.rs
third_party/rust/uuid/src/serde.rs
third_party/rust/uuid/src/std_support.rs
toolkit/library/rust/shared/Cargo.toml
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -33,16 +33,21 @@ name = "app_units"
 version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "num-traits 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "arrayref"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "arrayvec"
 version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -437,21 +442,21 @@ name = "cssparser"
 version = "0.24.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cssparser-macros 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "dtoa-short 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "cssparser-macros"
 version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -672,16 +677,35 @@ name = "euclid"
 version = "0.19.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "num-traits 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "failure"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "failure_derive"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "fallible"
 version = "0.0.1"
 dependencies = [
  "hashglobe 0.1.0",
  "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -787,17 +811,17 @@ dependencies = [
  "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "mozprofile 0.3.0",
  "mozrunner 0.7.0",
  "mozversion 0.1.3",
  "regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "uuid 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "webdriver 0.36.0",
  "zip 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "geckoservo"
 version = "0.0.1"
 dependencies = [
@@ -850,16 +874,17 @@ dependencies = [
  "geckoservo 0.0.1",
  "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "mozurl 0.0.1",
  "mp4parse_capi 0.10.1",
  "netwerk_helper 0.0.1",
  "nserror 0.1.0",
  "nsstring 0.1.0",
  "prefs_parser 0.0.1",
+ "rkv 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rsdparsa_capi 0.1.0",
  "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "u2fhid 0.2.0",
  "webrender_bindings 0.1.0",
  "xpcom 0.1.0",
 ]
 
 [[package]]
@@ -1102,16 +1127,36 @@ dependencies = [
 ]
 
 [[package]]
 name = "linked-hash-map"
 version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "lmdb-rkv"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lmdb-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "lmdb-sys"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "lock_api"
 version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "scopeguard 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1592,17 +1637,17 @@ name = "proc-macro2"
 version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "proc-macro2"
-version = "0.4.6"
+version = "0.4.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "procedural-masquerade"
 version = "0.1.1"
@@ -1641,17 +1686,17 @@ dependencies = [
  "proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "quote"
 version = "0.6.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rand"
 version = "0.3.18"
 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)",
@@ -1717,16 +1762,32 @@ source = "registry+https://github.com/ru
 name = "regex-syntax"
 version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "rkv"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "arrayref 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lmdb-rkv 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "new-ordered-float 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "uuid 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "ron"
 version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1846,19 +1907,19 @@ dependencies = [
  "serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "serde_derive"
 version = "1.0.66"
 source = "git+https://github.com/servo/serde?branch=deserialize_from_enums8#c4457d804b38b14e699b45c01d1909f93f25ab5e"
 dependencies = [
- "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "servo_arc"
 version = "0.1.1"
 dependencies = [
  "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2043,36 +2104,47 @@ source = "registry+https://github.com/ru
 dependencies = [
  "proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "syn"
-version = "0.14.2"
+version = "0.14.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "synstructure"
 version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "synstructure"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.1.0 (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.18 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2285,21 +2357,20 @@ dependencies = [
 
 [[package]]
 name = "utf8-ranges"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "uuid"
-version = "0.1.18"
+version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "vcpkg"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -2409,17 +2480,17 @@ dependencies = [
  "euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "nsstring 0.1.0",
  "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "uuid 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "webrender 0.57.2",
 ]
 
 [[package]]
 name = "which"
 version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -2537,16 +2608,17 @@ dependencies = [
 ]
 
 [metadata]
 "checksum Inflector 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1b33cd9b653730fc539c53c7b3c672d2f47108fa20c6df571fa5817178f5a14c"
 "checksum adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6cbd0b9af8587c72beadc9f72d35b9fbb070982c9e6203e46e93f10df25f8f45"
 "checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"
 "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
 "checksum app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9dadc668390b373e73e4abbfc1f07238b09a25858f2f39c06cebc6d8e141d774"
+"checksum arrayref 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0fd1479b7c29641adbd35ff3b5c293922d696a92f25c8c975da3e0acbc87258f"
 "checksum arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2f0ef4a9820019a0c91d918918c93dc71d469f581a49b47ddc1d285d4270bbe2"
 "checksum ascii-canvas 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b385d69402821a1c254533a011a312531cbcc0e3e24f19bbb4747a5a2daf37e2"
 "checksum atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb2dcb6e6d35f20276943cc04bb98e538b348d525a04ac79c10021561d202f21"
 "checksum atty 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d0fd4c0631f06448cc45a6bbb3b710ebb7ff8ccb96a0800c994afe23a70d5df2"
 "checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159"
 "checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9"
 "checksum binary-space-partition 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88ceb0d16c4fd0e42876e298d7d3ce3780dd9ebdcbe4199816a32c77e08597ff"
 "checksum bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bda13183df33055cbb84b847becce220d392df502ebe7a4a78d7021771ed94d0"
@@ -2600,16 +2672,18 @@ dependencies = [
 "checksum dwrote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b26e30aaa6bf31ec830db15fec14ed04f0f2ecfcc486ecfce88c55d3389b237f"
 "checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a"
 "checksum ena 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cabe5a5078ac8c506d3e4430763b1ba9b609b1286913e7d08e581d1c2de9b7e5"
 "checksum encoding_c 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "769ecb8b33323998e482b218c0d13cd64c267609023b4b7ec3ee740714c318ee"
 "checksum encoding_rs 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "88a1b66a0d28af4b03a8c8278c6dcb90e6e600d89c14500a9e7a02e64b9ee3ac"
 "checksum env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0561146661ae44c579e993456bc76d11ce1e0c7d745e57b2fa7146b6e49fa2ad"
 "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
 "checksum euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "70a2ebdf55fb9d6329046e026329a55ef8fbaae5ea833f56e170beb3125a8a5f"
+"checksum failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7efb22686e4a466b1ec1a15c2898f91fa9cb340452496dca654032de20ff95b9"
+"checksum failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "946d0e98a50d9831f5d589038d2ca7f8f455b1c21028c0db0e84116a12696426"
 "checksum fixedbitset 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "85cb8fec437468d86dc7c83ca7cfc933341d561873275f22dd5eedefa63a6478"
 "checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909"
 "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344"
 "checksum foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ebc04f19019fff1f2d627b5581574ead502f80c48c88900575a46e0840fe5d0"
 "checksum freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b659e75b7a7338fe75afd7f909fc2b71937845cffb6ebe54ba2e50f13d8e903d"
 "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"
@@ -2638,16 +2712,18 @@ dependencies = [
 "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
 "checksum lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e6412c5e2ad9584b0b8e979393122026cdd6d2a80b933f890dcd694ddbe73739"
 "checksum lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce12306c4739d86ee97c23139f3a34ddf0387bbf181bc7929d287025a8c3ef6b"
 "checksum libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)" = "f54263ad99207254cf58b5f701ecb432c717445ea2ee8af387334bdd1a03fdff"
 "checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2"
 "checksum libudev 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea626d3bdf40a1c5aee3bcd4f40826970cae8d80a8fec934c82a63840094dcfe"
 "checksum libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd64ef8ee652185674455c1d450b83cbc8ad895625d543b5324d923f82e4d8"
 "checksum linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70fb39025bc7cdd76305867c4eccf2f2dcf6e9a57f5b21a93e1c2d86cd03ec9e"
+"checksum lmdb-rkv 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "07d8d72d709440ac7a19b71e04fb66684ec7547b3831817872454b01fdaefe23"
+"checksum lmdb-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5b392838cfe8858e86fac37cf97a0e8c55cc60ba0a18365cadc33092f128ce9"
 "checksum lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "949826a5ccf18c1b3a7c3d57692778d21768b79e46eb9dd07bfc4c2160036c54"
 "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
 "checksum log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6fddaa003a65722a7fb9e26b0ce95921fe4ba590542ced664d8ce2fa26f9f3ac"
 "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
 "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a"
 "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
 "checksum memmap 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46f3c7359028b31999287dae4e5047ddfe90a23b7dca2282ce759b491080c99b"
 "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
@@ -2683,30 +2759,31 @@ dependencies = [
 "checksum phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d62594c0bb54c464f633175d502038177e90309daf2e0158be42ed5f023ce88f"
 "checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03"
 "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.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ff3a4fc9e31d70eb6828e9a2d7a401a824d9f281686a39a8fc06f08796edb1bb"
 "checksum podio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e5422a1ee1bc57cc47ae717b0137314258138f38fd5f3cea083f43a9725383a0"
 "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 "checksum proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "77997c53ae6edd6d187fec07ec41b207063b5ee6f33680e9fa86d405cdd313d4"
-"checksum proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "effdb53b25cdad54f8f48843d67398f7ef2e14f12c1b4cb4effc549a6462a4d6"
+"checksum proc-macro2 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "cccdc7557a98fe98453030f077df7f3a042052fae465bb61d2c2c41435cfd9b6"
 "checksum procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9f566249236c6ca4340f7ca78968271f0ed2b0f234007a61b66f9ecd0af09260"
 "checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4"
 "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
 "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8"
 "checksum quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e44651a0dc4cdd99f71c83b561e221f714912d11af1a4dff0631f923d53af035"
 "checksum rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6475140dfd8655aeb72e1fd4b7a1cc1c202be65d71669476e392fe62532b9edd"
 "checksum rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "485541959c8ecc49865526fe6c4de9653dd6e60d829d6edf0be228167b60372d"
 "checksum rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8"
 "checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0"
 "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b"
 "checksum regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75ecf88252dce580404a22444fc7d626c01815debba56a7f4f536772a5ff19d3"
 "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
 "checksum regex-syntax 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1ac0f60d675cc6cf13a20ec076568254472551051ad5dd050364d70671bf6b"
+"checksum rkv 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "21983ae9330b1e1cb1d01868229618a3c7cc5134955f0dc1a86a0a1886f3acb7"
 "checksum ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "da06feaa07f69125ab9ddc769b11de29090122170b402547f64b86fe16ebc399"
 "checksum runloop 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d79b4b604167921892e84afbbaad9d5ad74e091bf6c511d9dbfb0593f09fabd"
 "checksum rust-ini 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8a654c5bda722c699be6b0fe4c0d90de218928da5b724c3e467fc48865c37263"
 "checksum rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "76d7ba1feafada44f2d38eed812bd2489a03c0f5abb975799251518b68848649"
 "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
 "checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69"
 "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f"
 "checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637"
@@ -2724,18 +2801,19 @@ dependencies = [
 "checksum smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "26df3bb03ca5eac2e64192b723d51f56c1b1e0860e7c766281f4598f181acdc8"
 "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
 "checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423"
 "checksum string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "479cde50c3539481f33906a387f2bd17c8e87cb848c35b6021d41fb81ff9b4d7"
 "checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc"
 "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
 "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
 "checksum syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91b52877572087400e83d24b9178488541e3d535259e04ff17a63df1e5ceff59"
-"checksum syn 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c67da57e61ebc7b7b6fff56bb34440ca3a83db037320b0507af4c10368deda7d"
+"checksum syn 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4e4b5274d4a0a3d2749d5c158dc64d3403e60554dc61194648787ada5212473d"
 "checksum synstructure 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "98cad891cd238c98e1f0aec9f7c0f620aa696e4e5f7daba56ac67b5e86a6b049"
+"checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7"
 "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
 "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
 "checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209"
 "checksum termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "adc4587ead41bf016f11af03e55a624c06568b5a19db4e90fde573d805074f83"
 "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
 "checksum thin-slice 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c"
 "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963"
 "checksum thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf947d192a9be60ef5131cc7a4648886ba89d712f16700ebbf80c8a69d05d48f"
@@ -2752,17 +2830,17 @@ dependencies = [
 "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
 "checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f"
 "checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1"
 "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
 "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
 "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
 "checksum url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f808aadd8cfec6ef90e4a14eb46f24511824d1ac596b9682703c87056c8678b7"
 "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
-"checksum uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "78c590b5bd79ed10aad8fb75f078a59d8db445af6c743e55c4a53227fc01c13f"
+"checksum uuid 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcc7e3b898aa6f6c08e5295b6c89258d1331e9ac578cc992fb818759951bdc22"
 "checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b"
 "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
 "checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d"
 "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
 "checksum walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63636bd0eb3d00ccb8b9036381b526efac53caf112b7783b730ab3f8e44da369"
 "checksum webidl 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc14e4b71f94b5bb4c6d696e3b3be4d2e9ee6750a60870ecae09ff7138a131a7"
 "checksum which 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4be6cfa54dab45266e98b5d7be2f8ce959ddd49abd141a05d52dce4b07f803bb"
 "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
--- a/gfx/webrender_bindings/Cargo.toml
+++ b/gfx/webrender_bindings/Cargo.toml
@@ -8,17 +8,17 @@ license = "MPL-2.0"
 rayon = "1"
 thread_profiler = "0.1.1"
 euclid = { version = "0.19", features = ["serde"] }
 app_units = "0.7"
 gleam = "0.6"
 log = "0.4"
 nsstring = { path = "../../servo/support/gecko/nsstring" }
 bincode = "1.0"
-uuid = {version = "0.1.18"}
+uuid = { version = "0.5", features = ["v4"] }
 fxhash = "0.2.1"
 
 [dependencies.webrender]
 path = "../webrender"
 version = "0.57.2"
 default-features = false
 features = ["capture", "serialize_program"]
 
--- a/gfx/webrender_bindings/src/program_cache.rs
+++ b/gfx/webrender_bindings/src/program_cache.rs
@@ -114,17 +114,17 @@ impl WrProgramBinaryDiskCache {
             if self.program_count > MAX_CACHED_PROGRAM_COUNT {
                 // Disable disk cache to avoid storing more shader programs to disk
                 self.is_enabled = false;
                 return;
             }
 
             // Use uuid for file name
             let uuid1 = Uuid::new_v4();
-            let file_name = uuid1.to_hyphenated_string();
+            let file_name = uuid1.hyphenated().to_string();
             let program_binary = Arc::clone(program_binary);
             let file_path = cache_path.join(&file_name);
 
             let program_count = self.program_count;
 
             // Save to disk on worker thread
             self.workers.spawn(move || {
 
--- a/testing/geckodriver/Cargo.toml
+++ b/testing/geckodriver/Cargo.toml
@@ -14,14 +14,14 @@ clap = { version = "^2.19", default-feat
 hyper = "0.10"
 lazy_static = "1.0"
 log = { version = "0.4", features = ["std"] }
 mozprofile = { path = "../mozbase/rust/mozprofile" }
 mozrunner = { path = "../mozbase/rust/mozrunner" }
 mozversion = { path = "../mozbase/rust/mozversion" }
 regex = "1.0"
 rustc-serialize = "0.3"
-uuid = "0.1.18"
+uuid = { version = "0.5", features = ["v4"] }
 webdriver = { path = "../webdriver" }
 zip = "0.3"
 
 [[bin]]
 name = "geckodriver"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/arrayref/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{".travis.yml":"19382d5f7c535638c53c19821fdfc3d8e3b2acb521a20339ce710ac6155c3c4e","Cargo.toml":"b96c2e28f7d3b8fad8564490f1a250f8d84c82e2314a2e19d98435f73c68e420","LICENSE":"1bc7e6f475b3ec99b7e2643411950ae2368c250dd4c5c325f80f9811362a94a1","README.md":"f77d8910fa16f9f0ad2d72d039a7e8ac2979834e0acf435b7c84744c90cb21ec","examples/array_refs.rs":"336b52f6ab31d78766bd1653cea60b9f183d80369f3feec55e454ccbcb3adaaa","examples/array_refs_with_const.rs":"9e49959de714c611bc2e48bb0dd51c3023abc2b3e6b6e0428e7d7b30be8900e4","examples/simple-case.rs":"12a7c596db0d8e89415dfd75a8fe390a7141b24771ad70aee73286857a37b5fb","src/lib.rs":"eb60cfac35e5e61d792bb0ae902afbb82d01fa75fa9691e57a89785207e687d8"},"package":"0fd1479b7c29641adbd35ff3b5c293922d696a92f25c8c975da3e0acbc87258f"}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/arrayref/.travis.yml
@@ -0,0 +1,31 @@
+language: rust
+addons:
+  apt:
+    packages:
+    - libcurl4-openssl-dev
+    - libelf-dev
+    - libdw-dev
+rust:
+  - nightly
+  - beta
+  - stable
+matrix:
+  allow_failures:
+    - rust: nightly
+before_script:
+- |
+  pip install 'travis-cargo<0.2' --user &&
+  export PATH=$HOME/.local/bin:$PATH
+script:
+- |
+  travis-cargo build &&
+  travis-cargo test &&
+  travis-cargo bench &&
+  travis-cargo --only stable doc
+after_success:
+- travis-cargo --only stable doc-upload
+- travis-cargo coveralls --no-sudo
+env:
+  global:
+  - TRAVIS_CARGO_NIGHTLY_FEATURE=nightly
+  - secure: 8dzqJGkV5184c0sV9BiMjjs5lxQjK2CvfGAU6ab2YFWN3roN/u37wBkoyqeSIzR3Uv0EXUOIM/BwuaeIwDHrZtTQMNnRw8Aa9A0mIeVCz1zlOFRK18NVGKoxBkkzlAvQn51D9X7sF9g9xLoDB7zyH63qhrerz6vjUivXaXkKZKAUZeBZMQ5riUxaHkt2LJtQhngXPS3Ar+ajSjIGkhg9x8gkqgkQCewbyoR9S9BwiyIUdYyYRSTgUgFtp3tuzMhQ8qykj53PqrbcCfiYC3O3lsGfQ0nqerT7cxPIHIg25+dZYJjLFk1908+GZFVqia9JFT8bbep7IkICDtfRQswAcxKTV6TvExfkEh8/vapzCueXuFMbszUDXxFkE+QWEO9RcDCQZjVAXuKx/iacok4XFXr/yE3QKVB+up7bKcEpAMMxjPd2+Z3EHVKZ53DtlzuzxM6ByjPy+0hRHkLWq3ZyzxyF3PAHq1tWlJ8B37eOqJIk4n+OBBpPOg1WF6nFq/7UV44SRkBbfC69wk8ANb46gWlIiB4+VKAsxEkRMYURtsPqTpgGqSdB2aNm8xpzke9d3d7Z+Zy8ma6tykqN9TlY7ke5fxJhaeNdTpdUykc0MHcKF8RvZbi170UmMqLRQMsMusXGP6QnhpVQhQB/bTRNZWJwKCTZ54jtEKImShInhTk=
new file mode 100644
--- /dev/null
+++ b/third_party/rust/arrayref/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "arrayref"
+version = "0.3.4"
+authors = ["David Roundy <roundyd@physics.oregonstate.edu>"]
+description = "Macros to take array references of slices"
+license = "BSD-2-Clause"
+repository = "https://github.com/droundy/arrayref"
+documentation = "https://docs.rs/arrayref"
+
+[dev-dependencies]
+quickcheck = "0.4"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/arrayref/LICENSE
@@ -0,0 +1,26 @@
+Copyright (c) 2015 David Roundy <roundyd@physics.oregonstate.edu>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+2. 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.
+
+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
+HOLDER 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/arrayref/README.md
@@ -0,0 +1,109 @@
+# arrayref
+
+[![Build Status](https://travis-ci.org/droundy/arrayref.svg?branch=master)](https://travis-ci.org/droundy/arrayref)
+[![Coverage Status](https://coveralls.io/repos/droundy/arrayref/badge.svg?branch=master&service=github)](https://coveralls.io/github/droundy/arrayref?branch=master)
+
+[Documentation](https://docs.rs/arrayref)
+
+This is a very small rust module, which contains just four macros, for
+the taking of array references to slices of... sliceable things.
+These macros (which are awkwardly named) should be perfectly safe, and
+have seen just a tad of code review.
+
+## Why would I want this?
+
+The goal of arrayref is to enable the effective use of APIs that
+involve array references rather than slices, for situations where
+parameters must have a given size.  As an example, consider the
+`byteorder` crate.  This is a very nice crate with a simple API
+containing functions that look like:
+
+```rust
+fn read_u16(buf: &[u8]) -> u16;
+fn write_u16(buf: &mut [u8], n: u16);
+```
+
+Looking at this, you might wonder why they accept a slice reference as
+input.  After all, they always want just two bytes.  These functions
+must panic if given a slice that is too small, which means that unless
+they are inlined, then a runtime bounds-check is forced, even if it
+may be statically known that the input is the right size.
+
+Wouldn't it be nicer if we had functions more like
+
+```rust
+fn read_u16_array(buf: &[u8; 2]) -> u16;
+fn write_u16_array(buf: &mut [u8; 2], n: u16);
+```
+
+The type signature would tell users precisely what size of input is
+required, and the compiler could check at compile time that the input
+is of the appropriate size: this sounds like the zero-cost
+abstractions rust is famous for!  However, there is a catch, which
+arises when you try to *use* these nicer functions, which is that
+usually you are looking at two bytes in a stream.  So, e.g. consider
+that we are working with a hypothetical (and simplified) ipv6 address.
+
+Doing this with our array version (which looks so beautiful in terms
+of accurately describing what we want!) looks terrible:
+
+```rust
+let addr: &[u8; 16] = ...;
+let mut segments = [0u16; 8];
+// array-based API
+for i in 0 .. 8 {
+    let mut two_bytes = [addr[2*i], addr[2*i+1]];
+    segments[i] = read_u16_array(&two_bytes);
+}
+// slice-based API
+for i in 0 .. 8 {
+    segments[i] = read_u16(&addr[2*i..]);
+}
+```
+
+The array-based approach looks way worse.  We need to create a fresh
+copy of the bytes, just so it will be in an array of the proper size!
+Thus the whole "zero-cost abstraction" argument for using array
+references fails.  The trouble is that there is no (safe) way (until
+[RFC 495][1] lands) to obtain an array reference to a portion of a
+larger array or slice.  Doing so is the equivalent of taking a slice
+with a size known at compile time, and ought to be built into the
+language.
+
+[1]: https://github.com/rust-lang/rfcs/blob/master/text/0495-array-pattern-changes.md
+
+The arrayref crate allows you to do this kind of slicing.  So the
+above (very contrived) example can be implemented with array
+references as:
+
+```rust
+let addr: &[u8; 16] = ...;
+let mut segments = [0u16; 8];
+// array-based API with arrayref
+for i in 0 .. 8 {
+    segments[i] = read_u16_array(array_ref![addr,2*i,2]);
+}
+```
+
+Here the `array_ref![addr,2*i,2]` macro allows us to take an array
+reference to a slice consisting of two bytes starting at `2*i`.  Apart
+from the syntax (less nice than slicing), it is essentially the same
+as the slice approach.  However, this code makes explicit the
+need for precisely *two* bytes both in the caller, and in the function
+signature.
+
+This module provides three other macros providing related
+functionality, which you can read about in the
+[documentation](https://droundy.github.io/arrayref).
+
+For an example of how these macros can be used in an actual program,
+see [my rust translation of tweetnacl][2], which uses `arrayref`
+to almost exclusively accept array references in functions, with the
+only exception being those which truly expect data of arbitrary
+length.  In my opinion, the result is code that is far more legible
+than the original C code, since the size of each argument is
+explicit.  Moreover (although I have not tested this), the use of
+array references rather than slices *should* result in far fewer
+bounds checks, since almost all sizes are known at compile time.
+
+[2]: https://github.com/droundy/onionsalt/blob/master/src/crypto.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/arrayref/examples/array_refs.rs
@@ -0,0 +1,13 @@
+#[macro_use]
+extern crate arrayref;
+
+fn main() {
+    let x = [0,1,2,3,4,5,6,7,8,9];
+    let (a,b,c) = array_refs!(&x, 2, 3, 5);
+    assert_eq!(2, a.len());
+    assert_eq!(3, b.len());
+    assert_eq!(5, c.len());
+    assert_eq!(*a, [0,1]);
+    assert_eq!(*b, [2,3,4]);
+    assert_eq!(*c, [5,6,7,8,9]);
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/arrayref/examples/array_refs_with_const.rs
@@ -0,0 +1,18 @@
+#[macro_use]
+extern crate arrayref;
+
+const SIZE: usize = 10;
+const SIZE_A: usize = 2;
+const SIZE_B: usize = 3;
+const SIZE_C: usize = 5;
+
+fn main() {
+    let x: [u8; SIZE] = [0,1,2,3,4,5,6,7,8,9];
+    let (a,b,c) = array_refs!(&x, SIZE_A, SIZE_B, SIZE_C);
+    assert_eq!(SIZE_A, a.len());
+    assert_eq!(SIZE_B, b.len());
+    assert_eq!(SIZE_C, c.len());
+    assert_eq!(*a, [0,1]);
+    assert_eq!(*b, [2,3,4]);
+    assert_eq!(*c, [5,6,7,8,9]);
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/arrayref/examples/simple-case.rs
@@ -0,0 +1,15 @@
+#[macro_use]
+extern crate arrayref;
+
+fn add_three(a: &[u8; 3]) -> u8 {
+    a[0] + a[1] + a[2]
+}
+
+fn main() {
+    let mut x = [0u8; 30];
+    x[20] = 1;
+    x[21] = 4;
+    x[24] = 3;
+    x[0] = add_three(array_mut_ref![x,20,3]);
+    assert_eq!(x[0], 8);
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/arrayref/src/lib.rs
@@ -0,0 +1,365 @@
+//! This package contains just four macros, which enable the creation
+//! of array references to portions of arrays or slices (or things
+//! that can be sliced).
+//!
+//! # Examples
+//!
+//! Here is a simple example of slicing and dicing a slice into array
+//! references with these macros.  Here we implement a simple
+//! little-endian conversion from bytes to `u16`, and demonstrate code
+//! that uses `array_ref!` to extract an array reference from a larger
+//! array.  Note that the documentation for each macro also has an
+//! example of its use.
+//!
+//! ```
+//! #[macro_use]
+//! extern crate arrayref;
+//!
+//! fn read_u16(bytes: &[u8; 2]) -> u16 {
+//!      bytes[0] as u16 + ((bytes[1] as u16) << 8)
+//! }
+//! // ...
+//! # fn main() {
+//! let data = [0,1,2,3,4,0,6,7,8,9];
+//! assert_eq!(256, read_u16(array_ref![data,0,2]));
+//! assert_eq!(4, read_u16(array_ref![data,4,2]));
+//! # }
+//! ```
+#![deny(warnings)]
+#![no_std]
+
+#[cfg(test)]
+#[macro_use]
+extern crate std;
+
+/// You can use `array_ref` to generate an array reference to a subset
+/// of a sliceable bit of data (which could be an array, or a slice,
+/// or a Vec).
+///
+/// **Panics** if the slice is out of bounds.
+///
+/// ```
+/// #[macro_use]
+/// extern crate arrayref;
+///
+/// fn read_u16(bytes: &[u8; 2]) -> u16 {
+///      bytes[0] as u16 + ((bytes[1] as u16) << 8)
+/// }
+/// // ...
+/// # fn main() {
+/// let data = [0,1,2,3,4,0,6,7,8,9];
+/// assert_eq!(256, read_u16(array_ref![data,0,2]));
+/// assert_eq!(4, read_u16(array_ref![data,4,2]));
+/// # }
+/// ```
+
+#[macro_export]
+macro_rules! array_ref {
+    ($arr:expr, $offset:expr, $len:expr) => {{
+        {
+            #[inline]
+            unsafe fn as_array<T>(slice: &[T]) -> &[T; $len] {
+                &*(slice.as_ptr() as *const [_; $len])
+            }
+            let offset = $offset;
+            let slice = & $arr[offset..offset + $len];
+            unsafe {
+                as_array(slice)
+            }
+        }
+    }}
+}
+
+/// You can use `array_refs` to generate a series of array references
+/// to an input array reference.  The idea is if you want to break an
+/// array into a series of contiguous and non-overlapping arrays.
+/// `array_refs` is a bit funny in that it insists on slicing up the
+/// *entire* array.  This is intentional, as I find it handy to make
+/// me ensure that my sub-arrays add up to the entire array.  This
+/// macro will *never* panic, since the sizes are all checked at
+/// compile time.
+///
+/// Note that unlike `array_ref!`, `array_refs` *requires* that the
+/// first argument be an array reference.  The following arguments are
+/// the lengths of each subarray you wish a reference to.  The total
+/// of these arguments *must* equal the size of the array itself.
+///
+/// ```
+/// #[macro_use]
+/// extern crate arrayref;
+///
+/// fn read_u16(bytes: &[u8; 2]) -> u16 {
+///      bytes[0] as u16 + ((bytes[1] as u16) << 8)
+/// }
+/// // ...
+/// # fn main() {
+/// let data = [0,1,2,3,4,0,6,7];
+/// let (a,b,c) = array_refs![&data,2,2,4];
+/// assert_eq!(read_u16(a), 256);
+/// assert_eq!(read_u16(b), 3*256+2);
+/// assert_eq!(*c, [4,0,6,7]);
+/// # }
+/// ```
+#[macro_export]
+macro_rules! array_refs {
+    ( $arr:expr, $( $len:expr ),* ) => {{
+        {
+            #[inline]
+            #[allow(unused_assignments)]
+            unsafe fn as_arrays<T>(a: &[T; $( $len + )* 0 ]) -> ( $( &[T; $len], )* ) {
+                let mut p = a.as_ptr();
+                ( $( {
+                    let aref = &*(p as *const [T; $len]);
+                    p = p.offset($len as isize);
+                    aref
+                } ),* )
+            }
+            let input = $arr;
+            unsafe {
+                as_arrays(input)
+            }
+        }
+    }}
+}
+
+
+/// You can use `mut_array_refs` to generate a series of mutable array
+/// references to an input mutable array reference.  The idea is if
+/// you want to break an array into a series of contiguous and
+/// non-overlapping mutable array references.  Like `array_refs!`,
+/// `mut_array_refs!` is a bit funny in that it insists on slicing up
+/// the *entire* array.  This is intentional, as I find it handy to
+/// make me ensure that my sub-arrays add up to the entire array.
+/// This macro will *never* panic, since the sizes are all checked at
+/// compile time.
+///
+/// Note that unlike `array_mut_ref!`, `mut_array_refs` *requires*
+/// that the first argument be a mutable array reference.  The
+/// following arguments are the lengths of each subarray you wish a
+/// reference to.  The total of these arguments *must* equal the size
+/// of the array itself.  Also note that this macro allows you to take
+/// out multiple mutable references to a single object, which is both
+/// weird and powerful.
+///
+/// ```
+/// #[macro_use]
+/// extern crate arrayref;
+///
+/// fn write_u16(bytes: &mut [u8; 2], num: u16) {
+///      bytes[0] = num as u8;
+///      bytes[1] = (num >> 8) as u8;
+/// }
+/// fn write_u32(bytes: &mut [u8; 4], num: u32) {
+///      bytes[0] = num as u8;
+///      bytes[1] = (num >> 8) as u8; // this is buggy to save space...
+/// }
+/// // ...
+/// # fn main() {
+/// let mut data = [0,1,2,3,4,0,6,7];
+/// let (a,b,c) = mut_array_refs![&mut data,2,2,4];
+/// // let's write out some nice prime numbers!
+/// write_u16(a, 37);
+/// write_u16(b, 73);
+/// write_u32(c, 137); // approximate inverse of the fine structure constant!
+/// # }
+/// ```
+#[macro_export]
+macro_rules! mut_array_refs {
+    ( $arr:expr, $( $len:expr ),* ) => {{
+        {
+            #[inline]
+            #[allow(unused_assignments)]
+            unsafe fn as_arrays<T>(a: &mut [T; $( $len + )* 0 ]) -> ( $( &mut [T; $len], )* ) {
+                let mut p = a.as_mut_ptr();
+                ( $( {
+                    let aref = &mut *(p as *mut [T; $len]);
+                    p = p.offset($len as isize);
+                    aref
+                } ),* )
+            }
+            let input = $arr;
+            unsafe {
+                as_arrays(input)
+            }
+        }
+    }}
+}
+
+/// You can use `array_mut_ref` to generate a mutable array reference
+/// to a subset of a sliceable bit of data (which could be an array,
+/// or a slice, or a Vec).
+///
+/// **Panics** if the slice is out of bounds.
+///
+/// ```
+/// #[macro_use]
+/// extern crate arrayref;
+///
+/// fn write_u16(bytes: &mut [u8; 2], num: u16) {
+///      bytes[0] = num as u8;
+///      bytes[1] = (num >> 8) as u8;
+/// }
+/// // ...
+/// # fn main() {
+/// let mut data = [0,1,2,3,4,0,6,7,8,9];
+/// write_u16(array_mut_ref![data,0,2], 1);
+/// write_u16(array_mut_ref![data,2,2], 5);
+/// assert_eq!(*array_ref![data,0,4], [1,0,5,0]);
+/// *array_mut_ref![data,4,5] = [4,3,2,1,0];
+/// assert_eq!(data, [1,0,5,0,4,3,2,1,0,9]);
+/// # }
+/// ```
+#[macro_export]
+macro_rules! array_mut_ref {
+    ($arr:expr, $offset:expr, $len:expr) => {{
+        {
+            #[inline]
+            unsafe fn as_array<T>(slice: &mut [T]) -> &mut [T; $len] {
+                &mut *(slice.as_mut_ptr() as *mut [_; $len])
+            }
+            let offset = $offset;
+            let slice = &mut $arr[offset..offset + $len];
+            unsafe {
+                as_array(slice)
+            }
+        }
+    }}
+}
+
+
+#[cfg(test)]
+mod test {
+
+extern crate quickcheck;
+
+use std::vec::Vec;
+
+// use super::*;
+
+#[test]
+#[should_panic]
+fn checks_bounds() {
+    let foo: [u8; 11] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+    let bar = array_ref!(foo, 1, 11);
+    println!("I am checking that I can dereference bar[0] = {}", bar[0]);
+}
+
+#[test]
+fn simple_case_works() {
+    fn check(expected: [u8; 3], actual: &[u8; 3]) {
+        for (e, a) in (&expected).iter().zip(actual.iter()) {
+            assert_eq!(e, a)
+        }
+    }
+    let mut foo: [u8; 11] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+    {
+        let bar = array_ref!(foo, 2, 3);
+        check([2, 3, 4], bar);
+    }
+    check([0, 1, 2], array_ref!(foo, 0, 3));
+    fn zero2(x: &mut [u8; 2]) {
+        x[0] = 0;
+        x[1] = 0;
+    }
+    zero2(array_mut_ref!(foo, 8, 2));
+    check([0, 0, 10], array_ref!(foo, 8, 3));
+}
+
+
+#[test]
+fn check_array_ref_5() {
+    fn f(data: Vec<u8>, offset: usize) -> quickcheck::TestResult {
+        if data.len() < offset + 5 {
+            return quickcheck::TestResult::discard();
+        }
+        let out = array_ref!(data, offset, 5);
+        quickcheck::TestResult::from_bool(out.len() == 5)
+    }
+    quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult);
+}
+
+#[test]
+fn check_array_ref_out_of_bounds_5() {
+    fn f(data: Vec<u8>, offset: usize) -> quickcheck::TestResult {
+        if data.len() >= offset + 5 {
+            return quickcheck::TestResult::discard();
+        }
+        quickcheck::TestResult::must_fail(move || {
+            array_ref!(data, offset, 5);
+        })
+    }
+    quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult);
+}
+
+#[test]
+fn check_array_mut_ref_7() {
+    fn f(mut data: Vec<u8>, offset: usize) -> quickcheck::TestResult {
+        if data.len() < offset + 7 {
+            return quickcheck::TestResult::discard();
+        }
+        let out = array_mut_ref!(data, offset, 7);
+        out[6] = 3;
+        quickcheck::TestResult::from_bool(out.len() == 7)
+    }
+    quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult);
+}
+
+
+#[test]
+fn check_array_mut_ref_out_of_bounds_32() {
+    fn f(mut data: Vec<u8>, offset: usize) -> quickcheck::TestResult {
+        if data.len() >= offset + 32 {
+            return quickcheck::TestResult::discard();
+        }
+        quickcheck::TestResult::must_fail(move || {
+            array_mut_ref!(data, offset, 32);
+        })
+    }
+    quickcheck::quickcheck(f as fn(Vec<u8>, usize) -> quickcheck::TestResult);
+}
+
+
+#[test]
+fn test_5_array_refs() {
+    let mut data: [usize; 128] = [0; 128];
+    for i in 0..128 {
+        data[i] = i;
+    }
+    let data = data;
+    let (a,b,c,d,e) = array_refs!(&data, 1, 14, 3, 100, 10);
+    assert_eq!(a.len(), 1 as usize);
+    assert_eq!(b.len(), 14 as usize);
+    assert_eq!(c.len(), 3 as usize);
+    assert_eq!(d.len(), 100 as usize);
+    assert_eq!(e.len(), 10 as usize);
+    assert_eq!(a, array_ref![data, 0, 1]);
+    assert_eq!(b, array_ref![data, 1, 14]);
+    assert_eq!(c, array_ref![data, 15, 3]);
+    assert_eq!(e, array_ref![data, 118, 10]);
+}
+
+
+#[test]
+fn test_5_mut_xarray_refs() {
+    let mut data: [usize; 128] = [0; 128];
+    {
+        // temporarily borrow the data to modify it.
+        let (a,b,c,d,e) = mut_array_refs!(&mut data, 1, 14, 3, 100, 10);
+        assert_eq!(a.len(), 1 as usize);
+        assert_eq!(b.len(), 14 as usize);
+        assert_eq!(c.len(), 3 as usize);
+        assert_eq!(d.len(), 100 as usize);
+        assert_eq!(e.len(), 10 as usize);
+        *a = [1; 1];
+        *b = [14; 14];
+        *c = [3; 3];
+        *d = [100; 100];
+        *e = [10; 10];
+    }
+    assert_eq!(&[1;1], array_ref![data, 0, 1]);
+    assert_eq!(&[14;14], array_ref![data, 1, 14]);
+    assert_eq!(&[3;3], array_ref![data, 15, 3]);
+    assert_eq!(&[10;10], array_ref![data, 118, 10]);
+}
+
+} // mod test
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{".gitlab-ci.yml":"dfbe8fcda3a10c658667ea934358eae2189f7c711e3cff710fba47615b80c75f",".travis.yml":"a2f3133877d5c4b9a7bbbff6baa7773800243ff2e1e58a06203c4568afe3a305","CODE_OF_CONDUCT.md":"9a7bc3fdffac1288f51485e70a910a4e9de1260a64fbe894f60ad73b3386dda9","Cargo.toml":"3a98883b13c1a173040be8f56823d99ad386a6f6af9b132409ee73abf3216f37","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","Makefile":"61a649ecb55115ba0f357215eb322fa6676ce163ca20bff59d7c5e275aa37035","README.md":"d4dba8ed8b388c1e24bcaaa0f0e75a0830885d6db9bedc9630591a180c744f73","RELEASES.md":"1bc2465747601bb73792db0522dd65811c48344bf3dfe4647403a9e02b52c0ad","book/src/SUMMARY.md":"362b6457309da979003cbd447fe24be43ac62bfee1aab764b41b43d21451cdf9","book/src/bail-and-ensure.md":"08fb463570143ec6568189468f1f54a7210b0a1ad66a57f7f7c36619831b4d72","book/src/custom-fail.md":"d4b1501201f9c54637bc40a2413e333f6f7d4fcfc8e3de74bf40d48eca0d4e41","book/src/derive-fail.md":"69916338286f970ae6709fb309bd4d80c321fea10b927f14efe402e3c0a5fdc9","book/src/error-errorkind.md":"40663de622bfb89a3dedcf6e093ec61eb1ab704d512d725e33f66aec38911757","book/src/error-msg.md":"2ab003bde8e88e0e3b9d1559d95e84b0ca7068522e324235bc4b2fdb88996d51","book/src/error.md":"c978778e7986e5febfb37e635525053ef73c534e4b6e9fc25deb576fdbdc111d","book/src/fail.md":"fab53bd4c0ad9a70809a95221c6c6b7103130b1f399a91bef9b963a8c924e210","book/src/guidance.md":"614cb85ae32c2b59119cd1db7eea008e50b051563c15ba1305f312fa2eeb3ac0","book/src/howto.md":"e18744011f5cc5779f5bb981ebd10f0af440c98398b2eb5af0ee27b9662ee410","book/src/intro.md":"eeb23e1ac3ccf75c4779603662910e96df647a02c73665a206dcc34c56d77eaf","book/src/use-error.md":"a7f91e06eb676318da04a56e4b31c73dd7db888d43c215e1534a5bc415e98258","build-docs.sh":"27b611219773192b9f972b2054522481fd5c2c9419c155535f58d05bfc31fffe","examples/bail_ensure.rs":"fffc71e41f9fbbc2a7db453ef20779716007ed6bbb01e45fbcefb1e073745ecc","examples/simple.rs":"7a5fc0673b6bb5bd3716416a6545f7ff471d182292a2c8424cf18bc4a72f6936","src/backtrace/internal.rs":"3fc4943061d4396c855571f134cd922f428cbe930689c8191376867b729d7b08","src/backtrace/mod.rs":"df3a348300775182c2780c542f119c989a6004cff841d817bdf7b93eef9a0dd3","src/box_std.rs":"224f3e3f48ad217ba34a54a62f608f9cba3ce95b176558684706c2f7fe72ce72","src/compat.rs":"97ed4fa49ac80c915b384b29a1bf678430cf1ea8ea61aa794a6014a1c3217762","src/context.rs":"ec6407ce720bbb92219b02500647e1e72c9e1dca3bbb8d67b4231c81f60d1157","src/error/error_impl.rs":"df9f904ee1e7d3aeb18ea5de7ea2fb38f9b6f500244093fa253036f066a785ea","src/error/error_impl_small.rs":"e6cbbd4d12e8eec1bd0f15713d33a0e525599268c9316dd40240eb7cd9e19a9d","src/error/mod.rs":"48e9504329eb894a37b5d800ae448acfdc15ef2acf5f73f402867ca6719197de","src/error_message.rs":"2a45a3bd142e6547fc5da27c182fb690e2990de11db2a9b8ce63e50d9c589997","src/lib.rs":"c09752622baad0ef9d8d7deb828f2e3e48afe8231802350f2612fa1b4dce4cd4","src/macros.rs":"79c2acd8127a8dc2a3a8dab9bc7f72db549990d297120fcd9dd80a416781dd55","src/result_ext.rs":"8088c3cb1481e81891014c99cc0f1b75f25a2f212b52ae856583e4c1f1901d09","src/small_error.rs":"652bf6ff2016d8e31b6ee709ad3efaff9f4e96d5aec8120ea3986a0bb8f57c54","src/sync_failure.rs":"a92a2e8b416196322718a4e7e1262f5b1b0a6be47b849d9a7e1050c1d33490db","travis.sh":"836024f7a56fdbe24a99ab9ce9350713831f4375a60f02593aad6637b766a330"},"package":"7efb22686e4a466b1ec1a15c2898f91fa9cb340452496dca654032de20ff95b9"}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/.gitlab-ci.yml
@@ -0,0 +1,10 @@
+image: "rust:latest"
+
+pages:
+  script:
+    - sh ./build-docs.sh
+  artifacts:
+    paths:
+      - public
+  only:
+    - master
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/.travis.yml
@@ -0,0 +1,11 @@
+language: rust
+rust:
+    - 1.18.0
+    - stable
+    - beta
+    - nightly
+cache: cargo
+script:
+  - cargo test
+  - cargo test --features backtrace
+  - cargo check --no-default-features
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/CODE_OF_CONDUCT.md
@@ -0,0 +1,46 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at boats@mozilla.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
+
+[homepage]: http://contributor-covenant.org
+[version]: http://contributor-covenant.org/version/1/4/
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/Cargo.toml
@@ -0,0 +1,33 @@
+# 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 = "failure"
+version = "0.1.2"
+authors = ["Without Boats <boats@mozilla.com>"]
+description = "Experimental error handling abstraction."
+homepage = "https://boats.gitlab.io/failure"
+documentation = "https://docs.rs/failure"
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/rust-lang-nursery/failure"
+[dependencies.backtrace]
+version = "0.3.3"
+optional = true
+
+[dependencies.failure_derive]
+version = "0.1.2"
+optional = true
+
+[features]
+default = ["std", "derive"]
+derive = ["failure_derive"]
+std = ["backtrace"]
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/LICENSE-APACHE
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+	http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/LICENSE-MIT
@@ -0,0 +1,23 @@
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/Makefile
@@ -0,0 +1,15 @@
+all: test
+.PHONY: all
+
+test: 
+	@echo TEST DEFAULT FEATURES
+	@cargo test --all
+	@echo TEST WITH BACKTRACE
+	@cargo test --features backtrace --all
+	@echo TEST NO DEFAULT FEATURES
+	@cargo check --no-default-features --all
+.PHONY: test
+
+check:
+	@cargo check --all
+.PHONY: check
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/README.md
@@ -0,0 +1,119 @@
+# failure - a new error management story
+
+[![Build Status](https://travis-ci.org/rust-lang-nursery/failure.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/failure)
+[![Latest Version](https://img.shields.io/crates/v/failure.svg)](https://crates.io/crates/failure)
+[![docs](https://docs.rs/failure/badge.svg)](https://docs.rs/failure)
+
+`failure` is designed to make it easier to manage errors in Rust. It is
+intended to replace error management based on `std::error::Error` with a new
+system based on lessons learned over the past several years, including those
+learned from experience with quick-error and error-chain.
+
+`failure` provides two core components:
+
+* `Fail`: A new trait for custom error types.
+* `Error`: A struct which any type that implements `Fail` can be cast into.
+
+## Evolution
+
+Failure is currently evolving as a library.  First of all there is work going
+on in Rust itself to [fix the error trait](https://github.com/rust-lang/rfcs/pull/2504)
+secondarily the original plan for Failure towards 1.0 is unlikely to happen
+in the current form.
+
+As such the original master branch towards 1.0 of failure was removed and
+master now represents the future iteration steps of 0.1 until it's clear
+what happens in the stdlib.
+
+The original 1.0 branch can be found in [evolution/1.0](https://github.com/rust-lang-nursery/failure/tree/evolution/1.0).
+
+## Example
+
+```rust
+extern crate serde;
+extern crate toml;
+
+#[macro_use] extern crate failure;
+#[macro_use] extern crate serde_derive;
+
+use std::collections::HashMap;
+use std::path::PathBuf;
+use std::str::FromStr;
+
+use failure::Error;
+
+// This is a new error type that you've created. It represents the ways a
+// toolchain could be invalid.
+//
+// The custom derive for Fail derives an impl of both Fail and Display.
+// We don't do any other magic like creating new types.
+#[derive(Debug, Fail)]
+enum ToolchainError {
+    #[fail(display = "invalid toolchain name: {}", name)]
+    InvalidToolchainName {
+        name: String,
+    },
+    #[fail(display = "unknown toolchain version: {}", version)]
+    UnknownToolchainVersion {
+        version: String,
+    }
+}
+
+pub struct ToolchainId {
+    // ... etc
+}
+
+impl FromStr for ToolchainId {
+    type Err = ToolchainError;
+
+    fn from_str(s: &str) -> Result<ToolchainId, ToolchainError> {
+        // ... etc
+    }
+}
+
+pub type Toolchains = HashMap<ToolchainId, PathBuf>;
+
+// This opens a toml file containing associations between ToolchainIds and
+// Paths (the roots of those toolchains).
+//
+// This could encounter an io Error, a toml parsing error, or a ToolchainError,
+// all of them will be thrown into the special Error type
+pub fn read_toolchains(path: PathBuf) -> Result<Toolchains, Error>
+{
+    use std::fs::File;
+    use std::io::Read;
+
+    let mut string = String::new();
+    File::open(path)?.read_to_string(&mut string)?;
+
+    let toml: HashMap<String, PathBuf> = toml::from_str(&string)?;
+
+    let toolchains = toml.iter().map(|(key, path)| {
+        let toolchain_id = key.parse()?;
+        Ok((toolchain_id, path))
+    }).collect::<Result<Toolchains, ToolchainError>>()?;
+
+    Ok(toolchains)
+}
+```
+
+## Requirements
+
+Both failure and failure_derive are intended to compile on all stable versions
+of Rust newer than 1.18.0, as well as the latest beta and the latest nightly.
+If either crate fails to compile on any version newer than 1.18.0, please open
+an issue.
+
+failure is **no_std** compatible, though some aspects of it (primarily the
+`Error` type) will not be available in no_std mode.
+
+## License
+
+failure is licensed under the terms of the MIT License or the Apache License
+2.0, at your choosing.
+
+## Code of Conduct
+
+Contribution to the failure crate is organized under the terms of the
+Contributor Covenant, the maintainer of failure, @withoutboats, promises to
+intervene to uphold that code of conduct.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/RELEASES.md
@@ -0,0 +1,17 @@
+# Version 0.1.1
+
+- Add a `Causes` iterator, which iterates over the causes of a failure. Can be
+  accessed through the `Fail::causes` or `Error::causes` methods.
+- Add the `bail!` macro, which "throws" from the function.
+- Add the `ensure!` macro, which is like an "assert" which throws instead of
+  panicking.
+- The derive now supports a no_std mode.
+- The derive is re-exported from `failure` by default, so that users do not
+  have to directly depend on `failure_derive`.
+- Add a impl of `From<D> for Context<D>`, allowing users to `?` the `D` type to
+  produce a `Context<D>` (for cases where there is no further underlying
+  error).
+
+# Version 0.1.0
+
+- Initial version.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/book/src/SUMMARY.md
@@ -0,0 +1,13 @@
+# Summary
+
+- [failure](./intro.md)
+- [How to use failure](./howto.md)
+    - [The Fail trait](./fail.md)
+    - [Deriving Fail](./derive-fail.md)
+    - [The Error type](./error.md)
+    - [`bail!` and `ensure!`](./bail-and-ensure.md)
+- [Patterns & Guidance](./guidance.md)
+    - [Strings as errors](./error-msg.md)
+    - [A Custom Fail type](./custom-fail.md)
+    - [Using the Error type](./use-error.md)
+    - [An Error and ErrorKind pair](./error-errorkind.md)
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/book/src/bail-and-ensure.md
@@ -0,0 +1,18 @@
+# `bail!` and `ensure!`
+
+If you were a fan of the `bail!` and ensure! macros from error-chain, good news. failure has a version of these macros as well.
+
+The `bail!` macro returns an error immediately, based on a format string. The `ensure!` macro additionally takes a conditional, and returns the error only if that conditional is false. You can think of `bail!` and `ensure!` as being analogous to `panic!` and `assert!`, but throwing errors instead of panicking.
+
+`bail!` and `ensure!` macros are useful when you are prototyping and you want to write your custom errors later. It is also the simplest example of using the failure crate.
+
+## Example
+```rust
+#[macro_use] extern crate failure;
+
+fn safe_cast_to_unsigned(n:i32) -> Result<u32, error::Failure>
+{
+    ensure!(n>=0, "number cannot be smaller than 0!");
+    (u32) n
+}
+```
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/book/src/custom-fail.md
@@ -0,0 +1,75 @@
+# A Custom Fail type
+
+This pattern is a way to define a new kind of failure. Defining a new kind of
+failure can be an effective way of representing an error for which you control
+all of the possible failure cases. It has several advantages:
+
+1. You can enumerate exactly all of the possible failures that can occur in
+this context.
+2. You have total control over the representation of the failure type.
+3. Callers can destructure your error without any sort of downcasting.
+
+To implement this pattern, you should define your own type that implements
+`Fail`. You can use the [custom derive][derive-fail] to make this easier. For
+example:
+
+```rust
+#[derive(Fail, Debug)]
+#[fail(display = "Input was invalid UTF-8")]
+pub struct Utf8Error;
+```
+
+This type can become as large and complicated as is appropriate to your use
+case. It can be an enum with a different variant for each possible error, and
+it can carry data with more precise information about the error. For example:
+
+```rust
+#[derive(Fail, Debug)]
+#[fail(display = "Input was invalid UTF-8 at index {}", index)]
+pub struct Utf8Error {
+    index: usize,
+}
+```
+
+## When might you use this pattern?
+
+If you need to raise an error that doesn't come from one of your dependencies,
+this is a great pattern to use.
+
+You can also use this pattern in conjunction with [using `Error`][use-error] or
+defining an [Error and ErrorKind pair][error-errorkind]. Those functions which
+are "pure logic" and have a very constrained set of errors (such as parsing
+simple formats) might each return a different custom Fail type, and then the
+function which merges them all together, does IO, and so on, would return a
+more complex type like `Error` or your custom Error/ErrorKind.
+
+## Caveats on this pattern
+
+When you have a dependency which returns a different error type, often you will
+be inclined to add it as a variant on your own error type. When you do that,
+you should tag the underlying error as the `#[fail(cause)]` of your error:
+
+```rust
+#[derive(Fail, Debug)]
+pub enum MyError {
+    #[fail(display = "Input was invalid UTF-8 at index {}", _0)]
+    Utf8Error(usize),
+    #[fail(display = "{}", _0)]
+    Io(#[fail(cause)] io::Error),
+}
+```
+
+Up to a limit, this design can work. However, it has some problems:
+
+- It can be hard to be forward compatible with new dependencies that raise
+  their own kinds of errors in the future.
+- It defines a 1-1 relationship between a variant of the error and an
+  underlying error.
+
+Depending on your use case, as your function grows in complexity, it can be
+better to transition to [using Error][use-error] or [defining an Error &
+ErrorKind pair][error-errorkind].
+
+[derive-fail]: ./derive-fail.html
+[use-error]: ./use-error.html
+[error-errorkind]: ./error-errorkind.html
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/book/src/derive-fail.md
@@ -0,0 +1,177 @@
+# Deriving `Fail`
+
+Though you can implement `Fail` yourself, we also provide a derive macro to
+generate the impl for you. To get access to this macro, you must tag the extern
+crate declaration with `#[macro_use]`, as in:
+
+```rust
+#[macro_use] extern crate failure;
+```
+
+In its smallest form, deriving Fail looks like this:
+
+```rust
+#[macro_use] extern crate failure;
+
+use std::fmt;
+
+#[derive(Fail, Debug)]
+struct MyError;
+
+impl fmt::Display for MyError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "An error occurred.")
+    }
+}
+```
+
+All failures need to implement `Display`, so we have added an impl of
+Display. However, implementing `Display` is much more boilerplate than
+implementing `Fail` - this is why we support deriving `Display` for you.
+
+## Deriving `Display`
+
+You can derive an implementation of `Display` with a special attribute:
+
+```rust
+#[macro_use] extern crate failure;
+
+#[derive(Fail, Debug)]
+#[fail(display = "An error occurred.")]
+struct MyError;
+```
+
+This attribute will cause the `Fail` derive to also generate an impl of
+`Display`, so that you don't have to implement one yourself.
+
+### String interpolation
+
+String literals are not enough for error messages in many cases. Often, you
+want to include parts of the error value interpolated into the message. You can
+do this with failure using the same string interpolation syntax as Rust's
+formatting and printing macros:
+
+```rust
+#[macro_use] extern crate failure;
+
+#[derive(Fail, Debug)]
+#[fail(display = "An error occurred with error code {}. ({})", code, message)]
+struct MyError {
+    code: i32,
+    message: String,
+}
+```
+
+Note that unlike code that would appear in a method, this does not use
+something like `self.code` or `self.message`; it just uses the field names
+directly. This is because of a limitation in Rust's current attribute syntax.
+As a result, you can only interpolate fields through the derivation; you cannot
+perform method calls or use other arbitrary expressions.
+
+### Tuple structs
+
+With regular structs, you can use the name of the field in string
+interpolation. When deriving Fail for a tuple struct, you might expect to use
+the numeric index to refer to fields `0`, `1`, et cetera. However, a compiler
+limitation prevents this from parsing today.
+
+For the time being, tuple field accesses in the display attribute need to be
+prefixed with an underscore:
+
+```rust
+#[macro_use] extern crate failure;
+
+#[derive(Fail, Debug)]
+#[fail(display = "An error occurred with error code {}.", _0)]
+struct MyError(i32);
+
+
+#[derive(Fail, Debug)]
+#[fail(display = "An error occurred with error code {} ({}).", _0, _1)]
+struct MyOtherError(i32, String);
+```
+
+### Enums
+
+Implementing Display is also supported for enums by applying the attribute to
+each variant of the enum, rather than to the enum as a whole. The Display impl
+will match over the enum to generate the correct error message. For example:
+
+```rust
+#[macro_use] extern crate failure;
+
+#[derive(Fail, Debug)]
+enum MyError {
+    #[fail(display = "{} is not a valid version.", _0)]
+    InvalidVersion(u32),
+    #[fail(display = "IO error: {}", error)]
+    IoError { error: io::Error },
+    #[fail(display = "An unknown error has occurred.")]
+    UnknownError,
+}
+```
+
+## Overriding `backtrace`
+
+The backtrace method will be automatically overridden if the type contains a
+field with the type `Backtrace`. This works for both structs and enums.
+
+```rust
+#[macro_use] extern crate failure;
+
+use failure::Backtrace;
+
+/// MyError::backtrace will return a reference to the backtrace field
+#[derive(Fail, Debug)]
+#[fail(display = "An error occurred.")]
+struct MyError {
+    backtrace: Backtrace,
+}
+
+/// MyEnumError::backtrace will return a reference to the backtrace only if it
+/// is Variant2, otherwise it will return None.
+#[derive(Fail, Debug)]
+enum MyEnumError {
+    #[fail(display = "An error occurred.")]
+    Variant1,
+    #[fail(display = "A different error occurred.")]
+    Variant2(Backtrace),
+}
+```
+
+This happens automatically; no other annotations are necessary. It only works
+if the type is named Backtrace, and not if you have created an alias for the
+Backtrace type.
+
+## Overriding `cause`
+
+In contrast to `backtrace`, the cause cannot be determined by type name alone
+because it could be any type which implements `Fail`. For this reason, if your
+error has an underlying cause field, you need to annotate that field with
+the `#[fail(cause)]` attribute.
+
+This can be used in fields of enums as well as structs.
+
+
+```rust
+#[macro_use] extern crate failure;
+
+use std::io;
+
+/// MyError::cause will return a reference to the io_error field
+#[derive(Fail, Debug)]
+#[fail(display = "An error occurred.")]
+struct MyError {
+    #[fail(cause)] io_error: io::Error,
+}
+
+/// MyEnumError::cause will return a reference only if it is Variant2,
+/// otherwise it will return None.
+#[derive(Fail, Debug)]
+enum MyEnumError {
+    #[fail(display = "An error occurred.")]
+    Variant1,
+    #[fail(display = "A different error occurred.")]
+    Variant2(#[fail(cause)] io::Error),
+}
+```
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/book/src/error-errorkind.md
@@ -0,0 +1,143 @@
+# An Error and ErrorKind pair
+
+This pattern is the most robust way to manage errors - and also the most high
+maintenance. It combines some of the advantages of the [using Error][use-error]
+pattern and the [custom failure][custom-fail] patterns, while avoiding some of
+the disadvantages each of those patterns has:
+
+1. Like `Error`, this is forward compatible with new underlying kinds of
+errors from your dependencies.
+2. Like custom failures, this pattern allows you to specify additional information about the error that your dependencies don't give you.
+3. Like `Error`, it can be easier to convert underlying errors from dependency
+into this type than for custom failures.
+4. Like custom failures, users can gain some information about the error
+without downcasting.
+
+The pattern is to create two new failure types: an `Error` and an `ErrorKind`,
+and to leverage [the `Context` type][context-api] provided by failure.
+
+```rust
+#[derive(Debug)]
+struct MyError {
+    inner: Context<MyErrorKind>,
+}
+
+#[derive(Copy, Clone, Eq, PartialEq, Debug, Fail)]
+enum MyErrorKind {
+    // A plain enum with no data in any of its variants
+    //
+    // For example:
+    #[fail(display = "A contextual error message.")]
+    OneVariant,
+    // ...
+}
+```
+
+Unfortunately, it is not easy to correctly derive `Fail` for `MyError` so that
+it delegates things to its inner `Context`. You should write those impls
+yourself:
+
+```rust
+impl Fail for MyError {
+    fn cause(&self) -> Option<&Fail> {
+        self.inner.cause()
+    }
+
+    fn backtrace(&self) -> Option<&Backtrace> {
+        self.inner.backtrace()
+    }
+}
+
+impl Display for MyError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        Display::fmt(&self.inner, f)
+    }
+}
+```
+
+You should also provide some conversions and accessors, to go between a
+Context, your ErrorKind, and your Error:
+
+```rust
+impl MyError {
+    pub fn kind(&self) -> MyErrorKind {
+        *self.inner.get_context()
+    }
+}
+
+impl From<MyErrorKind> for MyError {
+    fn from(kind: MyErrorKind) -> MyError {
+        MyError { inner: Context::new(kind) }
+    }
+}
+
+impl From<Context<MyErrorKind>> for MyError {
+    fn from(inner: Context<MyErrorKind>) -> MyError {
+        MyError { inner: inner }
+    }
+}
+```
+
+With this code set up, you can use the context method from failure to apply
+your ErrorKind to `Result`s in underlying libraries:
+
+```rust
+use failure::ResultExt;
+perform_some_io().context(ErrorKind::NetworkFailure)?;
+```
+
+You can also directly throw `ErrorKind` without an underlying error when
+appropriate:
+
+```rust
+Err(ErrorKind::DomainSpecificError)?
+```
+
+### What should your ErrorKind contain?
+
+Your error kind probably should not carry data - and if it does, it should only
+carry stateless data types that provide additional information about what the
+`ErrorKind` means. This way, your `ErrorKind` can be `Eq`, making it
+easy to use as a way of comparing errors.
+
+Your ErrorKind is a way of providing information about what errors mean
+appropriate to the level of abstraction that your library operates at. As some
+examples:
+
+- If your library expects to read from the user's `Cargo.toml`, you might have
+  a `InvalidCargoToml` variant, to capture what `io::Error` and `toml::Error`
+  mean in the context of your library.
+- If your library does both file system activity and network activity, you
+  might have `Filesystem` and `Network` variants, to divide up the `io::Error`s
+  between which system in particular failed.
+
+Exactly what semantic information is appropriate depends entirely on what this
+bit of code is intended to do.
+
+## When might you use this pattern?
+
+The most likely use cases for this pattern are mid-layer which perform a
+function that requires many dependencies, and that are intended to be used in
+production. Libraries with few dependencies do not need to manage many
+underlying error types and can probably suffice with a simpler [custom
+failure][custom-fail]. Applications that know they are almost always just going
+to log these errors can get away with [using the Error type][use-error] rather
+than managing extra context information.
+
+That said, when you need to provide the most expressive information about an
+error possible, this can be a good approach.
+
+## Caveats on this pattern
+
+This pattern is the most involved pattern documented in this book. It involves
+a lot of boilerplate to set up (which may be automated away eventually), and it
+requires you to apply a contextual message to every underlying error that is
+thrown inside your code. It can be a lot of work to maintain this pattern.
+
+Additionally, like the Error type, the Context type may use an allocation and a
+dynamic dispatch internally. If you know this is too expensive for your use
+case, you should not use this pattern.
+
+[use-error]: ./use-error.html
+[custom-fail]: ./custom-fail.html
+[context-api]: https://boats.gitlab.io/failure/doc/failure/struct.Context.html
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/book/src/error-msg.md
@@ -0,0 +1,59 @@
+# Strings as errors
+
+This pattern is a way to create new errors without doing much set up. It is
+definitely the sloppiest way to throw errors. It can be great to use this
+during prototyping, but maybe not in the final product.
+
+String types do not implement `Fail`, which is why there are two adapters to
+create failures from a string:
+
+- [`failure::err_msg`][err-msg-api] - a function that takes a displayable
+  type and creates a failure from it. This can take a String or a string
+  literal.
+- [`format_err!`][format-err-api] - a macro with string interpolation, similar
+  to `format!` or `println!`.
+
+```rust
+fn check_range(x: usize, range: Range<usize>) -> Result<usize, Error> {
+    if x < range.start {
+        return Err(format_err!("{} is below {}", x, range.start));
+    }
+    if x >= range.end {
+        return Err(format_err!("{} is above {}", x, range.end));
+    }
+    Ok(x)
+}
+```
+
+If you're going to use strings as errors, we recommend [using
+`Error`][use-error] as your error type, rather than `ErrorMessage`; this way,
+if some of your strings are `String` and some are `&'static str`, you don't
+need worry about merging them into a single string type.
+
+## When might you use this pattern?
+
+This pattern is the easiest to set up and get going with, so it can be great
+when prototyping or spiking out an early design. It can also be great when you
+know that an error variant is extremely uncommon, and that there is really no
+way to handle it other than to log the error and move on.
+
+## Caveats on this pattern
+
+If you are writing a library you plan to publish to crates.io, this is probably
+not a good way to handle errors, because it doesn't give your clients very much
+control. For public, open source libraries, we'd recommend using [custom
+failures][custom-fail] in the cases where you would use a string as an error.
+
+This pattern can also be very brittle. If you ever want to branch over which
+error was returned, you would have to match on the exact contents of the
+string. If you ever change the string contents, that will silently break that
+match.
+
+For these reasons, we strongly recommend against using this pattern except for
+prototyping and when you know the error is just going to get logged or reported
+to the users.
+
+[custom-fail]: ./custom-fail.html
+[use-error]: ./use-error.html
+[err-msg-api]: https://boats.gitlab.io/failure/doc/failure/fn.err_msg.html
+[format-err-api]: https://boats.gitlab.io/failure/doc/failure/macro.format_err.html
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/book/src/error.md
@@ -0,0 +1,100 @@
+# The `Error` type
+
+In addition to the trait `Fail`, failure provides a type called `Error`. Any
+type that implements `Fail` can be cast into `Error` using From and Into, which
+allows users to throw errors using `?` which have different types, if the
+function returns an `Error`.
+
+For example:
+
+```rust
+// Something you can deserialize
+#[derive(Deserialize)]
+struct Object {
+    ...
+}
+
+impl Object {
+    // This throws both IO Errors and JSON Errors, but they both get converted
+    // into the Error type.
+    fn from_file(path: &Path) -> Result<Object, Error> {
+        let mut string = String::new();
+        File::open(path)?.read_to_string(&mut string)?;
+        let object = json::from_str(&string)?;
+        Ok(object)
+    }
+}
+```
+
+## Causes and Backtraces
+
+The Error type has all of the methods from the Fail trait, with a few notable
+differences. Most importantly, the cause and backtrace methods on Error do not
+return Options - an Error is *guaranteed* to have a cause and a backtrace.
+
+```rust
+// Both methods are guaranteed to return an &Fail and an &Backtrace
+println!("{}, {}", error.cause(), error.backtrace())
+```
+
+An `Error`'s cause is always the failure that was cast into this `Error`.
+That failure may have further underlying causes. Unlike Fail, this means that
+the cause of an Error will have the same Display representation as the Error
+itself.
+
+As to the error's guaranteed backtrace, when the conversion into the Error type
+happens, if the underlying failure does not provide a backtrace, a new
+backtrace is constructed pointing to that conversion point (rather than the
+origin of the error). This construction only happens if there is no underlying
+backtrace; if it does have a backtrace no new backtrace is constructed.
+
+## Downcasting
+
+The Error type also supports downcasting into any concrete Fail type. It can be
+downcast by reference or by value - when downcasting by value, the return type
+is `Result<T, Error>`, allowing you to get the error back out of it.
+
+```rust
+match error.downcast::<io::Error>() {
+    Ok(io_error)    => { ... }
+    Err(error)      => { ... }
+}
+```
+
+## Implementation details
+
+`Error` is essentially a trait object, but with some fanciness it may generate
+and store the backtrace if the underlying failure did not have one. In
+particular, we use a custom dynamically sized type to store the backtrace
+information inline with the trait object data.
+
+```rust
+struct Error {
+    // Inner<Fail> is a dynamically sized type
+    inner: Box<Inner<Fail>>,
+}
+
+struct Inner<F: Fail> {
+    backtrace: Backtrace,
+    failure: F,
+}
+```
+
+By storing the backtrace in the heap this way, we avoid increasing the size of
+the Error type beyond that of two non-nullable pointers. This keeps the size of
+the `Result` type from getting too large, avoiding having a negative impact on
+the "happy path" of returning Ok. For example, a `Result<(), Error>` should be
+represented as a pair of nullable pointers, with the null case representing
+`Ok`. Similar optimizations can be applied to values up to at least a pointer
+in size.
+
+To emphasize: Error is intended for use cases where the error case is
+considered relatively uncommon. This optimization makes the overhead of an
+error less than it otherwise would be for the Ok branch. In cases where errors
+are going to be returned extremely frequently, returning this Error type is
+probably not appropriate, but you should benchmark in those cases.
+
+(As a rule of thumb: if you're not sure if you can afford to have a trait
+object, you probably *can* afford it. Heap allocations are not nearly as cheap
+as stack allocations, but they're cheap enough that you can almost always
+afford them.)
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/book/src/fail.md
@@ -0,0 +1,152 @@
+# The `Fail` trait
+
+The `Fail` trait is a replacement for [`std::error::Error`][stderror]. It has
+been designed to support a number of operations:
+
+- Because it is bound by both `Debug` and `Display`, any failure can be
+  printed in two ways.
+- It has both a `backtrace` and a `cause` method, allowing users to get
+  information about how the error occurred.
+- It supports wrapping failures in additional contextual information.
+- Because it is bound by `Send` and `Sync`, failures can be moved and share
+  between threads easily.
+- Because it is bound by `'static`, the abstract `Fail` trait object can be
+  downcast into concrete types.
+
+Every new error type in your code should implement `Fail`, so it can be
+integrated into the entire system built around this trait. You can manually
+implement `Fail` yourself, or you can use the derive for `Fail` defined
+in a separate crate and documented [here][derive-docs].
+
+Implementors of this trait are called 'failures'.
+
+## Cause
+
+Often, an error type contains (or could contain) another underlying error type
+which represents the "cause" of this error - for example, if your custom error
+contains an `io::Error`, that is the cause of your error.
+
+The cause method on the `Fail` trait allows all errors to expose their underlying
+cause - if they have one - in a consistent way. Users can loop over the chain
+of causes, for example, getting the entire series of causes for an error:
+
+```rust
+// Assume err is a type that implements `Fail`
+let mut fail: &Fail = err;
+
+while let Some(cause) = fail.cause() {
+    println!("{}", cause);
+
+    // Make `fail` the reference to the cause of the previous fail, making the
+    // loop "dig deeper" into the cause chain.
+    fail = cause;
+}
+```
+
+Because `&Fail` supports downcasting, you can also inspect causes in more
+detail if you are expecting a certain failure:
+
+```rust
+while let Some(cause) = fail.cause() {
+
+    if let Some(err) = cause.downcast_ref::<io::Error>() {
+        // treat io::Error specially
+    } else {
+        // fallback case
+    }
+
+    fail = cause;
+}
+```
+
+For convenience an iterator is also provided:
+
+```rust
+// Assume err is a type that implements `Fail`
+let mut fail: &Fail = err;
+
+for cause in fail.iter_causes() {
+    println!("{}", cause);
+}
+```
+
+## Backtraces
+
+Errors can also generate a backtrace when they are constructed, helping you
+determine the place the error was generated and the function chain that called into
+that. Like causes, this is entirely optional - the authors of each failure
+have to decide if generating a backtrace is appropriate in their use case.
+
+The backtrace method allows all errors to expose their backtrace if they have
+one. This enables a consistent method for getting the backtrace from an error:
+
+```rust
+// We don't even know the type of the cause, but we can still get its
+// backtrace.
+if let Some(bt) = err.cause().and_then(|cause| cause.backtrace()) {
+    println!("{}", bt)
+}
+```
+
+The `Backtrace` type exposed by `failure` is different from the `Backtrace` exposed
+by the [backtrace crate][backtrace-crate], in that it has several optimizations:
+
+- It has a `no_std` compatible form which will never be generated (because
+  backtraces require heap allocation), and should be entirely compiled out.
+- It will not be generated unless the `RUST_BACKTRACE` environment variable has
+  been set at runtime.
+- Symbol resolution is delayed until the backtrace is actually printed, because
+  this is the most expensive part of generating a backtrace.
+
+## Context
+
+Often, the libraries you are using will present error messages that don't
+provide very helpful information about what exactly has gone wrong. For
+example, if an `io::Error` says that an entity was "Not Found," that doesn't
+communicate much about what specific file was missing - if it even was a file
+(as opposed to a directory for example).
+
+You can inject additional context to be carried with this error value,
+providing semantic information about the nature of the error appropriate to the
+level of abstraction that the code you are writing operates at. The `context`
+method on `Fail` takes any displayable value (such as a string) to act as
+context for this error.
+
+Using the `ResultExt` trait, you can also get `context` as a convenient method on
+`Result` directly. For example, suppose that your code attempted to read from a
+Cargo.toml. You can wrap the `io::Error`s that occur with additional context
+about what operation has failed:
+
+```rust
+use failure::ResultExt;
+
+let mut file = File::open(cargo_toml_path).context("Missing Cargo.toml")?;
+file.read_to_end(&buffer).context("Could not read Cargo.toml")?;
+```
+
+The `Context` object also has a constructor that does not take an underlying
+error, allowing you to create ad hoc Context errors alongside those created by
+applying the `context` method to an underlying error.
+
+## Backwards compatibility
+
+We've taken several steps to make transitioning from `std::error` to `failure` as
+painless as possible.
+
+First, there is a blanket implementation of `Fail` for all types that implement
+`std::error::Error`, as long as they are `Send + Sync + 'static`. If you are
+dealing with a library that hasn't shifted to `Fail`, it is automatically
+compatible with `failure` already.
+
+Second, `Fail` contains a method called `compat`, which produces a type that
+implements `std::error::Error`. If you have a type that implements `Fail`, but
+not the older `Error` trait, you can call `compat` to get a type that does
+implement that trait (for example, if you need to return a `Box<Error>`).
+
+The biggest hole in our backwards compatibility story is that you cannot
+implement `std::error::Error` and also override the backtrace and cause methods
+on `Fail`. We intend to enable this with specialization when it becomes stable.
+
+[derive-docs]: https://boats.gitlab.io/failure/derive-fail.html
+[stderror]: https://doc.rust-lang.org/std/error/trait.Error.html
+[backtrace-crate]: http://alexcrichton.com/backtrace-rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/book/src/guidance.md
@@ -0,0 +1,24 @@
+# Patterns & Guidance
+
+failure is not a "one size fits all" approach to error management. There are
+multiple patterns that emerge from the API this library provides, and users
+need to determine which pattern makes sense for them. This section documents
+some patterns and how users might use them.
+
+In brief, these are the patterns documented here:
+
+- **[Strings as errors](./error-msg.md):** Using strings as your error
+  type. Good for prototyping.
+- **[A Custom Fail type](./custom-fail.md):** Defining a custom type to be
+  your error type. Good for APIs where you control all or more of the
+  possible failures.
+- **[Using the Error type](./use-error.md):** Using the Error type to pull
+  together multiple failures of different types. Good for applications and
+  APIs that know the error won't be inspected much more.
+- **[An Error and ErrorKind pair](./error-errorkind.md):** Using both a
+  custom error type and an ErrorKind enum to create a very robust error
+  type. Good for public APIs in large crates.
+
+(Though each of these items identifies a use case which this pattern would be
+good for, in truth each of them can be applied in various contexts. Its up to
+you to decide what makes the most sense for your particular use case.)
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/book/src/howto.md
@@ -0,0 +1,8 @@
+# How to use failure
+
+This section of the documentation is about how the APIs exposed in failure can
+be used. It is organized around the major APIs of failure:
+
+- **[The Fail trait](./fail.md):** The primary abstraction provided by failure.
+- **[Deriving Fail](./derive-fail.md):** A custom derive for the Fail trait.
+- **[The Error type](./error.md):** A convenient wrapper around any Fail type.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/book/src/intro.md
@@ -0,0 +1,77 @@
+# failure
+
+This is the documentation for the failure crate, which provides a system for
+creating and managing errors in Rust. Additional documentation is found here:
+
+* [API documentation][api]
+* [failure source code][repo]
+
+[api]: https://boats.gitlab.io/failure/doc/failure
+[repo]: https://github.com/rust-lang-nursery/failure
+
+```rust
+extern crate serde;
+extern crate toml;
+
+#[macro_use] extern crate failure;
+#[macro_use] extern crate serde_derive;
+
+use std::collections::HashMap;
+use std::path::PathBuf;
+use std::str::FromStr;
+
+use failure::Error;
+
+// This is a new error type that you've created. It represents the ways a
+// toolchain could be invalid.
+//
+// The custom derive for Fail derives an impl of both Fail and Display.
+// We don't do any other magic like creating new types.
+#[derive(Debug, Fail)]
+enum ToolchainError {
+    #[fail(display = "invalid toolchain name: {}", name)]
+    InvalidToolchainName {
+        name: String,
+    },
+    #[fail(display = "unknown toolchain version: {}", version)]
+    UnknownToolchainVersion {
+        version: String,
+    }
+}
+
+pub struct ToolchainId {
+    // ... etc
+}
+
+impl FromStr for ToolchainId {
+    type Err = ToolchainError;
+
+    fn from_str(s: &str) -> Result<ToolchainId, ToolchainError> {
+        // ... etc
+    }
+}
+
+pub type Toolchains = HashMap<ToolchainId, PathBuf>;
+
+// This opens a toml file containing associations between ToolchainIds and
+// Paths (the roots of those toolchains).
+//
+// This could encounter an io Error, a toml parsing error, or a ToolchainError,
+// all of them will be thrown into the special Error type
+pub fn read_toolchains(path: PathBuf) -> Result<Toolchains, Error>
+{
+    use std::fs::File;
+    use std::io::Read;
+
+    let mut string = String::new();
+    File::open(path)?.read_to_string(&mut string)?;
+
+    let toml: HashMap<String, PathBuf> = toml::from_str(&string)?;
+
+    let toolchains = toml.iter().map(|(key, path)| {
+        let toolchain_id = key.parse()?;
+        Ok((toolchain_id, path))
+    }).collect::<Result<Toolchains, ToolchainError>>()?;
+
+    Ok(toolchains)
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/book/src/use-error.md
@@ -0,0 +1,66 @@
+# Use the `Error` type
+
+This pattern is a way to manage errors when you have multiple kinds of failure
+that could occur during a single function. It has several distinct advantages:
+
+1. You can start using it without defining any of your own failure types.
+2. All types that implement `Fail` can be thrown into the `Error` type using
+the `?` operator.
+3. As you start adding new dependencies with their own failure types, you can
+start throwing them without making a breaking change.
+
+To use this pattern, all you need to do is return `Result<_, Error>` from your
+functions:
+
+```rust
+use std::io;
+use std::io::BufRead;
+
+use failure::Error;
+use failure::err_msg;
+
+fn my_function() -> Result<(), Error> {
+    let stdin = io::stdin();
+
+    for line in stdin.lock().lines() {
+        let line = line?;
+
+        if line.chars().all(|c| c.is_whitespace()) {
+            break
+        }
+
+        if !line.starts_with("$") {
+            return Err(format_err!("Input did not begin with `$`"));
+        }
+
+        println!("{}", &line[1..]);
+    }
+
+    Ok(())
+}
+```
+
+## When might you use this pattern?
+
+This pattern is very effective when you know you will usually not need to
+destructure the error this function returns. For example:
+
+- When prototyping.
+- When you know you are going to log this error, or display it to the user,
+  either all of the time or nearly all of the time.
+- When it would be impractical for this API to report more custom context for
+  the error (e.g. because it is a trait that doesn't want to add a new Error
+  associated type).
+
+## Caveats on this pattern
+
+There are two primary downsides to this pattern:
+
+- The `Error` type allocates. There are cases where this would be too
+  expensive. In those cases you should use a [custom failure][custom-fail].
+- You cannot recover more information about this error without downcasting. If
+  your API needs to express more contextual information about the error, use
+  the [Error and ErrorKind][error-errorkind] pattern.
+
+[custom-fail]: ./custom-fail.html
+[error-errorkind]: ./error-errorkind.html
new file mode 100755
--- /dev/null
+++ b/third_party/rust/failure/build-docs.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+mkdir public
+cargo doc --no-deps
+cargo install mdbook --no-default-features
+mdbook build ./book
+cp -r ./target/doc/ ./public
+cp -r ./book/book/* ./public
+find $PWD/public | grep "\.html\$"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/examples/bail_ensure.rs
@@ -0,0 +1,26 @@
+#[macro_use]
+extern crate failure;
+
+use failure::Error;
+
+fn bailer() -> Result<(), Error> {
+    // bail!("ruh roh");
+    bail!("ruh {}", "roh");
+}
+
+fn ensures() -> Result<(), Error> {
+    ensure!(true, "true is false");
+    ensure!(false, "false is false");
+    Ok(())
+}
+
+fn main() {
+    match bailer() {
+        Ok(_) => println!("ok"),
+        Err(e) => println!("{}", e),
+    }
+    match ensures() {
+        Ok(_) => println!("ok"),
+        Err(e) => println!("{}", e),
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/examples/simple.rs
@@ -0,0 +1,22 @@
+#[macro_use]
+extern crate failure;
+
+use failure::Fail;
+
+#[derive(Debug, Fail)]
+#[fail(display = "my error")]
+struct MyError;
+
+#[derive(Debug, Fail)]
+#[fail(display = "my wrapping error")]
+struct WrappingError(#[fail(cause)] MyError);
+
+fn bad_function() -> Result<(), WrappingError> {
+    Err(WrappingError(MyError))
+}
+
+fn main() {
+    for cause in Fail::iter_causes(&bad_function().unwrap_err()) {
+        println!("{}", cause);
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/src/backtrace/internal.rs
@@ -0,0 +1,130 @@
+use std::cell::UnsafeCell;
+use std::env;
+use std::ffi::OsString;
+use std::fmt;
+use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
+use std::sync::Mutex;
+
+pub use super::backtrace::Backtrace;
+
+const GENERAL_BACKTRACE: &str = "RUST_BACKTRACE";
+const FAILURE_BACKTRACE: &str = "RUST_FAILURE_BACKTRACE";
+
+pub(super) struct InternalBacktrace {
+    backtrace: Option<MaybeResolved>,
+}
+
+struct MaybeResolved {
+    resolved: Mutex<bool>,
+    backtrace: UnsafeCell<Backtrace>,
+}
+
+unsafe impl Send for MaybeResolved {}
+unsafe impl Sync for MaybeResolved {}
+
+impl InternalBacktrace {
+    pub(super) fn new() -> InternalBacktrace {
+        static ENABLED: AtomicUsize = ATOMIC_USIZE_INIT;
+
+        match ENABLED.load(Ordering::SeqCst) {
+            0 => {
+                let enabled = is_backtrace_enabled(|var| env::var_os(var));
+                ENABLED.store(enabled as usize + 1, Ordering::SeqCst);
+                if !enabled {
+                    return InternalBacktrace { backtrace: None }
+                }
+            }
+            1 => return InternalBacktrace { backtrace: None },
+            _ => {}
+        }
+
+        InternalBacktrace {
+            backtrace: Some(MaybeResolved {
+                resolved: Mutex::new(false),
+                backtrace: UnsafeCell::new(Backtrace::new_unresolved()),
+            }),
+        }
+    }
+
+    pub(super) fn none() -> InternalBacktrace {
+        InternalBacktrace { backtrace: None }
+    }
+
+    pub(super) fn as_backtrace(&self) -> Option<&Backtrace> {
+        let bt = match self.backtrace {
+            Some(ref bt) => bt,
+            None => return None,
+        };
+        let mut resolved = bt.resolved.lock().unwrap();
+        unsafe {
+            if !*resolved {
+                (*bt.backtrace.get()).resolve();
+                *resolved = true;
+            }
+            Some(&*bt.backtrace.get())
+        }
+    }
+
+    pub(super) fn is_none(&self) -> bool {
+        self.backtrace.is_none()
+    }
+}
+
+impl fmt::Debug for InternalBacktrace {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("InternalBacktrace")
+            .field("backtrace", &self.as_backtrace())
+            .finish()
+    }
+}
+
+fn is_backtrace_enabled<F: Fn(&str) -> Option<OsString>>(get_var: F) -> bool {
+    match get_var(FAILURE_BACKTRACE) {
+        Some(ref val) if val != "0" => true,
+        Some(ref val) if val == "0" => false,
+        _ => match get_var(GENERAL_BACKTRACE) {
+            Some(ref val) if val != "0" => true,
+            _                           => false,
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    const YEA: Option<&str> = Some("1");
+    const NAY: Option<&str> = Some("0");
+    const NOT_SET: Option<&str> = None;
+
+    macro_rules! test_enabled {
+        (failure: $failure:ident, general: $general:ident => $result:expr) => {{
+            assert_eq!(is_backtrace_enabled(|var| match var {
+                FAILURE_BACKTRACE   => $failure.map(OsString::from),
+                GENERAL_BACKTRACE   => $general.map(OsString::from),
+                _                   => panic!()
+            }), $result);
+        }}
+    }
+
+    #[test]
+    fn always_enabled_if_failure_is_set_to_yes() {
+        test_enabled!(failure: YEA, general: YEA => true);
+        test_enabled!(failure: YEA, general: NOT_SET => true);
+        test_enabled!(failure: YEA, general: NAY => true);
+    }
+
+    #[test]
+    fn never_enabled_if_failure_is_set_to_no() {
+        test_enabled!(failure: NAY, general: YEA => false);
+        test_enabled!(failure: NAY, general: NOT_SET => false);
+        test_enabled!(failure: NAY, general: NAY => false);
+    }
+
+    #[test]
+    fn follows_general_if_failure_is_not_set() {
+        test_enabled!(failure: NOT_SET, general: YEA => true);
+        test_enabled!(failure: NOT_SET, general: NOT_SET => false);
+        test_enabled!(failure: NOT_SET, general: NAY => false);
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/src/backtrace/mod.rs
@@ -0,0 +1,144 @@
+use core::fmt::{self, Debug, Display};
+
+macro_rules! with_backtrace { ($($i:item)*) => ($(#[cfg(all(feature = "backtrace", feature = "std"))]$i)*) }
+macro_rules! without_backtrace { ($($i:item)*) => ($(#[cfg(not(all(feature = "backtrace", feature = "std")))]$i)*) }
+
+without_backtrace! {
+    /// A `Backtrace`.
+    ///
+    /// This is an opaque wrapper around the backtrace provided by
+    /// libbacktrace. A variety of optimizations have been performed to avoid
+    /// unnecessary or ill-advised work:
+    ///
+    /// - If this crate is compiled in `no_std` compatible mode, `Backtrace`
+    ///   is an empty struct, and will be completely compiled away.
+    /// - If this crate is run without the `RUST_BACKTRACE` environmental
+    ///   variable enabled, the backtrace will not be generated at runtime.
+    /// - Even if a backtrace is generated, the most expensive part of
+    ///   generating a backtrace is symbol resolution. This backtrace does not
+    ///   perform symbol resolution until it is actually read (e.g. by
+    ///   printing it). If the Backtrace is never used for anything, symbols
+    ///   never get resolved.
+    ///
+    /// Even with these optimizations, including a backtrace in your failure
+    /// may not be appropriate to your use case. You are not required to put a
+    /// backtrace in a custom `Fail` type.
+    ///
+    /// > (We have detected that this crate was documented with no_std
+    /// > compatibility turned on. The version of this crate that has been
+    /// > documented here will never generate a backtrace.)
+    pub struct Backtrace {
+        _secret: (),
+    }
+
+    impl Backtrace {
+        /// Constructs a new backtrace. This will only create a real backtrace
+        /// if the crate is compiled in std mode and the `RUST_BACKTRACE`
+        /// environmental variable is activated.
+        ///
+        /// > (We have detected that this crate was documented with no_std
+        /// > compatibility turned on. The version of this crate that has been
+        /// > documented here will never generate a backtrace.)
+        pub fn new() -> Backtrace {
+            Backtrace { _secret: () }
+        }
+
+        #[cfg(feature = "std")]
+        pub(crate) fn none() -> Backtrace {
+            Backtrace { _secret: () }
+        }
+
+        #[cfg(feature = "std")]
+        pub(crate) fn is_none(&self) -> bool {
+            true
+        }
+    }
+
+    impl Default for Backtrace {
+        fn default() -> Backtrace {
+            Backtrace::new()
+        }
+    }
+
+    impl Debug for Backtrace {
+        fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
+            Ok(())
+        }
+    }
+
+    impl Display for Backtrace {
+        fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
+            Ok(())
+        }
+    }
+}
+
+with_backtrace! {
+    extern crate backtrace;
+
+    mod internal;
+
+    use self::internal::InternalBacktrace;
+
+    /// A `Backtrace`.
+    ///
+    /// This is an opaque wrapper around the backtrace provided by
+    /// libbacktrace. A variety of optimizations have been performed to avoid
+    /// unnecessary or ill-advised work:
+    ///
+    /// - If this crate is compiled in `no_std` compatible mode, `Backtrace`
+    ///   is an empty struct, and will be completely compiled away.
+    /// - If this crate is run without the `RUST_BACKTRACE` environmental
+    ///   variable enabled, the backtrace will not be generated at runtime.
+    /// - Even if a backtrace is generated, the most expensive part of
+    ///   generating a backtrace is symbol resolution. This backtrace does not
+    ///   perform symbol resolution until it is actually read (e.g. by
+    ///   printing it). If the Backtrace is never used for anything, symbols
+    ///   never get resolved.
+    ///
+    /// Even with these optimizations, including a backtrace in your failure
+    /// may not be appropriate to your use case. You are not required to put a
+    /// backtrace in a custom `Fail` type.
+    pub struct Backtrace {
+        internal: InternalBacktrace
+    }
+
+    impl Backtrace {
+        /// Constructs a new backtrace. This will only create a real backtrace
+        /// if the crate is compiled in std mode and the `RUST_BACKTRACE`
+        /// environmental variable is activated.
+        pub fn new() -> Backtrace {
+            Backtrace { internal: InternalBacktrace::new() }
+        }
+
+        pub(crate) fn none() -> Backtrace {
+            Backtrace { internal: InternalBacktrace::none() }
+        }
+
+        pub(crate) fn is_none(&self) -> bool {
+            self.internal.is_none()
+        }
+    }
+
+    impl Default for Backtrace {
+        fn default() -> Backtrace {
+            Backtrace::new()
+        }
+    }
+
+    impl Debug for Backtrace {
+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+            if let Some(bt) = self.internal.as_backtrace() {
+                bt.fmt(f)
+            } else { Ok(()) }
+        }
+    }
+
+    impl Display for Backtrace {
+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+            if let Some(bt) = self.internal.as_backtrace() {
+                bt.fmt(f)
+            } else { Ok(()) }
+        }
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/src/box_std.rs
@@ -0,0 +1,19 @@
+use std::error::Error;
+use std::fmt;
+use Fail;
+
+pub struct BoxStd(pub Box<Error + Send + Sync + 'static>);
+
+impl fmt::Display for BoxStd {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(&self.0, f)
+    }
+}
+
+impl fmt::Debug for BoxStd {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(&self.0, f)
+    }
+}
+
+impl Fail for BoxStd {}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/src/compat.rs
@@ -0,0 +1,47 @@
+use core::fmt::{self, Display};
+
+/// A compatibility wrapper around an error type from this crate.
+///
+/// `Compat` implements `std::error::Error`, allowing the types from this
+/// crate to be passed to interfaces that expect a type of that trait.
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default)]
+pub struct Compat<E> {
+    pub(crate) error: E,
+}
+
+impl<E: Display> Display for Compat<E> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        Display::fmt(&self.error, f)
+    }
+}
+
+impl<E> Compat<E> {
+    /// Unwraps this into the inner error.
+    pub fn into_inner(self) -> E {
+        self.error
+    }
+
+    /// Gets a reference to the inner error.
+    pub fn get_ref(&self) -> &E {
+        &self.error
+    }
+}
+
+with_std! {
+    use std::fmt::Debug;
+    use std::error::Error as StdError;
+
+    use Error;
+
+    impl<E: Display + Debug> StdError for Compat<E> {
+        fn description(&self) -> &'static str {
+            "An error has occurred."
+        }
+    }
+
+    impl From<Error> for Box<StdError> {
+        fn from(error: Error) -> Box<StdError> {
+            Box::new(Compat { error })
+        }
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/src/context.rs
@@ -0,0 +1,143 @@
+use core::fmt::{self, Debug, Display};
+
+use Fail;
+
+without_std! {
+    /// An error with context around it.
+    ///
+    /// The context is intended to be a human-readable, user-facing explanation for the
+    /// error that has occurred. The underlying error is not assumed to be end-user-relevant
+    /// information.
+    ///
+    /// The `Display` impl for `Context` only prints the human-readable context, while the
+    /// `Debug` impl also prints the underlying error.
+    pub struct Context<D: Display + Send + Sync + 'static> {
+        context: D,
+    }
+
+    impl<D: Display + Send + Sync + 'static> Context<D> {
+        /// Creates a new context without an underlying error message.
+        pub fn new(context: D) -> Context<D> {
+            Context { context }
+        }
+
+        /// Returns a reference to the context provided with this error.
+        pub fn get_context(&self) -> &D {
+            &self.context
+        }
+
+        pub(crate) fn with_err<E: Fail>(context: D, _: E) -> Context<D> {
+            Context { context }
+        }
+    }
+
+    impl<D: Display + Send + Sync + 'static> Fail for Context<D> { }
+
+    impl<D: Display + Send + Sync + 'static> Debug for Context<D> {
+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+            write!(f, "{}", self.context)
+        }
+    }
+
+    impl<D: Display + Send + Sync + 'static> Display for Context<D> {
+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+            write!(f, "{}", self.context)
+        }
+    }
+}
+
+with_std! {
+    use {Error, Backtrace};
+
+    /// An error with context around it.
+    ///
+    /// The context is intended to be a human-readable, user-facing explanation for the
+    /// error that has occurred. The underlying error is not assumed to be end-user-relevant
+    /// information.
+    ///
+    /// The `Display` impl for `Context` only prints the human-readable context, while the
+    /// `Debug` impl also prints the underlying error.
+    pub struct Context<D: Display + Send + Sync + 'static> {
+        context: D,
+        failure: Either<Backtrace, Error>,
+    }
+
+    impl<D: Display + Send + Sync + 'static> Context<D> {
+        /// Creates a new context without an underlying error message.
+        pub fn new(context: D) -> Context<D> {
+            let failure = Either::This(Backtrace::new());
+            Context { context, failure }
+        }
+
+        /// Returns a reference to the context provided with this error.
+        pub fn get_context(&self) -> &D {
+            &self.context
+        }
+
+        pub(crate) fn with_err<E: Into<Error>>(context: D, error: E) -> Context<D> {
+            let failure = Either::That(error.into());
+            Context { context, failure }
+        }
+    }
+
+    impl<D: Display + Send + Sync + 'static> Fail for Context<D> {
+        fn cause(&self) -> Option<&Fail> {
+            self.failure.as_cause()
+        }
+
+        fn backtrace(&self) -> Option<&Backtrace> {
+            Some(self.failure.backtrace())
+        }
+    }
+
+    impl<D: Display + Send + Sync + 'static> Debug for Context<D> {
+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+            write!(f, "{:?}\n\n{}", self.failure, self.context)
+        }
+    }
+
+    impl<D: Display + Send + Sync + 'static> Display for Context<D> {
+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+            write!(f, "{}", self.context)
+        }
+    }
+
+    enum Either<A, B> {
+        This(A),
+        That(B),
+    }
+
+    impl Either<Backtrace, Error> {
+        fn backtrace(&self) -> &Backtrace {
+            match *self {
+                Either::This(ref backtrace) => backtrace,
+                Either::That(ref error)     => error.backtrace(),
+            }
+        }
+
+        fn as_cause(&self) -> Option<&Fail> {
+            match *self {
+                Either::This(_)         => None,
+                Either::That(ref error) => Some(error.as_fail())
+            }
+        }
+    }
+
+    impl Debug for Either<Backtrace, Error> {
+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+            match *self {
+                Either::This(ref backtrace) => write!(f, "{:?}", backtrace),
+                Either::That(ref error)     => write!(f, "{:?}", error),
+            }
+        }
+    }
+}
+
+impl<D> From<D> for Context<D>
+where
+    D: Display + Send + Sync + 'static,
+{
+    fn from(display: D) -> Context<D> {
+        Context::new(display)
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/src/error/error_impl.rs
@@ -0,0 +1,59 @@
+use core::mem;
+use core::ptr;
+
+use Fail;
+use backtrace::Backtrace;
+
+pub(crate) struct ErrorImpl {
+    inner: Box<Inner<Fail>>,
+}
+
+struct Inner<F: ?Sized + Fail> {
+    backtrace: Backtrace,
+    pub(crate) failure: F,
+}
+
+impl<F: Fail> From<F> for ErrorImpl {
+    fn from(failure: F) -> ErrorImpl {
+        let inner: Inner<F> = {
+            let backtrace = if failure.backtrace().is_none() {
+                Backtrace::new()
+            } else { Backtrace::none() };
+            Inner { failure, backtrace }
+        };
+        ErrorImpl { inner: Box::new(inner) }
+    }
+}
+
+impl ErrorImpl {
+    pub(crate) fn failure(&self) -> &Fail {
+        &self.inner.failure
+    }
+
+    pub(crate) fn failure_mut(&mut self) -> &mut Fail {
+        &mut self.inner.failure
+    }
+
+    pub(crate) fn backtrace(&self) -> &Backtrace {
+        &self.inner.backtrace
+    }
+
+    pub(crate) fn downcast<T: Fail>(self) -> Result<T, ErrorImpl> {
+        let ret: Option<T> = self.failure().downcast_ref().map(|fail| {
+            unsafe {
+                // drop the backtrace
+                let _ = ptr::read(&self.inner.backtrace as *const Backtrace);
+                // read out the fail type
+                ptr::read(fail as *const T)
+            }
+        });
+        match ret {
+            Some(ret) => {
+                // forget self (backtrace is dropped, failure is moved
+                mem::forget(self);
+                Ok(ret)
+            }
+            _ => Err(self)
+        }
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/src/error/error_impl_small.rs
@@ -0,0 +1,132 @@
+use std::heap::{Heap, Alloc, Layout};
+
+use core::mem;
+use core::ptr;
+
+use Fail;
+use backtrace::Backtrace;
+
+pub(crate) struct ErrorImpl {
+    inner: &'static mut Inner,
+}
+
+// Dynamically sized inner value
+struct Inner {
+    backtrace: Backtrace,
+    vtable: *const VTable,
+    failure: FailData,
+}
+
+unsafe impl Send for Inner { }
+unsafe impl Sync for Inner { }
+
+extern {
+    type VTable;
+    type FailData;
+}
+
+#[allow(dead_code)]
+struct InnerRaw<F> {
+    header: InnerHeader,
+    failure: F,
+}
+
+#[allow(dead_code)]
+struct InnerHeader {
+    backtrace: Backtrace,
+    vtable: *const VTable,
+}
+
+struct TraitObject {
+    #[allow(dead_code)]
+    data: *const FailData,
+    vtable: *const VTable,
+}
+
+impl<F: Fail> From<F> for ErrorImpl {
+    fn from(failure: F) -> ErrorImpl {
+        let backtrace = if failure.backtrace().is_none() {
+            Backtrace::new()
+        } else {
+            Backtrace::none()
+        };
+
+        unsafe {
+            let vtable = mem::transmute::<_, TraitObject>(&failure as &Fail).vtable;
+
+            let ptr: *mut InnerRaw<F> = match Heap.alloc(Layout::new::<InnerRaw<F>>()) {
+                Ok(p)   => p as *mut InnerRaw<F>,
+                Err(e)  => Heap.oom(e),
+            };
+
+            // N.B. must use `ptr::write`, not `=`, to avoid dropping the contents of `*ptr`
+            ptr::write(ptr, InnerRaw {
+                header: InnerHeader {
+                    backtrace,
+                    vtable,
+                },
+                failure,
+            });
+
+            let inner: &'static mut Inner = mem::transmute(ptr);
+
+            ErrorImpl { inner }
+        }
+    }
+}
+
+impl ErrorImpl {
+    pub(crate) fn failure(&self) -> &Fail {
+        unsafe {
+            mem::transmute::<TraitObject, &Fail>(TraitObject {
+                data: &self.inner.failure as *const FailData,
+                vtable: self.inner.vtable,
+            })
+        }
+    }
+
+    pub(crate) fn failure_mut(&mut self) -> &mut Fail {
+        unsafe {
+            mem::transmute::<TraitObject, &mut Fail>(TraitObject {
+                data: &mut self.inner.failure as *const FailData,
+                vtable: self.inner.vtable,
+            })
+        }
+    }
+
+    pub(crate) fn backtrace(&self) -> &Backtrace {
+        &self.inner.backtrace
+    }
+
+    pub(crate) fn downcast<T: Fail>(self) -> Result<T, ErrorImpl> {
+        let ret: Option<T> = self.failure().downcast_ref().map(|fail| {
+            unsafe {
+                // drop the backtrace
+                let _ = ptr::read(&self.inner.backtrace as *const Backtrace);
+                // read out the fail type
+                ptr::read(fail as *const T)
+            }
+        });
+        match ret {
+            Some(ret) => {
+                // forget self (backtrace is dropped, failure is moved
+                mem::forget(self);
+                Ok(ret)
+            }
+            _ => Err(self)
+        }
+    }
+}
+
+
+#[cfg(test)]
+mod test {
+    use std::mem::size_of;
+
+    use super::ErrorImpl;
+
+    #[test]
+    fn assert_is_one_word() {
+        assert_eq!(size_of::<ErrorImpl>(), size_of::<usize>());
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/src/error/mod.rs
@@ -0,0 +1,228 @@
+use core::fmt::{self, Display, Debug};
+
+use {Causes, Fail};
+use backtrace::Backtrace;
+use context::Context;
+use compat::Compat;
+
+#[cfg(feature = "std")]
+use box_std::BoxStd;
+
+#[cfg_attr(feature = "small-error", path = "./error_impl_small.rs")]
+mod error_impl;
+use self::error_impl::ErrorImpl;
+
+#[cfg(feature = "std")]
+use std::error::Error as StdError;
+
+
+/// The `Error` type, which can contain any failure.
+///
+/// Functions which accumulate many kinds of errors should return this type.
+/// All failures can be converted into it, so functions which catch those
+/// errors can be tried with `?` inside of a function that returns this kind
+/// of error.
+///
+/// In addition to implementing `Debug` and `Display`, this type carries `Backtrace`
+/// information, and can be downcast into the failure that underlies it for
+/// more detailed inspection.
+pub struct Error {
+    imp: ErrorImpl,
+}
+
+impl<F: Fail> From<F> for Error {
+    fn from(failure: F) -> Error {
+        Error {
+            imp: ErrorImpl::from(failure)
+        }
+    }
+}
+
+impl Error {
+    /// Creates an `Error` from `Box<std::error::Error>`.
+    ///
+    /// This method is useful for comparability with code,
+    /// which does not use the `Fail` trait.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use std::error::Error as StdError;
+    /// use failure::Error;
+    ///
+    /// fn app_fn() -> Result<i32, Error> {
+    ///     let x = library_fn().map_err(Error::from_boxed_compat)?;
+    ///     Ok(x * 2)
+    /// }
+    ///
+    /// fn library_fn() -> Result<i32, Box<StdError + Sync + Send + 'static>> {
+    ///     Ok(92)
+    /// }
+    /// ```
+    #[cfg(feature = "std")]
+    pub fn from_boxed_compat(err: Box<StdError + Sync + Send + 'static>) -> Error {
+        Error::from(BoxStd(err))
+    }
+
+    /// Return a reference to the underlying failure that this `Error`
+    /// contains.
+    pub fn as_fail(&self) -> &Fail {
+        self.imp.failure()
+    }
+
+    /// Returns a reference to the underlying cause of this `Error`. Unlike the
+    /// method on `Fail`, this does not return an `Option`. The `Error` type
+    /// always has an underlying failure.
+    ///
+    /// This method has been deprecated in favor of the [Error::as_fail] method,
+    /// which does the same thing.
+    #[deprecated(since = "0.1.2", note = "please use 'as_fail()' method instead")]
+    pub fn cause(&self) -> &Fail {
+        self.as_fail()
+    }
+
+    /// Gets a reference to the `Backtrace` for this `Error`.
+    ///
+    /// If the failure this wrapped carried a backtrace, that backtrace will
+    /// be returned. Otherwise, the backtrace will have been constructed at
+    /// the point that failure was cast into the `Error` type.
+    pub fn backtrace(&self) -> &Backtrace {
+        self.imp.failure().backtrace().unwrap_or(&self.imp.backtrace())
+    }
+
+    /// Provides context for this `Error`.
+    ///
+    /// This can provide additional information about this error, appropriate
+    /// to the semantics of the current layer. That is, if you have a
+    /// lower-level error, such as an IO error, you can provide additional context
+    /// about what that error means in the context of your function. This
+    /// gives users of this function more information about what has gone
+    /// wrong.
+    ///
+    /// This takes any type that implements `Display`, as well as
+    /// `Send`/`Sync`/`'static`. In practice, this means it can take a `String`
+    /// or a string literal, or a failure, or some other custom context-carrying
+    /// type.
+    pub fn context<D: Display + Send + Sync + 'static>(self, context: D) -> Context<D> {
+        Context::with_err(context, self)
+    }
+
+    /// Wraps `Error` in a compatibility type.
+    ///
+    /// This type implements the `Error` trait from `std::error`. If you need
+    /// to pass failure's `Error` to an interface that takes any `Error`, you
+    /// can use this method to get a compatible type.
+    pub fn compat(self) -> Compat<Error> {
+        Compat { error: self }
+    }
+
+    /// Attempts to downcast this `Error` to a particular `Fail` type.
+    ///
+    /// This downcasts by value, returning an owned `T` if the underlying
+    /// failure is of the type `T`. For this reason it returns a `Result` - in
+    /// the case that the underlying error is of a different type, the
+    /// original `Error` is returned.
+    pub fn downcast<T: Fail>(self) -> Result<T, Error> {
+        self.imp.downcast().map_err(|imp| Error { imp })
+    }
+
+    /// Returns the "root cause" of this error - the last value in the
+    /// cause chain which does not return an underlying `cause`.
+    pub fn find_root_cause(&self) -> &Fail {
+        self.as_fail().find_root_cause()
+    }
+
+    /// Returns a iterator over the causes of this error with the cause
+    /// of the fail as the first item and the `root_cause` as the final item.
+    ///
+    /// Use `iter_chain` to also include the fail of this error itself.
+    pub fn iter_causes(&self) -> Causes {
+        self.as_fail().iter_causes()
+    }
+
+    /// Returns a iterator over all fails up the chain from the current
+    /// as the first item up to the `root_cause` as the final item.
+    ///
+    /// This means that the chain also includes the fail itself which
+    /// means that it does *not* start with `cause`.  To skip the outermost
+    /// fail use `iter_causes` instead.
+    pub fn iter_chain(&self) -> Causes {
+        self.as_fail().iter_chain()
+    }
+
+    /// Attempts to downcast this `Error` to a particular `Fail` type by
+    /// reference.
+    ///
+    /// If the underlying error is not of type `T`, this will return `None`.
+    pub fn downcast_ref<T: Fail>(&self) -> Option<&T> {
+        self.imp.failure().downcast_ref()
+    }
+
+    /// Attempts to downcast this `Error` to a particular `Fail` type by
+    /// mutable reference.
+    ///
+    /// If the underlying error is not of type `T`, this will return `None`.
+    pub fn downcast_mut<T: Fail>(&mut self) -> Option<&mut T> {
+        self.imp.failure_mut().downcast_mut()
+    }
+
+    /// Deprecated alias to `find_root_cause`.
+    #[deprecated(since = "0.1.2", note = "please use the 'find_root_cause()' method instead")]
+    pub fn root_cause(&self) -> &Fail {
+        ::find_root_cause(self.as_fail())
+    }
+
+    /// Deprecated alias to `iter_causes`.
+    #[deprecated(since = "0.1.2", note = "please use the 'iter_chain()' method instead")]
+    pub fn causes(&self) -> Causes {
+        Causes { fail: Some(self.as_fail()) }
+    }
+}
+
+impl Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        Display::fmt(&self.imp.failure(), f)
+    }
+}
+
+impl Debug for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let backtrace = self.imp.backtrace();
+        if backtrace.is_none() {
+            Debug::fmt(&self.imp.failure(), f)
+        } else {
+            write!(f, "{:?}\n\n{:?}", &self.imp.failure(), backtrace)
+        }
+    }
+}
+
+impl AsRef<Fail> for Error {
+    fn as_ref(&self) -> &Fail {
+        self.as_fail()
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use std::io;
+    use super::Error;
+
+    fn assert_just_data<T: Send + Sync + 'static>() { }
+
+    #[test]
+    fn assert_error_is_just_data() {
+        assert_just_data::<Error>();
+    }
+
+    #[test]
+    fn methods_seem_to_work() {
+        let io_error: io::Error = io::Error::new(io::ErrorKind::NotFound, "test");
+        let error: Error = io::Error::new(io::ErrorKind::NotFound, "test").into();
+        assert!(error.downcast_ref::<io::Error>().is_some());
+        let _: ::Backtrace = *error.backtrace();
+        assert_eq!(format!("{:?}", io_error), format!("{:?}", error));
+        assert_eq!(format!("{}", io_error), format!("{}", error));
+        drop(error);
+        assert!(true);
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/src/error_message.rs
@@ -0,0 +1,28 @@
+use core::fmt::{self, Display, Debug};
+
+use Fail;
+use Error;
+
+/// Constructs a `Fail` type from a string.
+///
+/// This is a convenient way to turn a string into an error value that
+/// can be passed around, if you do not want to create a new `Fail` type for
+/// this use case.
+pub fn err_msg<D: Display + Debug + Sync + Send + 'static>(msg: D) -> Error {
+    Error::from(ErrorMessage { msg })
+}
+
+/// A `Fail` type that just contains an error message. You can construct
+/// this from the `err_msg` function.
+#[derive(Debug)]
+struct ErrorMessage<D: Display + Debug + Sync + Send + 'static> {
+    msg: D,
+}
+
+impl<D: Display + Debug + Sync + Send + 'static> Fail for ErrorMessage<D> { }
+
+impl<D: Display + Debug + Sync + Send + 'static> Display for ErrorMessage<D> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        Display::fmt(&self.msg, f)
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/src/lib.rs
@@ -0,0 +1,289 @@
+//! An experimental new error-handling library. Guide-style introduction
+//! is available [here](https://boats.gitlab.io/failure/).
+//!
+//! The primary items exported by this library are:
+//!
+//! - `Fail`: a new trait for custom error types in Rust.
+//! - `Error`: a wrapper around `Fail` types to make it easy to coalesce them
+//!   at higher levels.
+//!
+//! As a general rule, library authors should create their own error types and
+//! implement `Fail` for them, whereas application authors should primarily
+//! deal with the `Error` type. There are exceptions to this rule, though, in
+//! both directions, and users should do whatever seems most appropriate to
+//! their situation.
+//!
+//! ## Backtraces
+//!
+//! Backtraces are disabled by default. To turn backtraces on, enable
+//! the `backtrace` Cargo feature and set the `RUST_BACKTRACE` environment
+//! variable to a non-zero value (this also enables backtraces for panics).
+//! Use the `RUST_FAILURE_BACKTRACE` variable to enable or disable backtraces
+//! for `failure` specifically.
+#![cfg_attr(not(feature = "std"), no_std)]
+#![deny(missing_docs)]
+#![deny(warnings)]
+#![cfg_attr(feature = "small-error", feature(extern_types, allocator_api))]
+
+macro_rules! with_std { ($($i:item)*) => ($(#[cfg(feature = "std")]$i)*) }
+macro_rules! without_std { ($($i:item)*) => ($(#[cfg(not(feature = "std"))]$i)*) }
+
+// Re-export libcore using an alias so that the macros can work without
+// requiring `extern crate core` downstream.
+#[doc(hidden)]
+pub extern crate core as _core;
+
+mod backtrace;
+#[cfg(feature = "std")]
+mod box_std;
+mod compat;
+mod context;
+mod result_ext;
+
+use core::any::TypeId;
+use core::fmt::{Debug, Display};
+
+pub use backtrace::Backtrace;
+pub use compat::Compat;
+pub use context::Context;
+pub use result_ext::ResultExt;
+
+#[cfg(feature = "failure_derive")]
+#[allow(unused_imports)]
+#[macro_use]
+extern crate failure_derive;
+
+#[cfg(feature = "failure_derive")]
+#[doc(hidden)]
+pub use failure_derive::*;
+
+with_std! {
+    extern crate core;
+
+    mod sync_failure;
+    pub use sync_failure::SyncFailure;
+
+    mod error;
+
+    use std::error::Error as StdError;
+
+    pub use error::Error;
+
+    /// A common result with an `Error`.
+    pub type Fallible<T> = Result<T, Error>;
+
+    mod macros;
+    mod error_message;
+    pub use error_message::err_msg;
+}
+
+/// The `Fail` trait.
+///
+/// Implementors of this trait are called 'failures'.
+///
+/// All error types should implement `Fail`, which provides a baseline of
+/// functionality that they all share.
+///
+/// `Fail` has no required methods, but it does require that your type
+/// implement several other traits:
+///
+/// - `Display`: to print a user-friendly representation of the error.
+/// - `Debug`: to print a verbose, developer-focused representation of the
+///   error.
+/// - `Send + Sync`: Your error type is required to be safe to transfer to and
+///   reference from another thread
+///
+/// Additionally, all failures must be `'static`. This enables downcasting.
+///
+/// `Fail` provides several methods with default implementations. Two of these
+/// may be appropriate to override depending on the definition of your
+/// particular failure: the `cause` and `backtrace` methods.
+///
+/// The `failure_derive` crate provides a way to derive the `Fail` trait for
+/// your type. Additionally, all types that already implement
+/// `std::error::Error`, and are also `Send`, `Sync`, and `'static`, implement
+/// `Fail` by a blanket impl.
+pub trait Fail: Display + Debug + Send + Sync + 'static {
+    /// Returns a reference to the underlying cause of this failure, if it
+    /// is an error that wraps other errors.
+    ///
+    /// Returns `None` if this failure does not have another error as its
+    /// underlying cause. By default, this returns `None`.
+    ///
+    /// This should **never** return a reference to `self`, but only return
+    /// `Some` when it can return a **different** failure. Users may loop
+    /// over the cause chain, and returning `self` would result in an infinite
+    /// loop.
+    fn cause(&self) -> Option<&Fail> {
+        None
+    }
+
+    /// Returns a reference to the `Backtrace` carried by this failure, if it
+    /// carries one.
+    ///
+    /// Returns `None` if this failure does not carry a backtrace. By
+    /// default, this returns `None`.
+    fn backtrace(&self) -> Option<&Backtrace> {
+        None
+    }
+
+    /// Provides context for this failure.
+    ///
+    /// This can provide additional information about this error, appropriate
+    /// to the semantics of the current layer. That is, if you have a
+    /// lower-level error, such as an IO error, you can provide additional context
+    /// about what that error means in the context of your function. This
+    /// gives users of this function more information about what has gone
+    /// wrong.
+    ///
+    /// This takes any type that implements `Display`, as well as
+    /// `Send`/`Sync`/`'static`. In practice, this means it can take a `String`
+    /// or a string literal, or another failure, or some other custom context-carrying
+    /// type.
+    fn context<D>(self, context: D) -> Context<D>
+    where
+        D: Display + Send + Sync + 'static,
+        Self: Sized,
+    {
+        Context::with_err(context, self)
+    }
+
+    /// Wraps this failure in a compatibility wrapper that implements
+    /// `std::error::Error`.
+    ///
+    /// This allows failures  to be compatible with older crates that
+    /// expect types that implement the `Error` trait from `std::error`.
+    fn compat(self) -> Compat<Self>
+    where
+        Self: Sized,
+    {
+        Compat { error: self }
+    }
+
+    #[doc(hidden)]
+    #[deprecated(since = "0.1.2", note = "please use the 'iter_causes()' method instead")]
+    fn causes(&self) -> Causes
+    where
+        Self: Sized,
+    {
+        Causes { fail: Some(self) }
+    }
+
+    #[doc(hidden)]
+    #[deprecated(since = "0.1.2", note = "please use the 'find_root_cause()' method instead")]
+    fn root_cause(&self) -> &Fail
+    where
+        Self: Sized,
+    {
+        find_root_cause(self)
+    }
+
+    #[doc(hidden)]
+    fn __private_get_type_id__(&self) -> TypeId {
+        TypeId::of::<Self>()
+    }
+}
+
+impl Fail {
+    /// Attempts to downcast this failure to a concrete type by reference.
+    ///
+    /// If the underlying error is not of type `T`, this will return `None`.
+    pub fn downcast_ref<T: Fail>(&self) -> Option<&T> {
+        if self.__private_get_type_id__() == TypeId::of::<T>() {
+            unsafe { Some(&*(self as *const Fail as *const T)) }
+        } else {
+            None
+        }
+    }
+
+    /// Attempts to downcast this failure to a concrete type by mutable
+    /// reference.
+    ///
+    /// If the underlying error is not of type `T`, this will return `None`.
+    pub fn downcast_mut<T: Fail>(&mut self) -> Option<&mut T> {
+        if self.__private_get_type_id__() == TypeId::of::<T>() {
+            unsafe { Some(&mut *(self as *mut Fail as *mut T)) }
+        } else {
+            None
+        }
+    }
+
+    /// Returns the "root cause" of this `Fail` - the last value in the
+    /// cause chain which does not return an underlying `cause`.
+    ///
+    /// If this type does not have a cause, `self` is returned, because
+    /// it is its own root cause.
+    ///
+    /// This is equivalent to iterating over `iter_causes()` and taking
+    /// the last item.
+    pub fn find_root_cause(&self) -> &Fail {
+        find_root_cause(self)
+    }
+
+    /// Returns a iterator over the causes of this `Fail` with the cause
+    /// of this fail as the first item and the `root_cause` as the final item.
+    ///
+    /// Use `iter_chain` to also include the fail itself.
+    pub fn iter_causes(&self) -> Causes {
+        Causes { fail: self.cause() }
+    }
+
+    /// Returns a iterator over all fails up the chain from the current
+    /// as the first item up to the `root_cause` as the final item.
+    ///
+    /// This means that the chain also includes the fail itself which
+    /// means that it does *not* start with `cause`.  To skip the outermost
+    /// fail use `iter_causes` instead.
+    pub fn iter_chain(&self) -> Causes {
+        Causes { fail: Some(self) }
+    }
+
+    /// Deprecated alias to `find_root_cause`.
+    #[deprecated(since = "0.1.2", note = "please use the 'find_root_cause()' method instead")]
+    pub fn root_cause(&self) -> &Fail {
+        find_root_cause(self)
+    }
+
+    /// Deprecated alias to `iter_causes`.
+    #[deprecated(since = "0.1.2", note = "please use the 'iter_chain()' method instead")]
+    pub fn causes(&self) -> Causes {
+        Causes { fail: Some(self) }
+    }
+}
+
+#[cfg(feature = "std")]
+impl<E: StdError + Send + Sync + 'static> Fail for E {}
+
+#[cfg(feature = "std")]
+impl Fail for Box<Fail> {
+    fn cause(&self) -> Option<&Fail> {
+        (**self).cause()
+    }
+
+    fn backtrace(&self) -> Option<&Backtrace> {
+        (**self).backtrace()
+    }
+}
+
+/// A iterator over the causes of a `Fail`
+pub struct Causes<'f> {
+    fail: Option<&'f Fail>,
+}
+
+impl<'f> Iterator for Causes<'f> {
+    type Item = &'f Fail;
+    fn next(&mut self) -> Option<&'f Fail> {
+        self.fail.map(|fail| {
+            self.fail = fail.cause();
+            fail
+        })
+    }
+}
+
+fn find_root_cause(mut fail: &Fail) -> &Fail {
+    while let Some(cause) = fail.cause() {
+        fail = cause;
+    }
+
+    fail
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/src/macros.rs
@@ -0,0 +1,51 @@
+/// Exits a function early with an `Error`.
+///
+/// The `bail!` macro provides an easy way to exit a function. `bail!(X)` is
+/// equivalent to writing:
+///
+/// ```rust,ignore
+/// return Err(format_err!(X))
+/// ```
+#[macro_export]
+macro_rules! bail {
+    ($e:expr) => {
+        return Err($crate::err_msg($e));
+    };
+    ($fmt:expr, $($arg:tt)+) => {
+        return Err($crate::err_msg(format!($fmt, $($arg)+)));
+    };
+}
+
+/// Exits a function early with an `Error` if the condition is not satisfied.
+///
+/// Similar to `assert!`, `ensure!` takes a condition and exits the function
+/// if the condition fails. Unlike `assert!`, `ensure!` returns an `Error`,
+/// it does not panic.
+#[macro_export]
+macro_rules! ensure {
+    ($cond:expr, $e:expr) => {
+        if !($cond) {
+            bail!($e);
+        }
+    };
+    ($cond:expr, $fmt:expr, $($arg:tt)+) => {
+        if !($cond) {
+            bail!($fmt, $($arg)+);
+        }
+    };
+}
+
+/// Constructs an `Error` using the standard string interpolation syntax.
+///
+/// ```rust
+/// #[macro_use] extern crate failure;
+///
+/// fn main() {
+///     let code = 101;
+///     let err = format_err!("Error code: {}", code);
+/// }
+/// ```
+#[macro_export]
+macro_rules! format_err {
+    ($($arg:tt)*) => { $crate::err_msg(format!($($arg)*)) }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/src/result_ext.rs
@@ -0,0 +1,203 @@
+use core::fmt::Display;
+
+use {Compat, Context, Fail};
+
+/// Extension methods for `Result`.
+pub trait ResultExt<T, E> {
+    /// Wraps the error in `Compat` to make it compatible with older error
+    /// handling APIs that expect `std::error::Error`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # fn main() {
+    /// #    tests::run_test();
+    /// # }
+    /// #
+    /// # #[cfg(not(all(feature = "std", feature = "derive")))] mod tests { pub fn run_test() { } }
+    /// #  
+    /// # #[cfg(all(feature = "std", feature = "derive"))] mod tests {
+    /// use std::error::Error;
+    /// # use std::fmt;
+    /// #
+    /// # extern crate failure;
+    /// #
+    /// # use tests::failure::ResultExt;
+    /// #
+    /// # #[derive(Debug)]
+    /// struct CustomError;
+    ///
+    /// impl Error for CustomError {
+    ///     fn description(&self) -> &str {
+    ///         "My custom error message"
+    ///     }
+    ///
+    ///     fn cause(&self) -> Option<&Error> {
+    ///         None
+    ///     }
+    /// }
+    /// #
+    /// # impl fmt::Display for CustomError {
+    /// #     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    /// #         write!(f, "{}", self.description())
+    /// #     }
+    /// # }
+    /// #
+    /// # pub fn run_test() {
+    ///
+    /// let x = (|| -> Result<(), failure::Error> {
+    ///     Err(CustomError).compat()?
+    /// })().with_context(|e| {
+    ///     format!("An error occured: {}", e)
+    /// }).unwrap_err();
+    ///
+    /// let x = format!("{}", x);
+    ///
+    /// assert_eq!(x, "An error occured: My custom error message");
+    /// # }
+    ///
+    /// # }
+    /// ```
+    fn compat(self) -> Result<T, Compat<E>>;
+
+    /// Wraps the error type in a context type.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #[cfg(all(feature = "std", feature = "derive"))]
+    /// # #[macro_use] extern crate failure;
+    /// #
+    /// # #[cfg(all(feature = "std", feature = "derive"))]
+    /// # #[macro_use] extern crate failure_derive;
+    /// #
+    /// # fn main() {
+    /// #    tests::run_test();
+    /// # }
+    /// #
+    /// # #[cfg(not(all(feature = "std", feature = "derive")))] mod tests { pub fn run_test() { } }
+    /// #
+    /// # #[cfg(all(feature = "std", feature = "derive"))] mod tests {
+    /// #
+    /// # use failure::{self, ResultExt};
+    /// #
+    /// #[derive(Fail, Debug)]
+    /// #[fail(display = "")]
+    /// struct CustomError;
+    /// #
+    /// # pub fn run_test() {
+    ///  
+    /// let x = (|| -> Result<(), failure::Error> {
+    ///     Err(CustomError)?
+    /// })().context(format!("An error occured")).unwrap_err();
+    ///
+    /// let x = format!("{}", x);
+    ///
+    /// assert_eq!(x, "An error occured");
+    /// # }
+    ///
+    /// # }
+    /// ```
+    fn context<D>(self, context: D) -> Result<T, Context<D>>
+    where
+        D: Display + Send + Sync + 'static;
+
+    /// Wraps the error type in a context type generated by looking at the
+    /// error value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #[cfg(all(feature = "std", feature = "derive"))]
+    /// # #[macro_use] extern crate failure;
+    /// #
+    /// # #[cfg(all(feature = "std", feature = "derive"))]
+    /// # #[macro_use] extern crate failure_derive;
+    /// #
+    /// # fn main() {
+    /// #    tests::run_test();
+    /// # }
+    /// #
+    /// # #[cfg(not(all(feature = "std", feature = "derive")))] mod tests { pub fn run_test() { } }
+    /// #
+    /// # #[cfg(all(feature = "std", feature = "derive"))] mod tests {
+    /// #
+    /// # use failure::{self, ResultExt};
+    /// #
+    /// #[derive(Fail, Debug)]
+    /// #[fail(display = "My custom error message")]
+    /// struct CustomError;
+    /// #
+    /// # pub fn run_test() {
+    ///
+    /// let x = (|| -> Result<(), failure::Error> {
+    ///     Err(CustomError)?
+    /// })().with_context(|e| {
+    ///     format!("An error occured: {}", e)
+    /// }).unwrap_err();
+    ///
+    /// let x = format!("{}", x);
+    ///
+    /// assert_eq!(x, "An error occured: My custom error message");
+    /// # }
+    ///
+    /// # }
+    /// ```
+    fn with_context<F, D>(self, f: F) -> Result<T, Context<D>>
+    where
+        F: FnOnce(&E) -> D,
+        D: Display + Send + Sync + 'static;
+}
+
+impl<T, E> ResultExt<T, E> for Result<T, E>
+where
+    E: Fail,
+{
+    fn compat(self) -> Result<T, Compat<E>> {
+        self.map_err(|err| err.compat())
+    }
+
+    fn context<D>(self, context: D) -> Result<T, Context<D>>
+    where
+        D: Display + Send + Sync + 'static,
+    {
+        self.map_err(|failure| failure.context(context))
+    }
+
+    fn with_context<F, D>(self, f: F) -> Result<T, Context<D>>
+    where
+        F: FnOnce(&E) -> D,
+        D: Display + Send + Sync + 'static,
+    {
+        self.map_err(|failure| {
+            let context = f(&failure);
+            failure.context(context)
+        })
+    }
+}
+
+with_std! {
+    use Error;
+
+    impl<T> ResultExt<T, Error> for Result<T, Error> {
+        fn compat(self) -> Result<T, Compat<Error>> {
+            self.map_err(|err| err.compat())
+        }
+
+        fn context<D>(self, context: D) -> Result<T, Context<D>> where
+            D: Display + Send + Sync + 'static
+        {
+            self.map_err(|failure| failure.context(context))
+        }
+
+        fn with_context<F, D>(self, f: F) -> Result<T, Context<D>> where
+            F: FnOnce(&Error) -> D,
+            D: Display + Send + Sync + 'static
+        {
+            self.map_err(|failure| {
+                let context = f(&failure);
+                failure.context(context)
+            })
+        }
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/src/small_error.rs
@@ -0,0 +1,264 @@
+use core::fmt::{self, Display, Debug};
+use std::heap::{Heap, Alloc, Layout};
+
+use core::mem;
+use core::ptr;
+
+use {Causes, Fail};
+use backtrace::Backtrace;
+use context::Context;
+use compat::Compat;
+
+/// The `Error` type, which can contain any failure.
+///
+/// Functions which accumulate many kinds of errors should return this type.
+/// All failures can be converted into it, so functions which catch those
+/// errors can be tried with `?` inside of a function that returns this kind
+/// of error.
+///
+/// In addition to implementing `Debug` and `Display`, this type carries `Backtrace`
+/// information, and can be downcast into the failure that underlies it for
+/// more detailed inspection.
+pub struct Error {
+    inner: &'static mut Inner,
+}
+
+// Dynamically sized inner value
+struct Inner {
+    backtrace: Backtrace,
+    vtable: *const VTable,
+    failure: FailData,
+}
+
+unsafe impl Send for Inner { }
+unsafe impl Sync for Inner { }
+
+extern {
+    type VTable;
+    type FailData;
+}
+
+struct InnerRaw<F> {
+    header: InnerHeader,
+    failure: F,
+}
+
+struct InnerHeader {
+    backtrace: Backtrace,
+    vtable: *const VTable,
+}
+
+struct TraitObject {
+    #[allow(dead_code)]
+    data: *const FailData,
+    vtable: *const VTable,
+}
+
+impl<F: Fail> From<F> for Error {
+    fn from(failure: F) -> Error {
+        let backtrace = if failure.backtrace().is_none() {
+            Backtrace::new()
+        } else {
+            Backtrace::none()
+        };
+
+        unsafe {
+            let vtable = mem::transmute::<_, TraitObject>(&failure as &Fail).vtable;
+
+            let ptr: *mut InnerRaw<F> = match Heap.alloc(Layout::new::<InnerRaw<F>>()) {
+                Ok(p)   => p as *mut InnerRaw<F>,
+                Err(e)  => Heap.oom(e),
+            };
+
+            // N.B. must use `ptr::write`, not `=`, to avoid dropping the contents of `*ptr`
+            ptr::write(ptr, InnerRaw {
+                header: InnerHeader {
+                    backtrace,
+                    vtable,
+                },
+                failure,
+            });
+
+            let inner: &'static mut Inner = mem::transmute(ptr);
+
+            Error { inner }
+        }
+    }
+}
+
+impl Inner {
+    fn failure(&self) -> &Fail {
+        unsafe {
+            mem::transmute::<TraitObject, &Fail>(TraitObject {
+                data: &self.failure as *const FailData,
+                vtable: self.vtable,
+            })
+        }
+    }
+
+    fn failure_mut(&mut self) -> &mut Fail {
+        unsafe {
+            mem::transmute::<TraitObject, &mut Fail>(TraitObject {
+                data: &mut self.failure as *const FailData,
+                vtable: self.vtable,
+            })
+        }
+    }
+}
+
+impl Error {
+    /// Returns a reference to the underlying cause of this `Error`. Unlike the
+    /// method on `Fail`, this does not return an `Option`. The `Error` type
+    /// always has an underlying failure.
+    pub fn cause(&self) -> &Fail {
+        self.inner.failure()
+    }
+
+    /// Gets a reference to the `Backtrace` for this `Error`.
+    ///
+    /// If the failure this wrapped carried a backtrace, that backtrace will
+    /// be returned. Otherwise, the backtrace will have been constructed at
+    /// the point that failure was cast into the `Error` type.
+    pub fn backtrace(&self) -> &Backtrace {
+        self.inner.failure().backtrace().unwrap_or(&self.inner.backtrace)
+    }
+
+    /// Provides context for this `Error`.
+    ///
+    /// This can provide additional information about this error, appropriate
+    /// to the semantics of the current layer. That is, if you have a
+    /// lower-level error, such as an IO error, you can provide additional context
+    /// about what that error means in the context of your function. This
+    /// gives users of this function more information about what has gone
+    /// wrong.
+    ///
+    /// This takes any type that implements `Display`, as well as
+    /// `Send`/`Sync`/`'static`. In practice, this means it can take a `String`
+    /// or a string literal, or a failure, or some other custom context-carrying
+    /// type.
+    pub fn context<D: Display + Send + Sync + 'static>(self, context: D) -> Context<D> {
+        Context::with_err(context, self)
+    }
+
+    /// Wraps `Error` in a compatibility type.
+    ///
+    /// This type implements the `Error` trait from `std::error`. If you need
+    /// to pass failure's `Error` to an interface that takes any `Error`, you
+    /// can use this method to get a compatible type.
+    pub fn compat(self) -> Compat<Error> {
+        Compat { error: self }
+    }
+
+    /// Attempts to downcast this `Error` to a particular `Fail` type.
+    ///
+    /// This downcasts by value, returning an owned `T` if the underlying
+    /// failure is of the type `T`. For this reason it returns a `Result` - in
+    /// the case that the underlying error is of a different type, the
+    /// original `Error` is returned.
+    pub fn downcast<T: Fail>(self) -> Result<T, Error> {
+        let ret: Option<T> = self.downcast_ref().map(|fail| {
+            unsafe {
+                // drop the backtrace
+                let _ = ptr::read(&self.inner.backtrace as *const Backtrace);
+                // read out the fail type
+                ptr::read(fail as *const T)
+            }
+        });
+        match ret {
+            Some(ret) => {
+                // forget self (backtrace is dropped, failure is moved
+                mem::forget(self);
+                Ok(ret)
+            }
+            _ => Err(self)
+        }
+    }
+
+    /// Returns the "root cause" of this error - the last value in the
+    /// cause chain which does not return an underlying `cause`.
+    pub fn root_cause(&self) -> &Fail {
+        ::find_root_cause(self.cause())
+    }
+
+    /// Attempts to downcast this `Error` to a particular `Fail` type by
+    /// reference.
+    ///
+    /// If the underlying error is not of type `T`, this will return `None`.
+    pub fn downcast_ref<T: Fail>(&self) -> Option<&T> {
+        self.inner.failure().downcast_ref()
+    }
+
+    /// Attempts to downcast this `Error` to a particular `Fail` type by
+    /// mutable reference.
+    ///
+    /// If the underlying error is not of type `T`, this will return `None`.
+    pub fn downcast_mut<T: Fail>(&mut self) -> Option<&mut T> {
+        self.inner.failure_mut().downcast_mut()
+    }
+
+    /// Returns a iterator over the causes of the `Error`, beginning with
+    /// the failure returned by the `cause` method and ending with the failure
+    /// returned by `root_cause`.
+    pub fn causes(&self) -> Causes {
+        Causes { fail: Some(self.cause()) }
+    }
+}
+
+impl Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        Display::fmt(self.inner.failure(), f)
+    }
+}
+
+impl Debug for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        if self.inner.backtrace.is_none() {
+            Debug::fmt(self.inner.failure(), f)
+        } else {
+            write!(f, "{:?}\n\n{:?}", self.inner.failure(), self.inner.backtrace)
+        }
+    }
+}
+
+impl Drop for Error {
+    fn drop(&mut self) {
+        unsafe {
+            let layout = {
+                let header = Layout::new::<InnerHeader>();
+                header.extend(Layout::for_value(self.inner.failure())).unwrap().0
+            };
+            Heap.dealloc(self.inner as *const _ as *const u8 as *mut u8, layout);
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use std::mem::size_of;
+    use std::io;
+
+    use super::Error;
+
+    #[test]
+    fn assert_error_is_just_data() {
+        fn assert_just_data<T: Send + Sync + 'static>() { }
+        assert_just_data::<Error>();
+    }
+
+    #[test]
+    fn assert_is_one_word() {
+        assert_eq!(size_of::<Error>(), size_of::<usize>());
+    }
+
+    #[test]
+    fn methods_seem_to_work() {
+        let io_error: io::Error = io::Error::new(io::ErrorKind::NotFound, "test");
+        let error: Error = io::Error::new(io::ErrorKind::NotFound, "test").into();
+        assert!(error.downcast_ref::<io::Error>().is_some());
+        let _: ::Backtrace = *error.backtrace();
+        assert_eq!(format!("{:?}", io_error), format!("{:?}", error));
+        assert_eq!(format!("{}", io_error), format!("{}", error));
+        drop(error);
+        assert!(true);
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/src/sync_failure.rs
@@ -0,0 +1,97 @@
+use Fail;
+use std::error::Error;
+use std::fmt::{self, Debug, Display};
+use std::sync::Mutex;
+
+/// Wrapper for `std` errors to make them `Sync`.
+///
+/// This exists to coerce existing types that are only `Error + Send +
+/// 'static` into a `Fail`-compatible representation, most notably for
+/// types generated by `error-chain`.
+///
+/// Unfortunately, this requires wrapping the error in a `Mutex`, which must
+/// be locked for every `Debug`/`Display`. Therefore, this should be
+/// something of a last resort in making the error work with `failure`.
+///
+pub struct SyncFailure<T> {
+    inner: Mutex<T>,
+}
+
+impl<E: Error + Send + 'static> SyncFailure<E> {
+    /// Wraps a non-`Sync` `Error` in order to make it implement `Fail`.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// extern crate failure;
+    ///
+    /// # use std::error::Error as StdError;
+    /// # use std::fmt::{self, Display};
+    /// use failure::{Error, SyncFailure};
+    /// use std::cell::RefCell;
+    ///
+    /// #[derive(Debug)]
+    /// struct NonSyncError {
+    ///     // RefCells are non-Sync, so structs containing them will be
+    ///     // non-Sync as well.
+    ///     count: RefCell<usize>,
+    /// }
+    ///
+    /// // implement Display/Error for NonSyncError...
+    /// #
+    /// # impl StdError for NonSyncError {
+    /// #     fn description(&self) -> &str {
+    /// #         "oops!"
+    /// #     }
+    /// # }
+    /// #
+    /// # impl Display for NonSyncError {
+    /// #     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    /// #         write!(f, "oops!")
+    /// #     }
+    /// # }
+    ///
+    /// fn returns_error() -> Result<(), NonSyncError> {
+    ///     // Do stuff
+    ///     # Ok(())
+    /// }
+    ///
+    /// fn my_function() -> Result<(), Error> {
+    ///     // without the map_err here, we end up with a compile error
+    ///     // complaining that NonSyncError doesn't implement Sync.
+    ///     returns_error().map_err(SyncFailure::new)?;
+    ///     // Do more stuff
+    ///     # Ok(())
+    /// }
+    /// #
+    /// # fn main() {
+    /// #    my_function().unwrap();
+    /// # }
+    /// ```
+    ///
+    pub fn new(err: E) -> Self {
+        SyncFailure {
+            inner: Mutex::new(err),
+        }
+    }
+}
+
+impl<T> Display for SyncFailure<T>
+where
+    T: Display,
+{
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.inner.lock().unwrap().fmt(f)
+    }
+}
+
+impl<T> Debug for SyncFailure<T>
+where
+    T: Debug,
+{
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        (*self.inner.lock().unwrap()).fmt(f)
+    }
+}
+
+impl<E: Error + Send + 'static> Fail for SyncFailure<E> {}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure/travis.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+
+cargo_test() {
+   cargo test "$@" || { exit 101; }
+}
+
+test_failure_in() {
+  cd $1
+  cargo_test
+  cargo_test --no-default-features
+  cargo_test --features backtrace
+  test_derive_in "$1/failure_derive"
+  cd $DIR
+}
+
+test_derive_in() {
+  cd $1
+  cargo_test
+  cd $DIR
+}
+
+test_nightly_features_in() {
+  cd $1
+  #cargo_test --features small-error
+  cargo_test --all-features
+  cd $DIR
+}
+
+main() {
+  test_failure_in "$DIR/failure-1.X"
+  test_failure_in "$DIR/failure-0.1.X"
+  if [ "${TRAVIS_RUST_VERSION}" = "nightly" ]; then
+    test_nightly_features_in "$DIR/failure-1.X"
+  fi
+}
+
+main
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure_derive/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{"Cargo.toml":"f6b769cd7eea271de41074015d661f7a5a3a1cbafb4c59607eaa329c4cea2066","build.rs":"c7481c027fc4c09e2d6dc8ac642ec5314b6a02269fb022b0f3c1850f000d31f5","src/lib.rs":"10c93690a2a73dd862a6ac483b86a2aa16f4c6b682f343868350856d3d0aedea","tests/backtrace.rs":"56b2b97f83e5341108aac403a50491560dc6d897d6002973248c9c9014c0e494","tests/custom_type_bounds.rs":"745d3e488738f5d90bcb1fa66a6784b64a88881b1d62c241cba2f863f4eb31c8","tests/no_derive_display.rs":"3ab159aadf809a95d578b4909470f6ecca24cea0caf514509d326601cc7b933b","tests/tests.rs":"eaf131c01cc101b94fd6478a9964f5e3d919f2260f6d327f0e435ac3520fe71e","tests/wraps.rs":"e00c2761ccd9fe84df47bd102945818f5d8868c95bcab719ebdde0db8334d4a6"},"package":"946d0e98a50d9831f5d589038d2ca7f8f455b1c21028c0db0e84116a12696426"}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure_derive/Cargo.toml
@@ -0,0 +1,41 @@
+# 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 = "failure_derive"
+version = "0.1.2"
+authors = ["Without Boats <woboats@gmail.com>"]
+build = "build.rs"
+description = "derives for the failure crate"
+homepage = "https://boats.gitlab.io/failure"
+documentation = "https://boats.gitlab.io/failure"
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/withoutboats/failure_derive"
+
+[lib]
+proc-macro = true
+[dependencies.proc-macro2]
+version = "0.4.8"
+
+[dependencies.quote]
+version = "0.6.3"
+
+[dependencies.syn]
+version = "0.14.4"
+
+[dependencies.synstructure]
+version = "0.9.0"
+[dev-dependencies.failure]
+version = "0.1.0"
+
+[features]
+std = []
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure_derive/build.rs
@@ -0,0 +1,39 @@
+use std::env;
+use std::process::Command;
+use std::str;
+use std::str::FromStr;
+
+fn main() {
+    if rustc_has_dyn_trait() {
+        println!("cargo:rustc-cfg=has_dyn_trait");
+    }
+}
+
+fn rustc_has_dyn_trait() -> bool {
+    let rustc = match env::var_os("RUSTC") {
+        Some(rustc) => rustc,
+        None => return false,
+    };
+
+    let output = match Command::new(rustc).arg("--version").output() {
+        Ok(output) => output,
+        Err(_) => return false,
+    };
+
+    let version = match str::from_utf8(&output.stdout) {
+        Ok(version) => version,
+        Err(_) => return false,
+    };
+
+    let mut pieces = version.split('.');
+    if pieces.next() != Some("rustc 1") {
+        return true;
+    }
+
+    let next = match pieces.next() {
+        Some(next) => next,
+        None => return false,
+    };
+
+    u32::from_str(next).unwrap_or(0) >= 27
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure_derive/src/lib.rs
@@ -0,0 +1,200 @@
+extern crate proc_macro2;
+extern crate syn;
+
+#[macro_use]
+extern crate synstructure;
+#[macro_use]
+extern crate quote;
+
+use proc_macro2::TokenStream;
+
+decl_derive!([Fail, attributes(fail, cause)] => fail_derive);
+
+fn fail_derive(s: synstructure::Structure) -> TokenStream {
+    let make_dyn = if cfg!(has_dyn_trait) {
+        quote! { &dyn }
+    } else {
+        quote! { & }
+    };
+
+    let cause_body = s.each_variant(|v| {
+        if let Some(cause) = v.bindings().iter().find(is_cause) {
+            quote!(return Some(#cause))
+        } else {
+            quote!(return None)
+        }
+    });
+
+    let bt_body = s.each_variant(|v| {
+        if let Some(bi) = v.bindings().iter().find(is_backtrace) {
+            quote!(return Some(#bi))
+        } else {
+            quote!(return None)
+        }
+    });
+
+    let fail = s.unbound_impl(
+        quote!(::failure::Fail),
+        quote! {
+            #[allow(unreachable_code)]
+            fn cause(&self) -> ::failure::_core::option::Option<#make_dyn(::failure::Fail)> {
+                match *self { #cause_body }
+                None
+            }
+
+            #[allow(unreachable_code)]
+            fn backtrace(&self) -> ::failure::_core::option::Option<&::failure::Backtrace> {
+                match *self { #bt_body }
+                None
+            }
+        },
+    );
+    let display = display_body(&s).map(|display_body| {
+        s.unbound_impl(
+            quote!(::failure::_core::fmt::Display),
+            quote! {
+                #[allow(unreachable_code)]
+                fn fmt(&self, f: &mut ::failure::_core::fmt::Formatter) -> ::failure::_core::fmt::Result {
+                    match *self { #display_body }
+                    write!(f, "An error has occurred.")
+                }
+            },
+        )
+    });
+
+    (quote! {
+        #fail
+        #display
+    }).into()
+}
+
+fn display_body(s: &synstructure::Structure) -> Option<quote::__rt::TokenStream> {
+    let mut msgs = s.variants().iter().map(|v| find_error_msg(&v.ast().attrs));
+    if msgs.all(|msg| msg.is_none()) {
+        return None;
+    }
+
+    Some(s.each_variant(|v| {
+        let msg =
+            find_error_msg(&v.ast().attrs).expect("All variants must have display attribute.");
+        if msg.nested.is_empty() {
+            panic!("Expected at least one argument to fail attribute");
+        }
+
+        let format_string = match msg.nested[0] {
+            syn::NestedMeta::Meta(syn::Meta::NameValue(ref nv)) if nv.ident == "display" => {
+                nv.lit.clone()
+            }
+            _ => {
+                panic!("Fail attribute must begin `display = \"\"` to control the Display message.")
+            }
+        };
+        let args = msg.nested.iter().skip(1).map(|arg| match *arg {
+            syn::NestedMeta::Literal(syn::Lit::Int(ref i)) => {
+                let bi = &v.bindings()[i.value() as usize];
+                quote!(#bi)
+            }
+            syn::NestedMeta::Meta(syn::Meta::Word(ref id)) => {
+                let id_s = id.to_string();
+                if id_s.starts_with("_") {
+                    if let Ok(idx) = id_s[1..].parse::<usize>() {
+                        let bi = match v.bindings().get(idx) {
+                            Some(bi) => bi,
+                            None => {
+                                panic!(
+                                    "display attempted to access field `{}` in `{}::{}` which \
+                                     does not exist (there are {} field{})",
+                                    idx,
+                                    s.ast().ident,
+                                    v.ast().ident,
+                                    v.bindings().len(),
+                                    if v.bindings().len() != 1 { "s" } else { "" }
+                                );
+                            }
+                        };
+                        return quote!(#bi);
+                    }
+                }
+                for bi in v.bindings() {
+                    if bi.ast().ident.as_ref() == Some(id) {
+                        return quote!(#bi);
+                    }
+                }
+                panic!(
+                    "Couldn't find field `{}` in `{}::{}`",
+                    id,
+                    s.ast().ident,
+                    v.ast().ident
+                );
+            }
+            _ => panic!("Invalid argument to fail attribute!"),
+        });
+
+        quote! {
+            return write!(f, #format_string #(, #args)*)
+        }
+    }))
+}
+
+fn find_error_msg(attrs: &[syn::Attribute]) -> Option<syn::MetaList> {
+    let mut error_msg = None;
+    for attr in attrs {
+        if let Some(meta) = attr.interpret_meta() {
+            if meta.name() == "fail" {
+                if error_msg.is_some() {
+                    panic!("Cannot have two display attributes")
+                } else {
+                    if let syn::Meta::List(list) = meta {
+                        error_msg = Some(list);
+                    } else {
+                        panic!("fail attribute must take a list in parentheses")
+                    }
+                }
+            }
+        }
+    }
+    error_msg
+}
+
+fn is_backtrace(bi: &&synstructure::BindingInfo) -> bool {
+    match bi.ast().ty {
+        syn::Type::Path(syn::TypePath {
+            qself: None,
+            path: syn::Path {
+                segments: ref path, ..
+            },
+        }) => path.last().map_or(false, |s| {
+            s.value().ident == "Backtrace" && s.value().arguments.is_empty()
+        }),
+        _ => false,
+    }
+}
+
+fn is_cause(bi: &&synstructure::BindingInfo) -> bool {
+    let mut found_cause = false;
+    for attr in &bi.ast().attrs {
+        if let Some(meta) = attr.interpret_meta() {
+            if meta.name() == "cause" {
+                if found_cause {
+                    panic!("Cannot have two `cause` attributes");
+                }
+                found_cause = true;
+            }
+            if meta.name() == "fail" {
+                if let syn::Meta::List(ref list) = meta {
+                    if let Some(ref pair) = list.nested.first() {
+                        if let &&syn::NestedMeta::Meta(syn::Meta::Word(ref word)) = pair.value() {
+                            if word == "cause" {
+                                if found_cause {
+                                    panic!("Cannot have two `cause` attributes");
+                                }
+                                found_cause = true;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    found_cause
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure_derive/tests/backtrace.rs
@@ -0,0 +1,64 @@
+extern crate failure;
+#[macro_use]
+extern crate failure_derive;
+
+use failure::{Backtrace, Fail};
+
+#[derive(Fail, Debug)]
+#[fail(display = "Error code: {}", code)]
+struct BacktraceError {
+    backtrace: Backtrace,
+    code: u32,
+}
+
+#[test]
+fn backtrace_error() {
+    let err = BacktraceError {
+        backtrace: Backtrace::new(),
+        code: 7,
+    };
+    let s = format!("{}", err);
+    assert_eq!(&s[..], "Error code: 7");
+    assert!(err.backtrace().is_some());
+}
+
+#[derive(Fail, Debug)]
+#[fail(display = "An error has occurred.")]
+struct BacktraceTupleError(Backtrace);
+
+#[test]
+fn backtrace_tuple_error() {
+    let err = BacktraceTupleError(Backtrace::new());
+    let s = format!("{}", err);
+    assert_eq!(&s[..], "An error has occurred.");
+    assert!(err.backtrace().is_some());
+}
+
+#[derive(Fail, Debug)]
+enum BacktraceEnumError {
+    #[fail(display = "Error code: {}", code)]
+    StructVariant { code: i32, backtrace: Backtrace },
+    #[fail(display = "Error: {}", _0)]
+    TupleVariant(&'static str, Backtrace),
+    #[fail(display = "An error has occurred.")]
+    UnitVariant,
+}
+
+#[test]
+fn backtrace_enum_error() {
+    let err = BacktraceEnumError::StructVariant {
+        code: 2,
+        backtrace: Backtrace::new(),
+    };
+    let s = format!("{}", err);
+    assert_eq!(&s[..], "Error code: 2");
+    assert!(err.backtrace().is_some());
+    let err = BacktraceEnumError::TupleVariant("foobar", Backtrace::new());
+    let s = format!("{}", err);
+    assert_eq!(&s[..], "Error: foobar");
+    assert!(err.backtrace().is_some());
+    let err = BacktraceEnumError::UnitVariant;
+    let s = format!("{}", err);
+    assert_eq!(&s[..], "An error has occurred.");
+    assert!(err.backtrace().is_none());
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure_derive/tests/custom_type_bounds.rs
@@ -0,0 +1,45 @@
+#[macro_use]
+extern crate failure;
+
+use std::fmt::Debug;
+
+use failure::Fail;
+
+#[derive(Debug, Fail)]
+#[fail(display = "An error has occurred.")]
+pub struct UnboundedGenericTupleError<T: 'static + Debug + Send + Sync>(T);
+
+#[test]
+fn unbounded_generic_tuple_error() {
+    let s = format!("{}", UnboundedGenericTupleError(()));
+    assert_eq!(&s[..], "An error has occurred.");
+}
+
+#[derive(Debug, Fail)]
+#[fail(display = "An error has occurred: {}", _0)]
+pub struct FailBoundsGenericTupleError<T: Fail>(T);
+
+#[test]
+fn fail_bounds_generic_tuple_error() {
+    let error = FailBoundsGenericTupleError(UnboundedGenericTupleError(()));
+    let s = format!("{}", error);
+    assert_eq!(&s[..], "An error has occurred: An error has occurred.");
+}
+
+pub trait NoDisplay: 'static + Debug + Send + Sync {}
+
+impl NoDisplay for &'static str {}
+
+#[derive(Debug, Fail)]
+#[fail(display = "An error has occurred: {:?}", _0)]
+pub struct CustomBoundsGenericTupleError<T: NoDisplay>(T);
+
+#[test]
+fn custom_bounds_generic_tuple_error() {
+    let error = CustomBoundsGenericTupleError("more details unavailable.");
+    let s = format!("{}", error);
+    assert_eq!(
+        &s[..],
+        "An error has occurred: \"more details unavailable.\""
+    );
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure_derive/tests/no_derive_display.rs
@@ -0,0 +1,21 @@
+extern crate failure;
+#[macro_use]
+extern crate failure_derive;
+
+use failure::Fail;
+use std::fmt::{self, Display};
+
+#[derive(Debug, Fail)]
+struct Foo;
+
+impl Display for Foo {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.write_str("An error occurred.")
+    }
+}
+
+#[test]
+fn handwritten_display() {
+    assert!(Foo.cause().is_none());
+    assert_eq!(&format!("{}", Foo)[..], "An error occurred.");
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure_derive/tests/tests.rs
@@ -0,0 +1,55 @@
+extern crate failure;
+#[macro_use]
+extern crate failure_derive;
+
+#[derive(Fail, Debug)]
+#[fail(display = "An error has occurred.")]
+struct UnitError;
+
+#[test]
+fn unit_struct() {
+    let s = format!("{}", UnitError);
+    assert_eq!(&s[..], "An error has occurred.");
+}
+
+#[derive(Fail, Debug)]
+#[fail(display = "Error code: {}", code)]
+struct RecordError {
+    code: u32,
+}
+
+#[test]
+fn record_struct() {
+    let s = format!("{}", RecordError { code: 0 });
+    assert_eq!(&s[..], "Error code: 0");
+}
+
+#[derive(Fail, Debug)]
+#[fail(display = "Error code: {}", _0)]
+struct TupleError(i32);
+
+#[test]
+fn tuple_struct() {
+    let s = format!("{}", TupleError(2));
+    assert_eq!(&s[..], "Error code: 2");
+}
+
+#[derive(Fail, Debug)]
+enum EnumError {
+    #[fail(display = "Error code: {}", code)]
+    StructVariant { code: i32 },
+    #[fail(display = "Error: {}", _0)]
+    TupleVariant(&'static str),
+    #[fail(display = "An error has occurred.")]
+    UnitVariant,
+}
+
+#[test]
+fn enum_error() {
+    let s = format!("{}", EnumError::StructVariant { code: 2 });
+    assert_eq!(&s[..], "Error code: 2");
+    let s = format!("{}", EnumError::TupleVariant("foobar"));
+    assert_eq!(&s[..], "Error: foobar");
+    let s = format!("{}", EnumError::UnitVariant);
+    assert_eq!(&s[..], "An error has occurred.");
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/failure_derive/tests/wraps.rs
@@ -0,0 +1,99 @@
+extern crate failure;
+#[macro_use]
+extern crate failure_derive;
+
+use std::fmt;
+use std::io;
+
+use failure::{Backtrace, Fail};
+
+#[derive(Fail, Debug)]
+#[fail(display = "An error has occurred: {}", inner)]
+struct WrapError {
+    #[fail(cause)]
+    inner: io::Error,
+}
+
+#[test]
+fn wrap_error() {
+    let inner = io::Error::from_raw_os_error(98);
+    let err = WrapError { inner };
+    assert!(
+        err.cause()
+            .and_then(|err| err.downcast_ref::<io::Error>())
+            .is_some()
+    );
+}
+
+#[derive(Fail, Debug)]
+#[fail(display = "An error has occurred: {}", _0)]
+struct WrapTupleError(#[fail(cause)] io::Error);
+
+#[test]
+fn wrap_tuple_error() {
+    let io_error = io::Error::from_raw_os_error(98);
+    let err: WrapTupleError = WrapTupleError(io_error);
+    assert!(
+        err.cause()
+            .and_then(|err| err.downcast_ref::<io::Error>())
+            .is_some()
+    );
+}
+
+#[derive(Fail, Debug)]
+#[fail(display = "An error has occurred: {}", inner)]
+struct WrapBacktraceError {
+    #[fail(cause)]
+    inner: io::Error,
+    backtrace: Backtrace,
+}
+
+#[test]
+fn wrap_backtrace_error() {
+    let inner = io::Error::from_raw_os_error(98);
+    let err: WrapBacktraceError = WrapBacktraceError {
+        inner,
+        backtrace: Backtrace::new(),
+    };
+    assert!(
+        err.cause()
+            .and_then(|err| err.downcast_ref::<io::Error>())
+            .is_some()
+    );
+    assert!(err.backtrace().is_some());
+}
+
+#[derive(Fail, Debug)]
+enum WrapEnumError {
+    #[fail(display = "An error has occurred: {}", _0)]
+    Io(#[fail(cause)] io::Error),
+    #[fail(display = "An error has occurred: {}", inner)]
+    Fmt {
+        #[fail(cause)]
+        inner: fmt::Error,
+        backtrace: Backtrace,
+    },
+}
+
+#[test]
+fn wrap_enum_error() {
+    let io_error = io::Error::from_raw_os_error(98);
+    let err: WrapEnumError = WrapEnumError::Io(io_error);
+    assert!(
+        err.cause()
+            .and_then(|err| err.downcast_ref::<io::Error>())
+            .is_some()
+    );
+    assert!(err.backtrace().is_none());
+    let fmt_error = fmt::Error::default();
+    let err: WrapEnumError = WrapEnumError::Fmt {
+        inner: fmt_error,
+        backtrace: Backtrace::new(),
+    };
+    assert!(
+        err.cause()
+            .and_then(|err| err.downcast_ref::<fmt::Error>())
+            .is_some()
+    );
+    assert!(err.backtrace().is_some());
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/lmdb-rkv/.appveyor.yml
@@ -0,0 +1,27 @@
+environment:
+  matrix:
+    - TARGET: x86_64-pc-windows-msvc
+    - TARGET: i686-pc-windows-msvc
+    # Temporarily disable MinGW builds due to https://github.com/rust-lang/rust/issues/47048.
+    # Once that issue is fixed, presumably by https://github.com/rust-lang/rust/pull/51989,
+    # we should reenable them.
+    # - TARGET: x86_64-pc-windows-gnu
+    #   MSYS_BITS: 64
+    # - TARGET: i686-pc-windows-gnu
+    #   MSYS_BITS: 32
+
+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
+  - if defined MSYS_BITS set PATH=%PATH%;C:\msys64\mingw%MSYS_BITS%\bin
+  - rustc -V
+  - cargo -V
+
+build_script:
+  - git submodule -q update --init
+  - cargo build --target %TARGET% --all -v
+
+test_script:
+  - SET RUST_BACKTRACE=1
+  - cargo test --target %TARGET% --all -v
new file mode 100644
--- /dev/null
+++ b/third_party/rust/lmdb-rkv/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{".appveyor.yml":"431ffb273c41171253d1dd9443b2bc6ea153402e056a234f5c1ac1ae35960bc3",".gitmodules":"7304263ea6fe3e349a2660f62389a3feace1c9b2c29ad899ad2dff8f23bb20bb",".rustfmt.toml":"3025e466e14d8ac54e5371397434f79be4976b5bf3faf64e36c5e941980a0cf2",".travis.yml":"3d3dc38d5274b0d76788d8d48dab360a6dd4da677f3fe58bba4c52d126ddb349","Cargo.toml":"7c3220dd808ac0d7d161eb289cffffbcd5d36fde28f4d352775296a9783716a3","LICENSE":"db6d163be642e3b568c5fb2104013da632316ecd4e75935df1613af8b0b37933","README.md":"97b61d73ff27afb03bde9ae960f12651093558214851303c8ae82f567abfe992","src/cursor.rs":"169e95f800425324dd71219b8e88d148c1c103983ff9ffc94821600af031a854","src/database.rs":"003a214f53acd632bc70f2f02d01dcb0bc5bf7e777e1781ef1ff19246f0157d0","src/environment.rs":"af4de52742e3f727f53b833ee66406870766b83d7621d3647b977d330b6fb937","src/error.rs":"0ea99c8bc1619f3789eff7734341efa7f48fcd8732dc9f3141804e0a802f5d71","src/flags.rs":"40fd3d4d72c8db8f9ecb893420300a3585e2ca4c49073065ec9ebf24fe23c064","src/lib.rs":"ae47ef9c92d425e1b8b9857899c747593984d87dfd318d2cf30e5f626904f215","src/transaction.rs":"e9e9485aafb19cab4688dc8a476eec033c21c8256717a89080cfb77d2dfe235c"},"package":"07d8d72d709440ac7a19b71e04fb66684ec7547b3831817872454b01fdaefe23"}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/lmdb-rkv/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "lmdb-sys/lmdb"]
+	path = lmdb-sys/lmdb
+	url = https://github.com/LMDB/lmdb
new file mode 100644
--- /dev/null
+++ b/third_party/rust/lmdb-rkv/.rustfmt.toml
@@ -0,0 +1,1 @@
+disable_all_formatting = true
new file mode 100644
--- /dev/null
+++ b/third_party/rust/lmdb-rkv/.travis.yml
@@ -0,0 +1,21 @@
+language: rust
+dist: trusty
+sudo: false
+
+cache: cargo
+
+os:
+  - linux
+  - osx
+
+rust:
+- 1.20.0
+- stable
+- nightly
+
+script:
+  - cargo build --verbose
+  - if [[ $TRAVIS_RUST_VERSION = nightly* ]]; then
+      env RUST_BACKTRACE=1 cargo test --all -v;
+      env RUST_BACKTRACE=1 cargo test --all -v --release;
+    fi
new file mode 100644
--- /dev/null
+++ b/third_party/rust/lmdb-rkv/Cargo.toml
@@ -0,0 +1,47 @@
+# 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 = "lmdb-rkv"
+version = "0.8.2"
+authors = ["Dan Burkert <dan@danburkert.com>"]
+description = "Idiomatic and safe LMDB wrapper."
+documentation = "https://docs.rs/lmdb-rkv"
+readme = "README.md"
+keywords = ["LMDB", "database", "storage-engine", "bindings", "library"]
+categories = ["database"]
+license = "Apache-2.0"
+repository = "https://github.com/mozilla/lmdb-rs.git"
+
+[lib]
+name = "lmdb"
+[dependencies.bitflags]
+version = "1"
+
+[dependencies.libc]
+version = "0.2"
+
+[dependencies.lmdb-sys]
+version = "0.8.0"
+[dev-dependencies.byteorder]
+version = "1.0"
+
+[dev-dependencies.rand]
+version = "0.4"
+
+[dev-dependencies.tempdir]
+version = "0.3"
+[badges.appveyor]
+repository = "mozilla/lmdb-rs"
+
+[badges.travis-ci]
+repository = "mozilla/lmdb-rs"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/lmdb-rkv/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright 2014 Dan Burkert
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/lmdb-rkv/README.md
@@ -0,0 +1,26 @@
+[![Build Status](https://travis-ci.org/mozilla/lmdb-rs.svg?branch=master)](https://travis-ci.org/mozilla/lmdb-rs)
+[![Windows Build status](https://ci.appveyor.com/api/projects/status/id69kkymorycld55/branch/master?svg=true)](https://ci.appveyor.com/project/mykmelez/lmdb-rs-rrsb3/branch/master)
+
+# lmdb-rs
+
+Idiomatic and safe APIs for interacting with the
+[Symas Lightning Memory-Mapped Database (LMDB)](http://symas.com/mdb/).
+
+This repo is a fork of [danburkert/lmdb-rs](https://github.com/danburkert/lmdb-rs)
+with fixes for issues encountered by [mozilla/rkv](https://github.com/mozilla/rkv).
+
+## Building from Source
+
+```bash
+git clone --recursive git@github.com:mozilla/lmdb-rs.git
+cd lmdb-rs
+cargo build
+```
+
+## Features
+
+* [x] lmdb-sys.
+* [x] Cursors.
+* [x] Zero-copy put API.
+* [x] Nested transactions.
+* [x] Database statistics.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/lmdb-rkv/src/cursor.rs
@@ -0,0 +1,619 @@
+use libc::{c_void, size_t, c_uint};
+use std::{fmt, ptr, result, slice};
+use std::marker::PhantomData;
+
+use database::Database;
+use error::{Error, Result, lmdb_result};
+use ffi;
+use flags::WriteFlags;
+use transaction::Transaction;
+
+/// An LMDB cursor.
+pub trait Cursor<'txn> {
+
+    /// Returns a raw pointer to the underlying LMDB cursor.
+    ///
+    /// The caller **must** ensure that the pointer is not used after the
+    /// lifetime of the cursor.
+    fn cursor(&self) -> *mut ffi::MDB_cursor;
+
+    /// Retrieves a key/data pair from the cursor. Depending on the cursor op,
+    /// the current key may be returned.
+    fn get(&self,
+           key: Option<&[u8]>,
+           data: Option<&[u8]>,
+           op: c_uint)
+           -> Result<(Option<&'txn [u8]>, &'txn [u8])> {
+        unsafe {
+            let mut key_val = slice_to_val(key);
+            let mut data_val = slice_to_val(data);
+            let key_ptr = key_val.mv_data;
+            lmdb_result(ffi::mdb_cursor_get(self.cursor(), &mut key_val, &mut data_val, op))?;
+            let key_out = if key_ptr != key_val.mv_data { Some(val_to_slice(key_val)) } else { None };
+            let data_out = val_to_slice(data_val);
+            Ok((key_out, data_out))
+        }
+    }
+
+    /// Iterate over database items. The iterator will begin with item next
+    /// after the cursor, and continue until the end of the database. For new
+    /// cursors, the iterator will begin with the first item in the database.
+    ///
+    /// For databases with duplicate data items (`DatabaseFlags::DUP_SORT`), the
+    /// duplicate data items of each key will be returned before moving on to
+    /// the next key.
+    fn iter(&mut self) -> Iter<'txn> {
+        Iter::new(self.cursor(), ffi::MDB_NEXT, ffi::MDB_NEXT)
+    }
+
+    /// Iterate over database items starting from the beginning of the database.
+    ///
+    /// For databases with duplicate data items (`DatabaseFlags::DUP_SORT`), the
+    /// duplicate data items of each key will be returned before moving on to
+    /// the next key.
+    fn iter_start(&mut self) -> Iter<'txn> {
+        self.get(None, None, ffi::MDB_FIRST).unwrap();
+        Iter::new(self.cursor(), ffi::MDB_GET_CURRENT, ffi::MDB_NEXT)
+    }
+
+    /// Iterate over database items starting from the given key.
+    ///
+    /// For databases with duplicate data items (`DatabaseFlags::DUP_SORT`), the
+    /// duplicate data items of each key will be returned before moving on to
+    /// the next key.
+    fn iter_from<K>(&mut self, key: K) -> Iter<'txn> where K: AsRef<[u8]> {
+        match self.get(Some(key.as_ref()), None, ffi::MDB_SET_RANGE) {
+            Err(Error::NotFound) => Ok(()),
+            Err(error) => Err(error),
+            Ok(_) => Ok(()),
+        }.unwrap();
+        Iter::new(self.cursor(), ffi::MDB_GET_CURRENT, ffi::MDB_NEXT)
+    }
+
+    /// Iterate over duplicate database items. The iterator will begin with the
+    /// item next after the cursor, and continue until the end of the database.
+    /// Each item will be returned as an iterator of its duplicates.
+    fn iter_dup(&mut self) -> IterDup<'txn> {
+        IterDup::new(self.cursor(), ffi::MDB_NEXT)
+    }
+
+    /// Iterate over duplicate database items starting from the beginning of the
+    /// database. Each item will be returned as an iterator of its duplicates.
+    fn iter_dup_start(&mut self) -> IterDup<'txn> {
+        self.get(None, None, ffi::MDB_FIRST).unwrap();
+        IterDup::new(self.cursor(), ffi::MDB_GET_CURRENT)
+    }
+
+    /// Iterate over duplicate items in the database starting from the given
+    /// key. Each item will be returned as an iterator of its duplicates.
+    fn iter_dup_from<K>(&mut self, key: &K) -> IterDup<'txn> where K: AsRef<[u8]> {
+        match self.get(Some(key.as_ref()), None, ffi::MDB_SET_RANGE) {
+            Err(Error::NotFound) => Ok(()),
+            Err(error) => Err(error),
+            Ok(_) => Ok(()),
+        }.unwrap();
+        IterDup::new(self.cursor(), ffi::MDB_GET_CURRENT)
+    }
+
+    /// Iterate over the duplicates of the item in the database with the given
+    /// key.
+    fn iter_dup_of<K>(&mut self, key: &K) -> Result<Iter<'txn>> where K:
+        AsRef<[u8]> {
+        self.get(Some(key.as_ref()), None, ffi::MDB_SET)?;
+        Ok(Iter::new(self.cursor(), ffi::MDB_GET_CURRENT, ffi::MDB_NEXT_DUP))
+    }
+}
+
+/// A read-only cursor for navigating the items within a database.
+pub struct RoCursor<'txn> {
+    cursor: *mut ffi::MDB_cursor,
+    _marker: PhantomData<fn() -> &'txn ()>,
+}
+
+impl <'txn> Cursor<'txn> for RoCursor<'txn> {
+    fn cursor(&self) -> *mut ffi::MDB_cursor {
+        self.cursor
+    }
+}
+
+impl <'txn> fmt::Debug for RoCursor<'txn> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
+        f.debug_struct("RoCursor").finish()
+    }
+}
+
+impl <'txn> Drop for RoCursor<'txn> {
+    fn drop(&mut self) {
+        unsafe { ffi::mdb_cursor_close(self.cursor) }
+    }
+}
+
+impl <'txn> RoCursor<'txn> {
+
+    /// Creates a new read-only cursor in the given database and transaction.
+    /// Prefer using `Transaction::open_cursor`.
+    pub(crate) fn new<T>(txn: &'txn T, db: Database) -> Result<RoCursor<'txn>> where T: Transaction {
+        let mut cursor: *mut ffi::MDB_cursor = ptr::null_mut();
+        unsafe { lmdb_result(ffi::mdb_cursor_open(txn.txn(), db.dbi(), &mut cursor))?; }
+        Ok(RoCursor {
+            cursor: cursor,
+            _marker: PhantomData,
+        })
+    }
+}
+
+/// A read-write cursor for navigating items within a database.
+pub struct RwCursor<'txn> {
+    cursor: *mut ffi::MDB_cursor,
+    _marker: PhantomData<fn() -> &'txn ()>,
+}
+
+impl <'txn> Cursor<'txn> for RwCursor<'txn> {
+    fn cursor(&self) -> *mut ffi::MDB_cursor {
+        self.cursor
+    }
+}
+
+impl <'txn> fmt::Debug for RwCursor<'txn> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
+        f.debug_struct("RwCursor").finish()
+    }
+}
+
+impl <'txn> Drop for RwCursor<'txn> {
+    fn drop(&mut self) {
+        unsafe { ffi::mdb_cursor_close(self.cursor) }
+    }
+}
+
+impl <'txn> RwCursor<'txn> {
+
+    /// Creates a new read-only cursor in the given database and transaction.
+    /// Prefer using `RwTransaction::open_rw_cursor`.
+    pub(crate) fn new<T>(txn: &'txn T, db: Database) -> Result<RwCursor<'txn>> where T: Transaction {
+        let mut cursor: *mut ffi::MDB_cursor = ptr::null_mut();
+        unsafe { lmdb_result(ffi::mdb_cursor_open(txn.txn(), db.dbi(), &mut cursor))?; }
+        Ok(RwCursor { cursor: cursor, _marker: PhantomData })
+    }
+
+    /// Puts a key/data pair into the database. The cursor will be positioned at
+    /// the new data item, or on failure usually near it.
+    pub fn put<K, D>(&mut self, key: &K, data: &D, flags: WriteFlags) -> Result<()>
+    where K: AsRef<[u8]>, D: AsRef<[u8]> {
+        let key = key.as_ref();
+        let data = data.as_ref();
+        let mut key_val: ffi::MDB_val = ffi::MDB_val { mv_size: key.len() as size_t,
+                                                       mv_data: key.as_ptr() as *mut c_void };
+        let mut data_val: ffi::MDB_val = ffi::MDB_val { mv_size: data.len() as size_t,
+                                                        mv_data: data.as_ptr() as *mut c_void };
+        unsafe {
+            lmdb_result(ffi::mdb_cursor_put(self.cursor(),
+                                            &mut key_val,
+                                            &mut data_val,
+                                            flags.bits()))
+        }
+    }
+
+    /// Deletes the current key/data pair.
+    ///
+    /// ### Flags
+    ///
+    /// `WriteFlags::NO_DUP_DATA` may be used to delete all data items for the
+    /// current key, if the database was opened with `DatabaseFlags::DUP_SORT`.
+    pub fn del(&mut self, flags: WriteFlags) -> Result<()> {
+        unsafe { lmdb_result(ffi::mdb_cursor_del(self.cursor(), flags.bits())) }
+    }
+}
+
+unsafe fn slice_to_val(slice: Option<&[u8]>) -> ffi::MDB_val {
+    match slice {
+        Some(slice) =>
+            ffi::MDB_val { mv_size: slice.len() as size_t,
+                           mv_data: slice.as_ptr() as *mut c_void },
+        None =>
+            ffi::MDB_val { mv_size: 0,
+                           mv_data: ptr::null_mut() },
+    }
+}
+
+unsafe fn val_to_slice<'a>(val: ffi::MDB_val) -> &'a [u8] {
+    slice::from_raw_parts(val.mv_data as *const u8, val.mv_size as usize)
+}
+
+/// An iterator over the values in an LMDB database.
+pub struct Iter<'txn> {
+    cursor: *mut ffi::MDB_cursor,
+    op: c_uint,
+    next_op: c_uint,
+    _marker: PhantomData<fn(&'txn ())>,
+}
+
+impl <'txn> Iter<'txn> {
+
+    /// Creates a new iterator backed by the given cursor.
+    fn new<'t>(cursor: *mut ffi::MDB_cursor, op: c_uint, next_op: c_uint) -> Iter<'t> {
+        Iter { cursor: cursor, op: op, next_op: next_op, _marker: PhantomData }
+    }
+}
+
+impl <'txn> fmt::Debug for Iter<'txn> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
+        f.debug_struct("Iter").finish()
+    }
+}
+
+impl <'txn> Iterator for Iter<'txn> {
+
+    type Item = (&'txn [u8], &'txn [u8]);
+
+    fn next(&mut self) -> Option<(&'txn [u8], &'txn [u8])> {
+        let mut key = ffi::MDB_val { mv_size: 0, mv_data: ptr::null_mut() };
+        let mut data = ffi::MDB_val { mv_size: 0, mv_data: ptr::null_mut() };
+
+        unsafe {
+            let err_code = ffi::mdb_cursor_get(self.cursor, &mut key, &mut data, self.op);
+            // Set the operation for the next get
+            self.op = self.next_op;
+            if err_code == ffi::MDB_SUCCESS {
+                Some((val_to_slice(key), val_to_slice(data)))
+            } else {
+                // The documentation for mdb_cursor_get specifies that it may fail with MDB_NOTFOUND
+                // and MDB_EINVAL (and we shouldn't be passing in invalid parameters).
+                // TODO: validate that these are the only failures possible.
+                debug_assert!(err_code == ffi::MDB_NOTFOUND,
+                              "Unexpected LMDB error {:?}.", Error::from_err_code(err_code));
+                None
+            }
+        }
+    }
+}
+
+/// An iterator over the keys and duplicate values in an LMDB database.
+///
+/// The yielded items of the iterator are themselves iterators over the duplicate values for a
+/// specific key.
+pub struct IterDup<'txn> {
+    cursor: *mut ffi::MDB_cursor,
+    op: c_uint,
+    _marker: PhantomData<fn(&'txn ())>,
+}
+
+impl <'txn> IterDup<'txn> {
+
+    /// Creates a new iterator backed by the given cursor.
+    fn new<'t>(cursor: *mut ffi::MDB_cursor, op: c_uint) -> IterDup<'t> {
+        IterDup { cursor: cursor, op: op, _marker: PhantomData }
+    }
+}
+
+impl <'txn> fmt::Debug for IterDup<'txn> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
+        f.debug_struct("IterDup").finish()
+    }
+}
+
+impl <'txn> Iterator for IterDup<'txn> {
+
+    type Item = Iter<'txn>;
+
+    fn next(&mut self) -> Option<Iter<'txn>> {
+        let mut key = ffi::MDB_val { mv_size: 0, mv_data: ptr::null_mut() };
+        let mut data = ffi::MDB_val { mv_size: 0, mv_data: ptr::null_mut() };
+        let err_code = unsafe {
+            ffi::mdb_cursor_get(self.cursor, &mut key, &mut data, self.op)
+        };
+
+        if err_code == ffi::MDB_SUCCESS {
+            self.op = ffi::MDB_NEXT;
+            Some(Iter::new(self.cursor, ffi::MDB_GET_CURRENT, ffi::MDB_NEXT_DUP))
+        } else {
+            None
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+
+    use std::ptr;
+    use test::{Bencher, black_box};
+
+    use tempdir::TempDir;
+
+    use environment::*;
+    use ffi::*;
+    use flags::*;
+    use super::*;
+    use test_utils::*;
+
+    #[test]
+    fn test_get() {
+        let dir = TempDir::new("test").unwrap();
+        let env = Environment::new().open(dir.path()).unwrap();
+        let db = env.open_db(None).unwrap();
+
+        let mut txn = env.begin_rw_txn().unwrap();
+        txn.put(db, b"key1", b"val1", WriteFlags::empty()).unwrap();
+        txn.put(db, b"key2", b"val2", WriteFlags::empty()).unwrap();
+        txn.put(db, b"key3", b"val3", WriteFlags::empty()).unwrap();
+
+        let cursor = txn.open_ro_cursor(db).unwrap();
+        assert_eq!((Some(&b"key1"[..]), &b"val1"[..]),
+                   cursor.get(None, None, MDB_FIRST).unwrap());
+        assert_eq!((Some(&b"key1"[..]), &b"val1"[..]),
+                   cursor.get(None, None, MDB_GET_CURRENT).unwrap());
+        assert_eq!((Some(&b"key2"[..]), &b"val2"[..]),
+                   cursor.get(None, None, MDB_NEXT).unwrap());
+        assert_eq!((Some(&b"key1"[..]), &b"val1"[..]),
+                   cursor.get(None, None, MDB_PREV).unwrap());
+        assert_eq!((Some(&b"key3"[..]), &b"val3"[..]),
+                   cursor.get(None, None, MDB_LAST).unwrap());
+        assert_eq!((None, &b"val2"[..]),
+                   cursor.get(Some(b"key2"), None, MDB_SET).unwrap());
+        assert_eq!((Some(&b"key3"[..]), &b"val3"[..]),
+                   cursor.get(Some(&b"key3"[..]), None, MDB_SET_KEY).unwrap());
+        assert_eq!((Some(&b"key3"[..]), &b"val3"[..]),
+                   cursor.get(Some(&b"key2\0"[..]), None, MDB_SET_RANGE).unwrap());
+    }
+
+    #[test]
+    fn test_get_dup() {
+        let dir = TempDir::new("test").unwrap();
+        let env = Environment::new().open(dir.path()).unwrap();
+        let db = env.create_db(None, DatabaseFlags::DUP_SORT).unwrap();
+
+        let mut txn = env.begin_rw_txn().unwrap();
+        txn.put(db, b"key1", b"val1", WriteFlags::empty()).unwrap();
+        txn.put(db, b"key1", b"val2", WriteFlags::empty()).unwrap();
+        txn.put(db, b"key1", b"val3", WriteFlags::empty()).unwrap();
+        txn.put(db, b"key2", b"val1", WriteFlags::empty()).unwrap();
+        txn.put(db, b"key2", b"val2", WriteFlags::empty()).unwrap();
+        txn.put(db, b"key2", b"val3", WriteFlags::empty()).unwrap();
+
+        let cursor = txn.open_ro_cursor(db).unwrap();
+        assert_eq!((Some(&b"key1"[..]), &b"val1"[..]),
+                   cursor.get(None, None, MDB_FIRST).unwrap());
+        assert_eq!((None, &b"val1"[..]),
+                   cursor.get(None, None, MDB_FIRST_DUP).unwrap());
+        assert_eq!((Some(&b"key1"[..]), &b"val1"[..]),
+                   cursor.get(None, None, MDB_GET_CURRENT).unwrap());
+        assert_eq!((Some(&b"key2"[..]), &b"val1"[..]),
+                   cursor.get(None, None, MDB_NEXT_NODUP).unwrap());
+        assert_eq!((Some(&b"key2"[..]), &b"val2"[..]),
+                   cursor.get(None, None, MDB_NEXT_DUP).unwrap());
+        assert_eq!((Some(&b"key2"[..]), &b"val3"[..]),
+                   cursor.get(None, None, MDB_NEXT_DUP).unwrap());
+        assert!(cursor.get(None, None, MDB_NEXT_DUP).is_err());
+        assert_eq!((Some(&b"key2"[..]), &b"val2"[..]),
+                   cursor.get(None, None, MDB_PREV_DUP).unwrap());
+        assert_eq!((None, &b"val3"[..]),
+                   cursor.get(None, None, MDB_LAST_DUP).unwrap());
+        assert_eq!((Some(&b"key1"[..]), &b"val3"[..]),
+                   cursor.get(None, None, MDB_PREV_NODUP).unwrap());
+        assert_eq!((None, &b"val1"[..]),
+                   cursor.get(Some(&b"key1"[..]), None, MDB_SET).unwrap());
+        assert_eq!((Some(&b"key2"[..]), &b"val1"[..]),
+                   cursor.get(Some(&b"key2"[..]), None, MDB_SET_KEY).unwrap());
+        assert_eq!((Some(&b"key2"[..]), &b"val1"[..]),
+                   cursor.get(Some(&b"key1\0"[..]), None, MDB_SET_RANGE).unwrap());
+        assert_eq!((None, &b"val3"[..]),
+                   cursor.get(Some(&b"key1"[..]), Some(&b"val3"[..]), MDB_GET_BOTH).unwrap());
+        assert_eq!((None, &b"val1"[..]),
+                   cursor.get(Some(&b"key2"[..]), Some(&b"val"[..]), MDB_GET_BOTH_RANGE).unwrap());
+    }
+
+    #[test]
+    fn test_get_dupfixed() {
+        let dir = TempDir::new("test").unwrap();
+        let env = Environment::new().open(dir.path()).unwrap();
+        let db = env.create_db(None, DatabaseFlags::DUP_SORT | DatabaseFlags::DUP_FIXED).unwrap();
+
+        let mut txn = env.begin_rw_txn().unwrap();
+        txn.put(db, b"key1", b"val1", WriteFlags::empty()).unwrap();
+        txn.put(db, b"key1", b"val2", WriteFlags::empty()).unwrap();
+        txn.put(db, b"key1", b"val3", WriteFlags::empty()).unwrap();
+        txn.put(db, b"key2", b"val4", WriteFlags::empty()).unwrap();
+        txn.put(db, b"key2", b"val5", WriteFlags::empty()).unwrap();
+        txn.put(db, b"key2", b"val6", WriteFlags::empty()).unwrap();
+
+        let cursor = txn.open_ro_cursor(db).unwrap();
+        assert_eq!((Some(&b"key1"[..]), &b"val1"[..]),
+                   cursor.get(None, None, MDB_FIRST).unwrap());
+        assert_eq!((None, &b"val1val2val3"[..]),
+                   cursor.get(None, None, MDB_GET_MULTIPLE).unwrap());
+        assert!(cursor.get(None, None, MDB_NEXT_MULTIPLE).is_err());
+    }
+
+    #[test]
+    fn test_iter() {
+        let dir = TempDir::new("test").unwrap();
+        let env = Environment::new().open(dir.path()).unwrap();
+        let db = env.open_db(None).unwrap();
+
+        let items: Vec<(&[u8], &[u8])> = vec!((b"key1", b"val1"),
+                                              (b"key2", b"val2"),
+                                              (b"key3", b"val3"),
+                                              (b"key5", b"val5"));
+
+        {
+            let mut txn = env.begin_rw_txn().unwrap();
+            for &(ref key, ref data) in &items {
+                txn.put(db, key, data, WriteFlags::empty()).unwrap();
+            }
+            txn.commit().unwrap();
+        }
+
+        let txn = env.begin_ro_txn().unwrap();
+        let mut cursor = txn.open_ro_cursor(db).unwrap();
+        assert_eq!(items, cursor.iter().collect::<Vec<_>>());
+
+        cursor.get(Some(b"key2"), None, MDB_SET).unwrap();
+        assert_eq!(items.clone().into_iter().skip(2).collect::<Vec<_>>(),
+                   cursor.iter().collect::<Vec<_>>());
+
+        assert_eq!(items, cursor.iter_start().collect::<Vec<_>>());
+
+        assert_eq!(items.clone().into_iter().skip(1).collect::<Vec<_>>(),
+                   cursor.iter_from(b"key2").collect::<Vec<_>>());
+
+        assert_eq!(items.clone().into_iter().skip(3).collect::<Vec<_>>(),
+                   cursor.iter_from(b"key4").collect::<Vec<_>>());
+
+        assert_eq!(vec!().into_iter().collect::<Vec<(&[u8], &[u8])>>(),
+                   cursor.iter_from(b"key6").collect::<Vec<_>>());
+    }
+
+    #[test]
+    fn test_iter_dup() {
+        let dir = TempDir::new("test").unwrap();
+        let env = Environment::new().open(dir.path()).unwrap();
+        let db = env.create_db(None, DatabaseFlags::DUP_SORT).unwrap();
+
+        let items: Vec<(&[u8], &[u8])> = vec!((b"a", b"1"),
+                                              (b"a", b"2"),
+                                              (b"a", b"3"),
+                                              (b"b", b"1"),
+                                              (b"b", b"2"),
+                                              (b"b", b"3"),
+                                              (b"c", b"1"),
+                                              (b"c", b"2"),
+                                              (b"c", b"3"),
+                                              (b"e", b"1"),
+                                              (b"e", b"2"),
+                                              (b"e", b"3"));
+
+        {
+            let mut txn = env.begin_rw_txn().unwrap();
+            for &(ref key, ref data) in &items {
+                txn.put(db, key, data, WriteFlags::empty()).unwrap();
+            }
+            txn.commit().unwrap();
+        }
+
+        let txn = env.begin_ro_txn().unwrap();
+        let mut cursor = txn.open_ro_cursor(db).unwrap();
+        assert_eq!(items, cursor.iter_dup().flat_map(|x| x).collect::<Vec<_>>());
+
+        cursor.get(Some(b"b"), None, MDB_SET).unwrap();
+        assert_eq!(items.clone().into_iter().skip(4).collect::<Vec<(&[u8], &[u8])>>(),
+                   cursor.iter_dup().flat_map(|x| x).collect::<Vec<_>>());
+
+        assert_eq!(items,
+                   cursor.iter_dup_start().flat_map(|x| x).collect::<Vec<(&[u8], &[u8])>>());
+
+        assert_eq!(items.clone().into_iter().skip(3).collect::<Vec<(&[u8], &[u8])>>(),
+                   cursor.iter_dup_from(b"b").flat_map(|x| x).collect::<Vec<_>>());
+
+        assert_eq!(items.clone().into_iter().skip(3).collect::<Vec<(&[u8], &[u8])>>(),
+                   cursor.iter_dup_from(b"ab").flat_map(|x| x).collect::<Vec<_>>());
+
+        assert_eq!(items.clone().into_iter().skip(9).collect::<Vec<(&[u8], &[u8])>>(),
+                   cursor.iter_dup_from(b"d").flat_map(|x| x).collect::<Vec<_>>());
+
+        assert_eq!(vec!().into_iter().collect::<Vec<(&[u8], &[u8])>>(),
+                   cursor.iter_dup_from(b"f").flat_map(|x| x).collect::<Vec<_>>());
+
+        assert_eq!(items.clone().into_iter().skip(3).take(3).collect::<Vec<(&[u8], &[u8])>>(),
+                   cursor.iter_dup_of(b"b").unwrap().collect::<Vec<_>>());
+
+        assert!(cursor.iter_dup_of(b"foo").is_err());
+    }
+
+    #[test]
+    fn test_put_del() {
+        let dir = TempDir::new("test").unwrap();
+        let env = Environment::new().open(dir.path()).unwrap();
+        let db = env.open_db(None).unwrap();
+
+        let mut txn = env.begin_rw_txn().unwrap();
+        let mut cursor = txn.open_rw_cursor(db).unwrap();
+
+        cursor.put(b"key1", b"val1", WriteFlags::empty()).unwrap();
+        cursor.put(b"key2", b"val2", WriteFlags::empty()).unwrap();
+        cursor.put(b"key3", b"val3", WriteFlags::empty()).unwrap();
+
+        assert_eq!((Some(&b"key3"[..]), &b"val3"[..]),
+                   cursor.get(None, None, MDB_GET_CURRENT).unwrap());
+
+        cursor.del(WriteFlags::empty()).unwrap();
+        assert_eq!((Some(&b"key2"[..]), &b"val2"[..]),
+                   cursor.get(None, None, MDB_LAST).unwrap());
+    }
+
+    /// Benchmark of iterator sequential read performance.
+    #[bench]
+    fn bench_get_seq_iter(b: &mut Bencher) {
+        let n = 100;
+        let (_dir, env) = setup_bench_db(n);
+        let db = env.open_db(None).unwrap();
+        let txn = env.begin_ro_txn().unwrap();
+
+        b.iter(|| {
+            let mut cursor = txn.open_ro_cursor(db).unwrap();
+            let mut i = 0;
+            let mut count = 0u32;
+
+            for (key, data) in cursor.iter() {
+                i = i + key.len() + data.len();
+                count = count + 1;
+            }
+
+            black_box(i);
+            assert_eq!(count, n);
+        });
+    }
+
+    /// Benchmark of cursor sequential read performance.
+    #[bench]
+    fn bench_get_seq_cursor(b: &mut Bencher) {
+        let n = 100;
+        let (_dir, env) = setup_bench_db(n);
+        let db = env.open_db(None).unwrap();
+        let txn = env.begin_ro_txn().unwrap();
+
+        b.iter(|| {
+            let cursor = txn.open_ro_cursor(db).unwrap();
+            let mut i = 0;
+            let mut count = 0u32;
+
+            while let Ok((key_opt, val)) = cursor.get(None, None, MDB_NEXT) {
+                i += key_opt.map(|key| key.len()).unwrap_or(0) + val.len();
+                count += 1;
+            }
+
+            black_box(i);
+            assert_eq!(count, n);
+        });
+    }
+
+    /// Benchmark of raw LMDB sequential read performance (control).
+    #[bench]
+    fn bench_get_seq_raw(b: &mut Bencher) {
+        let n = 100;
+        let (_dir, env) = setup_bench_db(n);
+        let db = env.open_db(None).unwrap();
+
+        let dbi: MDB_dbi = db.dbi();
+        let _txn = env.begin_ro_txn().unwrap();
+        let txn = _txn.txn();
+
+        let mut key = MDB_val { mv_size: 0, mv_data: ptr::null_mut() };
+        let mut data = MDB_val { mv_size: 0, mv_data: ptr::null_mut() };
+        let mut cursor: *mut MDB_cursor = ptr::null_mut();
+
+        b.iter(|| unsafe {
+            mdb_cursor_open(txn, dbi, &mut cursor);
+            let mut i = 0;
+            let mut count = 0u32;
+
+            while mdb_cursor_get(cursor, &mut key, &mut data, MDB_NEXT) == 0 {
+                i += key.mv_size + data.mv_size;
+                count += 1;
+            };
+
+            black_box(i);
+            assert_eq!(count, n);
+            mdb_cursor_close(cursor);
+        });
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/lmdb-rkv/src/database.rs
@@ -0,0 +1,44 @@
+use libc::c_uint;
+use std::ffi::CString;
+use std::ptr;
+
+use ffi;
+
+use error::{Result, lmdb_result};
+
+/// A handle to an individual database in an environment.
+///
+/// A database handle denotes the name and parameters of a database in an environment.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub struct Database {
+    dbi: ffi::MDB_dbi,
+}
+
+impl Database {
+
+    /// Opens a new database handle in the given transaction.
+    ///
+    /// Prefer using `Environment::open_db`, `Environment::create_db`, `TransactionExt::open_db`,
+    /// or `RwTransaction::create_db`.
+    pub(crate) unsafe fn new(txn: *mut ffi::MDB_txn,
+                             name: Option<&str>,
+                             flags: c_uint)
+                             -> Result<Database> {
+        let c_name = name.map(|n| CString::new(n).unwrap());
+        let name_ptr = if let Some(ref c_name) = c_name { c_name.as_ptr() } else { ptr::null() };
+        let mut dbi: ffi::MDB_dbi = 0;
+        lmdb_result(ffi::mdb_dbi_open(txn, name_ptr, flags, &mut dbi))?;
+        Ok(Database { dbi: dbi })
+    }
+
+    /// Returns the underlying LMDB database handle.
+    ///
+    /// The caller **must** ensure that the handle is not used after the lifetime of the
+    /// environment, or after the database has been closed.
+    pub fn dbi(&self) -> ffi::MDB_dbi {
+        self.dbi
+    }
+}
+
+unsafe impl Sync for Database {}
+unsafe impl Send for Database {}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/lmdb-rkv/src/environment.rs
@@ -0,0 +1,463 @@
+use libc::{c_uint, size_t};
+use std::{fmt, ptr, result, mem};
+use std::ffi::CString;
+#[cfg(unix)]
+use std::os::unix::ffi::OsStrExt;
+#[cfg(windows)]
+use std::ffi::OsStr;
+use std::path::Path;
+use std::sync::Mutex;
+
+use ffi;
+
+use error::{Result, lmdb_result};
+use database::Database;
+use transaction::{RoTransaction, RwTransaction, Transaction};
+use flags::{DatabaseFlags, EnvironmentFlags};
+
+#[cfg(windows)]
+/// Adding a 'missing' trait from windows OsStrExt
+trait OsStrExtLmdb {
+    fn as_bytes(&self) -> &[u8];
+}
+#[cfg(windows)]
+impl OsStrExtLmdb for OsStr {
+    fn as_bytes(&self) -> &[u8] {
+        &self.to_str().unwrap().as_bytes()
+    }
+}
+
+/// An LMDB environment.
+///
+/// An environment supports multiple databases, all residing in the same shared-memory map.
+pub struct Environment {
+    env: *mut ffi::MDB_env,
+    dbi_open_mutex: Mutex<()>,
+}
+
+impl Environment {
+
+    /// Creates a new builder for specifying options for opening an LMDB environment.
+    pub fn new() -> EnvironmentBuilder {
+        EnvironmentBuilder {
+            flags: EnvironmentFlags::empty(),
+            max_readers: None,
+            max_dbs: None,
+            map_size: None
+        }
+    }
+
+    /// Returns a raw pointer to the underlying LMDB environment.
+    ///
+    /// The caller **must** ensure that the pointer is not dereferenced after the lifetime of the
+    /// environment.
+    pub fn env(&self) -> *mut ffi::MDB_env {
+        self.env
+    }
+
+    /// Opens a handle to an LMDB database.
+    ///
+    /// If `name` is `None`, then the returned handle will be for the default database.
+    ///
+    /// If `name` is not `None`, then the returned handle will be for a named database. In this
+    /// case the environment must be configured to allow named databases through
+    /// `EnvironmentBuilder::set_max_dbs`.
+    ///
+    /// The returned database handle may be shared among any transaction in the environment.
+    ///
+    /// This function will fail with `Error::BadRslot` if called by a thread which has an ongoing
+    /// transaction.
+    ///
+    /// The database name may not contain the null character.
+    pub fn open_db<'env>(&'env self, name: Option<&str>) -> Result<Database> {
+        let mutex = self.dbi_open_mutex.lock();
+        let txn = self.begin_ro_txn()?;
+        let db = unsafe { txn.open_db(name)? };
+        txn.commit()?;
+        drop(mutex);
+        Ok(db)
+    }
+
+    /// Opens a handle to an LMDB database, creating the database if necessary.
+    ///
+    /// If the database is already created, the given option flags will be added to it.
+    ///
+    /// If `name` is `None`, then the returned handle will be for the default database.
+    ///
+    /// If `name` is not `None`, then the returned handle will be for a named database. In this
+    /// case the environment must be configured to allow named databases through
+    /// `EnvironmentBuilder::set_max_dbs`.
+    ///
+    /// The returned database handle may be shared among any transaction in the environment.
+    ///
+    /// This function will fail with `Error::BadRslot` if called by a thread with an open
+    /// transaction.
+    pub fn create_db<'env>(&'env self,
+                           name: Option<&str>,
+                           flags: DatabaseFlags)
+                           -> Result<Database> {
+        let mutex = self.dbi_open_mutex.lock();
+        let txn = self.begin_rw_txn()?;
+        let db = unsafe { txn.create_db(name, flags)? };
+        txn.commit()?;
+        drop(mutex);
+        Ok(db)
+    }
+
+    /// Retrieves the set of flags which the database is opened with.
+    ///
+    /// The database must belong to to this environment.
+    pub fn get_db_flags<'env>(&'env self, db: Database) -> Result<DatabaseFlags> {
+        let txn = self.begin_ro_txn()?;
+        let mut flags: c_uint = 0;
+        unsafe {
+            lmdb_result(ffi::mdb_dbi_flags(txn.txn(), db.dbi(), &mut flags))?;
+        }
+        Ok(DatabaseFlags::from_bits(flags).unwrap())
+    }
+
+    /// Create a read-only transaction for use with the environment.
+    pub fn begin_ro_txn<'env>(&'env self) -> Result<RoTransaction<'env>> {
+        RoTransaction::new(self)
+    }
+
+    /// Create a read-write transaction for use with the environment. This method will block while
+    /// there are any other read-write transactions open on the environment.
+    pub fn begin_rw_txn<'env>(&'env self) -> Result<RwTransaction<'env>> {
+        RwTransaction::new(self)
+    }
+
+    /// Flush data buffers to disk.
+    ///
+    /// Data is always written to disk when `Transaction::commit` is called, but the operating
+    /// system may keep it buffered. LMDB always flushes the OS buffers upon commit as well, unless
+    /// the environment was opened with `MDB_NOSYNC` or in part `MDB_NOMETASYNC`.
+    pub fn sync(&self, force: bool) -> Result<()> {
+        unsafe {
+            lmdb_result(ffi::mdb_env_sync(self.env(), if force { 1 } else { 0 }))
+        }
+    }
+
+    /// Closes the database handle. Normally unnecessary.
+    ///
+    /// Closing a database handle is not necessary, but lets `Transaction::open_database` reuse the
+    /// handle value. Usually it's better to set a bigger `EnvironmentBuilder::set_max_dbs`, unless
+    /// that value would be large.
+    ///
+    /// ## Safety
+    ///
+    /// This call is not mutex protected. Databases should only be closed by a single thread, and
+    /// only if no other threads are going to reference the database handle or one of its cursors
+    /// any further. Do not close a handle if an existing transaction has modified its database.
+    /// Doing so can cause misbehavior from database corruption to errors like
+    /// `Error::BadValSize` (since the DB name is gone).
+    pub unsafe fn close_db(&mut self, db: Database) {
+        ffi::mdb_dbi_close(self.env, db.dbi());
+    }
+
+    /// Retrieves statistics about this environment.
+    pub fn stat(&self) -> Result<Stat> {
+        unsafe {
+            let mut stat = Stat(mem::zeroed());
+            lmdb_try!(ffi::mdb_env_stat(self.env(), &mut stat.0));
+            Ok(stat)
+        }
+    }
+}
+
+/// Environment statistics.
+///
+/// Contains information about the size and layout of an LMDB environment.
+pub struct Stat(ffi::MDB_stat);
+
+impl Stat {
+    /// Size of a database page. This is the same for all databases in the environment.
+    #[inline]
+    pub fn page_size(&self) -> u32 {
+        self.0.ms_psize
+    }
+
+    /// Depth (height) of the B-tree.
+    #[inline]
+    pub fn depth(&self) -> u32 {
+        self.0.ms_depth
+    }
+
+    /// Number of internal (non-leaf) pages.
+    #[inline]
+    pub fn branch_pages(&self) -> usize {
+        self.0.ms_branch_pages
+    }
+
+    /// Number of leaf pages.
+    #[inline]
+    pub fn leaf_pages(&self) -> usize {
+        self.0.ms_leaf_pages
+    }
+
+    /// Number of overflow pages.
+    #[inline]
+    pub fn overflow_pages(&self) -> usize {
+        self.0.ms_overflow_pages
+    }
+
+    /// Number of data items.
+    #[inline]
+    pub fn entries(&self) -> usize {
+        self.0.ms_entries
+    }
+}
+
+unsafe impl Send for Environment {}
+unsafe impl Sync for Environment {}
+
+impl fmt::Debug for Environment {
+    fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
+        f.debug_struct("Environment").finish()
+    }
+}
+
+impl Drop for Environment {
+    fn drop(&mut self) {
+        unsafe { ffi::mdb_env_close(self.env) }
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+//// Environment Builder
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+/// Options for opening or creating an environment.
+#[derive(Debug, PartialEq, Eq, Copy, Clone)]
+pub struct EnvironmentBuilder {
+    flags: EnvironmentFlags,
+    max_readers: Option<c_uint>,
+    max_dbs: Option<c_uint>,
+    map_size: Option<size_t>,
+}
+
+impl EnvironmentBuilder {
+
+    /// Open an environment.
+    ///
+    /// On UNIX, the database files will be opened with 644 permissions.
+    ///
+    /// The path may not contain the null character.
+    pub fn open(&self, path: &Path) -> Result<Environment> {
+        self.open_with_permissions(path, 0o644)
+    }
+
+    /// Open an environment with the provided UNIX permissions.
+    ///
+    /// On Windows, the permissions will be ignored.
+    ///
+    /// The path may not contain the null character.
+    pub fn open_with_permissions(&self, path: &Path, mode: ffi::mode_t) -> Result<Environment> {
+        let mut env: *mut ffi::MDB_env = ptr::null_mut();
+        unsafe {
+            lmdb_try!(ffi::mdb_env_create(&mut env));
+            if let Some(max_readers) = self.max_readers {
+                lmdb_try_with_cleanup!(ffi::mdb_env_set_maxreaders(env, max_readers),
+                                       ffi::mdb_env_close(env))
+            }
+            if let Some(max_dbs) = self.max_dbs {
+                lmdb_try_with_cleanup!(ffi::mdb_env_set_maxdbs(env, max_dbs),
+                                       ffi::mdb_env_close(env))
+            }
+            if let Some(map_size) = self.map_size {
+                lmdb_try_with_cleanup!(ffi::mdb_env_set_mapsize(env, map_size),
+                                       ffi::mdb_env_close(env))
+            }
+            let path = match CString::new(path.as_os_str().as_bytes()) {
+                Ok(path) => path,
+                Err(..) => return Err(::Error::Invalid),
+            };
+            lmdb_try_with_cleanup!(ffi::mdb_env_open(env, path.as_ptr(), self.flags.bits(), mode),
+                                   ffi::mdb_env_close(env));
+        }
+        Ok(Environment { env: env, dbi_open_mutex: Mutex::new(()) })
+
+    }
+
+    /// Sets the provided options in the environment.
+    pub fn set_flags(&mut self, flags: EnvironmentFlags) -> &mut EnvironmentBuilder {
+        self.flags = flags;
+        self
+    }
+
+    /// Sets the maximum number of threads or reader slots for the environment.
+    ///
+    /// This defines the number of slots in the lock table that is used to track readers in the
+    /// the environment. The default is 126. Starting a read-only transaction normally ties a lock
+    /// table slot to the current thread until the environment closes or the thread exits. If
+    /// `MDB_NOTLS` is in use, `Environment::open_txn` instead ties the slot to the `Transaction`
+    /// object until it or the `Environment` object is destroyed.
+    pub fn set_max_readers(&mut self, max_readers: c_uint) -> &mut EnvironmentBuilder {
+        self.max_readers = Some(max_readers);
+        self
+    }
+
+    /// Sets the maximum number of named databases for the environment.
+    ///
+    /// This function is only needed if multiple databases will be used in the
+    /// environment. Simpler applications that use the environment as a single
+    /// unnamed database can ignore this option.
+    ///
+    /// Currently a moderate number of slots are cheap but a huge number gets
+    /// expensive: 7-120 words per transaction, and every `Transaction::open_db`
+    /// does a linear search of the opened slots.
+    pub fn set_max_dbs(&mut self, max_readers: c_uint) -> &mut EnvironmentBuilder {
+        self.max_dbs = Some(max_readers);
+        self
+    }
+
+    /// Sets the size of the memory map to use for the environment.
+    ///
+    /// The size should be a multiple of the OS page size. The default is
+    /// 10485760 bytes. The size of the memory map is also the maximum size
+    /// of the database. The value should be chosen as large as possible,
+    /// to accommodate future growth of the database. It may be increased at
+    /// later times.
+    ///
+    /// Any attempt to set a size smaller than the space already consumed
+    /// by the environment will be silently changed to the current size of the used space.
+    pub fn set_map_size(&mut self, map_size: size_t) -> &mut EnvironmentBuilder {
+        self.map_size = Some(map_size);
+        self
+    }
+}
+
+#[cfg(test)]
+mod test {
+
+    extern crate byteorder;
+
+    use tempdir::TempDir;
+    use self::byteorder::{ByteOrder, LittleEndian};
+
+    use flags::*;
+
+    use super::*;
+
+    #[test]
+    fn test_open() {
+        let dir = TempDir::new("test").unwrap();
+
+        // opening non-existent env with read-only should fail
+        assert!(Environment::new().set_flags(EnvironmentFlags::READ_ONLY)
+                                  .open(dir.path())
+                                  .is_err());
+
+        // opening non-existent env should succeed
+        assert!(Environment::new().open(dir.path()).is_ok());
+
+        // opening env with read-only should succeed
+        assert!(Environment::new().set_flags(EnvironmentFlags::READ_ONLY)
+                                  .open(dir.path())
+                                  .is_ok());
+    }
+
+    #[test]
+    fn test_begin_txn() {
+        let dir = TempDir::new("test").unwrap();
+
+        { // writable environment
+            let env = Environment::new().open(dir.path()).unwrap();
+
+            assert!(env.begin_rw_txn().is_ok());
+            assert!(env.begin_ro_txn().is_ok());
+        }
+
+        { // read-only environment
+            let env = Environment::new().set_flags(EnvironmentFlags::READ_ONLY)
+                                        .open(dir.path())
+                                        .unwrap();
+
+            assert!(env.begin_rw_txn().is_err());
+            assert!(env.begin_ro_txn().is_ok());
+        }
+    }
+
+    #[test]
+    fn test_open_db() {
+        let dir = TempDir::new("test").unwrap();
+        let env = Environment::new().set_max_dbs(1)
+                                    .open(dir.path())
+                                    .unwrap();
+
+        assert!(env.open_db(None).is_ok());
+        assert!(env.open_db(Some("testdb")).is_err());
+    }
+
+    #[test]
+    fn test_create_db() {
+        let dir = TempDir::new("test").unwrap();
+        let env = Environment::new().set_max_dbs(11)
+                                    .open(dir.path())
+                                    .unwrap();
+        assert!(env.open_db(Some("testdb")).is_err());
+        assert!(env.create_db(Some("testdb"), DatabaseFlags::empty()).is_ok());
+        assert!(env.open_db(Some("testdb")).is_ok())
+    }
+
+    #[test]
+    fn test_close_database() {
+        let dir = TempDir::new("test").unwrap();
+        let mut env = Environment::new().set_max_dbs(10)
+                                        .open(dir.path())
+                                        .unwrap();
+
+        let db = env.create_db(Some("db"), DatabaseFlags::empty()).unwrap();
+        unsafe { env.close_db(db); }
+        assert!(env.open_db(Some("db")).is_ok());
+    }
+
+    #[test]
+    fn test_sync() {
+        let dir = TempDir::new("test").unwrap();
+        {
+            let env = Environment::new().open(dir.path()).unwrap();
+            assert!(env.sync(true).is_ok());
+        } {
+            let env = Environment::new().set_flags(EnvironmentFlags::READ_ONLY)
+                                        .open(dir.path())
+                                        .unwrap();
+            assert!(env.sync(true).is_err());
+        }
+    }
+
+    #[test]
+    fn test_stat() {
+        let dir = TempDir::new("test").unwrap();
+        let env = Environment::new().open(dir.path()).unwrap();
+
+        // Stats should be empty initially.
+        let stat = env.stat().unwrap();
+        assert_eq!(stat.page_size(), 4096);
+        assert_eq!(stat.depth(), 0);
+        assert_eq!(stat.branch_pages(), 0);
+        assert_eq!(stat.leaf_pages(), 0);
+        assert_eq!(stat.overflow_pages(), 0);
+        assert_eq!(stat.entries(), 0);
+
+        let db = env.open_db(None).unwrap();
+
+        // Write a few small values.
+        for i in 0..64 {
+            let mut value = [0u8; 8];
+            LittleEndian::write_u64(&mut value, i);
+            let mut tx = env.begin_rw_txn().expect("begin_rw_txn");
+            tx.put(db, &value, &value, WriteFlags::default()).expect("tx.put");
+            tx.commit().expect("tx.commit")
+        }
+
+        // Stats should now reflect inserted values.
+        let stat = env.stat().unwrap();
+        assert_eq!(stat.page_size(), 4096);
+        assert_eq!(stat.depth(), 1);
+        assert_eq!(stat.branch_pages(), 0);
+        assert_eq!(stat.leaf_pages(), 1);
+        assert_eq!(stat.overflow_pages(), 0);
+        assert_eq!(stat.entries(), 64);
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/lmdb-rkv/src/error.rs
@@ -0,0 +1,154 @@
+use libc::c_int;
+use std::error::Error as StdError;
+use std::ffi::CStr;
+use std::os::raw::c_char;
+use std::{fmt, result, str};
+
+use ffi;
+
+/// An LMDB error kind.
+#[derive(Debug, Eq, PartialEq, Copy, Clone)]
+pub enum Error {
+    /// key/data pair already exists.
+    KeyExist,
+    /// key/data pair not found (EOF).
+    NotFound,
+    /// Requested page not found - this usually indicates corruption.
+    PageNotFound,
+    /// Located page was wrong type.
+    Corrupted,
+    /// Update of meta page failed or environment had fatal error.
+    Panic,
+    /// Environment version mismatch.
+    VersionMismatch,
+    /// File is not a valid LMDB file.
+    Invalid,
+    /// Environment mapsize reached.
+    MapFull,
+    /// Environment maxdbs reached.
+    DbsFull,
+    /// Environment maxreaders reached.
+    ReadersFull,
+    /// Too many TLS keys in use - Windows only.
+    TlsFull,
+    /// Txn has too many dirty pages.
+    TxnFull,
+    /// Cursor stack too deep - internal error.
+    CursorFull,
+    /// Page has not enough space - internal error.
+    PageFull,
+    /// Database contents grew beyond environment mapsize.
+    MapResized,
+    /// MDB_Incompatible: Operation and DB incompatible, or DB flags changed.
+    Incompatible,
+    /// Invalid reuse of reader locktable slot.
+    BadRslot,
+    /// Transaction cannot recover - it must be aborted.
+    BadTxn,
+    /// Unsupported size of key/DB name/data, or wrong DUP_FIXED size.
+    BadValSize,
+    /// The specified DBI was changed unexpectedly.
+    BadDbi,
+    /// Other error.
+    Other(c_int),
+}
+
+impl Error {
+
+    /// Converts a raw error code to an `Error`.
+    pub fn from_err_code(err_code: c_int) -> Error {
+        match err_code {
+            ffi::MDB_KEYEXIST         => Error::KeyExist,
+            ffi::MDB_NOTFOUND         => Error::NotFound,
+            ffi::MDB_PAGE_NOTFOUND    => Error::PageNotFound,
+            ffi::MDB_CORRUPTED        => Error::Corrupted,
+            ffi::MDB_PANIC            => Error::Panic,
+            ffi::MDB_VERSION_MISMATCH => Error::VersionMismatch,
+            ffi::MDB_INVALID          => Error::Invalid,
+            ffi::MDB_MAP_FULL         => Error::MapFull,
+            ffi::MDB_DBS_FULL         => Error::DbsFull,
+            ffi::MDB_READERS_FULL     => Error::ReadersFull,
+            ffi::MDB_TLS_FULL         => Error::TlsFull,
+            ffi::MDB_TXN_FULL         => Error::TxnFull,
+            ffi::MDB_CURSOR_FULL      => Error::CursorFull,
+            ffi::MDB_PAGE_FULL        => Error::PageFull,
+            ffi::MDB_MAP_RESIZED      => Error::MapResized,
+            ffi::MDB_INCOMPATIBLE     => Error::Incompatible,
+            ffi::MDB_BAD_RSLOT        => Error::BadRslot,
+            ffi::MDB_BAD_TXN          => Error::BadTxn,
+            ffi::MDB_BAD_VALSIZE      => Error::BadValSize,
+            ffi::MDB_BAD_DBI          => Error::BadDbi,
+            other                     => Error::Other(other),
+        }
+    }
+
+    /// Converts an `Error` to the raw error code.
+    pub fn to_err_code(&self) -> c_int {
+        match *self {
+            Error::KeyExist        => ffi::MDB_KEYEXIST,
+            Error::NotFound        => ffi::MDB_NOTFOUND,
+            Error::PageNotFound    => ffi::MDB_PAGE_NOTFOUND,
+            Error::Corrupted       => ffi::MDB_CORRUPTED,
+            Error::Panic           => ffi::MDB_PANIC,
+            Error::VersionMismatch => ffi::MDB_VERSION_MISMATCH,
+            Error::Invalid         => ffi::MDB_INVALID,
+            Error::MapFull         => ffi::MDB_MAP_FULL,
+            Error::DbsFull         => ffi::MDB_DBS_FULL,
+            Error::ReadersFull     => ffi::MDB_READERS_FULL,
+            Error::TlsFull         => ffi::MDB_TLS_FULL,
+            Error::TxnFull         => ffi::MDB_TXN_FULL,
+            Error::CursorFull      => ffi::MDB_CURSOR_FULL,
+            Error::PageFull        => ffi::MDB_PAGE_FULL,
+            Error::MapResized      => ffi::MDB_MAP_RESIZED,
+            Error::Incompatible    => ffi::MDB_INCOMPATIBLE,
+            Error::BadRslot        => ffi::MDB_BAD_RSLOT,
+            Error::BadTxn          => ffi::MDB_BAD_TXN,
+            Error::BadValSize      => ffi::MDB_BAD_VALSIZE,
+            Error::BadDbi          => ffi::MDB_BAD_DBI,
+            Error::Other(err_code) => err_code,
+        }
+    }
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        write!(fmt, "{}", self.description())
+    }
+}
+
+impl StdError for Error {
+    fn description(&self) -> &str {
+        unsafe {
+            // This is safe since the error messages returned from mdb_strerror are static.
+            let err: *const c_char = ffi::mdb_strerror(self.to_err_code()) as *const c_char;
+            str::from_utf8_unchecked(CStr::from_ptr(err).to_bytes())
+        }
+    }
+}
+
+/// An LMDB result.
+pub type Result<T> = result::Result<T, Error>;
+
+pub fn lmdb_result(err_code: c_int) -> Result<()> {
+    if err_code == ffi::MDB_SUCCESS {
+        Ok(())
+    } else {
+        Err(Error::from_err_code(err_code))
+    }
+}
+
+#[cfg(test)]
+mod test {
+
+    use std::error::Error as StdError;
+
+    use super::*;
+
+    #[test]
+    fn test_description() {
+        assert_eq!("Permission denied",
+                   Error::from_err_code(13).description());
+        assert_eq!("MDB_NOTFOUND: No matching key/data pair found",
+                   Error::NotFound.description());
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/lmdb-rkv/src/flags.rs
@@ -0,0 +1,173 @@
+use libc::c_uint;
+
+use ffi::*;
+
+bitflags! {
+    #[doc="Environment options."]
+    #[derive(Default)]
+    pub struct EnvironmentFlags: c_uint {
+
+        #[doc="Use a fixed address for the mmap region. This flag must be specified"]
+        #[doc="when creating the environment, and is stored persistently in the environment."]
+        #[doc="If successful, the memory map will always reside at the same virtual address"]
+        #[doc="and pointers used to reference data items in the database will be constant"]
+        #[doc="across multiple invocations. This option may not always work, depending on"]
+        #[doc="how the operating system has allocated memory to shared libraries and other uses."]
+        #[doc="The feature is highly experimental."]
+        const FIXED_MAP = MDB_FIXEDMAP;
+
+        #[doc="By default, LMDB creates its environment in a directory whose pathname is given in"]
+        #[doc="`path`, and creates its data and lock files under that directory. With this option,"]
+        #[doc="`path` is used as-is for the database main data file. The database lock file is the"]
+        #[doc="`path` with `-lock` appended."]
+        const NO_SUB_DIR = MDB_NOSUBDIR;
+
+        #[doc="Use a writeable memory map unless `READ_ONLY` is set. This is faster and uses"]
+        #[doc="fewer mallocs, but loses protection from application bugs like wild pointer writes"]
+        #[doc="and other bad updates into the database. Incompatible with nested transactions."]
+        #[doc="Processes with and without `WRITE_MAP` on the same environment do not cooperate"]
+        #[doc="well."]
+        const WRITE_MAP = MDB_WRITEMAP;
+
+        #[doc="Open the environment in read-only mode. No write operations will be allowed."]
+        #[doc="When opening an environment, LMDB will still modify the lock file - except on"]
+        #[doc="read-only filesystems, where LMDB does not use locks."]
+        const READ_ONLY = MDB_RDONLY;
+
+        #[doc="Flush system buffers to disk only once per transaction, omit the metadata flush."]
+        #[doc="Defer that until the system flushes files to disk, or next non-`READ_ONLY` commit"]
+        #[doc="or `Environment::sync`. This optimization maintains database integrity, but a"]
+        #[doc="system crash may undo the last committed transaction. I.e. it preserves the ACI"]
+        #[doc="(atomicity, consistency, isolation) but not D (durability) database property."]
+        #[doc="\n\nThis flag may be changed at any time using `Environment::set_flags`."]
+        const NO_META_SYNC = MDB_NOMETASYNC;
+
+        #[doc="Don't flush system buffers to disk when committing a transaction. This optimization"]
+        #[doc="means a system crash can corrupt the database or lose the last transactions if"]
+        #[doc="buffers are not yet flushed to disk. The risk is governed by how often the system"]
+        #[doc="flushes dirty buffers to disk and how often `Environment::sync` is called. However,"]
+        #[doc="if the filesystem preserves write order and the `WRITE_MAP` flag is not used,"]
+        #[doc="transactions exhibit ACI (atomicity, consistency, isolation) properties and only"]
+        #[doc="lose D (durability). I.e. database integrity is maintained, but a system"]
+        #[doc="crash may undo the final transactions. Note that (`NO_SYNC | WRITE_MAP`) leaves the"]
+        #[doc="system with no hint for when to write transactions to disk, unless"]
+        #[doc="`Environment::sync` is called. (`MAP_ASYNC | WRITE_MAP`) may be preferable."]
+        #[doc="\n\nThis flag may be changed at any time using `Environment::set_flags`."]
+        const NO_SYNC = MDB_NOSYNC;
+
+        #[doc="When using `WRITE_MAP`, use asynchronous flushes to disk. As with `NO_SYNC`, a"]
+        #[doc="system crash can then corrupt the database or lose the last transactions. Calling"]
+        #[doc="`Environment::sync` ensures on-disk database integrity until next commit."]
+        #[doc="\n\nThis flag may be changed at any time using `Environment::set_flags`."]
+        const MAP_ASYNC = MDB_MAPASYNC;
+
+        #[doc="Don't use thread-local storage. Tie reader locktable slots to transaction objects"]
+        #[doc="instead of to threads. I.e. `RoTransaction::reset` keeps the slot reserved for the"]
+        #[doc="transaction object. A thread may use parallel read-only transactions. A read-only"]
+        #[doc="transaction may span threads if the user synchronizes its use. Applications that"]
+        #[doc="multiplex many the user synchronizes its use. Applications that multiplex many user"]
+        #[doc="threads over individual OS threads need this option. Such an application must also"]
+        #[doc="serialize the write transactions in an OS thread, since LMDB's write locking is"]
+        #[doc="unaware of the user threads."]
+        const NO_TLS = MDB_NOTLS;
+
+        #[doc="Do not do any locking. If concurrent access is anticipated, the caller must manage"]
+        #[doc="all concurrency themself. For proper operation the caller must enforce"]
+        #[doc="single-writer semantics, and must ensure that no readers are using old"]
+        #[doc="transactions while a writer is active. The simplest approach is to use an exclusive"]
+        #[doc="lock so that no readers may be active at all when a writer begins."]
+        const NO_LOCK = MDB_NOLOCK;
+
+        #[doc="Turn off readahead. Most operating systems perform readahead on read requests by"]
+        #[doc="default. This option turns it off if the OS supports it. Turning it off may help"]
+        #[doc="random read performance when the DB is larger than RAM and system RAM is full."]
+        #[doc="The option is not implemented on Windows."]
+        const NO_READAHEAD = MDB_NORDAHEAD;
+
+        #[doc="Do not initialize malloc'd memory before writing to unused spaces in the data file."]
+        #[doc="By default, memory for pages written to the data file is obtained using malloc."]
+        #[doc="While these pages may be reused in subsequent transactions, freshly malloc'd pages"]
+        #[doc="will be initialized to zeroes before use. This avoids persisting leftover data from"]
+        #[doc="other code (that used the heap and subsequently freed the memory) into the data"]
+        #[doc="file. Note that many other system libraries may allocate and free memory from the"]
+        #[doc="heap for arbitrary uses. E.g., stdio may use the heap for file I/O buffers. This"]
+        #[doc="initialization step has a modest performance cost so some applications may want to"]
+        #[doc="disable it using this flag. This option can be a problem for applications which"]
+        #[doc="handle sensitive data like passwords, and it makes memory checkers like Valgrind"]
+        #[doc="noisy. This flag is not needed with `WRITE_MAP`, which writes directly to the mmap"]
+        #[doc="instead of using malloc for pages. The initialization is also skipped if writing"]
+        #[doc="with reserve; the caller is expected to overwrite all of the memory that was"]
+        #[doc="reserved in that case."]
+        #[doc="\n\nThis flag may be changed at any time using `Environment::set_flags`."]
+        const NO_MEM_INIT = MDB_NOMEMINIT;
+    }
+}
+
+bitflags! {
+    #[doc="Database options."]
+    #[derive(Default)]
+    pub struct DatabaseFlags: c_uint {
+
+        #[doc="Keys are strings to be compared in reverse order, from the end of the strings"]
+        #[doc="to the beginning. By default, Keys are treated as strings and compared from"]
+        #[doc="beginning to end."]
+        const REVERSE_KEY = MDB_REVERSEKEY;
+
+        #[doc="Duplicate keys may be used in the database. (Or, from another perspective,"]
+        #[doc="keys may have multiple data items, stored in sorted order.) By default"]
+        #[doc="keys must be unique and may have only a single data item."]
+        const DUP_SORT = MDB_DUPSORT;
+
+        #[doc="Keys are binary integers in native byte order. Setting this option requires all"]
+        #[doc="keys to be the same size, typically 32 or 64 bits."]
+        const INTEGER_KEY = MDB_INTEGERKEY;
+
+        #[doc="This flag may only be used in combination with `DUP_SORT`. This option tells"]
+        #[doc="the library that the data items for this database are all the same size, which"]
+        #[doc="allows further optimizations in storage and retrieval. When all data items are"]
+        #[doc="the same size, the `GET_MULTIPLE` and `NEXT_MULTIPLE` cursor operations may be"]
+        #[doc="used to retrieve multiple items at once."]
+        const DUP_FIXED = MDB_DUPFIXED;
+
+        #[doc="This option specifies that duplicate data items are also integers, and"]
+        #[doc="should be sorted as such."]
+        const INTEGER_DUP = MDB_INTEGERDUP;
+
+        #[doc="This option specifies that duplicate data items should be compared as strings"]
+        #[doc="in reverse order."]
+        const REVERSE_DUP = MDB_REVERSEDUP;
+    }
+}
+
+bitflags! {
+    #[doc="Write options."]
+    #[derive(Default)]
+    pub struct WriteFlags: c_uint {
+
+        #[doc="Insert the new item only if the key does not already appear in the database."]
+        #[doc="The function will return `LmdbError::KeyExist` if the key already appears in the"]
+        #[doc="database, even if the database supports duplicates (`DUP_SORT`)."]
+        const NO_OVERWRITE = MDB_NOOVERWRITE;
+
+        #[doc="Insert the new item only if it does not already appear in the database."]
+        #[doc="This flag may only be specified if the database was opened with `DUP_SORT`."]
+        #[doc="The function will return `LmdbError::KeyExist` if the item already appears in the"]
+        #[doc="database."]
+        const NO_DUP_DATA = MDB_NODUPDATA;
+
+        #[doc="For `Cursor::put`. Replace the item at the current cursor position. The key"]
+        #[doc="parameter must match the current position. If using sorted duplicates (`DUP_SORT`)"]
+        #[doc="the data item must still sort into the same position. This is intended to be used"]
+        #[doc="when the new data is the same size as the old. Otherwise it will simply perform a"]
+        #[doc="delete of the old record followed by an insert."]
+        const CURRENT = MDB_CURRENT;
+
+        #[doc="Append the given item to the end of the database. No key comparisons are performed."]
+        #[doc="This option allows fast bulk loading when keys are already known to be in the"]
+        #[doc="correct order. Loading unsorted keys with this flag will cause data corruption."]
+        const APPEND = MDB_APPEND;
+
+        #[doc="Same as `APPEND`, but for sorted dup data."]
+        const APPEND_DUP = MDB_APPENDDUP;
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/lmdb-rkv/src/lib.rs
@@ -0,0 +1,123 @@
+//! Idiomatic and safe APIs for interacting with the
+//! [Lightning Memory-mapped Database (LMDB)](https://symas.com/lmdb).
+
+#![cfg_attr(test, feature(test))]
+#![deny(missing_docs)]
+#![doc(html_root_url = "https://docs.rs/lmdb-rkv/0.8.1")]
+
+extern crate libc;
+extern crate lmdb_sys as ffi;
+
+#[cfg(test)] extern crate rand;
+#[cfg(test)] extern crate tempdir;
+#[cfg(test)] extern crate test;
+#[macro_use] extern crate bitflags;
+
+pub use cursor::{
+    Cursor,
+    RoCursor,
+    RwCursor,
+    Iter,
+    IterDup,
+};
+pub use database::Database;
+pub use environment::{Environment, Stat, EnvironmentBuilder};
+pub use error::{Error, Result};
+pub use flags::*;
+pub use transaction::{
+    InactiveTransaction,
+    RoTransaction,
+    RwTransaction,
+    Transaction,
+};
+
+macro_rules! lmdb_try {
+    ($expr:expr) => ({
+        match $expr {
+            ::ffi::MDB_SUCCESS => (),
+            err_code => return Err(::Error::from_err_code(err_code)),
+        }
+    })
+}
+
+macro_rules! lmdb_try_with_cleanup {
+    ($expr:expr, $cleanup:expr) => ({
+        match $expr {
+            ::ffi::MDB_SUCCESS => (),
+            err_code => {
+                let _ = $cleanup;
+                return Err(::Error::from_err_code(err_code))
+            },
+        }
+    })
+}
+
+mod flags;
+mod cursor;
+mod database;
+mod environment;
+mod error;
+mod transaction;
+
+#[cfg(test)]
+mod test_utils {
+
+    extern crate byteorder;
+
+    use self::byteorder::{ByteOrder, LittleEndian};
+    use tempdir::TempDir;
+
+    use super::*;
+
+    pub fn get_key(n: u32) -> String {
+        format!("key{}", n)
+    }
+
+    pub fn get_data(n: u32) -> String {
+        format!("data{}", n)
+    }
+
+    pub fn setup_bench_db<'a>(num_rows: u32) -> (TempDir, Environment) {
+        let dir = TempDir::new("test").unwrap();
+        let env = Environment::new().open(dir.path()).unwrap();
+
+        {
+            let db = env.open_db(None).unwrap();
+            let mut txn = env.begin_rw_txn().unwrap();
+            for i in 0..num_rows {
+                txn.put(db, &get_key(i), &get_data(i), WriteFlags::empty()).unwrap();
+            }
+            txn.commit().unwrap();
+        }
+        (dir, env)
+    }
+
+    /// Regression test for https://github.com/danburkert/lmdb-rs/issues/21.
+    /// This test reliably segfaults when run against lmbdb compiled with opt level -O3 and newer
+    /// GCC compilers.
+    #[test]
+    fn issue_21_regression() {
+        const HEIGHT_KEY: [u8; 1] = [0];
+
+        let dir = TempDir::new("test").unwrap();
+
+        let env = {
+            let mut builder = Environment::new();
+            builder.set_max_dbs(2);
+            builder.set_map_size(1_000_000);
+            builder.open(dir.path()).expect("open lmdb env")
+        };
+        let index = env.create_db(None, DatabaseFlags::DUP_SORT).expect("open index db");
+
+        for height in 0..1000 {
+            let mut value = [0u8; 8];
+            LittleEndian::write_u64(&mut value, height);
+            let mut tx = env.begin_rw_txn().expect("begin_rw_txn");
+            tx.put(index,
+                   &HEIGHT_KEY,
+                   &value,
+                   WriteFlags::empty()).expect("tx.put");
+            tx.commit().expect("tx.commit")
+        }
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/lmdb-rkv/src/transaction.rs
@@ -0,0 +1,699 @@
+use libc::{c_uint, c_void, size_t};
+use std::{fmt, mem, ptr, result, slice};
+use std::marker::PhantomData ;
+
+use ffi;
+
+use cursor::{RoCursor, RwCursor};
+use environment::Environment;
+use database::Database;
+use error::{Error, Result, lmdb_result};
+use flags::{DatabaseFlags, EnvironmentFlags, WriteFlags};
+
+/// An LMDB transaction.
+///
+/// All database operations require a transaction.
+pub trait Transaction : Sized {
+
+    /// Returns a raw pointer to the underlying LMDB transaction.
+    ///
+    /// The caller **must** ensure that the pointer is not used after the
+    /// lifetime of the transaction.
+    fn txn(&self) -> *mut ffi::MDB_txn;
+
+    /// Commits the transaction.
+    ///
+    /// Any pending operations will be saved.
+    fn commit(self) -> Result<()> {
+        unsafe {
+            let result = lmdb_result(ffi::mdb_txn_commit(self.txn()));
+            mem::forget(self);
+            result
+        }
+    }
+
+    /// Aborts the transaction.
+    ///
+    /// Any pending operations will not be saved.
+    fn abort(self) {
+        // Abort should be performed in transaction destructors.
+    }
+
+    /// Opens a database in the transaction.
+    ///
+    /// If `name` is `None`, then the default database will be opened, otherwise
+    /// a named database will be opened. The database handle will be private to
+    /// the transaction until the transaction is successfully committed. If the
+    /// transaction is aborted the returned database handle should no longer be
+    /// used.
+    ///
+    /// Prefer using `Environment::open_db`.
+    ///
+    /// ## Safety
+    ///
+    /// This function (as well as `Environment::open_db`,
+    /// `Environment::create_db`, and `Database::create`) **must not** be called
+    /// from multiple concurrent transactions in the same environment. A
+    /// transaction which uses this function must finish (either commit or
+    /// abort) before any other transaction may use this function.
+    unsafe fn open_db(&self, name: Option<&str>) -> Result<Database> {
+        Database::new(self.txn(), name, 0)
+    }
+
+    /// Gets an item from a database.
+    ///
+    /// This function retrieves the data associated with the given key in the
+    /// database. If the database supports duplicate keys
+    /// (`DatabaseFlags::DUP_SORT`) then the first data item for the key will be
+    /// returned. Retrieval of other items requires the use of
+    /// `Transaction::cursor_get`. If the item is not in the database, then
+    /// `Error::NotFound` will be returned.
+    fn get<'txn, K>(&'txn self,
+                    database: Database,
+                    key: &K)
+                    -> Result<&'txn [u8]>
+    where K: AsRef<[u8]> {
+        let key = key.as_ref();
+        let mut key_val: ffi::MDB_val = ffi::MDB_val { mv_size: key.len() as size_t,
+                                                       mv_data: key.as_ptr() as *mut c_void };
+        let mut data_val: ffi::MDB_val = ffi::MDB_val { mv_size: 0,
+                                                        mv_data: ptr::null_mut() };
+        unsafe {
+            match ffi::mdb_get(self.txn(), database.dbi(), &mut key_val, &mut data_val) {
+                ffi::MDB_SUCCESS => {
+                    Ok(slice::from_raw_parts(data_val.mv_data as *const u8,
+                                             data_val.mv_size as usize))
+                },
+                err_code => Err(Error::from_err_code(err_code)),
+            }
+        }
+    }
+
+    /// Open a new read-only cursor on the given database.
+    fn open_ro_cursor<'txn>(&'txn self, db: Database) -> Result<RoCursor<'txn>> {
+        RoCursor::new(self, db)
+    }
+
+    /// Gets the option flags for the given database in the transaction.
+    fn db_flags(&self, db: Database) -> Result<DatabaseFlags> {
+        let mut flags: c_uint = 0;
+        unsafe {
+            lmdb_result(ffi::mdb_dbi_flags(self.txn(), db.dbi(), &mut flags))?;
+        }
+        Ok(DatabaseFlags::from_bits_truncate(flags))
+    }
+}
+
+/// An LMDB read-only transaction.
+pub struct RoTransaction<'env> {
+    txn: *mut ffi::MDB_txn,
+    _marker: PhantomData<&'env ()>,
+}
+
+impl <'env> fmt::Debug for RoTransaction<'env> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
+        f.debug_struct("RoTransaction").finish()
+    }
+}
+
+impl <'env> Drop for RoTransaction<'env> {
+    fn drop(&mut self) {
+        unsafe { ffi::mdb_txn_abort(self.txn) }
+    }
+}
+
+impl <'env> RoTransaction<'env> {
+
+    /// Creates a new read-only transaction in the given environment. Prefer
+    /// using `Environment::begin_ro_txn`.
+    pub(crate) fn new(env: &'env Environment) -> Result<RoTransaction<'env>> {
+        let mut txn: *mut ffi::MDB_txn = ptr::null_mut();
+        unsafe {
+            lmdb_result(ffi::mdb_txn_begin(env.env(), ptr::null_mut(), ffi::MDB_RDONLY, &mut txn))?;
+            Ok(RoTransaction { txn: txn, _marker: PhantomData })
+        }
+    }
+
+    /// Resets the read-only transaction.
+    ///
+    /// Abort the transaction like `Transaction::abort`, but keep the
+    /// transaction handle.  `InactiveTransaction::renew` may reuse the handle.
+    /// This saves allocation overhead if the process will start a new read-only
+    /// transaction soon, and also locking overhead if
+    /// `EnvironmentFlags::NO_TLS` is in use. The reader table lock is released,
+    /// but the table slot stays tied to its thread or transaction. Reader locks
+    /// generally don't interfere with writers, but they keep old versions of
+    /// database pages allocated. Thus they prevent the old pages from being
+    /// reused when writers commit new data, and so under heavy load the
+    /// database size may grow much more rapidly than otherwise.
+    pub fn reset(self) -> InactiveTransaction<'env> {
+        let txn = self.txn;
+        unsafe {
+            mem::forget(self);
+            ffi::mdb_txn_reset(txn)
+        };
+        InactiveTransaction { txn: txn, _marker: PhantomData }
+    }
+}
+
+impl <'env> Transaction for RoTransaction<'env> {
+    fn txn(&self) -> *mut ffi::MDB_txn {
+        self.txn
+    }
+}
+
+/// An inactive read-only transaction.
+pub struct InactiveTransaction<'env> {
+    txn: *mut ffi::MDB_txn,
+    _marker: PhantomData<&'env ()>,
+}
+
+impl <'env> fmt::Debug for InactiveTransaction<'env> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
+        f.debug_struct("InactiveTransaction").finish()
+    }
+}
+
+impl <'env> Drop for InactiveTransaction<'env> {
+    fn drop(&mut self) {
+        unsafe { ffi::mdb_txn_abort(self.txn) }
+    }
+}
+
+impl <'env> InactiveTransaction<'env> {
+
+    /// Renews the inactive transaction, returning an active read-only
+    /// transaction.
+    ///
+    /// This acquires a new reader lock for a transaction handle that had been
+    /// released by `RoTransaction::reset`.
+    pub fn renew(self) -> Result<RoTransaction<'env>> {
+        let txn = self.txn;
+        unsafe {
+            mem::forget(self);
+            lmdb_result(ffi::mdb_txn_renew(txn))?
+        };
+        Ok(RoTransaction { txn: txn, _marker: PhantomData })
+    }
+}
+
+/// An LMDB read-write transaction.
+pub struct RwTransaction<'env> {
+    txn: *mut ffi::MDB_txn,
+    _marker: PhantomData<&'env ()>,
+}
+
+impl <'env> fmt::Debug for RwTransaction<'env> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
+        f.debug_struct("RwTransaction").finish()
+    }
+}
+
+impl <'env> Drop for RwTransaction<'env> {
+    fn drop(&mut self) {
+        unsafe { ffi::mdb_txn_abort(self.txn) }
+    }
+}
+
+impl <'env> RwTransaction<'env> {
+
+    /// Creates a new read-write transaction in the given environment. Prefer
+    /// using `Environment::begin_ro_txn`.
+    pub(crate) fn new(env: &'env Environment) -> Result<RwTransaction<'env>> {
+        let mut txn: *mut ffi::MDB_txn = ptr::null_mut();
+        unsafe {
+            lmdb_result(ffi::mdb_txn_begin(env.env(),
+                        ptr::null_mut(),
+                        EnvironmentFlags::empty().bits(),
+                        &mut txn))?;
+            Ok(RwTransaction { txn: txn, _marker: PhantomData })
+        }
+    }
+
+    /// Opens a database in the provided transaction, creating it if necessary.
+    ///
+    /// If `name` is `None`, then the default database will be opened, otherwise
+    /// a named database will be opened. The database handle will be private to
+    /// the transaction until the transaction is successfully committed. If the
+    /// transaction is aborted the returned database handle should no longer be
+    /// used.
+    ///
+    /// Prefer using `Environment::create_db`.
+    ///
+    /// ## Safety
+    ///
+    /// This function (as well as `Environment::open_db`,
+    /// `Environment::create_db`, and `Database::open`) **must not** be called
+    /// from multiple concurrent transactions in the same environment. A
+    /// transaction which uses this function must finish (either commit or
+    /// abort) before any other transaction may use this function.
+    pub unsafe fn create_db(&self, name: Option<&str>, flags: DatabaseFlags) -> Result<Database> {
+        Database::new(self.txn(), name, flags.bits() | ffi::MDB_CREATE)
+    }
+
+    /// Opens a new read-write cursor on the given database and transaction.
+    pub fn open_rw_cursor<'txn>(&'txn mut self, db: Database) -> Result<RwCursor<'txn>> {
+        RwCursor::new(self, db)
+    }
+
+    /// Stores an item into a database.
+    ///
+    /// This function stores key/data pairs in the database. The default
+    /// behavior is to enter the new key/data pair, replacing any previously
+    /// existing key if duplicates are disallowed, or adding a duplicate data
+    /// item if duplicates are allowed (`DatabaseFlags::DUP_SORT`).
+    pub fn put<K, D>(&mut self,
+                     database: Database,
+                     key: &K,
+                     data: &D,
+                     flags: WriteFlags)
+                     -> Result<()>
+    where K: AsRef<[u8]>, D: AsRef<[u8]> {
+        let key = key.as_ref();
+        let data = data.as_ref();
+        let mut key_val: ffi::MDB_val = ffi::MDB_val { mv_size: key.len() as size_t,
+                                                       mv_data: key.as_ptr() as *mut c_void };
+        let mut data_val: ffi::MDB_val = ffi::MDB_val { mv_size: data.len() as size_t,
+                                                        mv_data: data.as_ptr() as *mut c_void };
+        unsafe {
+            lmdb_result(ffi::mdb_put(self.txn(),
+                                     database.dbi(),
+                                     &mut key_val,
+                                     &mut data_val,
+                                     flags.bits()))
+        }
+    }
+
+    /// Returns a buffer which can be used to write a value into the item at the
+    /// given key and with the given length. The buffer must be completely
+    /// filled by the caller.
+    pub fn reserve<'txn, K>(&'txn mut self,
+                            database: Database,
+                            key: &K,
+                            len: size_t,
+                            flags: WriteFlags)
+                            -> Result<&'txn mut [u8]>
+    where K: AsRef<[u8]> {
+        let key = key.as_ref();
+        let mut key_val: ffi::MDB_val = ffi::MDB_val { mv_size: key.len() as size_t,
+                                                       mv_data: key.as_ptr() as *mut c_void };
+        let mut data_val: ffi::MDB_val = ffi::MDB_val { mv_size: len,
+                                                        mv_data: ptr::null_mut::<c_void>() };
+        unsafe {
+            lmdb_result(ffi::mdb_put(self.txn(),
+                        database.dbi(),
+                        &mut key_val,
+                        &mut data_val,
+                        flags.bits() | ffi::MDB_RESERVE))?;
+            Ok(slice::from_raw_parts_mut(data_val.mv_data as *mut u8,
+                                         data_val.mv_size as usize))
+        }
+    }
+
+    /// Deletes an item from a database.
+    ///
+    /// This function removes key/data pairs from the database. If the database
+    /// does not support sorted duplicate data items (`DatabaseFlags::DUP_SORT`)
+    /// the data parameter is ignored.  If the database supports sorted
+    /// duplicates and the data parameter is `None`, all of the duplicate data
+    /// items for the key will be deleted. Otherwise, if the data parameter is
+    /// `Some` only the matching data item will be deleted. This function will
+    /// return `Error::NotFound` if the specified key/data pair is not in the
+    /// database.
+    pub fn del<K>(&mut self,
+           database: Database,
+           key: &K,
+           data: Option<&[u8]>)
+           -> Result<()>
+    where K: AsRef<[u8]> {
+        let key = key.as_ref();
+        let mut key_val: ffi::MDB_val = ffi::MDB_val { mv_size: key.len() as size_t,
+                                                       mv_data: key.as_ptr() as *mut c_void };
+        let data_val: Option<ffi::MDB_val> =
+            data.map(|data| ffi::MDB_val { mv_size: data.len() as size_t,
+                                           mv_data: data.as_ptr() as *mut c_void });
+        unsafe {
+            lmdb_result(ffi::mdb_del(self.txn(),
+                                     database.dbi(),
+                                     &mut key_val,
+                                     data_val.map(|mut data_val| &mut data_val as *mut _)
+                                             .unwrap_or(ptr::null_mut())))
+        }
+    }
+
+    /// Empties the given database. All items will be removed.
+    pub fn clear_db(&mut self, db: Database) -> Result<()> {
+        unsafe { lmdb_result(ffi::mdb_drop(self.txn(), db.dbi(), 0)) }
+    }
+
+    /// Drops the database from the environment.
+    ///
+    /// ## Safety
+    ///
+    /// This method is unsafe in the same ways as `Environment::close_db`, and
+    /// should be used accordingly.
+    pub unsafe fn drop_db(&mut self, db: Database) -> Result<()> {
+        lmdb_result(ffi::mdb_drop(self.txn, db.dbi(), 1))
+    }
+
+    /// Begins a new nested transaction inside of this transaction.
+    pub fn begin_nested_txn<'txn>(&'txn mut self) -> Result<RwTransaction<'txn>> {
+        let mut nested: *mut ffi::MDB_txn = ptr::null_mut();
+        unsafe {
+            let env: *mut ffi::MDB_env = ffi::mdb_txn_env(self.txn());
+            ffi::mdb_txn_begin(env, self.txn(), 0, &mut nested);
+        }
+        Ok(RwTransaction { txn: nested, _marker: PhantomData })
+    }
+}
+
+impl <'env> Transaction for RwTransaction<'env> {
+    fn txn(&self) -> *mut ffi::MDB_txn {
+        self.txn
+    }
+}
+
+#[cfg(test)]
+mod test {
+
+    use libc::size_t;
+    use rand::{Rng, XorShiftRng};
+    use std::io::Write;
+    use std::ptr;
+    use std::sync::{Arc, Barrier};
+    use std::thread::{self, JoinHandle};
+    use test::{Bencher, black_box};
+
+    use tempdir::TempDir;
+
+    use environment::*;
+    use error::*;
+    use ffi::*;
+    use flags::*;
+    use super::*;
+    use test_utils::*;
+
+    #[test]
+    fn test_put_get_del() {
+        let dir = TempDir::new("test").unwrap();
+        let env = Environment::new().open(dir.path()).unwrap();
+        let db = env.open_db(None).unwrap();
+
+        let mut txn = env.begin_rw_txn().unwrap();
+        txn.put(db, b"key1", b"val1", WriteFlags::empty()).unwrap();
+        txn.put(db, b"key2", b"val2", WriteFlags::empty()).unwrap();
+        txn.put(db, b"key3", b"val3", WriteFlags::empty()).unwrap();
+        txn.commit().unwrap();
+
+        let mut txn = env.begin_rw_txn().unwrap();
+        assert_eq!(b"val1", txn.get(db, b"key1").unwrap());
+        assert_eq!(b"val2", txn.get(db, b"key2").unwrap());
+        assert_eq!(b"val3", txn.get(db, b"key3").unwrap());
+        assert_eq!(txn.get(db, b"key"), Err(Error::NotFound));
+
+        txn.del(db, b"key1", None).unwrap();
+        assert_eq!(txn.get(db, b"key1"), Err(Error::NotFound));
+    }
+
+    #[test]
+    fn test_reserve() {
+        let dir = TempDir::new("test").unwrap();
+        let env = Environment::new().open(dir.path()).unwrap();
+        let db = env.open_db(None).unwrap();
+
+        let mut txn = env.begin_rw_txn().unwrap();
+        {
+            let mut writer = txn.reserve(db, b"key1", 4, WriteFlags::empty()).unwrap();
+            writer.write_all(b"val1").unwrap();
+        }
+        txn.commit().unwrap();
+
+        let mut txn = env.begin_rw_txn().unwrap();
+        assert_eq!(b"val1", txn.get(db, b"key1").unwrap());
+        assert_eq!(txn.get(db, b"key"), Err(Error::NotFound));
+
+        txn.del(db, b"key1", None).unwrap();
+        assert_eq!(txn.get(db, b"key1"), Err(Error::NotFound));
+    }
+
+    #[test]
+    fn test_inactive_txn() {
+        let dir = TempDir::new("test").unwrap();
+        let env = Environment::new().open(dir.path()).unwrap();
+        let db = env.open_db(None).unwrap();
+
+        {
+            let mut txn = env.begin_rw_txn().unwrap();
+            txn.put(db, b"key", b"val", WriteFlags::empty()).unwrap();
+            txn.commit().unwrap();
+        }
+
+        let txn = env.begin_ro_txn().unwrap();
+        let inactive = txn.reset();
+        let active = inactive.renew().unwrap();
+        assert!(active.get(db, b"key").is_ok());
+    }
+
+    #[test]
+    fn test_nested_txn() {
+        let dir = TempDir::new("test").unwrap();
+        let env = Environment::new().open(dir.path()).unwrap();
+        let db = env.open_db(None).unwrap();
+
+        let mut txn = env.begin_rw_txn().unwrap();
+        txn.put(db, b"key1", b"val1", WriteFlags::empty()).unwrap();
+
+        {
+            let mut nested = txn.begin_nested_txn().unwrap();
+            nested.put(db, b"key2", b"val2", WriteFlags::empty()).unwrap();
+            assert_eq!(nested.get(db, b"key1").unwrap(), b"val1");
+            assert_eq!(nested.get(db, b"key2").unwrap(), b"val2");
+        }
+
+        assert_eq!(txn.get(db, b"key1").unwrap(), b"val1");
+        assert_eq!(txn.get(db, b"key2"), Err(Error::NotFound));
+    }
+
+    #[test]
+    fn test_clear_db() {
+        let dir = TempDir::new("test").unwrap();
+        let env = Environment::new().open(dir.path()).unwrap();
+        let db = env.open_db(None).unwrap();
+
+        {
+            let mut txn = env.begin_rw_txn().unwrap();
+            txn.put(db, b"key", b"val", WriteFlags::empty()).unwrap();
+            txn.commit().unwrap();
+        }
+
+        {
+            let mut txn = env.begin_rw_txn().unwrap();
+            txn.clear_db(db).unwrap();
+            txn.commit().unwrap();
+        }
+
+        let txn = env.begin_ro_txn().unwrap();
+        assert_eq!(txn.get(db, b"key"), Err(Error::NotFound));
+    }
+
+
+    #[test]
+    fn test_drop_db() {
+        let dir = TempDir::new("test").unwrap();
+        let env = Environment::new().set_max_dbs(2)
+                                        .open(dir.path()).unwrap();
+        let db = env.create_db(Some("test"), DatabaseFlags::empty()).unwrap();
+
+        {
+            let mut txn = env.begin_rw_txn().unwrap();
+            txn.put(db, b"key", b"val", WriteFlags::empty()).unwrap();
+            txn.commit().unwrap();
+        }
+        {
+            let mut txn = env.begin_rw_txn().unwrap();
+            unsafe { txn.drop_db(db).unwrap(); }
+            txn.commit().unwrap();
+        }
+
+        assert_eq!(env.open_db(Some("test")), Err(Error::NotFound));
+    }
+
+    #[test]
+    fn test_concurrent_readers_single_writer() {
+        let dir = TempDir::new("test").unwrap();
+        let env: Arc<Environment> = Arc::new(Environment::new().open(dir.path()).unwrap());
+
+        let n = 10usize; // Number of concurrent readers
+        let barrier = Arc::new(Barrier::new(n + 1));
+        let mut threads: Vec<JoinHandle<bool>> = Vec::with_capacity(n);
+
+        let key = b"key";
+        let val = b"val";
+
+        for _ in 0..n {
+            let reader_env = env.clone();
+            let reader_barrier = barrier.clone();
+
+            threads.push(thread::spawn(move|| {
+                let db = reader_env.open_db(None).unwrap();
+                {
+                    let txn = reader_env.begin_ro_txn().unwrap();
+                    assert_eq!(txn.get(db, key), Err(Error::NotFound));
+                    txn.abort();
+                }
+                reader_barrier.wait();
+                reader_barrier.wait();
+                {
+                    let txn = reader_env.begin_ro_txn().unwrap();
+                    txn.get(db, key).unwrap() == val
+                }
+            }));
+        }
+
+        let db = env.open_db(None).unwrap();
+        let mut txn = env.begin_rw_txn().unwrap();
+        barrier.wait();
+        txn.put(db, key, val, WriteFlags::empty()).unwrap();
+        txn.commit().unwrap();
+        barrier.wait();
+
+        assert!(threads.into_iter().all(|b| b.join().unwrap()))
+    }
+
+    #[test]
+    fn test_concurrent_writers() {
+        let dir = TempDir::new("test").unwrap();
+        let env = Arc::new(Environment::new().open(dir.path()).unwrap());
+
+        let n = 10usize; // Number of concurrent writers
+        let mut threads: Vec<JoinHandle<bool>> = Vec::with_capacity(n);
+
+        let key = "key";
+        let val = "val";
+
+        for i in 0..n {
+            let writer_env = env.clone();
+
+            threads.push(thread::spawn(move|| {
+                let db = writer_env.open_db(None).unwrap();
+                let mut txn = writer_env.begin_rw_txn().unwrap();
+                txn.put(db,
+                        &format!("{}{}", key, i),
+                        &format!("{}{}", val, i),
+                        WriteFlags::empty())
+                    .unwrap();
+                txn.commit().is_ok()
+            }));
+        }
+        assert!(threads.into_iter().all(|b| b.join().unwrap()));
+
+        let db = env.open_db(None).unwrap();
+        let txn = env.begin_ro_txn().unwrap();
+
+        for i in 0..n {
+            assert_eq!(format!("{}{}", val, i).as_bytes(),
+                       txn.get(db, &format!("{}{}", key, i)).unwrap());
+        }
+    }
+
+    #[bench]
+    fn bench_get_rand(b: &mut Bencher) {
+        let n = 100u32;
+        let (_dir, env) = setup_bench_db(n);
+        let db = env.open_db(None).unwrap();
+        let txn = env.begin_ro_txn().unwrap();
+
+        let mut keys: Vec<String> = (0..n).map(|n| get_key(n)).collect();
+        XorShiftRng::new_unseeded().shuffle(&mut keys[..]);
+
+        b.iter(|| {
+            let mut i = 0usize;
+            for key in &keys {
+                i = i + txn.get(db, key).unwrap().len();
+            }
+            black_box(i);
+        });
+    }
+
+    #[bench]
+    fn bench_get_rand_raw(b: &mut Bencher) {
+        let n = 100u32;
+        let (_dir, env) = setup_bench_db(n);
+        let db = env.open_db(None).unwrap();
+        let _txn = env.begin_ro_txn().unwrap();
+
+        let mut keys: Vec<String> = (0..n).map(|n| get_key(n)).collect();
+        XorShiftRng::new_unseeded().shuffle(&mut keys[..]);
+
+        let dbi = db.dbi();
+        let txn = _txn.txn();
+
+        let mut key_val: MDB_val = MDB_val { mv_size: 0, mv_data: ptr::null_mut() };
+        let mut data_val: MDB_val = MDB_val { mv_size: 0, mv_data: ptr::null_mut() };
+
+        b.iter(|| unsafe {
+            let mut i: size_t = 0;
+            for key in &keys {
+                key_val.mv_size = key.len() as size_t;
+                key_val.mv_data = key.as_bytes().as_ptr() as *mut _;
+
+                mdb_get(txn, dbi, &mut key_val, &mut data_val);
+
+                i = i + key_val.mv_size;
+            }
+            black_box(i);
+        });
+    }
+
+    #[bench]
+    fn bench_put_rand(b: &mut Bencher) {
+        let n = 100u32;
+        let (_dir, env) = setup_bench_db(0);
+        let db = env.open_db(None).unwrap();
+
+        let mut items: Vec<(String, String)> = (0..n).map(|n| (get_key(n), get_data(n))).collect();
+        XorShiftRng::new_unseeded().shuffle(&mut items[..]);
+
+        b.iter(|| {
+            let mut txn = env.begin_rw_txn().unwrap();
+            for &(ref key, ref data) in items.iter() {
+                txn.put(db, key, data, WriteFlags::empty()).unwrap();
+            }
+            txn.abort();
+        });
+    }
+
+    #[bench]
+    fn bench_put_rand_raw(b: &mut Bencher) {
+        let n = 100u32;
+        let (_dir, _env) = setup_bench_db(0);
+        let db = _env.open_db(None).unwrap();
+
+        let mut items: Vec<(String, String)> = (0..n).map(|n| (get_key(n), get_data(n))).collect();
+        XorShiftRng::new_unseeded().shuffle(&mut items[..]);
+
+        let dbi = db.dbi();
+        let env = _env.env();
+
+        let mut key_val: MDB_val = MDB_val { mv_size: 0, mv_data: ptr::null_mut() };
+        let mut data_val: MDB_val = MDB_val { mv_size: 0, mv_data: ptr::null_mut() };
+
+        b.iter(|| unsafe {
+            let mut txn: *mut MDB_txn = ptr::null_mut();
+            mdb_txn_begin(env, ptr::null_mut(), 0, &mut txn);
+
+            let mut i: ::libc::c_int = 0;
+            for &(ref key, ref data) in items.iter() {
+
+                key_val.mv_size = key.len() as size_t;
+                key_val.mv_data = key.as_bytes().as_ptr() as *mut _;
+                data_val.mv_size = data.len() as size_t;
+                data_val.mv_data = data.as_bytes().as_ptr() as *mut _;
+
+                i += mdb_put(txn, dbi, &mut key_val, &mut data_val, 0);
+            }
+            assert_eq!(0, i);
+            mdb_txn_abort(txn);
+        });
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/lmdb-sys/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{"Cargo.toml":"f934ea681a6ab7338d4fee18c0d7c2915321c3087e82e373484b3e586ad367ee","build.rs":"4204dd0891e2eca08cb7cbcccfb36d1bdac137651c383f4a36368478fd836402","lmdb/libraries/liblmdb/CHANGES":"d58e7fbdac22b7001c141df2f48b9d192770de52c9b4a0348552dcd4056ebbf7","lmdb/libraries/liblmdb/COPYRIGHT":"ce2436e2ab324485500b6fec5764b788ba082ac902ed00290f527d0170d8c90e","lmdb/libraries/liblmdb/Doxyfile":"5545f6b049040ce58e6d1a603eaea6b7fb8ae92459f2ab8d3bcbacabcce1014d","lmdb/libraries/liblmdb/LICENSE":"310fe25c858a9515fc8c8d7d1f24a67c9496f84a91e0a0e41ea9975b1371e569","lmdb/libraries/liblmdb/Makefile":"60b5f574e6642602f692a95956da61c588a265ad50b8059960c230b9e6aaf4fd","lmdb/libraries/liblmdb/intro.doc":"c7c2d970e7c277dc1f45bb3824c054fb73cf8d1666aa826e83c6a9a6a378839d","lmdb/libraries/liblmdb/lmdb.h":"c06ce42284b7544657e7b2d6b1f34cedd85234c193e673167b5d4b86372142ca","lmdb/libraries/liblmdb/mdb.c":"f7840eb8efaba2b55f7980dcecf9c0109b33db6261c07ae6dc1fea4f40789db4","lmdb/libraries/liblmdb/mdb_copy.1":"c01f113a295d3c76b60f432896f24862cb0d2dadb14e26d72c6de9b55a254e2f","lmdb/libraries/liblmdb/mdb_copy.c":"b75a4d9b18aea89b8910bff44938244587a1a5863d1d609134298b1b5f019bfe","lmdb/libraries/liblmdb/mdb_dump.1":"adf51a57167bc6a64e0e6635e28ad2175924754f25eb1e9d89278b543c5e78d3","lmdb/libraries/liblmdb/mdb_dump.c":"7a67fa80539cb976cedd2bf7c56082366c33e07c9eac409e47efabaf4e31b62f","lmdb/libraries/liblmdb/mdb_load.1":"c1f7369d12b84fc92908256d3c1e422fa05576bde378fc84aca272d5aa2f4102","lmdb/libraries/liblmdb/mdb_load.c":"136169ce000cf254149ac00a0d9d4b12e9548649e7cdc9f6d6bd0943c16c11ea","lmdb/libraries/liblmdb/mdb_stat.1":"9c531fa57f1a528fa4bc4da4351b2332bff2e34bbd6f76dd0c1bbd915888cbfd","lmdb/libraries/liblmdb/mdb_stat.c":"235b872ae85aff627dbf27ae495c66cf3ed80eeca2188fe90d27d0486c03d0fa","lmdb/libraries/liblmdb/midl.c":"4877d6421f114a18a7074076b5b56c68567c0ba1a8328018af788cf5bb5c4f87","lmdb/libraries/liblmdb/midl.h":"853fc3115d2b827d6b53afcb03d39e0dcab6be108108955e549990ee5ece5c8a","lmdb/libraries/liblmdb/mtest.c":"4fd58e1ab4e445a73a6c655275f2c84523c128d34afa958a98b128c1d5f7ec24","lmdb/libraries/liblmdb/mtest2.c":"4b5711048ecbc255e3393c2fab589630b78fc3fc423cc98281629c7e45e78b4b","lmdb/libraries/liblmdb/mtest3.c":"b8e895e093a9d5bacbfde677d8f8e0aca9f0b9d8c2f4392bb47ff227b9c6a08d","lmdb/libraries/liblmdb/mtest4.c":"6e1fd62ca1036795dbadd1306fae4e48c34f00576805c0ac1dd73114ec58f85c","lmdb/libraries/liblmdb/mtest5.c":"24906ec930c259be3c2af5250fe1cb06dbb0f40ce3bad3c9f4991f681642e1e9","lmdb/libraries/liblmdb/mtest6.c":"f5c40dc672e5946874fe8a6a2d10fe8da2f509ffe48c73bdd4199b2d6756031c","lmdb/libraries/liblmdb/sample-bdb.txt":"7692f24c5f909328856008ed90e48cf224de1eb466d1f7623ffb7f32148eb3d9","lmdb/libraries/liblmdb/sample-mdb.txt":"40902b2560d72d348d19a23711244c59e3d684871a4262071312cc5a67e5ecae","lmdb/libraries/liblmdb/tooltag":"4734c6dc1fa7aec8c2e9646bd04bc5218ef6a03ad83a3b18de2ac4069eb94120","src/constants.rs":"af67740b5acccdc71b2267ec051bb60e5433c4f0313fe16dc0627376a52dcdff","src/ffi.rs":"caa9bbfb3868a7a9e9ad822d775e60ffa8c8c2f2450ac4ed403a93ddb7547899","src/lib.rs":"93504d2712ee68182bb59d5c6ad440b42892c221ecf014e77c325f2bb5cdddf1"},"package":"d5b392838cfe8858e86fac37cf97a0e8c55cc60ba0a18365cadc33092f128ce9"}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/lmdb-sys/Cargo.toml
@@ -0,0 +1,31 @@
+# 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 = "lmdb-sys"
+version = "0.8.0"
+authors = ["Dan Burkert <dan@danburkert.com>"]
+build = "build.rs"
+description = "Rust bindings for liblmdb."
+documentation = "https://docs.rs/lmdb-sys"
+readme = "../README.md"
+keywords = ["LMDB", "database", "storage-engine", "bindings", "library"]
+categories = ["database", "external-ffi-bindings"]
+license = "Apache-2.0"
+repository = "https://github.com/danburkert/lmdb-rs.git"
+[dependencies.libc]
+version = "0.2"
+[build-dependencies.cc]
+version = "1"
+
+[build-dependencies.pkg-config]
+version = "0.3"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/lmdb-sys/build.rs
@@ -0,0 +1,21 @@
+extern crate pkg_config;
+extern crate cc;
+
+use std::env;
+use std::path::PathBuf;
+
+fn main() {
+    let mut lmdb: PathBuf = PathBuf::from(&env::var("CARGO_MANIFEST_DIR").unwrap());
+    lmdb.push("lmdb");
+    lmdb.push("libraries");
+    lmdb.push("liblmdb");
+
+    if !pkg_config::find_library("liblmdb").is_ok() {
+        cc::Build::new()
+                    .file(lmdb.join("mdb.c"))
+                    .file(lmdb.join("midl.c"))
+                    // https://github.com/LMDB/lmdb/blob/LMDB_0.9.21/libraries/liblmdb/Makefile#L25
+                    .opt_level(2)
+                    .compile("liblmdb.a")
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/lmdb-sys/lmdb/libraries/liblmdb/CHANGES
@@ -0,0 +1,228 @@
+LMDB 0.9 Change Log
+
+LMDB 0.9.21 Release (2017/06/01)
+	Fix xcursor after cursor_del (ITS#8622)
+
+LMDB 0.9.20 (Withdrawn)
+	Fix mdb_load with escaped plaintext (ITS#8558)
+	Fix mdb_cursor_last / mdb_put interaction (ITS#8557)
+
+LMDB 0.9.19 Release (2016/12/28)
+	Fix mdb_env_cwalk cursor init (ITS#8424)
+	Fix robust mutexes on Solaris 10/11 (ITS#8339)
+	Tweak Win32 error message buffer
+	Fix MDB_GET_BOTH on non-dup record (ITS#8393)
+	Optimize mdb_drop
+	Fix xcursors after mdb_cursor_del (ITS#8406)
+	Fix MDB_NEXT_DUP after mdb_cursor_del (ITS#8412)
+	Fix mdb_cursor_put resetting C_EOF (ITS#8489)
+	Fix mdb_env_copyfd2 to return EPIPE on SIGPIPE (ITS#8504)
+	Fix mdb_env_copy with empty DB (ITS#8209)
+	Fix behaviors with fork (ITS#8505)
+	Fix mdb_dbi_open with mainDB cursors (ITS#8542)
+	Fix robust mutexes on kFreeBSD (ITS#8554)
+	Fix utf8_to_utf16 error checks (ITS#7992)
+	Fix F_NOCACHE on MacOS, error is non-fatal (ITS#7682)
+	Build
+		Make shared lib suffix overridable (ITS#8481)
+	Documentation
+		Cleanup doxygen nits
+		Note reserved vs actual mem/disk usage
+
+
+LMDB 0.9.18 Release (2016/02/05)
+	Fix robust mutex detection on glibc 2.10-11 (ITS#8330)
+	Fix page_search_root assert on FreeDB (ITS#8336)
+	Fix MDB_APPENDDUP vs. rewrite(single item) (ITS#8334)
+	Fix mdb_copy of large files on Windows
+	Fix subcursor move after delete (ITS#8355)
+	Fix mdb_midl_shirnk off-by-one (ITS#8363)
+	Check for utf8_to_utf16 failures (ITS#7992)
+	Catch strdup failure in mdb_dbi_open
+	Build
+		Additional makefile var tweaks (ITS#8169)
+	Documentation
+		Add Getting Started page
+		Update WRITEMAP description
+	
+
+LMDB 0.9.17 Release (2015/11/30)
+	Fix ITS#7377 catch calloc failure
+	Fix ITS#8237 regression from ITS#7589
+	Fix ITS#8238 page_split for DUPFIXED pages
+	Fix ITS#8221 MDB_PAGE_FULL on delete/rebalance
+	Fix ITS#8258 rebalance/split assert
+	Fix ITS#8263 cursor_put cursor tracking
+	Fix ITS#8264 cursor_del cursor tracking
+	Fix ITS#8310 cursor_del cursor tracking
+	Fix ITS#8299 mdb_del cursor tracking
+	Fix ITS#8300 mdb_del cursor tracking
+	Fix ITS#8304 mdb_del cursor tracking
+	Fix ITS#7771 fakepage cursor tracking
+	Fix ITS#7789 ensure mapsize >= pages in use
+	Fix ITS#7971 mdb_txn_renew0() new reader slots
+	Fix ITS#7969 use __sync_synchronize on non-x86
+	Fix ITS#8311 page_split from update_key
+	Fix ITS#8312 loose pages in nested txn
+	Fix ITS#8313 mdb_rebalance dummy cursor
+	Fix ITS#8315 dirty_room in nested txn
+	Fix ITS#8323 dirty_list in nested txn
+	Fix ITS#8316 page_merge cursor tracking
+	Fix ITS#8321 cursor tracking
+	Fix ITS#8319 mdb_load error messages
+	Fix ITS#8320 mdb_load plaintext input
+	Added mdb_txn_id() (ITS#7994)
+	Added robust mutex support
+	Miscellaneous cleanup/simplification
+	Build
+		Create install dirs if needed (ITS#8256)
+		Fix ThreadProc decl on Win32/MSVC (ITS#8270)
+		Added ssize_t typedef for MSVC (ITS#8067)
+		Use ANSI apis on Windows (ITS#8069)
+		Use O_SYNC if O_DSYNC,MDB_DSYNC are not defined (ITS#7209)
+		Allow passing AR to make (ITS#8168)
+		Allow passing mandir to make install (ITS#8169)
+
+LMDB 0.9.16 Release (2015/08/14)
+	Fix cursor EOF bug (ITS#8190)
+	Fix handling of subDB records (ITS#8181)
+	Fix mdb_midl_shrink() usage (ITS#8200)
+
+LMDB 0.9.15 Release (2015/06/19)
+	Fix txn init (ITS#7961,#7987)
+	Fix MDB_PREV_DUP (ITS#7955,#7671)
+	Fix compact of empty env (ITS#7956)
+	Fix mdb_copy file mode
+	Fix mdb_env_close() after failed mdb_env_open()
+	Fix mdb_rebalance collapsing root (ITS#8062)
+	Fix mdb_load with large values (ITS#8066)
+	Fix to retry writes on EINTR (ITS#8106)
+	Fix mdb_cursor_del on empty DB (ITS#8109)
+	Fix MDB_INTEGERDUP key compare (ITS#8117)