Bug 1583439 - Run `./mach vendor rust` on clean tip, r=froydnj
authorVictor Porof <vporof@mozilla.com>
Thu, 26 Sep 2019 11:53:01 +0000
changeset 495111 46708ac67abfb315b5bebaa1acfe305a3155477f
parent 495110 7b9562f322cce957458c44734e3c94f5250a7752
child 495112 2f09b27b60f365cb8e08ba8736f001a129c02d32
push id96440
push uservporof@mozilla.com
push dateThu, 26 Sep 2019 11:53:50 +0000
treeherderautoland@46708ac67abf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1583439
milestone71.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 1583439 - Run `./mach vendor rust` on clean tip, r=froydnj Differential Revision: https://phabricator.services.mozilla.com/D46900
Cargo.lock
third_party/rust/bindgen/.cargo-checksum.json
third_party/rust/bindgen/Cargo.lock
third_party/rust/bindgen/Cargo.toml
third_party/rust/bindgen/src/ir/traversal.rs
third_party/rust/lmdb-rkv-sys/.cargo-checksum.json
third_party/rust/lmdb-rkv-sys/Cargo.toml
third_party/rust/lmdb-rkv-sys/bindgen.rs
third_party/rust/lmdb-rkv-sys/build.rs
third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/CHANGES
third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/COPYRIGHT
third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/lmdb.h
third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/mdb.c
third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/midl.c
third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/midl.h
third_party/rust/lmdb-rkv-sys/src/bindings.rs
third_party/rust/lmdb-rkv-sys/src/constants.rs
third_party/rust/lmdb-rkv-sys/src/ffi.rs
third_party/rust/lmdb-rkv-sys/src/lib.rs
third_party/rust/lmdb-rkv-sys/tests/fixtures/testdb/data.mdb
third_party/rust/lmdb-rkv-sys/tests/fixtures/testdb/lock.mdb
third_party/rust/lmdb-rkv-sys/tests/lmdb.rs
third_party/rust/lmdb-rkv-sys/tests/simple.rs
third_party/rust/lmdb-rkv/.cargo-checksum.json
third_party/rust/lmdb-rkv/Cargo.toml
third_party/rust/lmdb-rkv/README.md
third_party/rust/lmdb-rkv/benches/cursor.rs
third_party/rust/lmdb-rkv/benches/transaction.rs
third_party/rust/lmdb-rkv/benches/utils.rs
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/lib.rs
third_party/rust/lmdb-rkv/src/transaction.rs
third_party/rust/proc-macro2-0.4.27/.cargo-checksum.json
third_party/rust/proc-macro2-0.4.27/Cargo.toml
third_party/rust/proc-macro2-0.4.27/LICENSE-APACHE
third_party/rust/proc-macro2-0.4.27/LICENSE-MIT
third_party/rust/proc-macro2-0.4.27/README.md
third_party/rust/proc-macro2-0.4.27/build.rs
third_party/rust/proc-macro2-0.4.27/src/fallback.rs
third_party/rust/proc-macro2-0.4.27/src/lib.rs
third_party/rust/proc-macro2-0.4.27/src/strnom.rs
third_party/rust/proc-macro2-0.4.27/src/wrapper.rs
third_party/rust/proc-macro2-0.4.27/tests/marker.rs
third_party/rust/proc-macro2-0.4.27/tests/test.rs
third_party/rust/proc-macro2/.cargo-checksum.json
third_party/rust/proc-macro2/Cargo.toml
third_party/rust/proc-macro2/README.md
third_party/rust/proc-macro2/build.rs
third_party/rust/proc-macro2/src/fallback.rs
third_party/rust/proc-macro2/src/lib.rs
third_party/rust/proc-macro2/src/strnom.rs
third_party/rust/proc-macro2/src/wrapper.rs
third_party/rust/proc-macro2/tests/features.rs
third_party/rust/proc-macro2/tests/marker.rs
third_party/rust/proc-macro2/tests/test.rs
third_party/rust/quote-0.6.11/.cargo-checksum.json
third_party/rust/quote-0.6.11/Cargo.toml
third_party/rust/quote-0.6.11/LICENSE-APACHE
third_party/rust/quote-0.6.11/LICENSE-MIT
third_party/rust/quote-0.6.11/README.md
third_party/rust/quote-0.6.11/src/ext.rs
third_party/rust/quote-0.6.11/src/lib.rs
third_party/rust/quote-0.6.11/src/to_tokens.rs
third_party/rust/quote-0.6.11/tests/conditional/integer128.rs
third_party/rust/quote-0.6.11/tests/test.rs
third_party/rust/quote/.cargo-checksum.json
third_party/rust/quote/Cargo.toml
third_party/rust/quote/README.md
third_party/rust/quote/src/ext.rs
third_party/rust/quote/src/format.rs
third_party/rust/quote/src/ident_fragment.rs
third_party/rust/quote/src/lib.rs
third_party/rust/quote/src/runtime.rs
third_party/rust/quote/src/spanned.rs
third_party/rust/quote/src/to_tokens.rs
third_party/rust/quote/tests/compiletest.rs
third_party/rust/quote/tests/conditional/integer128.rs
third_party/rust/quote/tests/test.rs
third_party/rust/quote/tests/ui/does-not-have-iter-interpolated-dup.rs
third_party/rust/quote/tests/ui/does-not-have-iter-interpolated.rs
third_party/rust/quote/tests/ui/does-not-have-iter-separated.rs
third_party/rust/quote/tests/ui/does-not-have-iter.rs
third_party/rust/quote/tests/ui/not-quotable.rs
third_party/rust/quote/tests/ui/not-repeatable.rs
third_party/rust/quote/tests/ui/wrong-type-span.rs
third_party/rust/rkv/.cargo-checksum.json
third_party/rust/rkv/Cargo.lock
third_party/rust/rkv/Cargo.toml
third_party/rust/rkv/src/env.rs
third_party/rust/rkv/src/manager.rs
third_party/rust/rkv/tests/test_txn.rs
third_party/rust/unicode-xid-0.1.0/.cargo-checksum.json
third_party/rust/unicode-xid-0.1.0/COPYRIGHT
third_party/rust/unicode-xid-0.1.0/Cargo.toml
third_party/rust/unicode-xid-0.1.0/LICENSE-APACHE
third_party/rust/unicode-xid-0.1.0/LICENSE-MIT
third_party/rust/unicode-xid-0.1.0/README.md
third_party/rust/unicode-xid-0.1.0/scripts/unicode.py
third_party/rust/unicode-xid-0.1.0/src/lib.rs
third_party/rust/unicode-xid-0.1.0/src/tables.rs
third_party/rust/unicode-xid-0.1.0/src/tests.rs
third_party/rust/unicode-xid/.cargo-checksum.json
third_party/rust/unicode-xid/Cargo.toml
third_party/rust/unicode-xid/README.md
third_party/rust/unicode-xid/scripts/unicode.py
third_party/rust/unicode-xid/src/lib.rs
third_party/rust/unicode-xid/src/tables.rs
third_party/rust/unicode-xid/src/tests.rs
third_party/rust/which/.cargo-checksum.json
third_party/rust/which/Cargo.toml
third_party/rust/which/LICENSE.txt
third_party/rust/which/README.md
third_party/rust/which/appveyor.yml
third_party/rust/which/src/checker.rs
third_party/rust/which/src/error.rs
third_party/rust/which/src/finder.rs
third_party/rust/which/src/helper.rs
third_party/rust/which/src/lib.rs
third_party/rust/which/tests/basic.rs
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -183,17 +183,17 @@ dependencies = [
  "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "baldrdash"
 version = "0.1.0"
 dependencies = [
- "bindgen 0.51.1-oldsyn (registry+https://github.com/rust-lang/crates.io-index)",
+ "bindgen 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cranelift-codegen 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)",
  "cranelift-wasm 0.44.0 (git+https://github.com/CraneStation/Cranelift?rev=182414f15c18538dfebbe040469ec8001e93ecc5)",
  "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -236,30 +236,34 @@ version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "bindgen"
-version = "0.51.1-oldsyn"
+version = "0.51.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "cexpr 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "which 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "binjs_meta"
 version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "Inflector 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -410,22 +414,22 @@ source = "registry+https://github.com/ru
 
 [[package]]
 name = "cert_storage"
 version = "0.0.1"
 dependencies = [
  "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "lmdb-rkv 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lmdb-rkv 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "moz_task 0.1.0",
  "nserror 0.1.0",
  "nsstring 0.1.0",
- "rkv 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rkv 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rust_cascade 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "storage_variant 0.1.0",
  "style 0.0.1",
  "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "thin-vec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "xpcom 0.1.0",
@@ -553,17 +557,17 @@ dependencies = [
  "foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "coreaudio-sys"
 version = "0.2.2"
 dependencies = [
- "bindgen 0.51.1-oldsyn (registry+https://github.com/rust-lang/crates.io-index)",
+ "bindgen 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "coreaudio-sys-utils"
 version = "0.1.0"
 dependencies = [
  "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "coreaudio-sys 0.2.2",
@@ -1131,17 +1135,17 @@ dependencies = [
  "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "gecko-fuzz-targets"
 version = "0.1.0"
 dependencies = [
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
- "rkv 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rkv 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "geckodriver"
 version = "0.26.0-alpha.0"
 dependencies = [
  "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1230,17 +1234,17 @@ dependencies = [
  "cubeb-pulse 0.2.0",
  "cubeb-sys 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "encoding_glue 0.1.0",
  "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "geckoservo 0.0.1",
  "gkrust_utils 0.1.0",
  "jsrust_shared 0.1.0",
  "kvstore 0.1.0",
- "lmdb-rkv-sys 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lmdb-rkv-sys 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "mdns_service 0.1.0",
  "mozurl 0.0.1",
  "mp4parse_capi 0.11.2",
  "netwerk_helper 0.0.1",
  "nserror 0.1.0",
  "nsstring 0.1.0",
  "prefs_parser 0.0.1",
@@ -1475,17 +1479,17 @@ dependencies = [
 name = "itoa"
 version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "js"
 version = "0.1.4"
 dependencies = [
- "bindgen 0.51.1-oldsyn (registry+https://github.com/rust-lang/crates.io-index)",
+ "bindgen 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "mozjs_sys 0.0.0",
  "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1526,22 +1530,22 @@ source = "registry+https://github.com/ru
 name = "kvstore"
 version = "0.1.0"
 dependencies = [
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
- "lmdb-rkv 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lmdb-rkv 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "moz_task 0.1.0",
  "nserror 0.1.0",
  "nsstring 0.1.0",
- "rkv 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rkv 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "storage_variant 0.1.0",
  "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "thin-vec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "xpcom 0.1.0",
 ]
 
 [[package]]
 name = "lazy_static"
@@ -1613,30 +1617,31 @@ 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.11.4"
+version = "0.12.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
- "lmdb-rkv-sys 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lmdb-rkv-sys 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "lmdb-rkv-sys"
-version = "0.8.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bindgen 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.60 (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.3.1"
@@ -2265,16 +2270,24 @@ version = "0.0.1"
 name = "proc-macro2"
 version = "0.4.27"
 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 = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "procedural-masquerade"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "profiler_helper"
 version = "0.1.0"
 dependencies = [
@@ -2310,16 +2323,24 @@ source = "registry+https://github.com/ru
 name = "quote"
 version = "0.6.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "quote"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "rand"
 version = "0.6.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2494,26 +2515,26 @@ name = "ringbuf"
 version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rkv"
-version = "0.9.7"
+version = "0.10.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "lmdb-rkv 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lmdb-rkv 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "ordered-float 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2876,17 +2897,17 @@ source = "registry+https://github.com/ru
 
 [[package]]
 name = "style"
 version = "0.0.1"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "bindgen 0.51.1-oldsyn (registry+https://github.com/rust-lang/crates.io-index)",
+ "bindgen 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.25.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fallible 0.0.1",
  "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "hashglobe 0.1.0",
@@ -3362,16 +3383,21 @@ version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "unicode-xid"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "unicode-xid"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "unreachable"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -3594,16 +3620,24 @@ dependencies = [
 name = "weedle"
 version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "nom 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "which"
+version = "3.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "winapi"
 version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "winapi"
 version = "0.3.6"
 source = "git+https://github.com/froydnj/winapi-rs?branch=aarch64#ac8afeb7006b272bfaa470d8a252c959c175ffec"
@@ -3726,22 +3760,22 @@ dependencies = [
 name = "xulstore"
 version = "0.1.0"
 dependencies = [
  "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
- "lmdb-rkv 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lmdb-rkv 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "moz_task 0.1.0",
  "nserror 0.1.0",
  "nsstring 0.1.0",
- "rkv 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rkv 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "xpcom 0.1.0",
 ]
 
 [[package]]
 name = "yaml-rust"
 version = "0.4.2"
@@ -3775,17 +3809,17 @@ dependencies = [
 "checksum audio_thread_priority 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c1e4aab7f57d8334168073cd0d0f11c7d1f7f3aabef84a1733a42629d0da80c"
 "checksum authenticator 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ec149e5d5d4caa2c9ead53a8ce1ea9c4204c388c65bf3b96c2d1dc0fcf4aeb66"
 "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799"
 "checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a"
 "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0"
 "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
 "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"
-"checksum bindgen 0.51.1-oldsyn (registry+https://github.com/rust-lang/crates.io-index)" = "ae8266cdd336dfd53d71a95c33251232f64553b8770ebd85158039b3a734244b"
+"checksum bindgen 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ebd71393f1ec0509b553aa012b9b58e81dadbdff7130bd3b8cba576e69b32f75"
 "checksum binjs_meta 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6c9a0da2208ceb785c1626fa8b7d250d2e5546ae230294b4a998e4f818c1768e"
 "checksum bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb"
 "checksum bit_reverse 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5e97e02db5a2899c0377f3d6031d5da8296ca2b47abef6ed699de51b9e40a28c"
 "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
 "checksum bitreader 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "80b13e2ab064ff3aa0bdbf1eff533f9822dc37899821f5f98c67f263eab51707"
 "checksum blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "5850aeee1552f495dd0250014cf64b82b7c8879a89d83b33bbdace2cc4f63182"
 "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
 "checksum block-padding 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc4358306e344bf9775d0197fd00d2603e5afb0771bb353538630f022068ea3"
@@ -3893,18 +3927,18 @@ dependencies = [
 "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
 "checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb"
 "checksum libdbus-sys 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "18cb88963258d00f4962205dbb5933d82780d9962c8c8a064b651d2ad7189210"
 "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.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe"
 "checksum line-wrap 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9"
 "checksum linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70fb39025bc7cdd76305867c4eccf2f2dcf6e9a57f5b21a93e1c2d86cd03ec9e"
-"checksum lmdb-rkv 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e25b4069789bf7ac069d6fd58229f18aec20c6f7cc9173cb731d11c10dbb6b6e"
-"checksum lmdb-rkv-sys 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4d7d61f709086e3efb2f7255ad01cf1d7f9e407b7dfe96d83cd15e76ee8283b4"
+"checksum lmdb-rkv 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "605061e5465304475be2041f19967a900175ea1b6d8f47fbab84a84fb8c48452"
+"checksum lmdb-rkv-sys 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cad9a69dc385f7d2b77786bc41f3dd80f02fba6edc547e93af637f58d440ec8d"
 "checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc"
 "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
 "checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084"
 "checksum mach 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa"
 "checksum malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "35adee9ed962cf7d07d62cb58bc45029f3227f5b5b86246caa8632f06c187bc3"
 "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
 "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39"
 "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
@@ -3948,19 +3982,21 @@ dependencies = [
 "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
 "checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
 "checksum plane-split 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffe16a646a08f4b4dd74035b9ff8e378eb1a4012a74f14f5889e7001cdbece33"
 "checksum plist 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31850d149352e2b75f0e4b206045ee3775076c422892328343beca48a2b5cf17"
 "checksum png 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8422b27bb2c013dd97b9aef69e161ce262236f49aaf46a0489011c8ff0264602"
 "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.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915"
+"checksum proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afdc77cc74ec70ed262262942ebb7dac3d479e9e5cfa2da1841c0806f6cdabcc"
 "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.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1"
+"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
 "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
 "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
 "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
 "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0"
 "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
 "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
 "checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
 "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
@@ -3971,17 +4007,17 @@ dependencies = [
 "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
 "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
 "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
 "checksum redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecedbca3bf205f8d8f5c2b44d83cd0690e39ee84b951ed649e9f1841132b66d"
 "checksum regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d9d8297cc20bbb6184f8b45ff61c8ee6a9ac56c156cec8e38c3e5084773c44ad"
 "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716"
 "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
 "checksum ringbuf 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "588456c74d5ff0a5806bc084818e043e767533f743c11ee6f3ccf298599c6847"
-"checksum rkv 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)" = "4f9d6a4dd60be13a62ae1d19df68c0c85d77bbee3749b62bf35c49f207d3d750"
+"checksum rkv 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9aab7c645d32e977e186448b0a5c2c3139a91a7f630cfd8a8c314d1d145e78bf"
 "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-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf"
 "checksum rust-ini 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8a654c5bda722c699be6b0fe4c0d90de218928da5b724c3e467fc48865c37263"
 "checksum rust_cascade 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f3fe4900d38dab1ad21a515e44687dd0711e6b0ec5b214a3b1aa8857343bcf3a"
 "checksum rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "76d7ba1feafada44f2d38eed812bd2489a03c0f5abb975799251518b68848649"
 "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
 "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
@@ -4050,30 +4086,32 @@ dependencies = [
 "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
 "checksum uluru 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2606e9192f308ddc4f0b3c5d1bf3400e28a70fff956e9d9f46d23b094746d9f"
 "checksum unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84e5511b2a947f3ae965dcb29b13b7b1691b6e7332cf5dbc1744138d5acb7f6"
 "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 unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
 "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
 "checksum url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61"
 "checksum urlencoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3df3561629a8bb4c57e5a2e4c43348d9e29c7c29d9b1c4c1f47166deca8f37ed"
 "checksum utf8-ranges 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba"
 "checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a"
 "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.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
 "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 want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3"
 "checksum warp 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "33857527c63bc514452f885d0a57019f28139c58fef2b3566016ecc0d44e5d24"
 "checksum wasmparser 0.39.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a026c1436af49d5537c7561c7474f81f7a754e36445fe52e6e88795a9747291c"
 "checksum weedle 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "26a4c67f132386d965390b8a734d5d10adbcd30eb5cc74bd9229af8b83f10044"
+"checksum which 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "240a31163872f7e8e49f35b42b58485e35355b07eb009d9f3686733541339a69"
 "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
 "checksum winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)" = "<none>"
 "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
 "checksum winapi-i686-pc-windows-gnu 0.4.0 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)" = "<none>"
 "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9"
 "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)" = "<none>"
 "checksum wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9"
 "checksum winreg 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a27a759395c1195c4cc5cda607ef6f8f6498f64e78f7900f5de0a127a424704a"
--- a/third_party/rust/bindgen/.cargo-checksum.json
+++ b/third_party/rust/bindgen/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.lock":"08acbc65a73a371ed1468a7937888e4a92da259bcff32f3f76c2207b45f0f75f","Cargo.toml":"03fdbfce44fd7e90fd59b8ffc43bcb8cb92ce05c9f4aa22c21040a2fc7979d63","LICENSE":"c23953d9deb0a3312dbeaf6c128a657f3591acee45067612fa68405eaa4525db","README.md":"5a1f556c6a57c0a6ccc65e19c27718e0f4b32381a8efcc80f6601b33c58c5d59","build.rs":"e1f148e01150af6a66b6af2e5d955c8b9fa092cb4697bae2bcec8a00119055ae","csmith-fuzzing/README.md":"7107b70fedb0c0a0cadb3c439a49c1bd0119a6d38dc63b1aecc74d1942256ef2","src/callbacks.rs":"82e0be9ca02e9a652af934ed546f1cedfc6db0716643123d9a5aab33b360c7d0","src/clang.rs":"66e86bfbbe872cc247cf3bc88a2155e25f587414834023515d184dc13f8f7287","src/codegen/bitfield_unit.rs":"a8fb1a2d97a99685106fcaac87d2013f79d2690d6a46ff05ad1e3629b6075664","src/codegen/bitfield_unit_tests.rs":"dd252134118450800b516e375c872e17b4c1aee63a7b8adbe5b2cd53434bbc7e","src/codegen/error.rs":"ebc9e0f50c6adc9558b76ce774346c02316500a1ebe3cbf56ed00e5e9fe3e456","src/codegen/helpers.rs":"304c9eb56ea6b2c054e1f9fefd5812b0df3a156eee5876f3051fd0b48c7aeac3","src/codegen/impl_debug.rs":"428df604b4be105e3275275e8be81e8306b940abddc1b89675f98a01bf5de8c1","src/codegen/impl_partialeq.rs":"83707f7b13501dc413c904a17163cb54af11e56138f36dfef40ce46c823200fd","src/codegen/mod.rs":"42732503dd25ed4b7924b71862f9100cf281e22f99016540da61a602c78a3650","src/codegen/struct_layout.rs":"482bab6384e65c78346de4f8d8e4d1c3b7df38250788b58bdd1f7b1c7bf70bac","src/extra_assertions.rs":"494534bd4f18b80d89b180c8a93733e6617edcf7deac413e9a73fd6e7bc9ced7","src/features.rs":"2d82f0700c22ea44e010a89c3ae857c3feaf2c85cab3fe4d0277a41a8c2841c4","src/ir/analysis/derive.rs":"2a2322f178760859cdb4b2d45d947ff213c7c684840b4ade46b7ceb34fa6705b","src/ir/analysis/has_destructor.rs":"10380d06ed03d058f10f6f6835d9b8fbebac455a1ea218780430a0ffd8d63472","src/ir/analysis/has_float.rs":"1838ba81eb05a9c3e311687e2247d561cc5093377b15ef8008257025ea56da04","src/ir/analysis/has_type_param_in_array.rs":"dddc5511a705e3a653b5e754e359637031b4862e1a1fc1e17f711fb2fbfc1cef","src/ir/analysis/has_vtable.rs":"8da9deec23c4552ecd5b883eaa036e4f2174a5949194c333a62ef463d28dcb6a","src/ir/analysis/mod.rs":"54993cb77df1870bb12cbc6b3a243c2da942cdc967a7d21dacb430601b49b2a1","src/ir/analysis/sizedness.rs":"d0673e19add38a07680ae3a9a5e998a0b2c3917e68efb6639ffe7ea193ada1b1","src/ir/analysis/template_params.rs":"9b662b5ec99cd8409d771a16ee42df500962b0c26f0da85e430ede19cc2b17c9","src/ir/annotations.rs":"268f90fc1d40fadee329c26b183b2aaa9de98f9246fea580404ee0e626315546","src/ir/comment.rs":"31d64a49ae3d9c3c348fa2539e03306ca3a23fae429cab452e42b31ecf632145","src/ir/comp.rs":"73d5d32d70b8e62d33ad4ed6bcbb9b23273c59b5b45570b85a2357c6e1116028","src/ir/context.rs":"c30be52b22fdb489afb34426bcb2e048ae2594846b15324693dd1b71e7dc3369","src/ir/derive.rs":"e5581852eec87918901a129284b4965aefc8a19394187a8095779a084f28fabe","src/ir/dot.rs":"5da8336bf5fd8efabd784a06e0d764eb91566c19ced8ce017a24ae237f0cbe18","src/ir/enum_ty.rs":"c303f3b271d2703c2487e4afaf4b8c9b5bbedb9e1c6a8044de667c21ad8f67fb","src/ir/function.rs":"7a25a55d7f2ded1724894bd1f7ee4766a4bf5f193967bf3a2628ec604b918018","src/ir/int.rs":"68a86182743ec338d58e42203364dc7c8970cb7ec3550433ca92f0c9489b4442","src/ir/item.rs":"203fe53efb0203e0ddc3fb9fcff7b2068f80f252d249a39c137e0cc070663a49","src/ir/item_kind.rs":"7666a1ff1b8260978b790a08b4139ab56b5c65714a5652bbcec7faa7443adc36","src/ir/layout.rs":"936f96fafab34e35b622a5f9e56b0fbd2c97d2e9222470e3687f882f40db1349","src/ir/mod.rs":"713cd537434567003197a123cbae679602c715e976d22f7b23dafd0826ea4c70","src/ir/module.rs":"a26bb0ac90d4cabb0a45d9c1a42b5515c74d4c233dc084e2f85161eac12bff15","src/ir/objc.rs":"ced8242068d5daa2940469693f7277c79368019f8e30ce1e4f55d834bf24c411","src/ir/template.rs":"6c2823c9bab82ab1d70f4d643e8f4d6420be5eafcb78324fb69649e407561cec","src/ir/traversal.rs":"c9bc1b8d7f1673d6f709e14bc04b684ec7097c2d12de446a2327296d5efc9547","src/ir/ty.rs":"5af2b62d278c679b7c4e597263fce01113e90242e7d263b948d93bc4274dfe9a","src/ir/var.rs":"9226241b188877b6a7bea6523e14318a8523a6dba57c4f15809c377f87540061","src/lib.rs":"b968f8d0858e3145137a2e33c0913acf19d21f884f914bc513bc18eea1c37bf1","src/log_stubs.rs":"6dfdd908b7c6453da416cf232893768f9480e551ca4add0858ef88bf71ee6ceb","src/main.rs":"6b42a74dfd5c3bde75b7fb984a82f3b3d652abd45aa54b31a40fbda6b02ae674","src/options.rs":"f08facc9d58cb79c7ab93c9d614f13d4d3eca2b5801012da56490a790a8d8c4c","src/parse.rs":"be7d13cc84fae79ec7b3aa9e77063fa475a48d74a854423e2c72d75006a25202","src/regex_set.rs":"5cb72fc3714c0d79e9e942d003349c0775fafd7cd0c9603c65f5261883bbf9cf","src/time.rs":"8efe317e7c6b5ba8e0865ce7b49ca775ee8a02590f4241ef62f647fa3c22b68e"},"package":"ae8266cdd336dfd53d71a95c33251232f64553b8770ebd85158039b3a734244b"}
\ No newline at end of file
+{"files":{"Cargo.lock":"f1b56f3cb914b4ed3214d3ce87d599398b399841718fc938c1b5a309356a44ea","Cargo.toml":"a4656cdd7bd0794e6f10ba78ed3c9a82cd86bfcbec59be7731ee90984de64bde","LICENSE":"c23953d9deb0a3312dbeaf6c128a657f3591acee45067612fa68405eaa4525db","README.md":"5a1f556c6a57c0a6ccc65e19c27718e0f4b32381a8efcc80f6601b33c58c5d59","build.rs":"e1f148e01150af6a66b6af2e5d955c8b9fa092cb4697bae2bcec8a00119055ae","csmith-fuzzing/README.md":"7107b70fedb0c0a0cadb3c439a49c1bd0119a6d38dc63b1aecc74d1942256ef2","src/callbacks.rs":"82e0be9ca02e9a652af934ed546f1cedfc6db0716643123d9a5aab33b360c7d0","src/clang.rs":"66e86bfbbe872cc247cf3bc88a2155e25f587414834023515d184dc13f8f7287","src/codegen/bitfield_unit.rs":"a8fb1a2d97a99685106fcaac87d2013f79d2690d6a46ff05ad1e3629b6075664","src/codegen/bitfield_unit_tests.rs":"dd252134118450800b516e375c872e17b4c1aee63a7b8adbe5b2cd53434bbc7e","src/codegen/error.rs":"ebc9e0f50c6adc9558b76ce774346c02316500a1ebe3cbf56ed00e5e9fe3e456","src/codegen/helpers.rs":"304c9eb56ea6b2c054e1f9fefd5812b0df3a156eee5876f3051fd0b48c7aeac3","src/codegen/impl_debug.rs":"428df604b4be105e3275275e8be81e8306b940abddc1b89675f98a01bf5de8c1","src/codegen/impl_partialeq.rs":"83707f7b13501dc413c904a17163cb54af11e56138f36dfef40ce46c823200fd","src/codegen/mod.rs":"42732503dd25ed4b7924b71862f9100cf281e22f99016540da61a602c78a3650","src/codegen/struct_layout.rs":"482bab6384e65c78346de4f8d8e4d1c3b7df38250788b58bdd1f7b1c7bf70bac","src/extra_assertions.rs":"494534bd4f18b80d89b180c8a93733e6617edcf7deac413e9a73fd6e7bc9ced7","src/features.rs":"2d82f0700c22ea44e010a89c3ae857c3feaf2c85cab3fe4d0277a41a8c2841c4","src/ir/analysis/derive.rs":"2a2322f178760859cdb4b2d45d947ff213c7c684840b4ade46b7ceb34fa6705b","src/ir/analysis/has_destructor.rs":"10380d06ed03d058f10f6f6835d9b8fbebac455a1ea218780430a0ffd8d63472","src/ir/analysis/has_float.rs":"1838ba81eb05a9c3e311687e2247d561cc5093377b15ef8008257025ea56da04","src/ir/analysis/has_type_param_in_array.rs":"dddc5511a705e3a653b5e754e359637031b4862e1a1fc1e17f711fb2fbfc1cef","src/ir/analysis/has_vtable.rs":"8da9deec23c4552ecd5b883eaa036e4f2174a5949194c333a62ef463d28dcb6a","src/ir/analysis/mod.rs":"54993cb77df1870bb12cbc6b3a243c2da942cdc967a7d21dacb430601b49b2a1","src/ir/analysis/sizedness.rs":"d0673e19add38a07680ae3a9a5e998a0b2c3917e68efb6639ffe7ea193ada1b1","src/ir/analysis/template_params.rs":"9b662b5ec99cd8409d771a16ee42df500962b0c26f0da85e430ede19cc2b17c9","src/ir/annotations.rs":"268f90fc1d40fadee329c26b183b2aaa9de98f9246fea580404ee0e626315546","src/ir/comment.rs":"31d64a49ae3d9c3c348fa2539e03306ca3a23fae429cab452e42b31ecf632145","src/ir/comp.rs":"73d5d32d70b8e62d33ad4ed6bcbb9b23273c59b5b45570b85a2357c6e1116028","src/ir/context.rs":"c30be52b22fdb489afb34426bcb2e048ae2594846b15324693dd1b71e7dc3369","src/ir/derive.rs":"e5581852eec87918901a129284b4965aefc8a19394187a8095779a084f28fabe","src/ir/dot.rs":"5da8336bf5fd8efabd784a06e0d764eb91566c19ced8ce017a24ae237f0cbe18","src/ir/enum_ty.rs":"c303f3b271d2703c2487e4afaf4b8c9b5bbedb9e1c6a8044de667c21ad8f67fb","src/ir/function.rs":"7a25a55d7f2ded1724894bd1f7ee4766a4bf5f193967bf3a2628ec604b918018","src/ir/int.rs":"68a86182743ec338d58e42203364dc7c8970cb7ec3550433ca92f0c9489b4442","src/ir/item.rs":"203fe53efb0203e0ddc3fb9fcff7b2068f80f252d249a39c137e0cc070663a49","src/ir/item_kind.rs":"7666a1ff1b8260978b790a08b4139ab56b5c65714a5652bbcec7faa7443adc36","src/ir/layout.rs":"936f96fafab34e35b622a5f9e56b0fbd2c97d2e9222470e3687f882f40db1349","src/ir/mod.rs":"713cd537434567003197a123cbae679602c715e976d22f7b23dafd0826ea4c70","src/ir/module.rs":"a26bb0ac90d4cabb0a45d9c1a42b5515c74d4c233dc084e2f85161eac12bff15","src/ir/objc.rs":"ced8242068d5daa2940469693f7277c79368019f8e30ce1e4f55d834bf24c411","src/ir/template.rs":"6c2823c9bab82ab1d70f4d643e8f4d6420be5eafcb78324fb69649e407561cec","src/ir/traversal.rs":"5ac088277f4dfe2918d81b9294aaee41fd83db8e46def66a05f89de078bf4c49","src/ir/ty.rs":"5af2b62d278c679b7c4e597263fce01113e90242e7d263b948d93bc4274dfe9a","src/ir/var.rs":"9226241b188877b6a7bea6523e14318a8523a6dba57c4f15809c377f87540061","src/lib.rs":"b968f8d0858e3145137a2e33c0913acf19d21f884f914bc513bc18eea1c37bf1","src/log_stubs.rs":"6dfdd908b7c6453da416cf232893768f9480e551ca4add0858ef88bf71ee6ceb","src/main.rs":"6b42a74dfd5c3bde75b7fb984a82f3b3d652abd45aa54b31a40fbda6b02ae674","src/options.rs":"f08facc9d58cb79c7ab93c9d614f13d4d3eca2b5801012da56490a790a8d8c4c","src/parse.rs":"be7d13cc84fae79ec7b3aa9e77063fa475a48d74a854423e2c72d75006a25202","src/regex_set.rs":"5cb72fc3714c0d79e9e942d003349c0775fafd7cd0c9603c65f5261883bbf9cf","src/time.rs":"8efe317e7c6b5ba8e0865ce7b49ca775ee8a02590f4241ef62f647fa3c22b68e"},"package":"ebd71393f1ec0509b553aa012b9b58e81dadbdff7130bd3b8cba576e69b32f75"}
\ No newline at end of file
--- a/third_party/rust/bindgen/Cargo.lock
+++ b/third_party/rust/bindgen/Cargo.lock
@@ -23,30 +23,30 @@ source = "registry+https://github.com/ru
 dependencies = [
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "bindgen"
-version = "0.51.1-oldsyn"
+version = "0.51.1"
 dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "cexpr 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "clang-sys 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "which 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "bitflags"
@@ -180,33 +180,33 @@ dependencies = [
 
 [[package]]
 name = "peeking_take_while"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "proc-macro2"
-version = "0.4.19"
+version = "1.0.0"
 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)",
+ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "quick-error"
 version = "1.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "quote"
-version = "0.6.8"
+version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "redox_syscall"
 version = "0.1.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -296,17 +296,17 @@ source = "registry+https://github.com/ru
 
 [[package]]
 name = "unicode-width"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "unicode-xid"
-version = "0.1.0"
+version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "utf8-ranges"
 version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -380,33 +380,33 @@ dependencies = [
 "checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e"
 "checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7"
 "checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d"
 "checksum libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3ad660d7cb8c5822cd83d10897b0f1f1526792737a179e73896152f85b88c2"
 "checksum log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fcce5fa49cc693c312001daf1d13411c4a5283796bac1084299ea3e567113f"
 "checksum memchr 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4b3629fe9fdbff6daa6c33b90f7c08355c1aca05a3d01fa8063b822fcf185f3b"
 "checksum nom 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "898696750eb5c3ce5eb5afbfbe46e7f7c4e1936e19d3e97be4b7937da7b6d114"
 "checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
-"checksum proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "ffe022fb8c8bd254524b0b3305906c1921fa37a84a644e29079a9e62200c3901"
+"checksum proc-macro2 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "19f287c234c9b2d0308d692dee5c449c1a171167a6f8150f7cf2a49d8fd96967"
 "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
-"checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5"
+"checksum quote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ab938ebe6f1c82426b5fb82eaf10c3e3028c53deaa3fbe38f5904b37cf4d767"
 "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1"
 "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
 "checksum regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2069749032ea3ec200ca51e4a31df41759190a88edca0d2d86ee8bedf7073341"
 "checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d"
 "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
 "checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
 "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
 "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f"
 "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
 "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"
 "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
 "checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d"
 "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
-"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
+"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
 "checksum utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd70f467df6810094968e2fce0ee1bd0e87157aceb026a8c083bcf5e25b9efe4"
 "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
 "checksum version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7716c242968ee87e5542f8021178248f267f295a5c4803beae8b8b7fd9bc6051"
 "checksum which 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "240a31163872f7e8e49f35b42b58485e35355b07eb009d9f3686733541339a69"
 "checksum winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "773ef9dcc5f24b7d850d0ff101e542ff24c3b090a9768e03ff889fdef41f00fd"
 "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
 "checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab"
 "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
--- a/third_party/rust/bindgen/Cargo.toml
+++ b/third_party/rust/bindgen/Cargo.toml
@@ -7,17 +7,17 @@
 #
 # 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 = "bindgen"
-version = "0.51.1-oldsyn"
+version = "0.51.1"
 authors = ["Jyun-Yan You <jyyou.tw@gmail.com>", "Emilio Cobos Álvarez <emilio@crisal.io>", "Nick Fitzgerald <fitzgen@gmail.com>", "The Servo project developers"]
 build = "build.rs"
 include = ["LICENSE", "README.md", "Cargo.toml", "build.rs", "src/*.rs", "src/**/*.rs"]
 description = "Automatically generates Rust FFI bindings to C and C++ libraries."
 homepage = "https://rust-lang.github.io/rust-bindgen/"
 documentation = "https://docs.rs/bindgen"
 readme = "README.md"
 keywords = ["bindings", "ffi", "code-generation"]
@@ -60,21 +60,21 @@ version = "1"
 [dependencies.log]
 version = "0.4"
 optional = true
 
 [dependencies.peeking_take_while]
 version = "0.1.2"
 
 [dependencies.proc-macro2]
-version = "0.4"
+version = "1"
 default-features = false
 
 [dependencies.quote]
-version = "0.6"
+version = "1"
 default-features = false
 
 [dependencies.regex]
 version = "1.0"
 
 [dependencies.rustc-hash]
 version = "1.0.1"
 
--- a/third_party/rust/bindgen/src/ir/traversal.rs
+++ b/third_party/rust/bindgen/src/ir/traversal.rs
@@ -498,11 +498,11 @@ pub type AssertNoDanglingItemsTraversal<
 #[cfg(test)]
 mod tests {
     use super::*;
 
     #[test]
     #[allow(dead_code)]
     fn traversal_predicate_is_object_safe() {
         // This should compile only if TraversalPredicate is object safe.
-        fn takes_by_trait_object(_: &TraversalPredicate) {}
+        fn takes_by_trait_object(_: &dyn TraversalPredicate) {}
     }
 }
--- a/third_party/rust/lmdb-rkv-sys/.cargo-checksum.json
+++ b/third_party/rust/lmdb-rkv-sys/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"3cc7f803bee8b87f9d16870e5d6a91381be0d361472f88bb45354200e4177444","build.rs":"d001be8ded3d94c0ae26dd355b5481dc6c0e20e05ea55cbfbb9df572e0678fbc","lmdb/libraries/liblmdb/CHANGES":"12f41155ee12375b7ddeabd2f793399d3216e92bc44f1122d6f305b7637c2fec","lmdb/libraries/liblmdb/COPYRIGHT":"7cf04234accacc7b41b73fe6b3b19759fa49dee1ce705a9fa6533900400e4cca","lmdb/libraries/liblmdb/Doxyfile":"5545f6b049040ce58e6d1a603eaea6b7fb8ae92459f2ab8d3bcbacabcce1014d","lmdb/libraries/liblmdb/LICENSE":"310fe25c858a9515fc8c8d7d1f24a67c9496f84a91e0a0e41ea9975b1371e569","lmdb/libraries/liblmdb/Makefile":"60b5f574e6642602f692a95956da61c588a265ad50b8059960c230b9e6aaf4fd","lmdb/libraries/liblmdb/intro.doc":"9442e0db4fc9c70f058c43545e710476d8d5a80b959d20f4381240fd50c6b843","lmdb/libraries/liblmdb/lmdb.h":"a8194f7a061f4168d99de3c80464de5d279b2c851c24fdd102f1f14dd5828a77","lmdb/libraries/liblmdb/mdb.c":"ac74a364ac574814dfc49b03648e8cd32514a6cdf4b6f331bd11050bb9c10788","lmdb/libraries/liblmdb/mdb_copy.1":"3a6a8a7a91e1bd42dc4d2a0188ff62d699ff2b3b097a670f30681decf63f22f3","lmdb/libraries/liblmdb/mdb_copy.c":"d3d412a770a5c3afeb88c44b4acdde0f0b985cde22497198e8f38296281cdddd","lmdb/libraries/liblmdb/mdb_dump.1":"9257be883c7fcfcbd61003cc730f7c0900fa8f6feba074c8c1e46634a257b13a","lmdb/libraries/liblmdb/mdb_dump.c":"b046cffcd997254e6daea47a2d7fb74f9d23282174cbb1e3bf9f5fb51a90fe64","lmdb/libraries/liblmdb/mdb_load.1":"ea927473245a4a7777ba687aa26baf7f0951fb620daf82b8d730a090185b2bbc","lmdb/libraries/liblmdb/mdb_load.c":"4f722613c65350315db23060be98584fb572978108885dab271101ba7187dca4","lmdb/libraries/liblmdb/mdb_stat.1":"c0a70d96b4b2d32e73301383d9d5620bc0bbbefb019bfd54f32088dfd4bc921a","lmdb/libraries/liblmdb/mdb_stat.c":"e6405fa191d784ecfa8eb8d1f153a58facc49a8f5a2c891a93802e67acc4861e","lmdb/libraries/liblmdb/midl.c":"92b0933c7736443448018a93f9588e9e26ae2e242f91b19211dea9ed3ab91141","lmdb/libraries/liblmdb/midl.h":"b8fa0d35b5505001d9f722f8f23993b8602c3599eb71ec869bb556f5e4ef2fde","lmdb/libraries/liblmdb/mtest.c":"89ab9ac8bf1e14a9f32a33757c4b3254e4984e0f24e5a302e2d126eb2c86f6db","lmdb/libraries/liblmdb/mtest2.c":"076b00395fe1461dd9577f7bb5567908ce50cf470efbf652787e6fe1dc2fb68c","lmdb/libraries/liblmdb/mtest3.c":"51b9a055e123bd0757ee3082cc6864c836969cf630e646a9cc34e01398c20634","lmdb/libraries/liblmdb/mtest4.c":"b0a725405d80bda6ab95b3ecf410ae330ab8df7a081ca81dd6ea1f8db87642e9","lmdb/libraries/liblmdb/mtest5.c":"7f3b06ca3833315ea4c70d5e91feb1b677f6949f105f4f89d96c3ac35e104f2f","lmdb/libraries/liblmdb/mtest6.c":"e4d7880c36547ebf33bc020046730bf2c075c53aaacd5c876152cc5ae7ab5e6c","lmdb/libraries/liblmdb/sample-bdb.txt":"153d84f8fc49a3abba53ed52d5a41c8d6d4698753a10bbe0689a9e65d3513513","lmdb/libraries/liblmdb/sample-mdb.txt":"1f77385786cffdf72b33da06a91a444fe2827673c3627f89110903a8fe012795","lmdb/libraries/liblmdb/tooltag":"4734c6dc1fa7aec8c2e9646bd04bc5218ef6a03ad83a3b18de2ac4069eb94120","src/constants.rs":"af67740b5acccdc71b2267ec051bb60e5433c4f0313fe16dc0627376a52dcdff","src/ffi.rs":"caa9bbfb3868a7a9e9ad822d775e60ffa8c8c2f2450ac4ed403a93ddb7547899","src/lib.rs":"1de52cd4fda49bd2c414e57dc605d0a9915a64f1cd3ea3583ad0d6f34c13d6ad"},"package":"4d7d61f709086e3efb2f7255ad01cf1d7f9e407b7dfe96d83cd15e76ee8283b4"}
\ No newline at end of file
+{"files":{"Cargo.toml":"8d0140a5541de1e5feb200562bf6a059466b3e757f887090c52c12fa9cc5f74b","bindgen.rs":"bf1f032951cac23a18bd41063df739503bf040bf7c815e1e393238c86edbbb25","build.rs":"47042b2d98af39f06406ebdd2020ad15c01165195aef6a3bda30e09d8411834a","lmdb/libraries/liblmdb/CHANGES":"ba14b94dda8670db454275d2f5fb83510f810ccb3ccfca642176a0efef245e08","lmdb/libraries/liblmdb/COPYRIGHT":"fae797823b892c4b59913256b4d10b17d71f57d4bc45e46d901b84fd6dfc3d13","lmdb/libraries/liblmdb/Doxyfile":"5545f6b049040ce58e6d1a603eaea6b7fb8ae92459f2ab8d3bcbacabcce1014d","lmdb/libraries/liblmdb/LICENSE":"310fe25c858a9515fc8c8d7d1f24a67c9496f84a91e0a0e41ea9975b1371e569","lmdb/libraries/liblmdb/Makefile":"60b5f574e6642602f692a95956da61c588a265ad50b8059960c230b9e6aaf4fd","lmdb/libraries/liblmdb/intro.doc":"9442e0db4fc9c70f058c43545e710476d8d5a80b959d20f4381240fd50c6b843","lmdb/libraries/liblmdb/lmdb.h":"05abf244b621b2d14e838b0643e72d5075ce77d8df856b6dccde74ee51c9cf22","lmdb/libraries/liblmdb/mdb.c":"5c7a4e9269e1af7ddb8f10b07f5d2b7f0d111dd379826d5e4880f6101bff4efc","lmdb/libraries/liblmdb/mdb_copy.1":"3a6a8a7a91e1bd42dc4d2a0188ff62d699ff2b3b097a670f30681decf63f22f3","lmdb/libraries/liblmdb/mdb_copy.c":"d3d412a770a5c3afeb88c44b4acdde0f0b985cde22497198e8f38296281cdddd","lmdb/libraries/liblmdb/mdb_dump.1":"9257be883c7fcfcbd61003cc730f7c0900fa8f6feba074c8c1e46634a257b13a","lmdb/libraries/liblmdb/mdb_dump.c":"b046cffcd997254e6daea47a2d7fb74f9d23282174cbb1e3bf9f5fb51a90fe64","lmdb/libraries/liblmdb/mdb_load.1":"ea927473245a4a7777ba687aa26baf7f0951fb620daf82b8d730a090185b2bbc","lmdb/libraries/liblmdb/mdb_load.c":"4f722613c65350315db23060be98584fb572978108885dab271101ba7187dca4","lmdb/libraries/liblmdb/mdb_stat.1":"c0a70d96b4b2d32e73301383d9d5620bc0bbbefb019bfd54f32088dfd4bc921a","lmdb/libraries/liblmdb/mdb_stat.c":"e6405fa191d784ecfa8eb8d1f153a58facc49a8f5a2c891a93802e67acc4861e","lmdb/libraries/liblmdb/midl.c":"e19143db51dd606396c7eba765832e4b66167c0975614e576b950349f8f6cdfd","lmdb/libraries/liblmdb/midl.h":"52066a085aa0fc90799113fb1cc60ca78a5e35ca6191f5f5cb29488d4bd66dba","lmdb/libraries/liblmdb/mtest.c":"89ab9ac8bf1e14a9f32a33757c4b3254e4984e0f24e5a302e2d126eb2c86f6db","lmdb/libraries/liblmdb/mtest2.c":"076b00395fe1461dd9577f7bb5567908ce50cf470efbf652787e6fe1dc2fb68c","lmdb/libraries/liblmdb/mtest3.c":"51b9a055e123bd0757ee3082cc6864c836969cf630e646a9cc34e01398c20634","lmdb/libraries/liblmdb/mtest4.c":"b0a725405d80bda6ab95b3ecf410ae330ab8df7a081ca81dd6ea1f8db87642e9","lmdb/libraries/liblmdb/mtest5.c":"7f3b06ca3833315ea4c70d5e91feb1b677f6949f105f4f89d96c3ac35e104f2f","lmdb/libraries/liblmdb/mtest6.c":"e4d7880c36547ebf33bc020046730bf2c075c53aaacd5c876152cc5ae7ab5e6c","lmdb/libraries/liblmdb/sample-bdb.txt":"153d84f8fc49a3abba53ed52d5a41c8d6d4698753a10bbe0689a9e65d3513513","lmdb/libraries/liblmdb/sample-mdb.txt":"1f77385786cffdf72b33da06a91a444fe2827673c3627f89110903a8fe012795","lmdb/libraries/liblmdb/tooltag":"4734c6dc1fa7aec8c2e9646bd04bc5218ef6a03ad83a3b18de2ac4069eb94120","src/bindings.rs":"187b1cdf9c7cd91632030fb64f964113cf115155675cb12c4a6a8afb2292f79a","src/lib.rs":"4095e837845ab0e4ba5dbaacb92d786d0a9c1c0702f50635731be4f3af6cba31","tests/fixtures/testdb/data.mdb":"8a0cf8ad63473ae63d437a646042b0d64c112a8fa33d5c916f0678ce4d23189b","tests/fixtures/testdb/lock.mdb":"0e734f65f82f39556cfd62f5da1cc02e56e1cc435f48fe39168e4dc21628e586","tests/lmdb.rs":"5086cb43f3a7b6a8aaa257084c1e0bea664f279ff260b99a8ad0d3c598867a45","tests/simple.rs":"a7ffaef9e3e499bc9372dca9b37b05e7b4e70b3c7d9aac63f79dd0cb8512a41f"},"package":"cad9a69dc385f7d2b77786bc41f3dd80f02fba6edc547e93af637f58d440ec8d"}
\ No newline at end of file
--- a/third_party/rust/lmdb-rkv-sys/Cargo.toml
+++ b/third_party/rust/lmdb-rkv-sys/Cargo.toml
@@ -7,36 +7,51 @@
 #
 # 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-sys"
-version = "0.8.4"
-authors = ["Dan Burkert <dan@danburkert.com>"]
+version = "0.9.3"
+authors = ["Dan Burkert <dan@danburkert.com>", "Victor Porof <vporof@mozilla.com>"]
 build = "build.rs"
 description = "Rust bindings for liblmdb."
+homepage = "https://github.com/mozilla/lmdb-rs"
 documentation = "https://docs.rs/lmdb-rkv-sys"
 readme = "../README.md"
 keywords = ["LMDB", "database", "storage-engine", "bindings", "library"]
 categories = ["database", "external-ffi-bindings"]
 license = "Apache-2.0"
 repository = "https://github.com/mozilla/lmdb-rs.git"
+
+[lib]
+name = "lmdb_sys"
 [dependencies.libc]
 version = "0.2"
+[build-dependencies.bindgen]
+version = "0.51"
+
 [build-dependencies.cc]
-version = "1"
+version = "1.0"
 
 [build-dependencies.pkg-config]
-version = "0.3.2"
+version = "0.3"
 
 [features]
 default = []
 mdb_idl_logn_10 = []
 mdb_idl_logn_11 = []
 mdb_idl_logn_12 = []
 mdb_idl_logn_13 = []
 mdb_idl_logn_14 = []
 mdb_idl_logn_15 = []
 mdb_idl_logn_8 = []
 mdb_idl_logn_9 = []
+with-asan = []
+with-fuzzer = []
+with-fuzzer-no-link = []
+[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-sys/bindgen.rs
@@ -0,0 +1,68 @@
+extern crate bindgen;
+
+use bindgen::callbacks::IntKind;
+use bindgen::callbacks::ParseCallbacks;
+use std::env;
+use std::path::PathBuf;
+
+#[derive(Debug)]
+struct Callbacks;
+
+impl ParseCallbacks for Callbacks {
+    fn int_macro(&self, name: &str, _value: i64) -> Option<IntKind> {
+        match name {
+            "MDB_SUCCESS"
+            | "MDB_KEYEXIST"
+            | "MDB_NOTFOUND"
+            | "MDB_PAGE_NOTFOUND"
+            | "MDB_CORRUPTED"
+            | "MDB_PANIC"
+            | "MDB_VERSION_MISMATCH"
+            | "MDB_INVALID"
+            | "MDB_MAP_FULL"
+            | "MDB_DBS_FULL"
+            | "MDB_READERS_FULL"
+            | "MDB_TLS_FULL"
+            | "MDB_TXN_FULL"
+            | "MDB_CURSOR_FULL"
+            | "MDB_PAGE_FULL"
+            | "MDB_MAP_RESIZED"
+            | "MDB_INCOMPATIBLE"
+            | "MDB_BAD_RSLOT"
+            | "MDB_BAD_TXN"
+            | "MDB_BAD_VALSIZE"
+            | "MDB_BAD_DBI"
+            | "MDB_LAST_ERRCODE" => Some(IntKind::Int),
+            _ => Some(IntKind::UInt),
+        }
+    }
+}
+
+fn main() {
+    let mut lmdb = PathBuf::from(&env::var("CARGO_MANIFEST_DIR").unwrap());
+    lmdb.push("lmdb");
+    lmdb.push("libraries");
+    lmdb.push("liblmdb");
+
+    let mut out_path = PathBuf::from(&env::var("CARGO_MANIFEST_DIR").unwrap());
+    out_path.push("src");
+
+    let bindings = bindgen::Builder::default()
+        .header(lmdb.join("lmdb.h").to_string_lossy())
+        .whitelist_var("^(MDB|mdb)_.*")
+        .whitelist_type("^(MDB|mdb)_.*")
+        .whitelist_function("^(MDB|mdb)_.*")
+        .ctypes_prefix("::libc")
+        .blacklist_item("mode_t")
+        .blacklist_item("^__.*")
+        .parse_callbacks(Box::new(Callbacks {}))
+        .layout_tests(false)
+        .prepend_enum_name(false)
+        .rustfmt_bindings(true)
+        .generate()
+        .expect("Unable to generate bindings");
+
+    bindings
+        .write_to_file(out_path.join("bindings.rs"))
+        .expect("Couldn't write bindings!");
+}
--- a/third_party/rust/lmdb-rkv-sys/build.rs
+++ b/third_party/rust/lmdb-rkv-sys/build.rs
@@ -1,10 +1,10 @@
+extern crate cc;
 extern crate pkg_config;
-extern crate cc;
 
 use std::env;
 use std::path::PathBuf;
 
 #[cfg(feature = "mdb_idl_logn_8")]
 const MDB_IDL_LOGN: u8 = 8;
 #[cfg(feature = "mdb_idl_logn_9")]
 const MDB_IDL_LOGN: u8 = 9;
@@ -27,24 +27,50 @@ const MDB_IDL_LOGN: u8 = 15;
     feature = "mdb_idl_logn_11",
     feature = "mdb_idl_logn_12",
     feature = "mdb_idl_logn_13",
     feature = "mdb_idl_logn_14",
     feature = "mdb_idl_logn_15",
 )))]
 const MDB_IDL_LOGN: u8 = 16;
 
+macro_rules! warn {
+    ($message:expr) => {
+        println!("cargo:warning={}", $message);
+    };
+}
+
 fn main() {
-    let mut lmdb: PathBuf = PathBuf::from(&env::var("CARGO_MANIFEST_DIR").unwrap());
+    let mut lmdb = PathBuf::from(&env::var("CARGO_MANIFEST_DIR").unwrap());
     lmdb.push("lmdb");
     lmdb.push("libraries");
     lmdb.push("liblmdb");
 
+    if cfg!(feature = "with-fuzzer") && cfg!(feature = "with-fuzzer-no-link") {
+        warn!("Features `with-fuzzer` and `with-fuzzer-no-link` are mutually exclusive.");
+        warn!("Building with `-fsanitize=fuzzer`.");
+    }
+
     if !pkg_config::find_library("liblmdb").is_ok() {
-        cc::Build::new()
-                    .define("MDB_IDL_LOGN", Some(MDB_IDL_LOGN.to_string().as_str()))
-                    .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")
+        let mut builder = cc::Build::new();
+
+        builder
+            .define("MDB_IDL_LOGN", Some(MDB_IDL_LOGN.to_string().as_str()))
+            .file(lmdb.join("mdb.c"))
+            .file(lmdb.join("midl.c"))
+            // https://github.com/mozilla/lmdb/blob/b7df2cac50fb41e8bd16aab4cc5fd167be9e032a/libraries/liblmdb/Makefile#L23
+            .flag_if_supported("-Wno-unused-parameter")
+            .flag_if_supported("-Wbad-function-cast")
+            .flag_if_supported("-Wuninitialized");
+
+        if env::var("CARGO_FEATURE_WITH_ASAN").is_ok() {
+            builder.flag("-fsanitize=address");
+        }
+
+        if env::var("CARGO_FEATURE_WITH_FUZZER").is_ok() {
+            builder.flag("-fsanitize=fuzzer");
+        } else if env::var("CARGO_FEATURE_WITH_FUZZER_NO_LINK").is_ok() {
+            builder.flag("-fsanitize=fuzzer-no-link");
+        }
+
+        builder.compile("liblmdb.a")
     }
 }
--- a/third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/CHANGES
+++ b/third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/CHANGES
@@ -1,10 +1,15 @@
 LMDB 0.9 Change Log
 
+LMDB 0.9.24 Release (2019/07/24)
+	ITS#8969 Tweak mdb_page_split
+	ITS#8975 WIN32 fix writemap set_mapsize crash
+	ITS#9007 Fix loose pages in WRITEMAP
+
 LMDB 0.9.23 Release (2018/12/19)
 	ITS#8756 Fix loose pages in dirty list
 	ITS#8831 Fix mdb_load flag init
 	ITS#8844 Fix mdb_env_close in forked process
 	Documentation
 		ITS#8857 mdb_cursor_del doesn't invalidate cursor
 		ITS#8908 GET_MULTIPLE etc don't change passed in key
 
--- a/third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/COPYRIGHT
+++ b/third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/COPYRIGHT
@@ -1,9 +1,9 @@
-Copyright 2011-2018 Howard Chu, Symas Corp.
+Copyright 2011-2019 Howard Chu, Symas Corp.
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted only as authorized by the OpenLDAP
 Public License.
 
 A copy of this license is available in the file LICENSE in the
 top-level directory of the distribution or, alternatively, at
--- a/third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/lmdb.h
+++ b/third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/lmdb.h
@@ -130,17 +130,17 @@
  *	  possibly memory map sync, and certainly sync between programs
  *	  on different hosts.
  *
  *	- Opening a database can fail if another process is opening or
  *	  closing it at exactly the same time.
  *
  *	@author	Howard Chu, Symas Corporation.
  *
- *	@copyright Copyright 2011-2018 Howard Chu, Symas Corp. All rights reserved.
+ *	@copyright Copyright 2011-2019 Howard Chu, Symas Corp. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted only as authorized by the OpenLDAP
  * Public License.
  *
  * A copy of this license is available in the file LICENSE in the
  * top-level directory of the distribution or, alternatively, at
  * <http://www.OpenLDAP.org/license.html>.
@@ -195,27 +195,27 @@ typedef int mdb_filehandle_t;
 /** @defgroup Version Version Macros
  *	@{
  */
 /** Library major version */
 #define MDB_VERSION_MAJOR	0
 /** Library minor version */
 #define MDB_VERSION_MINOR	9
 /** Library patch version */
-#define MDB_VERSION_PATCH	23
+#define MDB_VERSION_PATCH	24
 
 /** Combine args a,b,c into a single integer for easy version comparisons */
 #define MDB_VERINT(a,b,c)	(((a) << 24) | ((b) << 16) | (c))
 
 /** The full library version as a single integer */
 #define MDB_VERSION_FULL	\
 	MDB_VERINT(MDB_VERSION_MAJOR,MDB_VERSION_MINOR,MDB_VERSION_PATCH)
 
 /** The release date of this library version */
-#define MDB_VERSION_DATE	"December 19, 2018"
+#define MDB_VERSION_DATE	"July 24, 2019"
 
 /** A stringifier for the version info */
 #define MDB_VERSTR(a,b,c,d)	"LMDB " #a "." #b "." #c ": (" d ")"
 
 /** A helper for the stringifier macro */
 #define MDB_VERFOO(a,b,c,d)	MDB_VERSTR(a,b,c,d)
 
 /** The full library version as a C string */
--- a/third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/mdb.c
+++ b/third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/mdb.c
@@ -1,16 +1,16 @@
 /** @file mdb.c
  *	@brief Lightning memory-mapped database library
  *
  *	A Btree-based database management library modeled loosely on the
  *	BerkeleyDB API, but much simplified.
  */
 /*
- * Copyright 2011-2018 Howard Chu, Symas Corp.
+ * Copyright 2011-2019 Howard Chu, Symas Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted only as authorized by the OpenLDAP
  * Public License.
  *
  * A copy of this license is available in the file LICENSE in the
  * top-level directory of the distribution or, alternatively, at
@@ -3103,19 +3103,19 @@ mdb_freelist_save(MDB_txn *txn)
 			if (txn->mt_flags & MDB_TXN_WRITEMAP) {
 				for (x=1; x<=dl[0].mid; x++)
 					if (dl[x].mid == mp->mp_pgno)
 						break;
 				mdb_tassert(txn, x <= dl[0].mid);
 			} else {
 				x = mdb_mid2l_search(dl, mp->mp_pgno);
 				mdb_tassert(txn, dl[x].mid == mp->mp_pgno);
+				mdb_dpage_free(env, mp);
 			}
 			dl[x].mptr = NULL;
-			mdb_dpage_free(env, mp);
 		}
 		{
 			/* squash freed slots out of the dirty list */
 			unsigned y;
 			for (y=1; dl[y].mptr && y <= dl[0].mid; y++);
 			if (y <= dl[0].mid) {
 				for(x=y, y++;;) {
 					while (!dl[y].mptr && y <= dl[0].mid) y++;
@@ -3985,19 +3985,19 @@ mdb_env_map(MDB_env *env, void *addr)
 		msize = env->me_mapsize;
 		sizelo = msize & 0xffffffff;
 		sizehi = msize >> 16 >> 16; /* only needed on Win64 */
 
 		/* Windows won't create mappings for zero length files.
 		 * and won't map more than the file size.
 		 * Just set the maxsize right now.
 		 */
-		if (SetFilePointer(env->me_fd, sizelo, &sizehi, 0) != (DWORD)sizelo
+		if (!(flags & MDB_WRITEMAP) && (SetFilePointer(env->me_fd, sizelo, &sizehi, 0) != (DWORD)sizelo
 			|| !SetEndOfFile(env->me_fd)
-			|| SetFilePointer(env->me_fd, 0, NULL, 0) != 0)
+			|| SetFilePointer(env->me_fd, 0, NULL, 0) != 0))
 			return ErrCode();
 	}
 
 	mh = CreateFileMapping(env->me_fd, NULL, flags & MDB_WRITEMAP ?
 		PAGE_READWRITE : PAGE_READONLY,
 		sizehi, sizelo, NULL);
 	if (!mh)
 		return ErrCode();
@@ -8743,17 +8743,17 @@ mdb_page_split(MDB_cursor *mc, MDB_val *
 			 * item is also "large" and falls on the half with
 			 * "large" nodes, it also may not fit.
 			 *
 			 * As a final tweak, if the new item goes on the last
 			 * spot on the page (and thus, onto the new page), bias
 			 * the split so the new page is emptier than the old page.
 			 * This yields better packing during sequential inserts.
 			 */
-			if (nkeys < 20 || nsize > pmax/16 || newindx >= nkeys) {
+			if (nkeys < 32 || nsize > pmax/16 || newindx >= nkeys) {
 				/* Find split point */
 				psize = 0;
 				if (newindx <= split_indx || newindx >= nkeys) {
 					i = 0; j = 1;
 					k = newindx >= nkeys ? nkeys : split_indx+1+IS_LEAF(mp);
 				} else {
 					i = nkeys; j = -1;
 					k = split_indx-1;
--- a/third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/midl.c
+++ b/third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/midl.c
@@ -1,14 +1,14 @@
 /**	@file midl.c
  *	@brief ldap bdb back-end ID List functions */
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2000-2018 The OpenLDAP Foundation.
+ * Copyright 2000-2019 The OpenLDAP Foundation.
  * Portions Copyright 2001-2018 Howard Chu, Symas Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted only as authorized by the OpenLDAP
  * Public License.
  *
  * A copy of this license is available in the file LICENSE in the
--- a/third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/midl.h
+++ b/third_party/rust/lmdb-rkv-sys/lmdb/libraries/liblmdb/midl.h
@@ -6,17 +6,17 @@
  *	in this file are unused, just left over from the original.
  *
  *	This file is only used internally in libmdb and its definitions
  *	are not exposed publicly.
  */
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2000-2018 The OpenLDAP Foundation.
+ * Copyright 2000-2019 The OpenLDAP Foundation.
  * Portions Copyright 2001-2018 Howard Chu, Symas Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted only as authorized by the OpenLDAP
  * Public License.
  *
  * A copy of this license is available in the file LICENSE in the
new file mode 100644
--- /dev/null
+++ b/third_party/rust/lmdb-rkv-sys/src/bindings.rs
@@ -0,0 +1,1395 @@
+/* automatically generated by rust-bindgen */
+
+pub const MDB_VERSION_MAJOR: ::libc::c_uint = 0;
+pub const MDB_VERSION_MINOR: ::libc::c_uint = 9;
+pub const MDB_VERSION_PATCH: ::libc::c_uint = 24;
+pub const MDB_VERSION_DATE: &'static [u8; 14usize] = b"July 24, 2019\0";
+pub const MDB_FIXEDMAP: ::libc::c_uint = 1;
+pub const MDB_NOSUBDIR: ::libc::c_uint = 16384;
+pub const MDB_NOSYNC: ::libc::c_uint = 65536;
+pub const MDB_RDONLY: ::libc::c_uint = 131072;
+pub const MDB_NOMETASYNC: ::libc::c_uint = 262144;
+pub const MDB_WRITEMAP: ::libc::c_uint = 524288;
+pub const MDB_MAPASYNC: ::libc::c_uint = 1048576;
+pub const MDB_NOTLS: ::libc::c_uint = 2097152;
+pub const MDB_NOLOCK: ::libc::c_uint = 4194304;
+pub const MDB_NORDAHEAD: ::libc::c_uint = 8388608;
+pub const MDB_NOMEMINIT: ::libc::c_uint = 16777216;
+pub const MDB_REVERSEKEY: ::libc::c_uint = 2;
+pub const MDB_DUPSORT: ::libc::c_uint = 4;
+pub const MDB_INTEGERKEY: ::libc::c_uint = 8;
+pub const MDB_DUPFIXED: ::libc::c_uint = 16;
+pub const MDB_INTEGERDUP: ::libc::c_uint = 32;
+pub const MDB_REVERSEDUP: ::libc::c_uint = 64;
+pub const MDB_CREATE: ::libc::c_uint = 262144;
+pub const MDB_NOOVERWRITE: ::libc::c_uint = 16;
+pub const MDB_NODUPDATA: ::libc::c_uint = 32;
+pub const MDB_CURRENT: ::libc::c_uint = 64;
+pub const MDB_RESERVE: ::libc::c_uint = 65536;
+pub const MDB_APPEND: ::libc::c_uint = 131072;
+pub const MDB_APPENDDUP: ::libc::c_uint = 262144;
+pub const MDB_MULTIPLE: ::libc::c_uint = 524288;
+pub const MDB_CP_COMPACT: ::libc::c_uint = 1;
+pub const MDB_SUCCESS: ::libc::c_int = 0;
+pub const MDB_KEYEXIST: ::libc::c_int = -30799;
+pub const MDB_NOTFOUND: ::libc::c_int = -30798;
+pub const MDB_PAGE_NOTFOUND: ::libc::c_int = -30797;
+pub const MDB_CORRUPTED: ::libc::c_int = -30796;
+pub const MDB_PANIC: ::libc::c_int = -30795;
+pub const MDB_VERSION_MISMATCH: ::libc::c_int = -30794;
+pub const MDB_INVALID: ::libc::c_int = -30793;
+pub const MDB_MAP_FULL: ::libc::c_int = -30792;
+pub const MDB_DBS_FULL: ::libc::c_int = -30791;
+pub const MDB_READERS_FULL: ::libc::c_int = -30790;
+pub const MDB_TLS_FULL: ::libc::c_int = -30789;
+pub const MDB_TXN_FULL: ::libc::c_int = -30788;
+pub const MDB_CURSOR_FULL: ::libc::c_int = -30787;
+pub const MDB_PAGE_FULL: ::libc::c_int = -30786;
+pub const MDB_MAP_RESIZED: ::libc::c_int = -30785;
+pub const MDB_INCOMPATIBLE: ::libc::c_int = -30784;
+pub const MDB_BAD_RSLOT: ::libc::c_int = -30783;
+pub const MDB_BAD_TXN: ::libc::c_int = -30782;
+pub const MDB_BAD_VALSIZE: ::libc::c_int = -30781;
+pub const MDB_BAD_DBI: ::libc::c_int = -30780;
+pub const MDB_LAST_ERRCODE: ::libc::c_int = -30780;
+pub type mdb_mode_t = mode_t;
+pub type mdb_filehandle_t = ::libc::c_int;
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct MDB_env {
+    _unused: [u8; 0],
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct MDB_txn {
+    _unused: [u8; 0],
+}
+#[doc = " @brief A handle for an individual database in the DB environment."]
+pub type MDB_dbi = ::libc::c_uint;
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct MDB_cursor {
+    _unused: [u8; 0],
+}
+#[doc = " @brief Generic structure used for passing keys and data in and out"]
+#[doc = " of the database."]
+#[doc = ""]
+#[doc = " Values returned from the database are valid only until a subsequent"]
+#[doc = " update operation, or the end of the transaction. Do not modify or"]
+#[doc = " free them, they commonly point into the database itself."]
+#[doc = ""]
+#[doc = " Key sizes must be between 1 and #mdb_env_get_maxkeysize() inclusive."]
+#[doc = " The same applies to data sizes in databases with the #MDB_DUPSORT flag."]
+#[doc = " Other data items can in theory be from 0 to 0xffffffff bytes long."]
+#[repr(C)]
+pub struct MDB_val {
+    #[doc = "< size of the data item"]
+    pub mv_size: usize,
+    #[doc = "< address of the data item"]
+    pub mv_data: *mut ::libc::c_void,
+}
+#[doc = " @brief A callback function used to compare two keys in a database"]
+pub type MDB_cmp_func = ::std::option::Option<
+    unsafe extern "C" fn(a: *const MDB_val, b: *const MDB_val) -> ::libc::c_int,
+>;
+#[doc = " @brief A callback function used to relocate a position-dependent data item"]
+#[doc = " in a fixed-address database."]
+#[doc = ""]
+#[doc = " The \\b newptr gives the item's desired address in"]
+#[doc = " the memory map, and \\b oldptr gives its previous address. The item's actual"]
+#[doc = " data resides at the address in \\b item.  This callback is expected to walk"]
+#[doc = " through the fields of the record in \\b item and modify any"]
+#[doc = " values based at the \\b oldptr address to be relative to the \\b newptr address."]
+#[doc = " @param[in,out] item The item that is to be relocated."]
+#[doc = " @param[in] oldptr The previous address."]
+#[doc = " @param[in] newptr The new address to relocate to."]
+#[doc = " @param[in] relctx An application-provided context, set by #mdb_set_relctx()."]
+#[doc = " @todo This feature is currently unimplemented."]
+pub type MDB_rel_func = ::std::option::Option<
+    unsafe extern "C" fn(
+        item: *mut MDB_val,
+        oldptr: *mut ::libc::c_void,
+        newptr: *mut ::libc::c_void,
+        relctx: *mut ::libc::c_void,
+    ),
+>;
+#[doc = "< Position at first key/data item"]
+pub const MDB_FIRST: MDB_cursor_op = 0;
+#[doc = "< Position at first data item of current key."]
+#[doc = "Only for #MDB_DUPSORT"]
+pub const MDB_FIRST_DUP: MDB_cursor_op = 1;
+#[doc = "< Position at key/data pair. Only for #MDB_DUPSORT"]
+pub const MDB_GET_BOTH: MDB_cursor_op = 2;
+#[doc = "< position at key, nearest data. Only for #MDB_DUPSORT"]
+pub const MDB_GET_BOTH_RANGE: MDB_cursor_op = 3;
+#[doc = "< Return key/data at current cursor position"]
+pub const MDB_GET_CURRENT: MDB_cursor_op = 4;
+#[doc = "< Return up to a page of duplicate data items"]
+#[doc = "from current cursor position. Move cursor to prepare"]
+#[doc = "for #MDB_NEXT_MULTIPLE. Only for #MDB_DUPFIXED"]
+pub const MDB_GET_MULTIPLE: MDB_cursor_op = 5;
+#[doc = "< Position at last key/data item"]
+pub const MDB_LAST: MDB_cursor_op = 6;
+#[doc = "< Position at last data item of current key."]
+#[doc = "Only for #MDB_DUPSORT"]
+pub const MDB_LAST_DUP: MDB_cursor_op = 7;
+#[doc = "< Position at next data item"]
+pub const MDB_NEXT: MDB_cursor_op = 8;
+#[doc = "< Position at next data item of current key."]
+#[doc = "Only for #MDB_DUPSORT"]
+pub const MDB_NEXT_DUP: MDB_cursor_op = 9;
+#[doc = "< Return up to a page of duplicate data items"]
+#[doc = "from next cursor position. Move cursor to prepare"]
+#[doc = "for #MDB_NEXT_MULTIPLE. Only for #MDB_DUPFIXED"]
+pub const MDB_NEXT_MULTIPLE: MDB_cursor_op = 10;
+#[doc = "< Position at first data item of next key"]
+pub const MDB_NEXT_NODUP: MDB_cursor_op = 11;
+#[doc = "< Position at previous data item"]
+pub const MDB_PREV: MDB_cursor_op = 12;
+#[doc = "< Position at previous data item of current key."]
+#[doc = "Only for #MDB_DUPSORT"]
+pub const MDB_PREV_DUP: MDB_cursor_op = 13;
+#[doc = "< Position at last data item of previous key"]
+pub const MDB_PREV_NODUP: MDB_cursor_op = 14;
+#[doc = "< Position at specified key"]
+pub const MDB_SET: MDB_cursor_op = 15;
+#[doc = "< Position at specified key, return key + data"]
+pub const MDB_SET_KEY: MDB_cursor_op = 16;
+#[doc = "< Position at first key greater than or equal to specified key."]
+pub const MDB_SET_RANGE: MDB_cursor_op = 17;
+#[doc = "< Position at previous page and return up to"]
+#[doc = "a page of duplicate data items. Only for #MDB_DUPFIXED"]
+pub const MDB_PREV_MULTIPLE: MDB_cursor_op = 18;
+#[doc = " @brief Cursor Get operations."]
+#[doc = ""]
+#[doc = "\tThis is the set of all operations for retrieving data"]
+#[doc = "\tusing a cursor."]
+pub type MDB_cursor_op = u32;
+#[doc = " @brief Statistics for a database in the environment"]
+#[repr(C)]
+pub struct MDB_stat {
+    #[doc = "< Size of a database page."]
+    #[doc = "This is currently the same for all databases."]
+    pub ms_psize: ::libc::c_uint,
+    #[doc = "< Depth (height) of the B-tree"]
+    pub ms_depth: ::libc::c_uint,
+    #[doc = "< Number of internal (non-leaf) pages"]
+    pub ms_branch_pages: usize,
+    #[doc = "< Number of leaf pages"]
+    pub ms_leaf_pages: usize,
+    #[doc = "< Number of overflow pages"]
+    pub ms_overflow_pages: usize,
+    #[doc = "< Number of data items"]
+    pub ms_entries: usize,
+}
+#[doc = " @brief Information about the environment"]
+#[repr(C)]
+pub struct MDB_envinfo {
+    #[doc = "< Address of map, if fixed"]
+    pub me_mapaddr: *mut ::libc::c_void,
+    #[doc = "< Size of the data memory map"]
+    pub me_mapsize: usize,
+    #[doc = "< ID of the last used page"]
+    pub me_last_pgno: usize,
+    #[doc = "< ID of the last committed transaction"]
+    pub me_last_txnid: usize,
+    #[doc = "< max reader slots in the environment"]
+    pub me_maxreaders: ::libc::c_uint,
+    #[doc = "< max reader slots used in the environment"]
+    pub me_numreaders: ::libc::c_uint,
+}
+extern "C" {
+    #[doc = " @brief Return the LMDB library version information."]
+    #[doc = ""]
+    #[doc = " @param[out] major if non-NULL, the library major version number is copied here"]
+    #[doc = " @param[out] minor if non-NULL, the library minor version number is copied here"]
+    #[doc = " @param[out] patch if non-NULL, the library patch version number is copied here"]
+    #[doc = " @retval \"version string\" The library version as a string"]
+    pub fn mdb_version(
+        major: *mut ::libc::c_int,
+        minor: *mut ::libc::c_int,
+        patch: *mut ::libc::c_int,
+    ) -> *mut ::libc::c_char;
+}
+extern "C" {
+    #[doc = " @brief Return a string describing a given error code."]
+    #[doc = ""]
+    #[doc = " This function is a superset of the ANSI C X3.159-1989 (ANSI C) strerror(3)"]
+    #[doc = " function. If the error code is greater than or equal to 0, then the string"]
+    #[doc = " returned by the system function strerror(3) is returned. If the error code"]
+    #[doc = " is less than 0, an error string corresponding to the LMDB library error is"]
+    #[doc = " returned. See @ref errors for a list of LMDB-specific error codes."]
+    #[doc = " @param[in] err The error code"]
+    #[doc = " @retval \"error message\" The description of the error"]
+    pub fn mdb_strerror(err: ::libc::c_int) -> *mut ::libc::c_char;
+}
+extern "C" {
+    #[doc = " @brief Create an LMDB environment handle."]
+    #[doc = ""]
+    #[doc = " This function allocates memory for a #MDB_env structure. To release"]
+    #[doc = " the allocated memory and discard the handle, call #mdb_env_close()."]
+    #[doc = " Before the handle may be used, it must be opened using #mdb_env_open()."]
+    #[doc = " Various other options may also need to be set before opening the handle,"]
+    #[doc = " e.g. #mdb_env_set_mapsize(), #mdb_env_set_maxreaders(), #mdb_env_set_maxdbs(),"]
+    #[doc = " depending on usage requirements."]
+    #[doc = " @param[out] env The address where the new handle will be stored"]
+    #[doc = " @return A non-zero error value on failure and 0 on success."]
+    pub fn mdb_env_create(env: *mut *mut MDB_env) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Open an environment handle."]
+    #[doc = ""]
+    #[doc = " If this function fails, #mdb_env_close() must be called to discard the #MDB_env handle."]
+    #[doc = " @param[in] env An environment handle returned by #mdb_env_create()"]
+    #[doc = " @param[in] path The directory in which the database files reside. This"]
+    #[doc = " directory must already exist and be writable."]
+    #[doc = " @param[in] flags Special options for this environment. This parameter"]
+    #[doc = " must be set to 0 or by bitwise OR'ing together one or more of the"]
+    #[doc = " values described here."]
+    #[doc = " Flags set by mdb_env_set_flags() are also used."]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>#MDB_FIXEDMAP"]
+    #[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 = "\t\tIf successful, the memory map will always reside at the same virtual address"]
+    #[doc = "\t\tand pointers used to reference data items in the database will be constant"]
+    #[doc = "\t\tacross multiple invocations. This option may not always work, depending on"]
+    #[doc = "\t\thow the operating system has allocated memory to shared libraries and other uses."]
+    #[doc = "\t\tThe feature is highly experimental."]
+    #[doc = "\t<li>#MDB_NOSUBDIR"]
+    #[doc = "\t\tBy default, LMDB creates its environment in a directory whose"]
+    #[doc = "\t\tpathname is given in \\b path, and creates its data and lock files"]
+    #[doc = "\t\tunder that directory. With this option, \\b path is used as-is for"]
+    #[doc = "\t\tthe database main data file. The database lock file is the \\b path"]
+    #[doc = "\t\twith \"-lock\" appended."]
+    #[doc = "\t<li>#MDB_RDONLY"]
+    #[doc = "\t\tOpen the environment in read-only mode. No write operations will be"]
+    #[doc = "\t\tallowed. LMDB will still modify the lock file - except on read-only"]
+    #[doc = "\t\tfilesystems, where LMDB does not use locks."]
+    #[doc = "\t<li>#MDB_WRITEMAP"]
+    #[doc = "\t\tUse a writeable memory map unless MDB_RDONLY is set. This uses"]
+    #[doc = "\t\tfewer mallocs but loses protection from application bugs"]
+    #[doc = "\t\tlike wild pointer writes and other bad updates into the database."]
+    #[doc = "\t\tThis may be slightly faster for DBs that fit entirely in RAM, but"]
+    #[doc = "\t\tis slower for DBs larger than RAM."]
+    #[doc = "\t\tIncompatible with nested transactions."]
+    #[doc = "\t\tDo not mix processes with and without MDB_WRITEMAP on the same"]
+    #[doc = "\t\tenvironment.  This can defeat durability (#mdb_env_sync etc)."]
+    #[doc = "\t<li>#MDB_NOMETASYNC"]
+    #[doc = "\t\tFlush system buffers to disk only once per transaction, omit the"]
+    #[doc = "\t\tmetadata flush. Defer that until the system flushes files to disk,"]
+    #[doc = "\t\tor next non-MDB_RDONLY commit or #mdb_env_sync(). This optimization"]
+    #[doc = "\t\tmaintains database integrity, but a system crash may undo the last"]
+    #[doc = "\t\tcommitted transaction. I.e. it preserves the ACI (atomicity,"]
+    #[doc = "\t\tconsistency, isolation) but not D (durability) database property."]
+    #[doc = "\t\tThis flag may be changed at any time using #mdb_env_set_flags()."]
+    #[doc = "\t<li>#MDB_NOSYNC"]
+    #[doc = "\t\tDon't flush system buffers to disk when committing a transaction."]
+    #[doc = "\t\tThis optimization means a system crash can corrupt the database or"]
+    #[doc = "\t\tlose the last transactions if buffers are not yet flushed to disk."]
+    #[doc = "\t\tThe risk is governed by how often the system flushes dirty buffers"]
+    #[doc = "\t\tto disk and how often #mdb_env_sync() is called.  However, if the"]
+    #[doc = "\t\tfilesystem preserves write order and the #MDB_WRITEMAP flag is not"]
+    #[doc = "\t\tused, transactions exhibit ACI (atomicity, consistency, isolation)"]
+    #[doc = "\t\tproperties and only lose D (durability).  I.e. database integrity"]
+    #[doc = "\t\tis maintained, but a system crash may undo the final transactions."]
+    #[doc = "\t\tNote that (#MDB_NOSYNC | #MDB_WRITEMAP) leaves the system with no"]
+    #[doc = "\t\thint for when to write transactions to disk, unless #mdb_env_sync()"]
+    #[doc = "\t\tis called. (#MDB_MAPASYNC | #MDB_WRITEMAP) may be preferable."]
+    #[doc = "\t\tThis flag may be changed at any time using #mdb_env_set_flags()."]
+    #[doc = "\t<li>#MDB_MAPASYNC"]
+    #[doc = "\t\tWhen using #MDB_WRITEMAP, use asynchronous flushes to disk."]
+    #[doc = "\t\tAs with #MDB_NOSYNC, a system crash can then corrupt the"]
+    #[doc = "\t\tdatabase or lose the last transactions. Calling #mdb_env_sync()"]
+    #[doc = "\t\tensures on-disk database integrity until next commit."]
+    #[doc = "\t\tThis flag may be changed at any time using #mdb_env_set_flags()."]
+    #[doc = "\t<li>#MDB_NOTLS"]
+    #[doc = "\t\tDon't use Thread-Local Storage. Tie reader locktable slots to"]
+    #[doc = "\t\t#MDB_txn objects instead of to threads. I.e. #mdb_txn_reset() keeps"]
+    #[doc = "\t\tthe slot reseved for the #MDB_txn object. A thread may use parallel"]
+    #[doc = "\t\tread-only transactions. A read-only transaction may span threads if"]
+    #[doc = "\t\tthe user synchronizes its use. Applications that multiplex many"]
+    #[doc = "\t\tuser threads over individual OS threads need this option. Such an"]
+    #[doc = "\t\tapplication must also serialize the write transactions in an OS"]
+    #[doc = "\t\tthread, since LMDB's write locking is unaware of the user threads."]
+    #[doc = "\t<li>#MDB_NOLOCK"]
+    #[doc = "\t\tDon't do any locking. If concurrent access is anticipated, the"]
+    #[doc = "\t\tcaller must manage all concurrency itself. For proper operation"]
+    #[doc = "\t\tthe caller must enforce single-writer semantics, and must ensure"]
+    #[doc = "\t\tthat no readers are using old transactions while a writer is"]
+    #[doc = "\t\tactive. The simplest approach is to use an exclusive lock so that"]
+    #[doc = "\t\tno readers may be active at all when a writer begins."]
+    #[doc = "\t<li>#MDB_NORDAHEAD"]
+    #[doc = "\t\tTurn off readahead. Most operating systems perform readahead on"]
+    #[doc = "\t\tread requests by default. This option turns it off if the OS"]
+    #[doc = "\t\tsupports it. Turning it off may help random read performance"]
+    #[doc = "\t\twhen the DB is larger than RAM and system RAM is full."]
+    #[doc = "\t\tThe option is not implemented on Windows."]
+    #[doc = "\t<li>#MDB_NOMEMINIT"]
+    #[doc = "\t\tDon't initialize malloc'd memory before writing to unused spaces"]
+    #[doc = "\t\tin the data file. By default, memory for pages written to the data"]
+    #[doc = "\t\tfile is obtained using malloc. While these pages may be reused in"]
+    #[doc = "\t\tsubsequent transactions, freshly malloc'd pages will be initialized"]
+    #[doc = "\t\tto zeroes before use. This avoids persisting leftover data from other"]
+    #[doc = "\t\tcode (that used the heap and subsequently freed the memory) into the"]
+    #[doc = "\t\tdata file. Note that many other system libraries may allocate"]
+    #[doc = "\t\tand free memory from the heap for arbitrary uses. E.g., stdio may"]
+    #[doc = "\t\tuse the heap for file I/O buffers. This initialization step has a"]
+    #[doc = "\t\tmodest performance cost so some applications may want to disable"]
+    #[doc = "\t\tit using this flag. This option can be a problem for applications"]
+    #[doc = "\t\twhich handle sensitive data like passwords, and it makes memory"]
+    #[doc = "\t\tcheckers like Valgrind noisy. This flag is not needed with #MDB_WRITEMAP,"]
+    #[doc = "\t\twhich writes directly to the mmap instead of using malloc for pages. The"]
+    #[doc = "\t\tinitialization is also skipped if #MDB_RESERVE is used; the"]
+    #[doc = "\t\tcaller is expected to overwrite all of the memory that was"]
+    #[doc = "\t\treserved in that case."]
+    #[doc = "\t\tThis flag may be changed at any time using #mdb_env_set_flags()."]
+    #[doc = " </ul>"]
+    #[doc = " @param[in] mode The UNIX permissions to set on created files and semaphores."]
+    #[doc = " This parameter is ignored on Windows."]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>#MDB_VERSION_MISMATCH - the version of the LMDB library doesn't match the"]
+    #[doc = "\tversion that created the database environment."]
+    #[doc = "\t<li>#MDB_INVALID - the environment file headers are corrupted."]
+    #[doc = "\t<li>ENOENT - the directory specified by the path parameter doesn't exist."]
+    #[doc = "\t<li>EACCES - the user didn't have permission to access the environment files."]
+    #[doc = "\t<li>EAGAIN - the environment was locked by another process."]
+    #[doc = " </ul>"]
+    pub fn mdb_env_open(
+        env: *mut MDB_env,
+        path: *const ::libc::c_char,
+        flags: ::libc::c_uint,
+        mode: mdb_mode_t,
+    ) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Copy an LMDB environment to the specified path."]
+    #[doc = ""]
+    #[doc = " This function may be used to make a backup of an existing environment."]
+    #[doc = " No lockfile is created, since it gets recreated at need."]
+    #[doc = " @note This call can trigger significant file size growth if run in"]
+    #[doc = " parallel with write transactions, because it employs a read-only"]
+    #[doc = " transaction. See long-lived transactions under @ref caveats_sec."]
+    #[doc = " @param[in] env An environment handle returned by #mdb_env_create(). It"]
+    #[doc = " must have already been opened successfully."]
+    #[doc = " @param[in] path The directory in which the copy will reside. This"]
+    #[doc = " directory must already exist and be writable but must otherwise be"]
+    #[doc = " empty."]
+    #[doc = " @return A non-zero error value on failure and 0 on success."]
+    pub fn mdb_env_copy(env: *mut MDB_env, path: *const ::libc::c_char) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Copy an LMDB environment to the specified file descriptor."]
+    #[doc = ""]
+    #[doc = " This function may be used to make a backup of an existing environment."]
+    #[doc = " No lockfile is created, since it gets recreated at need."]
+    #[doc = " @note This call can trigger significant file size growth if run in"]
+    #[doc = " parallel with write transactions, because it employs a read-only"]
+    #[doc = " transaction. See long-lived transactions under @ref caveats_sec."]
+    #[doc = " @param[in] env An environment handle returned by #mdb_env_create(). It"]
+    #[doc = " must have already been opened successfully."]
+    #[doc = " @param[in] fd The filedescriptor to write the copy to. It must"]
+    #[doc = " have already been opened for Write access."]
+    #[doc = " @return A non-zero error value on failure and 0 on success."]
+    pub fn mdb_env_copyfd(env: *mut MDB_env, fd: mdb_filehandle_t) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Copy an LMDB environment to the specified path, with options."]
+    #[doc = ""]
+    #[doc = " This function may be used to make a backup of an existing environment."]
+    #[doc = " No lockfile is created, since it gets recreated at need."]
+    #[doc = " @note This call can trigger significant file size growth if run in"]
+    #[doc = " parallel with write transactions, because it employs a read-only"]
+    #[doc = " transaction. See long-lived transactions under @ref caveats_sec."]
+    #[doc = " @param[in] env An environment handle returned by #mdb_env_create(). It"]
+    #[doc = " must have already been opened successfully."]
+    #[doc = " @param[in] path The directory in which the copy will reside. This"]
+    #[doc = " directory must already exist and be writable but must otherwise be"]
+    #[doc = " empty."]
+    #[doc = " @param[in] flags Special options for this operation. This parameter"]
+    #[doc = " must be set to 0 or by bitwise OR'ing together one or more of the"]
+    #[doc = " values described here."]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>#MDB_CP_COMPACT - Perform compaction while copying: omit free"]
+    #[doc = "\t\tpages and sequentially renumber all pages in output. This option"]
+    #[doc = "\t\tconsumes more CPU and runs more slowly than the default."]
+    #[doc = "\t\tCurrently it fails if the environment has suffered a page leak."]
+    #[doc = " </ul>"]
+    #[doc = " @return A non-zero error value on failure and 0 on success."]
+    pub fn mdb_env_copy2(
+        env: *mut MDB_env,
+        path: *const ::libc::c_char,
+        flags: ::libc::c_uint,
+    ) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Copy an LMDB environment to the specified file descriptor,"]
+    #[doc = "\twith options."]
+    #[doc = ""]
+    #[doc = " This function may be used to make a backup of an existing environment."]
+    #[doc = " No lockfile is created, since it gets recreated at need. See"]
+    #[doc = " #mdb_env_copy2() for further details."]
+    #[doc = " @note This call can trigger significant file size growth if run in"]
+    #[doc = " parallel with write transactions, because it employs a read-only"]
+    #[doc = " transaction. See long-lived transactions under @ref caveats_sec."]
+    #[doc = " @param[in] env An environment handle returned by #mdb_env_create(). It"]
+    #[doc = " must have already been opened successfully."]
+    #[doc = " @param[in] fd The filedescriptor to write the copy to. It must"]
+    #[doc = " have already been opened for Write access."]
+    #[doc = " @param[in] flags Special options for this operation."]
+    #[doc = " See #mdb_env_copy2() for options."]
+    #[doc = " @return A non-zero error value on failure and 0 on success."]
+    pub fn mdb_env_copyfd2(
+        env: *mut MDB_env,
+        fd: mdb_filehandle_t,
+        flags: ::libc::c_uint,
+    ) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Return statistics about the LMDB environment."]
+    #[doc = ""]
+    #[doc = " @param[in] env An environment handle returned by #mdb_env_create()"]
+    #[doc = " @param[out] stat The address of an #MDB_stat structure"]
+    #[doc = " \twhere the statistics will be copied"]
+    pub fn mdb_env_stat(env: *mut MDB_env, stat: *mut MDB_stat) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Return information about the LMDB environment."]
+    #[doc = ""]
+    #[doc = " @param[in] env An environment handle returned by #mdb_env_create()"]
+    #[doc = " @param[out] stat The address of an #MDB_envinfo structure"]
+    #[doc = " \twhere the information will be copied"]
+    pub fn mdb_env_info(env: *mut MDB_env, stat: *mut MDB_envinfo) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Flush the data buffers to disk."]
+    #[doc = ""]
+    #[doc = " Data is always written to disk when #mdb_txn_commit() is called,"]
+    #[doc = " but the operating system may keep it buffered. LMDB always flushes"]
+    #[doc = " the OS buffers upon commit as well, unless the environment was"]
+    #[doc = " opened with #MDB_NOSYNC or in part #MDB_NOMETASYNC. This call is"]
+    #[doc = " not valid if the environment was opened with #MDB_RDONLY."]
+    #[doc = " @param[in] env An environment handle returned by #mdb_env_create()"]
+    #[doc = " @param[in] force If non-zero, force a synchronous flush.  Otherwise"]
+    #[doc = "  if the environment has the #MDB_NOSYNC flag set the flushes"]
+    #[doc = "\twill be omitted, and with #MDB_MAPASYNC they will be asynchronous."]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>EACCES - the environment is read-only."]
+    #[doc = "\t<li>EINVAL - an invalid parameter was specified."]
+    #[doc = "\t<li>EIO - an error occurred during synchronization."]
+    #[doc = " </ul>"]
+    pub fn mdb_env_sync(env: *mut MDB_env, force: ::libc::c_int) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Close the environment and release the memory map."]
+    #[doc = ""]
+    #[doc = " Only a single thread may call this function. All transactions, databases,"]
+    #[doc = " and cursors must already be closed before calling this function. Attempts to"]
+    #[doc = " use any such handles after calling this function will cause a SIGSEGV."]
+    #[doc = " The environment handle will be freed and must not be used again after this call."]
+    #[doc = " @param[in] env An environment handle returned by #mdb_env_create()"]
+    pub fn mdb_env_close(env: *mut MDB_env);
+}
+extern "C" {
+    #[doc = " @brief Set environment flags."]
+    #[doc = ""]
+    #[doc = " This may be used to set some flags in addition to those from"]
+    #[doc = " #mdb_env_open(), or to unset these flags.  If several threads"]
+    #[doc = " change the flags at the same time, the result is undefined."]
+    #[doc = " @param[in] env An environment handle returned by #mdb_env_create()"]
+    #[doc = " @param[in] flags The flags to change, bitwise OR'ed together"]
+    #[doc = " @param[in] onoff A non-zero value sets the flags, zero clears them."]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>EINVAL - an invalid parameter was specified."]
+    #[doc = " </ul>"]
+    pub fn mdb_env_set_flags(
+        env: *mut MDB_env,
+        flags: ::libc::c_uint,
+        onoff: ::libc::c_int,
+    ) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Get environment flags."]
+    #[doc = ""]
+    #[doc = " @param[in] env An environment handle returned by #mdb_env_create()"]
+    #[doc = " @param[out] flags The address of an integer to store the flags"]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>EINVAL - an invalid parameter was specified."]
+    #[doc = " </ul>"]
+    pub fn mdb_env_get_flags(env: *mut MDB_env, flags: *mut ::libc::c_uint) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Return the path that was used in #mdb_env_open()."]
+    #[doc = ""]
+    #[doc = " @param[in] env An environment handle returned by #mdb_env_create()"]
+    #[doc = " @param[out] path Address of a string pointer to contain the path. This"]
+    #[doc = " is the actual string in the environment, not a copy. It should not be"]
+    #[doc = " altered in any way."]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>EINVAL - an invalid parameter was specified."]
+    #[doc = " </ul>"]
+    pub fn mdb_env_get_path(env: *mut MDB_env, path: *mut *const ::libc::c_char) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Return the filedescriptor for the given environment."]
+    #[doc = ""]
+    #[doc = " This function may be called after fork(), so the descriptor can be"]
+    #[doc = " closed before exec*().  Other LMDB file descriptors have FD_CLOEXEC."]
+    #[doc = " (Until LMDB 0.9.18, only the lockfile had that.)"]
+    #[doc = ""]
+    #[doc = " @param[in] env An environment handle returned by #mdb_env_create()"]
+    #[doc = " @param[out] fd Address of a mdb_filehandle_t to contain the descriptor."]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>EINVAL - an invalid parameter was specified."]
+    #[doc = " </ul>"]
+    pub fn mdb_env_get_fd(env: *mut MDB_env, fd: *mut mdb_filehandle_t) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Set the size of the memory map to use for this environment."]
+    #[doc = ""]
+    #[doc = " The size should be a multiple of the OS page size. The default is"]
+    #[doc = " 10485760 bytes. The size of the memory map is also the maximum size"]
+    #[doc = " of the database. The value should be chosen as large as possible,"]
+    #[doc = " to accommodate future growth of the database."]
+    #[doc = " This function should be called after #mdb_env_create() and before #mdb_env_open()."]
+    #[doc = " It may be called at later times if no transactions are active in"]
+    #[doc = " this process. Note that the library does not check for this condition,"]
+    #[doc = " the caller must ensure it explicitly."]
+    #[doc = ""]
+    #[doc = " The new size takes effect immediately for the current process but"]
+    #[doc = " will not be persisted to any others until a write transaction has been"]
+    #[doc = " committed by the current process. Also, only mapsize increases are"]
+    #[doc = " persisted into the environment."]
+    #[doc = ""]
+    #[doc = " If the mapsize is increased by another process, and data has grown"]
+    #[doc = " beyond the range of the current mapsize, #mdb_txn_begin() will"]
+    #[doc = " return #MDB_MAP_RESIZED. This function may be called with a size"]
+    #[doc = " of zero to adopt the new size."]
+    #[doc = ""]
+    #[doc = " Any attempt to set a size smaller than the space already consumed"]
+    #[doc = " by the environment will be silently changed to the current size of the used space."]
+    #[doc = " @param[in] env An environment handle returned by #mdb_env_create()"]
+    #[doc = " @param[in] size The size in bytes"]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>EINVAL - an invalid parameter was specified, or the environment has"]
+    #[doc = "   \tan active write transaction."]
+    #[doc = " </ul>"]
+    pub fn mdb_env_set_mapsize(env: *mut MDB_env, size: usize) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Set the maximum number of threads/reader slots for the environment."]
+    #[doc = ""]
+    #[doc = " This defines the number of slots in the lock table that is used to track readers in the"]
+    #[doc = " the environment. The default is 126."]
+    #[doc = " Starting a read-only transaction normally ties a lock table slot to the"]
+    #[doc = " current thread until the environment closes or the thread exits. If"]
+    #[doc = " MDB_NOTLS is in use, #mdb_txn_begin() instead ties the slot to the"]
+    #[doc = " MDB_txn object until it or the #MDB_env object is destroyed."]
+    #[doc = " This function may only be called after #mdb_env_create() and before #mdb_env_open()."]
+    #[doc = " @param[in] env An environment handle returned by #mdb_env_create()"]
+    #[doc = " @param[in] readers The maximum number of reader lock table slots"]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>EINVAL - an invalid parameter was specified, or the environment is already open."]
+    #[doc = " </ul>"]
+    pub fn mdb_env_set_maxreaders(env: *mut MDB_env, readers: ::libc::c_uint) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Get the maximum number of threads/reader slots for the environment."]
+    #[doc = ""]
+    #[doc = " @param[in] env An environment handle returned by #mdb_env_create()"]
+    #[doc = " @param[out] readers Address of an integer to store the number of readers"]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>EINVAL - an invalid parameter was specified."]
+    #[doc = " </ul>"]
+    pub fn mdb_env_get_maxreaders(env: *mut MDB_env, readers: *mut ::libc::c_uint)
+        -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Set the maximum number of named databases for the environment."]
+    #[doc = ""]
+    #[doc = " This function is only needed if multiple databases will be used in the"]
+    #[doc = " environment. Simpler applications that use the environment as a single"]
+    #[doc = " unnamed database can ignore this option."]
+    #[doc = " This function may only be called after #mdb_env_create() and before #mdb_env_open()."]
+    #[doc = ""]
+    #[doc = " Currently a moderate number of slots are cheap but a huge number gets"]
+    #[doc = " expensive: 7-120 words per transaction, and every #mdb_dbi_open()"]
+    #[doc = " does a linear search of the opened slots."]
+    #[doc = " @param[in] env An environment handle returned by #mdb_env_create()"]
+    #[doc = " @param[in] dbs The maximum number of databases"]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>EINVAL - an invalid parameter was specified, or the environment is already open."]
+    #[doc = " </ul>"]
+    pub fn mdb_env_set_maxdbs(env: *mut MDB_env, dbs: MDB_dbi) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Get the maximum size of keys and #MDB_DUPSORT data we can write."]
+    #[doc = ""]
+    #[doc = " Depends on the compile-time constant #MDB_MAXKEYSIZE. Default 511."]
+    #[doc = " See @ref MDB_val."]
+    #[doc = " @param[in] env An environment handle returned by #mdb_env_create()"]
+    #[doc = " @return The maximum size of a key we can write"]
+    pub fn mdb_env_get_maxkeysize(env: *mut MDB_env) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Set application information associated with the #MDB_env."]
+    #[doc = ""]
+    #[doc = " @param[in] env An environment handle returned by #mdb_env_create()"]
+    #[doc = " @param[in] ctx An arbitrary pointer for whatever the application needs."]
+    #[doc = " @return A non-zero error value on failure and 0 on success."]
+    pub fn mdb_env_set_userctx(env: *mut MDB_env, ctx: *mut ::libc::c_void) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Get the application information associated with the #MDB_env."]
+    #[doc = ""]
+    #[doc = " @param[in] env An environment handle returned by #mdb_env_create()"]
+    #[doc = " @return The pointer set by #mdb_env_set_userctx()."]
+    pub fn mdb_env_get_userctx(env: *mut MDB_env) -> *mut ::libc::c_void;
+}
+#[doc = " @brief A callback function for most LMDB assert() failures,"]
+#[doc = " called before printing the message and aborting."]
+#[doc = ""]
+#[doc = " @param[in] env An environment handle returned by #mdb_env_create()."]
+#[doc = " @param[in] msg The assertion message, not including newline."]
+pub type MDB_assert_func =
+    ::std::option::Option<unsafe extern "C" fn(env: *mut MDB_env, msg: *const ::libc::c_char)>;
+extern "C" {
+    #[doc = " Set or reset the assert() callback of the environment."]
+    #[doc = " Disabled if liblmdb is buillt with NDEBUG."]
+    #[doc = " @note This hack should become obsolete as lmdb's error handling matures."]
+    #[doc = " @param[in] env An environment handle returned by #mdb_env_create()."]
+    #[doc = " @param[in] func An #MDB_assert_func function, or 0."]
+    #[doc = " @return A non-zero error value on failure and 0 on success."]
+    pub fn mdb_env_set_assert(env: *mut MDB_env, func: MDB_assert_func) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Create a transaction for use with the environment."]
+    #[doc = ""]
+    #[doc = " The transaction handle may be discarded using #mdb_txn_abort() or #mdb_txn_commit()."]
+    #[doc = " @note A transaction and its cursors must only be used by a single"]
+    #[doc = " thread, and a thread may only have a single transaction at a time."]
+    #[doc = " If #MDB_NOTLS is in use, this does not apply to read-only transactions."]
+    #[doc = " @note Cursors may not span transactions."]
+    #[doc = " @param[in] env An environment handle returned by #mdb_env_create()"]
+    #[doc = " @param[in] parent If this parameter is non-NULL, the new transaction"]
+    #[doc = " will be a nested transaction, with the transaction indicated by \\b parent"]
+    #[doc = " as its parent. Transactions may be nested to any level. A parent"]
+    #[doc = " transaction and its cursors may not issue any other operations than"]
+    #[doc = " mdb_txn_commit and mdb_txn_abort while it has active child transactions."]
+    #[doc = " @param[in] flags Special options for this transaction. This parameter"]
+    #[doc = " must be set to 0 or by bitwise OR'ing together one or more of the"]
+    #[doc = " values described here."]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>#MDB_RDONLY"]
+    #[doc = "\t\tThis transaction will not perform any write operations."]
+    #[doc = " </ul>"]
+    #[doc = " @param[out] txn Address where the new #MDB_txn handle will be stored"]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>#MDB_PANIC - a fatal error occurred earlier and the environment"]
+    #[doc = "\t\tmust be shut down."]
+    #[doc = "\t<li>#MDB_MAP_RESIZED - another process wrote data beyond this MDB_env's"]
+    #[doc = "\t\tmapsize and this environment's map must be resized as well."]
+    #[doc = "\t\tSee #mdb_env_set_mapsize()."]
+    #[doc = "\t<li>#MDB_READERS_FULL - a read-only transaction was requested and"]
+    #[doc = "\t\tthe reader lock table is full. See #mdb_env_set_maxreaders()."]
+    #[doc = "\t<li>ENOMEM - out of memory."]
+    #[doc = " </ul>"]
+    pub fn mdb_txn_begin(
+        env: *mut MDB_env,
+        parent: *mut MDB_txn,
+        flags: ::libc::c_uint,
+        txn: *mut *mut MDB_txn,
+    ) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Returns the transaction's #MDB_env"]
+    #[doc = ""]
+    #[doc = " @param[in] txn A transaction handle returned by #mdb_txn_begin()"]
+    pub fn mdb_txn_env(txn: *mut MDB_txn) -> *mut MDB_env;
+}
+extern "C" {
+    #[doc = " @brief Return the transaction's ID."]
+    #[doc = ""]
+    #[doc = " This returns the identifier associated with this transaction. For a"]
+    #[doc = " read-only transaction, this corresponds to the snapshot being read;"]
+    #[doc = " concurrent readers will frequently have the same transaction ID."]
+    #[doc = ""]
+    #[doc = " @param[in] txn A transaction handle returned by #mdb_txn_begin()"]
+    #[doc = " @return A transaction ID, valid if input is an active transaction."]
+    pub fn mdb_txn_id(txn: *mut MDB_txn) -> usize;
+}
+extern "C" {
+    #[doc = " @brief Commit all the operations of a transaction into the database."]
+    #[doc = ""]
+    #[doc = " The transaction handle is freed. It and its cursors must not be used"]
+    #[doc = " again after this call, except with #mdb_cursor_renew()."]
+    #[doc = " @note Earlier documentation incorrectly said all cursors would be freed."]
+    #[doc = " Only write-transactions free cursors."]
+    #[doc = " @param[in] txn A transaction handle returned by #mdb_txn_begin()"]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>EINVAL - an invalid parameter was specified."]
+    #[doc = "\t<li>ENOSPC - no more disk space."]
+    #[doc = "\t<li>EIO - a low-level I/O error occurred while writing."]
+    #[doc = "\t<li>ENOMEM - out of memory."]
+    #[doc = " </ul>"]
+    pub fn mdb_txn_commit(txn: *mut MDB_txn) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Abandon all the operations of the transaction instead of saving them."]
+    #[doc = ""]
+    #[doc = " The transaction handle is freed. It and its cursors must not be used"]
+    #[doc = " again after this call, except with #mdb_cursor_renew()."]
+    #[doc = " @note Earlier documentation incorrectly said all cursors would be freed."]
+    #[doc = " Only write-transactions free cursors."]
+    #[doc = " @param[in] txn A transaction handle returned by #mdb_txn_begin()"]
+    pub fn mdb_txn_abort(txn: *mut MDB_txn);
+}
+extern "C" {
+    #[doc = " @brief Reset a read-only transaction."]
+    #[doc = ""]
+    #[doc = " Abort the transaction like #mdb_txn_abort(), but keep the transaction"]
+    #[doc = " handle. #mdb_txn_renew() may reuse the handle. This saves allocation"]
+    #[doc = " overhead if the process will start a new read-only transaction soon,"]
+    #[doc = " and also locking overhead if #MDB_NOTLS is in use. The reader table"]
+    #[doc = " lock is released, but the table slot stays tied to its thread or"]
+    #[doc = " #MDB_txn. Use mdb_txn_abort() to discard a reset handle, and to free"]
+    #[doc = " its lock table slot if MDB_NOTLS is in use."]
+    #[doc = " Cursors opened within the transaction must not be used"]
+    #[doc = " again after this call, except with #mdb_cursor_renew()."]
+    #[doc = " Reader locks generally don't interfere with writers, but they keep old"]
+    #[doc = " versions of database pages allocated. Thus they prevent the old pages"]
+    #[doc = " from being reused when writers commit new data, and so under heavy load"]
+    #[doc = " the database size may grow much more rapidly than otherwise."]
+    #[doc = " @param[in] txn A transaction handle returned by #mdb_txn_begin()"]
+    pub fn mdb_txn_reset(txn: *mut MDB_txn);
+}
+extern "C" {
+    #[doc = " @brief Renew a read-only transaction."]
+    #[doc = ""]
+    #[doc = " This acquires a new reader lock for a transaction handle that had been"]
+    #[doc = " released by #mdb_txn_reset(). It must be called before a reset transaction"]
+    #[doc = " may be used again."]
+    #[doc = " @param[in] txn A transaction handle returned by #mdb_txn_begin()"]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>#MDB_PANIC - a fatal error occurred earlier and the environment"]
+    #[doc = "\t\tmust be shut down."]
+    #[doc = "\t<li>EINVAL - an invalid parameter was specified."]
+    #[doc = " </ul>"]
+    pub fn mdb_txn_renew(txn: *mut MDB_txn) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Open a database in the environment."]
+    #[doc = ""]
+    #[doc = " A database handle denotes the name and parameters of a database,"]
+    #[doc = " independently of whether such a database exists."]
+    #[doc = " The database handle may be discarded by calling #mdb_dbi_close()."]
+    #[doc = " The old database handle is returned if the database was already open."]
+    #[doc = " The handle may only be closed once."]
+    #[doc = ""]
+    #[doc = " The database handle will be private to the current transaction until"]
+    #[doc = " the transaction is successfully committed. If the transaction is"]
+    #[doc = " aborted the handle will be closed automatically."]
+    #[doc = " After a successful commit the handle will reside in the shared"]
+    #[doc = " environment, and may be used by other transactions."]
+    #[doc = ""]
+    #[doc = " This function must not be called from multiple concurrent"]
+    #[doc = " transactions in the same process. A transaction that uses"]
+    #[doc = " this function must finish (either commit or abort) before"]
+    #[doc = " any other transaction in the process may use this function."]
+    #[doc = ""]
+    #[doc = " To use named databases (with name != NULL), #mdb_env_set_maxdbs()"]
+    #[doc = " must be called before opening the environment.  Database names are"]
+    #[doc = " keys in the unnamed database, and may be read but not written."]
+    #[doc = ""]
+    #[doc = " @param[in] txn A transaction handle returned by #mdb_txn_begin()"]
+    #[doc = " @param[in] name The name of the database to open. If only a single"]
+    #[doc = " \tdatabase is needed in the environment, this value may be NULL."]
+    #[doc = " @param[in] flags Special options for this database. This parameter"]
+    #[doc = " must be set to 0 or by bitwise OR'ing together one or more of the"]
+    #[doc = " values described here."]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>#MDB_REVERSEKEY"]
+    #[doc = "\t\tKeys are strings to be compared in reverse order, from the end"]
+    #[doc = "\t\tof the strings to the beginning. By default, Keys are treated as strings and"]
+    #[doc = "\t\tcompared from beginning to end."]
+    #[doc = "\t<li>#MDB_DUPSORT"]
+    #[doc = "\t\tDuplicate keys may be used in the database. (Or, from another perspective,"]
+    #[doc = "\t\tkeys may have multiple data items, stored in sorted order.) By default"]
+    #[doc = "\t\tkeys must be unique and may have only a single data item."]
+    #[doc = "\t<li>#MDB_INTEGERKEY"]
+    #[doc = "\t\tKeys are binary integers in native byte order, either unsigned int"]
+    #[doc = "\t\tor size_t, and will be sorted as such."]
+    #[doc = "\t\tThe keys must all be of the same size."]
+    #[doc = "\t<li>#MDB_DUPFIXED"]
+    #[doc = "\t\tThis flag may only be used in combination with #MDB_DUPSORT. This option"]
+    #[doc = "\t\ttells the library that the data items for this database are all the same"]
+    #[doc = "\t\tsize, which allows further optimizations in storage and retrieval. When"]
+    #[doc = "\t\tall data items are the same size, the #MDB_GET_MULTIPLE, #MDB_NEXT_MULTIPLE"]
+    #[doc = "\t\tand #MDB_PREV_MULTIPLE cursor operations may be used to retrieve multiple"]
+    #[doc = "\t\titems at once."]
+    #[doc = "\t<li>#MDB_INTEGERDUP"]
+    #[doc = "\t\tThis option specifies that duplicate data items are binary integers,"]
+    #[doc = "\t\tsimilar to #MDB_INTEGERKEY keys."]
+    #[doc = "\t<li>#MDB_REVERSEDUP"]
+    #[doc = "\t\tThis option specifies that duplicate data items should be compared as"]
+    #[doc = "\t\tstrings in reverse order."]
+    #[doc = "\t<li>#MDB_CREATE"]
+    #[doc = "\t\tCreate the named database if it doesn't exist. This option is not"]
+    #[doc = "\t\tallowed in a read-only transaction or a read-only environment."]
+    #[doc = " </ul>"]
+    #[doc = " @param[out] dbi Address where the new #MDB_dbi handle will be stored"]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>#MDB_NOTFOUND - the specified database doesn't exist in the environment"]
+    #[doc = "\t\tand #MDB_CREATE was not specified."]
+    #[doc = "\t<li>#MDB_DBS_FULL - too many databases have been opened. See #mdb_env_set_maxdbs()."]
+    #[doc = " </ul>"]
+    pub fn mdb_dbi_open(
+        txn: *mut MDB_txn,
+        name: *const ::libc::c_char,
+        flags: ::libc::c_uint,
+        dbi: *mut MDB_dbi,
+    ) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Retrieve statistics for a database."]
+    #[doc = ""]
+    #[doc = " @param[in] txn A transaction handle returned by #mdb_txn_begin()"]
+    #[doc = " @param[in] dbi A database handle returned by #mdb_dbi_open()"]
+    #[doc = " @param[out] stat The address of an #MDB_stat structure"]
+    #[doc = " \twhere the statistics will be copied"]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>EINVAL - an invalid parameter was specified."]
+    #[doc = " </ul>"]
+    pub fn mdb_stat(txn: *mut MDB_txn, dbi: MDB_dbi, stat: *mut MDB_stat) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Retrieve the DB flags for a database handle."]
+    #[doc = ""]
+    #[doc = " @param[in] txn A transaction handle returned by #mdb_txn_begin()"]
+    #[doc = " @param[in] dbi A database handle returned by #mdb_dbi_open()"]
+    #[doc = " @param[out] flags Address where the flags will be returned."]
+    #[doc = " @return A non-zero error value on failure and 0 on success."]
+    pub fn mdb_dbi_flags(
+        txn: *mut MDB_txn,
+        dbi: MDB_dbi,
+        flags: *mut ::libc::c_uint,
+    ) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Close a database handle. Normally unnecessary. Use with care:"]
+    #[doc = ""]
+    #[doc = " This call is not mutex protected. Handles should only be closed by"]
+    #[doc = " a single thread, and only if no other threads are going to reference"]
+    #[doc = " the database handle or one of its cursors any further. Do not close"]
+    #[doc = " a handle if an existing transaction has modified its database."]
+    #[doc = " Doing so can cause misbehavior from database corruption to errors"]
+    #[doc = " like MDB_BAD_VALSIZE (since the DB name is gone)."]
+    #[doc = ""]
+    #[doc = " Closing a database handle is not necessary, but lets #mdb_dbi_open()"]
+    #[doc = " reuse the handle value.  Usually it's better to set a bigger"]
+    #[doc = " #mdb_env_set_maxdbs(), unless that value would be large."]
+    #[doc = ""]
+    #[doc = " @param[in] env An environment handle returned by #mdb_env_create()"]
+    #[doc = " @param[in] dbi A database handle returned by #mdb_dbi_open()"]
+    pub fn mdb_dbi_close(env: *mut MDB_env, dbi: MDB_dbi);
+}
+extern "C" {
+    #[doc = " @brief Empty or delete+close a database."]
+    #[doc = ""]
+    #[doc = " See #mdb_dbi_close() for restrictions about closing the DB handle."]
+    #[doc = " @param[in] txn A transaction handle returned by #mdb_txn_begin()"]
+    #[doc = " @param[in] dbi A database handle returned by #mdb_dbi_open()"]
+    #[doc = " @param[in] del 0 to empty the DB, 1 to delete it from the"]
+    #[doc = " environment and close the DB handle."]
+    #[doc = " @return A non-zero error value on failure and 0 on success."]
+    pub fn mdb_drop(txn: *mut MDB_txn, dbi: MDB_dbi, del: ::libc::c_int) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Set a custom key comparison function for a database."]
+    #[doc = ""]
+    #[doc = " The comparison function is called whenever it is necessary to compare a"]
+    #[doc = " key specified by the application with a key currently stored in the database."]
+    #[doc = " If no comparison function is specified, and no special key flags were specified"]
+    #[doc = " with #mdb_dbi_open(), the keys are compared lexically, with shorter keys collating"]
+    #[doc = " before longer keys."]
+    #[doc = " @warning This function must be called before any data access functions are used,"]
+    #[doc = " otherwise data corruption may occur. The same comparison function must be used by every"]
+    #[doc = " program accessing the database, every time the database is used."]
+    #[doc = " @param[in] txn A transaction handle returned by #mdb_txn_begin()"]
+    #[doc = " @param[in] dbi A database handle returned by #mdb_dbi_open()"]
+    #[doc = " @param[in] cmp A #MDB_cmp_func function"]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>EINVAL - an invalid parameter was specified."]
+    #[doc = " </ul>"]
+    pub fn mdb_set_compare(txn: *mut MDB_txn, dbi: MDB_dbi, cmp: MDB_cmp_func) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Set a custom data comparison function for a #MDB_DUPSORT database."]
+    #[doc = ""]
+    #[doc = " This comparison function is called whenever it is necessary to compare a data"]
+    #[doc = " item specified by the application with a data item currently stored in the database."]
+    #[doc = " This function only takes effect if the database was opened with the #MDB_DUPSORT"]
+    #[doc = " flag."]
+    #[doc = " If no comparison function is specified, and no special key flags were specified"]
+    #[doc = " with #mdb_dbi_open(), the data items are compared lexically, with shorter items collating"]
+    #[doc = " before longer items."]
+    #[doc = " @warning This function must be called before any data access functions are used,"]
+    #[doc = " otherwise data corruption may occur. The same comparison function must be used by every"]
+    #[doc = " program accessing the database, every time the database is used."]
+    #[doc = " @param[in] txn A transaction handle returned by #mdb_txn_begin()"]
+    #[doc = " @param[in] dbi A database handle returned by #mdb_dbi_open()"]
+    #[doc = " @param[in] cmp A #MDB_cmp_func function"]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>EINVAL - an invalid parameter was specified."]
+    #[doc = " </ul>"]
+    pub fn mdb_set_dupsort(txn: *mut MDB_txn, dbi: MDB_dbi, cmp: MDB_cmp_func) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Set a relocation function for a #MDB_FIXEDMAP database."]
+    #[doc = ""]
+    #[doc = " @todo The relocation function is called whenever it is necessary to move the data"]
+    #[doc = " of an item to a different position in the database (e.g. through tree"]
+    #[doc = " balancing operations, shifts as a result of adds or deletes, etc.). It is"]
+    #[doc = " intended to allow address/position-dependent data items to be stored in"]
+    #[doc = " a database in an environment opened with the #MDB_FIXEDMAP option."]
+    #[doc = " Currently the relocation feature is unimplemented and setting"]
+    #[doc = " this function has no effect."]
+    #[doc = " @param[in] txn A transaction handle returned by #mdb_txn_begin()"]
+    #[doc = " @param[in] dbi A database handle returned by #mdb_dbi_open()"]
+    #[doc = " @param[in] rel A #MDB_rel_func function"]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>EINVAL - an invalid parameter was specified."]
+    #[doc = " </ul>"]
+    pub fn mdb_set_relfunc(txn: *mut MDB_txn, dbi: MDB_dbi, rel: MDB_rel_func) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Set a context pointer for a #MDB_FIXEDMAP database's relocation function."]
+    #[doc = ""]
+    #[doc = " See #mdb_set_relfunc and #MDB_rel_func for more details."]
+    #[doc = " @param[in] txn A transaction handle returned by #mdb_txn_begin()"]
+    #[doc = " @param[in] dbi A database handle returned by #mdb_dbi_open()"]
+    #[doc = " @param[in] ctx An arbitrary pointer for whatever the application needs."]
+    #[doc = " It will be passed to the callback function set by #mdb_set_relfunc"]
+    #[doc = " as its \\b relctx parameter whenever the callback is invoked."]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>EINVAL - an invalid parameter was specified."]
+    #[doc = " </ul>"]
+    pub fn mdb_set_relctx(
+        txn: *mut MDB_txn,
+        dbi: MDB_dbi,
+        ctx: *mut ::libc::c_void,
+    ) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Get items from a database."]
+    #[doc = ""]
+    #[doc = " This function retrieves key/data pairs from the database. The address"]
+    #[doc = " and length of the data associated with the specified \\b key are returned"]
+    #[doc = " in the structure to which \\b data refers."]
+    #[doc = " If the database supports duplicate keys (#MDB_DUPSORT) then the"]
+    #[doc = " first data item for the key will be returned. Retrieval of other"]
+    #[doc = " items requires the use of #mdb_cursor_get()."]
+    #[doc = ""]
+    #[doc = " @note The memory pointed to by the returned values is owned by the"]
+    #[doc = " database. The caller need not dispose of the memory, and may not"]
+    #[doc = " modify it in any way. For values returned in a read-only transaction"]
+    #[doc = " any modification attempts will cause a SIGSEGV."]
+    #[doc = " @note Values returned from the database are valid only until a"]
+    #[doc = " subsequent update operation, or the end of the transaction."]
+    #[doc = " @param[in] txn A transaction handle returned by #mdb_txn_begin()"]
+    #[doc = " @param[in] dbi A database handle returned by #mdb_dbi_open()"]
+    #[doc = " @param[in] key The key to search for in the database"]
+    #[doc = " @param[out] data The data corresponding to the key"]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>#MDB_NOTFOUND - the key was not in the database."]
+    #[doc = "\t<li>EINVAL - an invalid parameter was specified."]
+    #[doc = " </ul>"]
+    pub fn mdb_get(
+        txn: *mut MDB_txn,
+        dbi: MDB_dbi,
+        key: *mut MDB_val,
+        data: *mut MDB_val,
+    ) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Store items into a database."]
+    #[doc = ""]
+    #[doc = " This function stores key/data pairs in the database. The default behavior"]
+    #[doc = " is to enter the new key/data pair, replacing any previously existing key"]
+    #[doc = " if duplicates are disallowed, or adding a duplicate data item if"]
+    #[doc = " duplicates are allowed (#MDB_DUPSORT)."]
+    #[doc = " @param[in] txn A transaction handle returned by #mdb_txn_begin()"]
+    #[doc = " @param[in] dbi A database handle returned by #mdb_dbi_open()"]
+    #[doc = " @param[in] key The key to store in the database"]
+    #[doc = " @param[in,out] data The data to store"]
+    #[doc = " @param[in] flags Special options for this operation. This parameter"]
+    #[doc = " must be set to 0 or by bitwise OR'ing together one or more of the"]
+    #[doc = " values described here."]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>#MDB_NODUPDATA - enter the new key/data pair only if it does not"]
+    #[doc = "\t\talready appear in the database. This flag may only be specified"]
+    #[doc = "\t\tif the database was opened with #MDB_DUPSORT. The function will"]
+    #[doc = "\t\treturn #MDB_KEYEXIST if the key/data pair already appears in the"]
+    #[doc = "\t\tdatabase."]
+    #[doc = "\t<li>#MDB_NOOVERWRITE - enter the new key/data pair only if the key"]
+    #[doc = "\t\tdoes not already appear in the database. The function will return"]
+    #[doc = "\t\t#MDB_KEYEXIST if the key already appears in the database, even if"]
+    #[doc = "\t\tthe database supports duplicates (#MDB_DUPSORT). The \\b data"]
+    #[doc = "\t\tparameter will be set to point to the existing item."]
+    #[doc = "\t<li>#MDB_RESERVE - reserve space for data of the given size, but"]
+    #[doc = "\t\tdon't copy the given data. Instead, return a pointer to the"]
+    #[doc = "\t\treserved space, which the caller can fill in later - before"]
+    #[doc = "\t\tthe next update operation or the transaction ends. This saves"]
+    #[doc = "\t\tan extra memcpy if the data is being generated later."]
+    #[doc = "\t\tLMDB does nothing else with this memory, the caller is expected"]
+    #[doc = "\t\tto modify all of the space requested. This flag must not be"]
+    #[doc = "\t\tspecified if the database was opened with #MDB_DUPSORT."]
+    #[doc = "\t<li>#MDB_APPEND - append the given key/data pair to the end of the"]
+    #[doc = "\t\tdatabase. This option allows fast bulk loading when keys are"]
+    #[doc = "\t\talready known to be in the correct order. Loading unsorted keys"]
+    #[doc = "\t\twith this flag will cause a #MDB_KEYEXIST error."]
+    #[doc = "\t<li>#MDB_APPENDDUP - as above, but for sorted dup data."]
+    #[doc = " </ul>"]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>#MDB_MAP_FULL - the database is full, see #mdb_env_set_mapsize()."]
+    #[doc = "\t<li>#MDB_TXN_FULL - the transaction has too many dirty pages."]
+    #[doc = "\t<li>EACCES - an attempt was made to write in a read-only transaction."]
+    #[doc = "\t<li>EINVAL - an invalid parameter was specified."]
+    #[doc = " </ul>"]
+    pub fn mdb_put(
+        txn: *mut MDB_txn,
+        dbi: MDB_dbi,
+        key: *mut MDB_val,
+        data: *mut MDB_val,
+        flags: ::libc::c_uint,
+    ) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Delete items from a database."]
+    #[doc = ""]
+    #[doc = " This function removes key/data pairs from the database."]
+    #[doc = " If the database does not support sorted duplicate data items"]
+    #[doc = " (#MDB_DUPSORT) the data parameter is ignored."]
+    #[doc = " If the database supports sorted duplicates and the data parameter"]
+    #[doc = " is NULL, all of the duplicate data items for the key will be"]
+    #[doc = " deleted. Otherwise, if the data parameter is non-NULL"]
+    #[doc = " only the matching data item will be deleted."]
+    #[doc = " This function will return #MDB_NOTFOUND if the specified key/data"]
+    #[doc = " pair is not in the database."]
+    #[doc = " @param[in] txn A transaction handle returned by #mdb_txn_begin()"]
+    #[doc = " @param[in] dbi A database handle returned by #mdb_dbi_open()"]
+    #[doc = " @param[in] key The key to delete from the database"]
+    #[doc = " @param[in] data The data to delete"]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>EACCES - an attempt was made to write in a read-only transaction."]
+    #[doc = "\t<li>EINVAL - an invalid parameter was specified."]
+    #[doc = " </ul>"]
+    pub fn mdb_del(
+        txn: *mut MDB_txn,
+        dbi: MDB_dbi,
+        key: *mut MDB_val,
+        data: *mut MDB_val,
+    ) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Create a cursor handle."]
+    #[doc = ""]
+    #[doc = " A cursor is associated with a specific transaction and database."]
+    #[doc = " A cursor cannot be used when its database handle is closed.  Nor"]
+    #[doc = " when its transaction has ended, except with #mdb_cursor_renew()."]
+    #[doc = " It can be discarded with #mdb_cursor_close()."]
+    #[doc = " A cursor in a write-transaction can be closed before its transaction"]
+    #[doc = " ends, and will otherwise be closed when its transaction ends."]
+    #[doc = " A cursor in a read-only transaction must be closed explicitly, before"]
+    #[doc = " or after its transaction ends. It can be reused with"]
+    #[doc = " #mdb_cursor_renew() before finally closing it."]
+    #[doc = " @note Earlier documentation said that cursors in every transaction"]
+    #[doc = " were closed when the transaction committed or aborted."]
+    #[doc = " @param[in] txn A transaction handle returned by #mdb_txn_begin()"]
+    #[doc = " @param[in] dbi A database handle returned by #mdb_dbi_open()"]
+    #[doc = " @param[out] cursor Address where the new #MDB_cursor handle will be stored"]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>EINVAL - an invalid parameter was specified."]
+    #[doc = " </ul>"]
+    pub fn mdb_cursor_open(
+        txn: *mut MDB_txn,
+        dbi: MDB_dbi,
+        cursor: *mut *mut MDB_cursor,
+    ) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Close a cursor handle."]
+    #[doc = ""]
+    #[doc = " The cursor handle will be freed and must not be used again after this call."]
+    #[doc = " Its transaction must still be live if it is a write-transaction."]
+    #[doc = " @param[in] cursor A cursor handle returned by #mdb_cursor_open()"]
+    pub fn mdb_cursor_close(cursor: *mut MDB_cursor);
+}
+extern "C" {
+    #[doc = " @brief Renew a cursor handle."]
+    #[doc = ""]
+    #[doc = " A cursor is associated with a specific transaction and database."]
+    #[doc = " Cursors that are only used in read-only"]
+    #[doc = " transactions may be re-used, to avoid unnecessary malloc/free overhead."]
+    #[doc = " The cursor may be associated with a new read-only transaction, and"]
+    #[doc = " referencing the same database handle as it was created with."]
+    #[doc = " This may be done whether the previous transaction is live or dead."]
+    #[doc = " @param[in] txn A transaction handle returned by #mdb_txn_begin()"]
+    #[doc = " @param[in] cursor A cursor handle returned by #mdb_cursor_open()"]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>EINVAL - an invalid parameter was specified."]
+    #[doc = " </ul>"]
+    pub fn mdb_cursor_renew(txn: *mut MDB_txn, cursor: *mut MDB_cursor) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Return the cursor's transaction handle."]
+    #[doc = ""]
+    #[doc = " @param[in] cursor A cursor handle returned by #mdb_cursor_open()"]
+    pub fn mdb_cursor_txn(cursor: *mut MDB_cursor) -> *mut MDB_txn;
+}
+extern "C" {
+    #[doc = " @brief Return the cursor's database handle."]
+    #[doc = ""]
+    #[doc = " @param[in] cursor A cursor handle returned by #mdb_cursor_open()"]
+    pub fn mdb_cursor_dbi(cursor: *mut MDB_cursor) -> MDB_dbi;
+}
+extern "C" {
+    #[doc = " @brief Retrieve by cursor."]
+    #[doc = ""]
+    #[doc = " This function retrieves key/data pairs from the database. The address and length"]
+    #[doc = " of the key are returned in the object to which \\b key refers (except for the"]
+    #[doc = " case of the #MDB_SET option, in which the \\b key object is unchanged), and"]
+    #[doc = " the address and length of the data are returned in the object to which \\b data"]
+    #[doc = " refers."]
+    #[doc = " See #mdb_get() for restrictions on using the output values."]
+    #[doc = " @param[in] cursor A cursor handle returned by #mdb_cursor_open()"]
+    #[doc = " @param[in,out] key The key for a retrieved item"]
+    #[doc = " @param[in,out] data The data of a retrieved item"]
+    #[doc = " @param[in] op A cursor operation #MDB_cursor_op"]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>#MDB_NOTFOUND - no matching key found."]
+    #[doc = "\t<li>EINVAL - an invalid parameter was specified."]
+    #[doc = " </ul>"]
+    pub fn mdb_cursor_get(
+        cursor: *mut MDB_cursor,
+        key: *mut MDB_val,
+        data: *mut MDB_val,
+        op: MDB_cursor_op,
+    ) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Store by cursor."]
+    #[doc = ""]
+    #[doc = " This function stores key/data pairs into the database."]
+    #[doc = " The cursor is positioned at the new item, or on failure usually near it."]
+    #[doc = " @note Earlier documentation incorrectly said errors would leave the"]
+    #[doc = " state of the cursor unchanged."]
+    #[doc = " @param[in] cursor A cursor handle returned by #mdb_cursor_open()"]
+    #[doc = " @param[in] key The key operated on."]
+    #[doc = " @param[in] data The data operated on."]
+    #[doc = " @param[in] flags Options for this operation. This parameter"]
+    #[doc = " must be set to 0 or one of the values described here."]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>#MDB_CURRENT - replace the item at the current cursor position."]
+    #[doc = "\t\tThe \\b key parameter must still be provided, and must match it."]
+    #[doc = "\t\tIf using sorted duplicates (#MDB_DUPSORT) the data item must still"]
+    #[doc = "\t\tsort into the same place. This is intended to be used when the"]
+    #[doc = "\t\tnew data is the same size as the old. Otherwise it will simply"]
+    #[doc = "\t\tperform a delete of the old record followed by an insert."]
+    #[doc = "\t<li>#MDB_NODUPDATA - enter the new key/data pair only if it does not"]
+    #[doc = "\t\talready appear in the database. This flag may only be specified"]
+    #[doc = "\t\tif the database was opened with #MDB_DUPSORT. The function will"]
+    #[doc = "\t\treturn #MDB_KEYEXIST if the key/data pair already appears in the"]
+    #[doc = "\t\tdatabase."]
+    #[doc = "\t<li>#MDB_NOOVERWRITE - enter the new key/data pair only if the key"]
+    #[doc = "\t\tdoes not already appear in the database. The function will return"]
+    #[doc = "\t\t#MDB_KEYEXIST if the key already appears in the database, even if"]
+    #[doc = "\t\tthe database supports duplicates (#MDB_DUPSORT)."]
+    #[doc = "\t<li>#MDB_RESERVE - reserve space for data of the given size, but"]
+    #[doc = "\t\tdon't copy the given data. Instead, return a pointer to the"]
+    #[doc = "\t\treserved space, which the caller can fill in later - before"]
+    #[doc = "\t\tthe next update operation or the transaction ends. This saves"]
+    #[doc = "\t\tan extra memcpy if the data is being generated later. This flag"]
+    #[doc = "\t\tmust not be specified if the database was opened with #MDB_DUPSORT."]
+    #[doc = "\t<li>#MDB_APPEND - append the given key/data pair to the end of the"]
+    #[doc = "\t\tdatabase. No key comparisons are performed. This option allows"]
+    #[doc = "\t\tfast bulk loading when keys are already known to be in the"]
+    #[doc = "\t\tcorrect order. Loading unsorted keys with this flag will cause"]
+    #[doc = "\t\ta #MDB_KEYEXIST error."]
+    #[doc = "\t<li>#MDB_APPENDDUP - as above, but for sorted dup data."]
+    #[doc = "\t<li>#MDB_MULTIPLE - store multiple contiguous data elements in a"]
+    #[doc = "\t\tsingle request. This flag may only be specified if the database"]
+    #[doc = "\t\twas opened with #MDB_DUPFIXED. The \\b data argument must be an"]
+    #[doc = "\t\tarray of two MDB_vals. The mv_size of the first MDB_val must be"]
+    #[doc = "\t\tthe size of a single data element. The mv_data of the first MDB_val"]
+    #[doc = "\t\tmust point to the beginning of the array of contiguous data elements."]
+    #[doc = "\t\tThe mv_size of the second MDB_val must be the count of the number"]
+    #[doc = "\t\tof data elements to store. On return this field will be set to"]
+    #[doc = "\t\tthe count of the number of elements actually written. The mv_data"]
+    #[doc = "\t\tof the second MDB_val is unused."]
+    #[doc = " </ul>"]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>#MDB_MAP_FULL - the database is full, see #mdb_env_set_mapsize()."]
+    #[doc = "\t<li>#MDB_TXN_FULL - the transaction has too many dirty pages."]
+    #[doc = "\t<li>EACCES - an attempt was made to write in a read-only transaction."]
+    #[doc = "\t<li>EINVAL - an invalid parameter was specified."]
+    #[doc = " </ul>"]
+    pub fn mdb_cursor_put(
+        cursor: *mut MDB_cursor,
+        key: *mut MDB_val,
+        data: *mut MDB_val,
+        flags: ::libc::c_uint,
+    ) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Delete current key/data pair"]
+    #[doc = ""]
+    #[doc = " This function deletes the key/data pair to which the cursor refers."]
+    #[doc = " This does not invalidate the cursor, so operations such as MDB_NEXT"]
+    #[doc = " can still be used on it."]
+    #[doc = " Both MDB_NEXT and MDB_GET_CURRENT will return the same record after"]
+    #[doc = " this operation."]
+    #[doc = " @param[in] cursor A cursor handle returned by #mdb_cursor_open()"]
+    #[doc = " @param[in] flags Options for this operation. This parameter"]
+    #[doc = " must be set to 0 or one of the values described here."]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>#MDB_NODUPDATA - delete all of the data items for the current key."]
+    #[doc = "\t\tThis flag may only be specified if the database was opened with #MDB_DUPSORT."]
+    #[doc = " </ul>"]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>EACCES - an attempt was made to write in a read-only transaction."]
+    #[doc = "\t<li>EINVAL - an invalid parameter was specified."]
+    #[doc = " </ul>"]
+    pub fn mdb_cursor_del(cursor: *mut MDB_cursor, flags: ::libc::c_uint) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Return count of duplicates for current key."]
+    #[doc = ""]
+    #[doc = " This call is only valid on databases that support sorted duplicate"]
+    #[doc = " data items #MDB_DUPSORT."]
+    #[doc = " @param[in] cursor A cursor handle returned by #mdb_cursor_open()"]
+    #[doc = " @param[out] countp Address where the count will be stored"]
+    #[doc = " @return A non-zero error value on failure and 0 on success. Some possible"]
+    #[doc = " errors are:"]
+    #[doc = " <ul>"]
+    #[doc = "\t<li>EINVAL - cursor is not initialized, or an invalid parameter was specified."]
+    #[doc = " </ul>"]
+    pub fn mdb_cursor_count(cursor: *mut MDB_cursor, countp: *mut usize) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Compare two data items according to a particular database."]
+    #[doc = ""]
+    #[doc = " This returns a comparison as if the two data items were keys in the"]
+    #[doc = " specified database."]
+    #[doc = " @param[in] txn A transaction handle returned by #mdb_txn_begin()"]
+    #[doc = " @param[in] dbi A database handle returned by #mdb_dbi_open()"]
+    #[doc = " @param[in] a The first item to compare"]
+    #[doc = " @param[in] b The second item to compare"]
+    #[doc = " @return < 0 if a < b, 0 if a == b, > 0 if a > b"]
+    pub fn mdb_cmp(
+        txn: *mut MDB_txn,
+        dbi: MDB_dbi,
+        a: *const MDB_val,
+        b: *const MDB_val,
+    ) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Compare two data items according to a particular database."]
+    #[doc = ""]
+    #[doc = " This returns a comparison as if the two items were data items of"]
+    #[doc = " the specified database. The database must have the #MDB_DUPSORT flag."]
+    #[doc = " @param[in] txn A transaction handle returned by #mdb_txn_begin()"]
+    #[doc = " @param[in] dbi A database handle returned by #mdb_dbi_open()"]
+    #[doc = " @param[in] a The first item to compare"]
+    #[doc = " @param[in] b The second item to compare"]
+    #[doc = " @return < 0 if a < b, 0 if a == b, > 0 if a > b"]
+    pub fn mdb_dcmp(
+        txn: *mut MDB_txn,
+        dbi: MDB_dbi,
+        a: *const MDB_val,
+        b: *const MDB_val,
+    ) -> ::libc::c_int;
+}
+#[doc = " @brief A callback function used to print a message from the library."]
+#[doc = ""]
+#[doc = " @param[in] msg The string to be printed."]
+#[doc = " @param[in] ctx An arbitrary context pointer for the callback."]
+#[doc = " @return < 0 on failure, >= 0 on success."]
+pub type MDB_msg_func = ::std::option::Option<
+    unsafe extern "C" fn(msg: *const ::libc::c_char, ctx: *mut ::libc::c_void) -> ::libc::c_int,
+>;
+extern "C" {
+    #[doc = " @brief Dump the entries in the reader lock table."]
+    #[doc = ""]
+    #[doc = " @param[in] env An environment handle returned by #mdb_env_create()"]
+    #[doc = " @param[in] func A #MDB_msg_func function"]
+    #[doc = " @param[in] ctx Anything the message function needs"]
+    #[doc = " @return < 0 on failure, >= 0 on success."]
+    pub fn mdb_reader_list(
+        env: *mut MDB_env,
+        func: MDB_msg_func,
+        ctx: *mut ::libc::c_void,
+    ) -> ::libc::c_int;
+}
+extern "C" {
+    #[doc = " @brief Check for stale entries in the reader lock table."]
+    #[doc = ""]
+    #[doc = " @param[in] env An environment handle returned by #mdb_env_create()"]
+    #[doc = " @param[out] dead Number of stale slots that were cleared"]
+    #[doc = " @return 0 on success, non-zero on failure."]
+    pub fn mdb_reader_check(env: *mut MDB_env, dead: *mut ::libc::c_int) -> ::libc::c_int;
+}
deleted file mode 100644
--- a/third_party/rust/lmdb-rkv-sys/src/constants.rs
+++ /dev/null
@@ -1,125 +0,0 @@
-use libc::{c_int, c_uint};
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//// Environment Flags
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-/// mmap at a fixed address (experimental)
-pub const MDB_FIXEDMAP: c_uint = 0x01;
-/// no environment directory
-pub const MDB_NOSUBDIR: c_uint = 0x4000;
-/// don't fsync after commit
-pub const MDB_NOSYNC: c_uint = 0x10000;
-/// read only
-pub const MDB_RDONLY: c_uint = 0x20000;
-/// don't fsync metapage after commit
-pub const MDB_NOMETASYNC: c_uint = 0x40000;
-/// use writable mmap
-pub const MDB_WRITEMAP: c_uint = 0x80000;
-/// use asynchronous msync when #MDB_WRITEMAP is used
-pub const MDB_MAPASYNC: c_uint = 0x100000;
-/// tie reader locktable slots to #MDB_txn objects instead of to threads
-pub const MDB_NOTLS: c_uint = 0x200000;
-/// don't do any locking, caller must manage their own locks
-pub const MDB_NOLOCK: c_uint = 0x400000;
-/// don't do readahead (no effect on Windows)
-pub const MDB_NORDAHEAD: c_uint = 0x800000;
-/// don't initialize malloc'd memory before writing to datafile
-pub const MDB_NOMEMINIT: c_uint = 0x1000000;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//// Database Flags
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-/// use reverse string keys
-pub const MDB_REVERSEKEY: c_uint = 0x02;
-/// use sorted duplicates
-pub const MDB_DUPSORT: c_uint = 0x04;
-/// numeric keys in native byte order. The keys must all be of the same size.
-pub const MDB_INTEGERKEY: c_uint = 0x08;
-/// with `MDB_DUPSORT`, sorted dup items have fixed size.
-pub const MDB_DUPFIXED: c_uint = 0x10;
-/// with `MDB_DUPSORT`, dups are numeric in native byte order.
-pub const MDB_INTEGERDUP: c_uint = 0x20;
-/// with #MDB_DUPSORT, use reverse string dups.
-pub const MDB_REVERSEDUP: c_uint = 0x40;
-/// create DB if not already existing.
-pub const MDB_CREATE: c_uint = 0x40000;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//// Write Flags
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-/// For put: Don't write if the key already exists.
-pub const MDB_NOOVERWRITE: c_uint = 0x10;
-/// Only for `MDB_DUPSORT`.
-///
-/// For put: don't write if the key and data pair already exist.
-/// For `mdb_cursor_del`: remove all duplicate data items.
-pub const MDB_NODUPDATA: c_uint = 0x20;
-/// For `mdb_cursor_put`: overwrite the current key/data pair.
-pub const MDB_CURRENT: c_uint = 0x40;
-/// For put: Just reserve space for data, don't copy it. Return a pointer to the reserved space.
-pub const MDB_RESERVE: c_uint = 0x10000;
-/// Data is being appended, don't split full pages.
-pub const MDB_APPEND: c_uint = 0x20000;
-/// Duplicate data is being appended, don't split full pages.
-pub const MDB_APPENDDUP: c_uint = 0x40000;
-/// Store multiple data items in one call. Only for #MDB_DUPFIXED.
-pub const MDB_MULTIPLE: c_uint = 0x80000;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//// Copy Flags
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-/// Compacting copy: Omit free space from copy, and renumber all pages sequentially.
-pub const MDB_CP_COMPACT: c_uint = 0x01;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//// Return Codes
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-/// Successful result.
-pub const MDB_SUCCESS: c_int = 0;
-/// key/data pair already exists.
-pub const MDB_KEYEXIST: c_int = -30799;
-/// key/data pair not found (EOF).
-pub const MDB_NOTFOUND: c_int = -30798;
-/// Requested page not found - this usually indicates corruption.
-pub const MDB_PAGE_NOTFOUND: c_int = -30797;
-/// Located page was wrong type.
-pub const MDB_CORRUPTED: c_int = -30796;
-/// Update of meta page failed or environment had fatal error.
-pub const MDB_PANIC: c_int = -30795;
-/// Environment version mismatch.
-pub const MDB_VERSION_MISMATCH: c_int = -30794;
-/// File is not a valid LMDB file.
-pub const MDB_INVALID: c_int = -30793;
-/// Environment mapsize reached.
-pub const MDB_MAP_FULL: c_int = -30792;
-/// Environment maxdbs reached.
-pub const MDB_DBS_FULL: c_int = -30791;
-/// Environment maxreaders reached.
-pub const MDB_READERS_FULL: c_int = -30790;
-/// Too many TLS keys in use - Windows only.
-pub const MDB_TLS_FULL: c_int = -30789;
-/// Txn has too many dirty pages.
-pub const MDB_TXN_FULL: c_int = -30788;
-/// Cursor stack too deep - internal error.
-pub const MDB_CURSOR_FULL: c_int = -30787;
-/// Page has not enough space - internal error.
-pub const MDB_PAGE_FULL: c_int = -30786;
-/// Database contents grew beyond environment mapsize.
-pub const MDB_MAP_RESIZED: c_int = -30785;
-/// MDB_INCOMPATIBLE: Operation and DB incompatible, or DB flags changed.
-pub const MDB_INCOMPATIBLE: c_int = -30784;
-/// Invalid reuse of reader locktable slot.
-pub const MDB_BAD_RSLOT: c_int = -30783;
-/// Transaction cannot recover - it must be aborted.
-pub const MDB_BAD_TXN: c_int = -30782;
-/// Unsupported size of key/DB name/data, or wrong DUPFIXED size.
-pub const MDB_BAD_VALSIZE: c_int = -30781;
-/// The specified DBI was changed unexpectedly.
-pub const MDB_BAD_DBI: c_int = -30780;
-/// The last defined error code.
-pub const MDB_LAST_ERRCODE: c_int = MDB_BAD_DBI;
deleted file mode 100644
--- a/third_party/rust/lmdb-rkv-sys/src/ffi.rs
+++ /dev/null
@@ -1,118 +0,0 @@
-/* automatically generated by rust-bindgen and modified by hand */
-
-pub enum MDB_env { }
-pub enum MDB_txn { }
-pub type MDB_dbi = ::libc::c_uint;
-pub enum MDB_cursor { }
-
-#[repr(C)]
-pub struct MDB_val {
-    pub mv_size: ::libc::size_t,
-    pub mv_data: *mut ::libc::c_void,
-}
-
-pub type MDB_cmp_func = extern "C" fn(a: *const MDB_val, b: *const MDB_val) -> ::libc::c_int;
-pub type MDB_rel_func = extern "C" fn (item: *mut MDB_val, oldptr: *mut ::libc::c_void, newptr: *mut ::libc::c_void, relctx: *mut ::libc::c_void) -> ();
-
-pub const MDB_FIRST: ::libc::c_uint = 0;
-pub const MDB_FIRST_DUP: ::libc::c_uint = 1;
-pub const MDB_GET_BOTH: ::libc::c_uint = 2;
-pub const MDB_GET_BOTH_RANGE: ::libc::c_uint = 3;
-pub const MDB_GET_CURRENT: ::libc::c_uint = 4;
-pub const MDB_GET_MULTIPLE: ::libc::c_uint = 5;
-pub const MDB_LAST: ::libc::c_uint = 6;
-pub const MDB_LAST_DUP: ::libc::c_uint = 7;
-pub const MDB_NEXT: ::libc::c_uint = 8;
-pub const MDB_NEXT_DUP: ::libc::c_uint = 9;
-pub const MDB_NEXT_MULTIPLE: ::libc::c_uint = 10;
-pub const MDB_NEXT_NODUP: ::libc::c_uint = 11;
-pub const MDB_PREV: ::libc::c_uint = 12;
-pub const MDB_PREV_DUP: ::libc::c_uint = 13;
-pub const MDB_PREV_NODUP: ::libc::c_uint = 14;
-pub const MDB_SET: ::libc::c_uint = 15;
-pub const MDB_SET_KEY: ::libc::c_uint = 16;
-pub const MDB_SET_RANGE: ::libc::c_uint = 17;
-pub type MDB_cursor_op = ::libc::c_uint;
-
-#[repr(C)]
-#[derive(Clone, Copy)]
-pub struct MDB_stat {
-    pub ms_psize: ::libc::c_uint,
-    pub ms_depth: ::libc::c_uint,
-    pub ms_branch_pages: ::libc::size_t,
-    pub ms_leaf_pages: ::libc::size_t,
-    pub ms_overflow_pages: ::libc::size_t,
-    pub ms_entries: ::libc::size_t,
-}
-
-#[repr(C)]
-pub struct MDB_envinfo {
-    pub me_mapaddr: *mut ::libc::c_void,
-    pub me_mapsize: ::libc::size_t,
-    pub me_last_pgno: ::libc::size_t,
-    pub me_last_txnid: ::libc::size_t,
-    pub me_maxreaders: ::libc::c_uint,
-    pub me_numreaders: ::libc::c_uint,
-}
-
-pub type MDB_assert_func = extern "C" fn(env: *mut MDB_env, msg: *const ::libc::c_char) -> ();
-pub type MDB_msg_func = extern "C" fn(msg: *const ::libc::c_char, ctx: *mut ::libc::c_void) -> ::libc::c_int;
-
-extern "C" {
-    pub fn mdb_version(major: *mut ::libc::c_int, minor: *mut ::libc::c_int, patch: *mut ::libc::c_int) -> *mut ::libc::c_char;
-    pub fn mdb_strerror(err: ::libc::c_int) -> *mut ::libc::c_char;
-    pub fn mdb_env_create(env: *mut *mut MDB_env) -> ::libc::c_int;
-    pub fn mdb_env_open(env: *mut MDB_env, path: *const ::libc::c_char, flags: ::libc::c_uint, mode: super::mode_t) -> ::libc::c_int;
-    pub fn mdb_env_copy(env: *mut MDB_env, path: *const ::libc::c_char) -> ::libc::c_int;
-    pub fn mdb_env_copyfd(env: *mut MDB_env, fd: ::libc::c_int) -> ::libc::c_int;
-    pub fn mdb_env_copy2(env: *mut MDB_env, path: *const ::libc::c_char, flags: ::libc::c_uint) -> ::libc::c_int;
-    pub fn mdb_env_copyfd2(env: *mut MDB_env, fd: ::libc::c_int, flags: ::libc::c_uint) -> ::libc::c_int;
-    pub fn mdb_env_stat(env: *mut MDB_env, stat: *mut MDB_stat) -> ::libc::c_int;
-    pub fn mdb_env_info(env: *mut MDB_env, stat: *mut MDB_envinfo) -> ::libc::c_int;
-    pub fn mdb_env_sync(env: *mut MDB_env, force: ::libc::c_int) -> ::libc::c_int;
-    pub fn mdb_env_close(env: *mut MDB_env) -> ();
-    pub fn mdb_env_set_flags(env: *mut MDB_env, flags: ::libc::c_uint, onoff: ::libc::c_int) -> ::libc::c_int;
-    pub fn mdb_env_get_flags(env: *mut MDB_env, flags: *mut ::libc::c_uint) -> ::libc::c_int;
-    pub fn mdb_env_get_path(env: *mut MDB_env, path: *mut *const ::libc::c_char) -> ::libc::c_int;
-    pub fn mdb_env_get_fd(env: *mut MDB_env, fd: *mut ::libc::c_int) -> ::libc::c_int;
-    pub fn mdb_env_set_mapsize(env: *mut MDB_env, size: ::libc::size_t) -> ::libc::c_int;
-    pub fn mdb_env_set_maxreaders(env: *mut MDB_env, readers: ::libc::c_uint) -> ::libc::c_int;
-    pub fn mdb_env_get_maxreaders(env: *mut MDB_env, readers: *mut ::libc::c_uint) -> ::libc::c_int;
-    pub fn mdb_env_set_maxdbs(env: *mut MDB_env, dbs: MDB_dbi) -> ::libc::c_int;
-    pub fn mdb_env_get_maxkeysize(env: *mut MDB_env) -> ::libc::c_int;
-    pub fn mdb_env_set_userctx(env: *mut MDB_env, ctx: *mut ::libc::c_void) -> ::libc::c_int;
-    pub fn mdb_env_get_userctx(env: *mut MDB_env) -> *mut ::libc::c_void;
-    pub fn mdb_env_set_assert(env: *mut MDB_env, func: *mut ::std::option::Option<extern "C" fn() -> ()>) -> ::libc::c_int;
-    pub fn mdb_txn_begin(env: *mut MDB_env, parent: *mut MDB_txn, flags: ::libc::c_uint, txn: *mut *mut MDB_txn) -> ::libc::c_int;
-    pub fn mdb_txn_env(txn: *mut MDB_txn) -> *mut MDB_env;
-    pub fn mdb_txn_id(txn: *mut MDB_txn) -> ::libc::size_t;
-    pub fn mdb_txn_commit(txn: *mut MDB_txn) -> ::libc::c_int;
-    pub fn mdb_txn_abort(txn: *mut MDB_txn) -> ();
-    pub fn mdb_txn_reset(txn: *mut MDB_txn) -> ();
-    pub fn mdb_txn_renew(txn: *mut MDB_txn) -> ::libc::c_int;
-    pub fn mdb_dbi_open(txn: *mut MDB_txn, name: *const ::libc::c_char, flags: ::libc::c_uint, dbi: *mut MDB_dbi) -> ::libc::c_int;
-    pub fn mdb_stat(txn: *mut MDB_txn, dbi: MDB_dbi, stat: *mut MDB_stat) -> ::libc::c_int;
-    pub fn mdb_dbi_flags(txn: *mut MDB_txn, dbi: MDB_dbi, flags: *mut ::libc::c_uint) -> ::libc::c_int;
-    pub fn mdb_dbi_close(env: *mut MDB_env, dbi: MDB_dbi) -> ();
-    pub fn mdb_drop(txn: *mut MDB_txn, dbi: MDB_dbi, del: ::libc::c_int) -> ::libc::c_int;
-    pub fn mdb_set_compare(txn: *mut MDB_txn, dbi: MDB_dbi, cmp: *mut MDB_cmp_func) -> ::libc::c_int;
-    pub fn mdb_set_dupsort(txn: *mut MDB_txn, dbi: MDB_dbi, cmp: *mut MDB_cmp_func) -> ::libc::c_int;
-    pub fn mdb_set_relfunc(txn: *mut MDB_txn, dbi: MDB_dbi, rel: *mut MDB_rel_func) -> ::libc::c_int;
-    pub fn mdb_set_relctx(txn: *mut MDB_txn, dbi: MDB_dbi, ctx: *mut ::libc::c_void) -> ::libc::c_int;
-    pub fn mdb_get(txn: *mut MDB_txn, dbi: MDB_dbi, key: *mut MDB_val, data: *mut MDB_val) -> ::libc::c_int;
-    pub fn mdb_put(txn: *mut MDB_txn, dbi: MDB_dbi, key: *mut MDB_val, data: *mut MDB_val, flags: ::libc::c_uint) -> ::libc::c_int;
-    pub fn mdb_del(txn: *mut MDB_txn, dbi: MDB_dbi, key: *mut MDB_val, data: *mut MDB_val) -> ::libc::c_int;
-    pub fn mdb_cursor_open(txn: *mut MDB_txn, dbi: MDB_dbi, cursor: *mut *mut MDB_cursor) -> ::libc::c_int;
-    pub fn mdb_cursor_close(cursor: *mut MDB_cursor) -> ();
-    pub fn mdb_cursor_renew(txn: *mut MDB_txn, cursor: *mut MDB_cursor) -> ::libc::c_int;
-    pub fn mdb_cursor_txn(cursor: *mut MDB_cursor) -> *mut MDB_txn;
-    pub fn mdb_cursor_dbi(cursor: *mut MDB_cursor) -> MDB_dbi;
-    pub fn mdb_cursor_get(cursor: *mut MDB_cursor, key: *mut MDB_val, data: *mut MDB_val, op: MDB_cursor_op) -> ::libc::c_int;
-    pub fn mdb_cursor_put(cursor: *mut MDB_cursor, key: *mut MDB_val, data: *mut MDB_val, flags: ::libc::c_uint) -> ::libc::c_int;
-    pub fn mdb_cursor_del(cursor: *mut MDB_cursor, flags: ::libc::c_uint) -> ::libc::c_int;
-    pub fn mdb_cursor_count(cursor: *mut MDB_cursor, countp: *mut ::libc::size_t) -> ::libc::c_int;
-    pub fn mdb_cmp(txn: *mut MDB_txn, dbi: MDB_dbi, a: *const MDB_val, b: *const MDB_val) -> ::libc::c_int;
-    pub fn mdb_dcmp(txn: *mut MDB_txn, dbi: MDB_dbi, a: *const MDB_val, b: *const MDB_val) -> ::libc::c_int;
-    pub fn mdb_reader_list(env: *mut MDB_env, func: *mut MDB_msg_func, ctx: *mut ::libc::c_void) -> ::libc::c_int;
-    pub fn mdb_reader_check(env: *mut MDB_env, dead: *mut ::libc::c_int) -> ::libc::c_int;
-}
--- a/third_party/rust/lmdb-rkv-sys/src/lib.rs
+++ b/third_party/rust/lmdb-rkv-sys/src/lib.rs
@@ -1,18 +1,15 @@
+#![deny(warnings)]
 #![allow(non_camel_case_types)]
-#![deny(warnings)]
-#![doc(html_root_url = "https://docs.rs/lmdb-rkv-sys/0.8.4")]
+#![allow(clippy::all)]
+#![doc(html_root_url = "https://docs.rs/lmdb-rkv-sys/0.9.3")]
 
 extern crate libc;
 
 #[cfg(unix)]
 #[allow(non_camel_case_types)]
 pub type mode_t = ::libc::mode_t;
 #[cfg(windows)]
 #[allow(non_camel_case_types)]
 pub type mode_t = ::libc::c_int;
 
-pub use constants::*;
-pub use ffi::*;
-
-mod ffi;
-mod constants;
+include!("bindings.rs");
new file mode 100644
index 0000000000000000000000000000000000000000..63d0fc8faa1d3c9bd4dceb318124d6c79a7fa8df
GIT binary patch
literal 57344
zc%1E>JB-{!7{`5kd%1mh&k>5KQcRH|1%+qEV~@K?P*9{ufgnUQw=Yp31@VwlT#+&b
zMGA^5Qly|rK}kUoAqt8VC`yrn0-=-?kw6he3MBZxT|e$Nc>OIzf;;}d=)d0e{yiDb
zjO}^dY!H<67Oy{j`^z_5{6@XeTWo{7%dgJ{K|k24-1WO9onkv$*}Jv!eaY*^He5OG
zS^xk500000004lOP2G<FXYK#(V!L~6Z+rW{Jg#j2zblS800000000000Hkz|yt@=U
z9ERcJ=w5U`Jcy>@?eI$E!wb>#z3=z#?tQZN=HB_eUq|1K4o4r1E{)EOehwcF|HY^S
z000000PsI24!9n_6MX#XcsiCI^hZIU79YET*>{SSW|^8_zplpnAH8r;>9safEN^V9
z*UZL>l_i33^;EI4yxnVN6kk%7==N}D6UEYToHUs$?>JYi+_j&Z9mk55Cyl|@-hJ|t
za^u^*d8$~smUt;#Qm#$A*UuFz*Mc<j6fVhAJX*a}W?0?}@;IF-md^y|mQucvd?tuP
zY8A_;f;c#*SYDFH<Y9RyNHas_m*lnNy6}pX3CfO{#fp{L_H-~4t5{jwoDSR7yRG0{
z@HBcJJ&m43FW3M8000000001R0^t6<oyEIl|6aG)->n>-U>@A*U5O5&3lYx&Xdd;y
zAKnh9p%26G$?&V;t>Jsac-S5OF!*wCbMV&S;^6oGqy88D8~w|D)&H&cpm(SDVUOKQ
zfBo<1k;`MxZ$IvSedgj|x>bg8b?0*b$DM=jmG0-e_qv~*QT<DuGR*gPU)yOrZ&jYN
zaf;=VytUsXPBO*Hn!9;wuSpflHg{oFUTqV_vT=KVSM2u{ORovI@;a+nzPYQZ_Rc9>
zl5w#h9TLS#CFhn>TuC-<?|Y1=GsQAS;MH_)B;A~CwbxQ!kX&;&+L3dcDAt<p#QNOm
zKW7==-tQNubH&nve$_Z1E0%UnkjJrN`Q~h^y<>_4N#}w%Xs1|4Qr7KMu~LCoJ4!Q>
zP1?^*yG*fc(%x69-9)i$(tcfNIw_X%f@^+GX+|=VywFt6NNbAkk@!;C<$hx;h{Kf9
zmt@vtM&+e~z|w*-giY>I@cwtan>;U0n%C^dij`*V&w!1*IbFk~bj`!N_R_URO4Igh
z)6jjIl?uj`Ol}n`b%Jm`g-c2WV@f8=6f3n7FQpkNHG(mvl;S{2*F0ovFU5hB>h}Aj
zag@HKG!}R*<r~Rm5--Jp<Rp1vDIG{IZLjYbL+L<rf@i=c^+~gMzLM7p#saC{z;Z?q
zZcOP*az+r}c%oQNQXXP@wvn7*%vsOr*-dh>;MqN!DpryUyc6=0k~Ni$+DmaDC4zj@
z6Qfv(p#H1JGsQ}h_OVtyrur`_N!ssGdh8V|Nd$4&r+X?XF%mD;HAsozI@WaGV<m#|
zX`NG@i<AiF6>y!CmBfO4^OU|Mn+wXBcZy{Nbvf-Rk4e@G@{Q|Ii}?-h*Tp7noXzUA
zlnx{-DU)>n*NZt8g0jx-5RzSUpR60unEwv|00000z{%n-=KnV@*;Rh7>hNmuiuwPQ
z7xVuE%>O^#^Z(CO@6i4S000000N`Ztx7z>xa)(;HqWxca(f$w6{y*LA|9ZXtPVj1Q
zGrAc)ita{FcV9390000000000U}MfMUVGK{onn94DHj%7ReWFmE?&7_-=Ns`ifw1b
ze|5!Q{=Qz>*;kJHm&Y&L|2Lu=(Szs^?SB9O00000007{nP`3NuE<UgRF^(#}m$u_C
z7XGpyp<LIm>_;dY^yT0Cm*G{Df2jTcO7JXthPD3z000000001hQ^59-*LofSe*X^u
z000000000u`S5xk%fAsg{`-IR0)80(2LJ#70000008S6b$N$4>KgRz7000000001h
zlMavhFV_k<KK?(d935)^A4ZR&L#+P~0000000000ykwfz|1a0`yH<Q&ov+`to}Vg?
Ilm1@7pUy?b?*IS*
new file mode 100644
index 0000000000000000000000000000000000000000..fd45a7ae229bcee41b65c6906d803c29803718f8
GIT binary patch
literal 8192
zc%1Fbu?d4v00hwgSI8D(;S3Smv^D`J2o}F_BG(Wr$H)qfU<fgd0mVA+b$4+09Oog1
u7>Zj}rY3)6Db?+@4O{o0=HtEVc6LXW)i;m*bcv^5000000002szr6s?tQWQb
new file mode 100644
--- /dev/null
+++ b/third_party/rust/lmdb-rkv-sys/tests/lmdb.rs
@@ -0,0 +1,28 @@
+extern crate lmdb_sys;
+
+use std::env;
+use std::path::PathBuf;
+use std::process::Command;
+
+#[test]
+fn test_lmdb() {
+    let mut lmdb = PathBuf::from(&env::var("CARGO_MANIFEST_DIR").unwrap());
+    lmdb.push("lmdb");
+    lmdb.push("libraries");
+    lmdb.push("liblmdb");
+
+    let make_cmd = Command::new("make")
+        .current_dir(&lmdb)
+        .status()
+        .expect("failed to execute process");
+
+    assert_eq!(make_cmd.success(), true);
+
+    let make_test_cmd = Command::new("make")
+        .arg("test")
+        .current_dir(&lmdb)
+        .status()
+        .expect("failed to execute process");
+
+    assert_eq!(make_test_cmd.success(), true);
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/lmdb-rkv-sys/tests/simple.rs
@@ -0,0 +1,74 @@
+extern crate lmdb_sys;
+
+use lmdb_sys::*;
+
+use std::ffi::{c_void, CString};
+use std::ptr;
+
+// https://github.com/victorporof/lmdb/blob/mdb.master/libraries/liblmdb/moz-test.c
+
+macro_rules! E {
+    ($expr:expr) => {{
+        match $expr {
+            ::MDB_SUCCESS => (),
+            err_code => assert!(false, "Failed with code {}", err_code),
+        }
+    }};
+}
+
+macro_rules! str {
+    ($expr:expr) => {
+        ::CString::new($expr).unwrap().as_ptr()
+    };
+}
+
+#[test]
+#[cfg(all(target_os = "windows", target_arch = "x86"))]
+#[should_panic(expected = "Failed with code -30793")]
+fn test_simple_win_32() {
+    test_simple()
+}
+
+#[test]
+#[cfg(not(all(target_os = "windows", target_arch = "x86")))]
+fn test_simple_other() {
+    test_simple()
+}
+
+fn test_simple() {
+    let mut env: *mut MDB_env = ptr::null_mut();
+    let mut dbi: MDB_dbi = 0;
+    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 txn: *mut MDB_txn = ptr::null_mut();
+    let sval = str!("foo") as *mut c_void;
+    let dval = str!("bar") as *mut c_void;
+
+    unsafe {
+        E!(mdb_env_create(&mut env));
+        E!(mdb_env_set_maxdbs(env, 2));
+        E!(mdb_env_open(env, str!("./tests/fixtures/testdb"), 0, 0664));
+
+        E!(mdb_txn_begin(env, ptr::null_mut(), 0, &mut txn));
+        E!(mdb_dbi_open(txn, str!("subdb"), MDB_CREATE, &mut dbi));
+        E!(mdb_txn_commit(txn));
+
+        key.mv_size = 3;
+        key.mv_data = sval;
+        data.mv_size = 3;
+        data.mv_data = dval;
+
+        E!(mdb_txn_begin(env, ptr::null_mut(), 0, &mut txn));
+        E!(mdb_put(txn, dbi, &mut key, &mut data, 0));
+        E!(mdb_txn_commit(txn));
+
+        mdb_dbi_close(env, dbi);
+        mdb_env_close(env);
+    }
+}
--- a/third_party/rust/lmdb-rkv/.cargo-checksum.json
+++ b/third_party/rust/lmdb-rkv/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"aafdb8200f4d1db63ef096c47e1a43a156f4e1690133508e43e9e21b90b15f93","LICENSE":"db6d163be642e3b568c5fb2104013da632316ecd4e75935df1613af8b0b37933","README.md":"97b61d73ff27afb03bde9ae960f12651093558214851303c8ae82f567abfe992","src/cursor.rs":"f51184cbf015d1aef1a45f0cc1a950524114e1d4aadc50bde7bdb712030a839a","src/database.rs":"f0a750497ff32cf1fd4ea21ca0da9234630a6338bb5b4887f72f0abfc6316135","src/environment.rs":"b07df0fe38186e239980904f03db25ca0b1c14f2593dc1bfdefc418b0f26c192","src/error.rs":"0ea99c8bc1619f3789eff7734341efa7f48fcd8732dc9f3141804e0a802f5d71","src/flags.rs":"40fd3d4d72c8db8f9ecb893420300a3585e2ca4c49073065ec9ebf24fe23c064","src/lib.rs":"858e28ebbd9613e0b49b0e8a0ec48a837bc9b2401c0517b5ceabe66b2f0f2a85","src/transaction.rs":"23394768fa7b8603e1f9c3312ba10b8be9fbd74fc26b0300ab93424c3277a400"},"package":"e25b4069789bf7ac069d6fd58229f18aec20c6f7cc9173cb731d11c10dbb6b6e"}
\ No newline at end of file
+{"files":{"Cargo.toml":"6d06a849a674c6e18514d46e2f9cff156d7aaa7ae689a7a619432d5da46c537b","LICENSE":"db6d163be642e3b568c5fb2104013da632316ecd4e75935df1613af8b0b37933","README.md":"6d7b399235c2f09b4257c3b46369ab5dcd310b4fd2cb2cf6980eecbae6eceb2a","benches/cursor.rs":"3a3410940baf9cc9cfa552d23847ab39c71996477f38370803ed9edab3a45f03","benches/transaction.rs":"309cc7526d92274fc0748585200e1c4ff2e997514f8455f184360fe9dfb75035","benches/utils.rs":"e8c88b72cf7cc7a6ee331c03f630c6e52ec9f1a5462249ff5c25e53ddedc2f4f","src/cursor.rs":"fd7f1700c3e61bb1955e912d164fbe96cf7a7fc97918ef9f750af4f5c92b5469","src/database.rs":"9c52336a487e6141835607c04a4aa53fbe05b9329abb81a461d8f24dfd52f442","src/environment.rs":"6eadf5f1be000bdf7580c21f65ec966363f896fcce9ea004ff6722765eb1f060","src/error.rs":"19c97fee8b2a1bab25f047f34ec2c781062ad95b6dbac0830fdfd3c60e96307d","src/flags.rs":"40fd3d4d72c8db8f9ecb893420300a3585e2ca4c49073065ec9ebf24fe23c064","src/lib.rs":"e77abe7df39b44d2af2d796f027a3f03b6bc99582ae1f291f81e3b9c31d58ffe","src/transaction.rs":"dc81992311a0122bc1f138561b0431c36d8c1080cdf1c1dbf157a448ca3ba3ae"},"package":"605061e5465304475be2041f19967a900175ea1b6d8f47fbab84a84fb8c48452"}
\ No newline at end of file
--- a/third_party/rust/lmdb-rkv/Cargo.toml
+++ b/third_party/rust/lmdb-rkv/Cargo.toml
@@ -7,42 +7,49 @@
 #
 # 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.11.4"
-authors = ["Dan Burkert <dan@danburkert.com>"]
+version = "0.12.3"
+authors = ["Dan Burkert <dan@danburkert.com>", "Victor Porof <vporof@mozilla.com>"]
 exclude = ["/.appveyor.yml", "/.travis.yml", "/azure-pipelines-template.yml", "/azure-pipelines.yml"]
 description = "Idiomatic and safe LMDB wrapper."
+homepage = "https://github.com/mozilla/lmdb-rs"
 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.byteorder]
-version = "1.0"
+version = "1"
 
 [dependencies.libc]
 version = "0.2"
 
 [dependencies.lmdb-rkv-sys]
-version = "0.8.3"
+version = "0.9.3"
 [dev-dependencies.rand]
 version = "0.4"
 
 [dev-dependencies.tempdir]
 version = "0.3"
+
+[features]
+default = []
+with-asan = ["lmdb-rkv-sys/with-asan"]
+with-fuzzer = ["lmdb-rkv-sys/with-fuzzer"]
+with-fuzzer-no-link = ["lmdb-rkv-sys/with-fuzzer-no-link"]
 [badges.appveyor]
 repository = "mozilla/lmdb-rs"
 
 [badges.travis-ci]
 repository = "mozilla/lmdb-rs"
--- a/third_party/rust/lmdb-rkv/README.md
+++ b/third_party/rust/lmdb-rkv/README.md
@@ -12,15 +12,42 @@ with fixes for issues encountered by [mo
 ## Building from Source
 
 ```bash
 git clone --recursive git@github.com:mozilla/lmdb-rs.git
 cd lmdb-rs
 cargo build
 ```
 
+## Publishing to crates.io
+
+To publish the lmdb-rkv-sys crate to crates.io:
+
+```bash
+git clone --recursive git@github.com:mozilla/lmdb-rs.git
+cd lmdb-rs/lmdb-sys
+# Update the version string in lmdb-sys/Cargo.toml and lmdb-sys/src/lib.rs.
+cargo publish
+git tag lmdb-rkv-sys-$VERSION # where $VERSION is the updated version string
+git push git@github.com:mozilla/lmdb-rs.git --tags
+```
+
+To publish the lmdb-rkv crate to crates.io:
+
+```bash
+git clone --recursive git@github.com:mozilla/lmdb-rs.git
+cd lmdb-rs
+# Update the version string in Cargo.toml and src/lib.rs and temporarily change
+# the lmdb-rkv-sys dependency in Cargo.toml to the latest version on crates.io.
+cargo publish
+git tag $VERSION # where $VERSION is the updated version string
+git push git@github.com:mozilla/lmdb-rs.git --tags
+# Change the lmdb-rkv-sys dependency in Cargo.toml back to a path dependency
+# on the ./lmdb-sys directory.
+```
+
 ## 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/benches/cursor.rs
@@ -0,0 +1,118 @@
+#![feature(test)]
+
+extern crate lmdb;
+extern crate lmdb_sys as ffi;
+extern crate test;
+
+mod utils;
+
+use ffi::*;
+use lmdb::{
+    Cursor,
+    Result,
+    RoCursor,
+    Transaction,
+};
+use std::ptr;
+use test::{
+    black_box,
+    Bencher,
+};
+use utils::*;
+
+/// 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().map(Result::unwrap) {
+            i = i + key.len() + data.len();
+            count += 1;
+        }
+        for (key, data) in cursor.iter().filter_map(Result::ok) {
+            i = i + key.len() + data.len();
+            count += 1;
+        }
+
+        fn iterate(cursor: &mut RoCursor) -> Result<()> {
+            let mut i = 0;
+            for result in cursor.iter() {
+                let (key, data) = result?;
+                i = i + key.len() + data.len();
+            }
+            Ok(())
+        }
+        iterate(&mut cursor).unwrap();
+
+        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/benches/transaction.rs
@@ -0,0 +1,138 @@
+#![feature(test)]
+
+extern crate libc;
+extern crate lmdb;
+extern crate lmdb_sys as ffi;
+extern crate rand;
+extern crate test;
+
+mod utils;
+
+use ffi::*;
+use libc::size_t;
+use lmdb::{
+    Transaction,
+    WriteFlags,
+};
+use rand::{
+    Rng,
+    XorShiftRng,
+};
+use std::ptr;
+use test::{
+    black_box,
+    Bencher,
+};
+use utils::*;
+
+#[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(get_key).collect();
+    XorShiftRng::new_unseeded().shuffle(&mut keys[..]);
+
+    b.iter(|| {
+        let mut i = 0usize;
+        for key in &keys {
+            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(get_key).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 += 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-rkv/benches/utils.rs
@@ -0,0 +1,32 @@
+extern crate lmdb;
+extern crate tempdir;
+
+use self::tempdir::TempDir;
+use lmdb::{
+    Environment,
+    Transaction,
+    WriteFlags,
+};
+
+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(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)
+}
--- a/third_party/rust/lmdb-rkv/src/cursor.rs
+++ b/third_party/rust/lmdb-rkv/src/cursor.rs
@@ -1,37 +1,55 @@
 use std::marker::PhantomData;
-use std::{fmt, mem, ptr, result, slice};
+use std::{
+    fmt,
+    mem,
+    ptr,
+    result,
+    slice,
+};
 
-use libc::{EINVAL, c_void, size_t, c_uint};
+use libc::{
+    c_uint,
+    c_void,
+    size_t,
+    EINVAL,
+};
 
 use database::Database;
-use error::{Error, Result, lmdb_result};
+use error::{
+    lmdb_result,
+    Error,
+    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 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.
@@ -52,17 +70,20 @@ pub trait Cursor<'txn> {
         Iter::new(self.cursor(), ffi::MDB_FIRST, 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]> {
+    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) {
             Ok(_) | Err(Error::NotFound) => (),
             Err(error) => return Iter::Err(error),
         };
         Iter::new(self.cursor(), ffi::MDB_GET_CURRENT, ffi::MDB_NEXT)
     }
 
     /// Iterate over duplicate database items. The iterator will begin with the
@@ -75,143 +96,164 @@ pub trait Cursor<'txn> {
     /// 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> {
         IterDup::new(self.cursor(), ffi::MDB_FIRST)
     }
 
     /// 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]> {
+    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) {
             Ok(_) | Err(Error::NotFound) => (),
             Err(error) => return IterDup::Err(error),
         };
         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) -> Iter<'txn> where K: AsRef<[u8]> {
+    fn iter_dup_of<K>(&mut self, key: K) -> Iter<'txn>
+    where
+        K: AsRef<[u8]>,
+    {
         match self.get(Some(key.as_ref()), None, ffi::MDB_SET) {
             Ok(_) | Err(Error::NotFound) => (),
             Err(error) => return Iter::Err(error),
         };
         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> {
+impl<'txn> Cursor<'txn> for RoCursor<'txn> {
     fn cursor(&self) -> *mut ffi::MDB_cursor {
         self.cursor
     }
 }
 
-impl <'txn> fmt::Debug for RoCursor<'txn> {
+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> {
+impl<'txn> Drop for RoCursor<'txn> {
     fn drop(&mut self) {
         unsafe { ffi::mdb_cursor_close(self.cursor) }
     }
 }
 
-impl <'txn> RoCursor<'txn> {
-
+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 {
+    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))?; }
+        unsafe {
+            lmdb_result(ffi::mdb_cursor_open(txn.txn(), db.dbi(), &mut cursor))?;
+        }
         Ok(RoCursor {
-            cursor: 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> {
+impl<'txn> Cursor<'txn> for RwCursor<'txn> {
     fn cursor(&self) -> *mut ffi::MDB_cursor {
         self.cursor
     }
 }
 
-impl <'txn> fmt::Debug for RwCursor<'txn> {
+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> {
+impl<'txn> Drop for RwCursor<'txn> {
     fn drop(&mut self) {
         unsafe { ffi::mdb_cursor_close(self.cursor) }
     }
 }
 
-impl <'txn> RwCursor<'txn> {
-
+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 {
+    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 })
+        unsafe {
+            lmdb_result(ffi::mdb_cursor_open(txn.txn(), db.dbi(), &mut cursor))?;
+        }
+        Ok(RwCursor {
+            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]> {
+    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()))
-        }
+        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() },
+        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 key/value pairs in an LMDB database.
@@ -237,39 +279,53 @@ pub enum Iter<'txn> {
         /// The next and subsequent operations to perform.
         next_op: c_uint,
 
         /// A marker to ensure the iterator doesn't outlive the transaction.
         _marker: PhantomData<fn(&'txn ())>,
     },
 }
 
-impl <'txn> Iter<'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::Ok { cursor: cursor, op: op, next_op: next_op, _marker: PhantomData }
+        Iter::Ok {
+            cursor,
+            op,
+            next_op,
+            _marker: PhantomData,
+        }
     }
 }
 
-impl <'txn> fmt::Debug for Iter<'txn> {
+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> {
-
+impl<'txn> Iterator for Iter<'txn> {
     type Item = Result<(&'txn [u8], &'txn [u8])>;
 
     fn next(&mut self) -> Option<Result<(&'txn [u8], &'txn [u8])>> {
         match self {
-            &mut Iter::Ok { cursor, ref mut op, next_op, _marker } => {
-                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() };
+            &mut Iter::Ok {
+                cursor,
+                ref mut op,
+                next_op,
+                _marker,
+            } => {
+                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 op = mem::replace(op, next_op);
                 unsafe {
                     match ffi::mdb_cursor_get(cursor, &mut key, &mut data, op) {
                         ffi::MDB_SUCCESS => Some(Ok((val_to_slice(key), val_to_slice(data)))),
                         // EINVAL can occur when the cursor was previously seeked to a non-existent value,
                         // e.g. iter_from with a key greater than all values in the database.
                         ffi::MDB_NOTFOUND | EINVAL => None,
                         error => Some(Err(Error::from_err_code(error))),
@@ -304,97 +360,94 @@ pub enum IterDup<'txn> {
         /// The first operation to perform when the consumer calls Iter.next().
         op: c_uint,
 
         /// A marker to ensure the iterator doesn't outlive the transaction.
         _marker: PhantomData<fn(&'txn ())>,
     },
 }
 
-impl <'txn> IterDup<'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::Ok { cursor: cursor, op: op, _marker: PhantomData }
+        IterDup::Ok {
+            cursor,
+            op,
+            _marker: PhantomData,
+        }
     }
 }
 
-impl <'txn> fmt::Debug for IterDup<'txn> {
+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> {
-
+impl<'txn> Iterator for IterDup<'txn> {
     type Item = Iter<'txn>;
 
     fn next(&mut self) -> Option<Iter<'txn>> {
         match self {
-            &mut IterDup::Ok { cursor, ref mut op, _marker } => {
-                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() };
+            &mut IterDup::Ok {
+                cursor,
+                ref mut op,
+                _marker,
+            } => {
+                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 op = mem::replace(op, ffi::MDB_NEXT_NODUP);
-                let err_code = unsafe {
-                    ffi::mdb_cursor_get(cursor, &mut key, &mut data, op)
-                };
+                let err_code = unsafe { ffi::mdb_cursor_get(cursor, &mut key, &mut data, op) };
 
                 if err_code == ffi::MDB_SUCCESS {
                     Some(Iter::new(cursor, ffi::MDB_GET_CURRENT, ffi::MDB_NEXT_DUP))
                 } else {
                     None
                 }
             },
             &mut IterDup::Err(err) => Some(Iter::Err(err)),
         }
     }
 }
 
 #[cfg(test)]
 mod test {
-
-    use std::ptr;
-    use test::{Bencher, black_box};
-
     use tempdir::TempDir;
 
+    use super::*;
     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());
+        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();
 
@@ -402,45 +455,34 @@ mod test {
         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_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());
+        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();
 
@@ -448,33 +490,29 @@ mod test {
         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_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 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();
         }
@@ -487,29 +525,37 @@ mod test {
         // the collection type via the turbofish syntax.
         assert_eq!(items, cursor.iter().collect::<Result<Vec<_>>>().unwrap());
 
         // Alternately, we can collect it into an appropriately typed variable.
         let retr: Result<Vec<_>> = cursor.iter_start().collect();
         assert_eq!(items, retr.unwrap());
 
         cursor.get(Some(b"key2"), None, MDB_SET).unwrap();
-        assert_eq!(items.clone().into_iter().skip(2).collect::<Vec<_>>(),
-                   cursor.iter().collect::<Result<Vec<_>>>().unwrap());
+        assert_eq!(
+            items.clone().into_iter().skip(2).collect::<Vec<_>>(),
+            cursor.iter().collect::<Result<Vec<_>>>().unwrap()
+        );
 
         assert_eq!(items, cursor.iter_start().collect::<Result<Vec<_>>>().unwrap());
 
-        assert_eq!(items.clone().into_iter().skip(1).collect::<Vec<_>>(),
-                   cursor.iter_from(b"key2").collect::<Result<Vec<_>>>().unwrap());
+        assert_eq!(
+            items.clone().into_iter().skip(1).collect::<Vec<_>>(),
+            cursor.iter_from(b"key2").collect::<Result<Vec<_>>>().unwrap()
+        );
 
-        assert_eq!(items.clone().into_iter().skip(3).collect::<Vec<_>>(),
-                   cursor.iter_from(b"key4").collect::<Result<Vec<_>>>().unwrap());
+        assert_eq!(
+            items.clone().into_iter().skip(3).collect::<Vec<_>>(),
+            cursor.iter_from(b"key4").collect::<Result<Vec<_>>>().unwrap()
+        );
 
-        assert_eq!(vec!().into_iter().collect::<Vec<(&[u8], &[u8])>>(),
-                   cursor.iter_from(b"key6").collect::<Result<Vec<_>>>().unwrap());
+        assert_eq!(
+            vec!().into_iter().collect::<Vec<(&[u8], &[u8])>>(),
+            cursor.iter_from(b"key6").collect::<Result<Vec<_>>>().unwrap()
+        );
     }
 
     #[test]
     fn test_iter_empty_database() {
         let dir = TempDir::new("test").unwrap();
         let env = Environment::new().open(dir.path()).unwrap();
         let db = env.open_db(None).unwrap();
         let txn = env.begin_ro_txn().unwrap();
@@ -538,62 +584,75 @@ mod test {
     }
 
     #[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 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::<Result<Vec<_>>>().unwrap());
+        assert_eq!(items, cursor.iter_dup().flatten().collect::<Result<Vec<_>>>().unwrap());
 
         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::<Result<Vec<_>>>().unwrap());
+        assert_eq!(
+            items.clone().into_iter().skip(4).collect::<Vec<(&[u8], &[u8])>>(),
+            cursor.iter_dup().flatten().collect::<Result<Vec<_>>>().unwrap()
+        );
 
-        assert_eq!(items,
-                   cursor.iter_dup_start().flat_map(|x| x).collect::<Result<Vec<(&[u8], &[u8])>>>().unwrap());
+        assert_eq!(items, cursor.iter_dup_start().flatten().collect::<Result<Vec<(&[u8], &[u8])>>>().unwrap());
 
-        assert_eq!(items.clone().into_iter().skip(3).collect::<Vec<(&[u8], &[u8])>>(),
-                   cursor.iter_dup_from(b"b").flat_map(|x| x).collect::<Result<Vec<_>>>().unwrap());
+        assert_eq!(
+            items.clone().into_iter().skip(3).collect::<Vec<(&[u8], &[u8])>>(),
+            cursor.iter_dup_from(b"b").flatten().collect::<Result<Vec<_>>>().unwrap()
+        );
 
-        assert_eq!(items.clone().into_iter().skip(3).collect::<Vec<(&[u8], &[u8])>>(),
-                   cursor.iter_dup_from(b"ab").flat_map(|x| x).collect::<Result<Vec<_>>>().unwrap());
+        assert_eq!(
+            items.clone().into_iter().skip(3).collect::<Vec<(&[u8], &[u8])>>(),
+            cursor.iter_dup_from(b"ab").flatten().collect::<Result<Vec<_>>>().unwrap()
+        );
 
-        assert_eq!(items.clone().into_iter().skip(9).collect::<Vec<(&[u8], &[u8])>>(),
-                   cursor.iter_dup_from(b"d").flat_map(|x| x).collect::<Result<Vec<_>>>().unwrap());
+        assert_eq!(
+            items.clone().into_iter().skip(9).collect::<Vec<(&[u8], &[u8])>>(),
+            cursor.iter_dup_from(b"d").flatten().collect::<Result<Vec<_>>>().unwrap()
+        );
 
-        assert_eq!(vec!().into_iter().collect::<Vec<(&[u8], &[u8])>>(),
-                   cursor.iter_dup_from(b"f").flat_map(|x| x).collect::<Result<Vec<_>>>().unwrap());
+        assert_eq!(
+            vec!().into_iter().collect::<Vec<(&[u8], &[u8])>>(),
+            cursor.iter_dup_from(b"f").flatten().collect::<Result<Vec<_>>>().unwrap()
+        );
 
-        assert_eq!(items.clone().into_iter().skip(3).take(3).collect::<Vec<(&[u8], &[u8])>>(),
-                   cursor.iter_dup_of(b"b").collect::<Result<Vec<_>>>().unwrap());
+        assert_eq!(
+            items.clone().into_iter().skip(3).take(3).collect::<Vec<(&[u8], &[u8])>>(),
+            cursor.iter_dup_of(b"b").collect::<Result<Vec<_>>>().unwrap()
+        );
 
         assert_eq!(0, cursor.iter_dup_of(b"foo").count());
     }
 
     #[test]
     fn test_put_del() {
         let dir = TempDir::new("test").unwrap();
         let env = Environment::new().open(dir.path()).unwrap();
@@ -601,109 +660,14 @@ mod test {
 
         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());
+        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().map(Result::unwrap) {
-                i = i + key.len() + data.len();
-                count = count + 1;
-            }
-            for (key, data) in cursor.iter().filter_map(Result::ok) {
-                i = i + key.len() + data.len();
-                count = count + 1;
-            }
-
-            fn iterate<'a>(cursor: &mut RoCursor) -> Result<()> {
-                let mut i = 0;
-                let mut count = 0u32;
-                for result in cursor.iter() {
-                    let (key, data) = result?;
-                    i = i + key.len() + data.len();
-                    count = count + 1;
-                }
-                Ok(())
-            }
-            iterate(&mut cursor).unwrap();
-
-            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);
-        });
+        assert_eq!((Some(&b"key2"[..]), &b"val2"[..]), cursor.get(None, None, MDB_LAST).unwrap());
     }
 }
--- a/third_party/rust/lmdb-rkv/src/database.rs
+++ b/third_party/rust/lmdb-rkv/src/database.rs
@@ -1,50 +1,56 @@
 use libc::c_uint;
 use std::ffi::CString;
 use std::ptr;
 
 use ffi;
 
-use error::{Result, lmdb_result};
+use error::{
+    lmdb_result,
+    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> {
+    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 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 })
+        Ok(Database {
+            dbi,
+        })
     }
 
     pub(crate) fn freelist_db() -> Database {
         Database {
             dbi: 0,
         }
     }
 
     /// 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.
+    #[allow(clippy::trivially_copy_pass_by_ref)]
     pub fn dbi(&self) -> ffi::MDB_dbi {
         self.dbi
     }
 }
 
 unsafe impl Sync for Database {}
 unsafe impl Send for Database {}
--- a/third_party/rust/lmdb-rkv/src/environment.rs
+++ b/third_party/rust/lmdb-rkv/src/environment.rs
@@ -1,27 +1,49 @@
-use libc::{c_uint, size_t};
-use std::{fmt, ptr, result, mem};
+use libc::{
+    c_uint,
+    size_t,
+};
 use std::ffi::CString;
+#[cfg(windows)]
+use std::ffi::OsStr;
 #[cfg(unix)]
 use std::os::unix::ffi::OsStrExt;
-#[cfg(windows)]
-use std::ffi::OsStr;
 use std::path::Path;
 use std::sync::Mutex;
+use std::{
+    fmt,
+    mem,
+    ptr,
+    result,
+};
 
 use ffi;
 
-use byteorder::{ByteOrder, NativeEndian};
+use byteorder::{
+    ByteOrder,
+    NativeEndian,
+};
 
 use cursor::Cursor;
-use error::{Error, Result, lmdb_result};
 use database::Database;
-use transaction::{RoTransaction, RwTransaction, Transaction};
-use flags::{DatabaseFlags, EnvironmentFlags};
+use error::{
+    lmdb_result,
+    Error,
+    Result,
+};
+use flags::{
+    DatabaseFlags,
+    EnvironmentFlags,
+};
+use transaction::{
+    RoTransaction,
+    RwTransaction,
+    Transaction,
+};
 
 #[cfg(windows)]
 /// Adding a 'missing' trait from windows OsStrExt
 trait OsStrExtLmdb {
     fn as_bytes(&self) -> &[u8];
 }
 #[cfg(windows)]
 impl OsStrExtLmdb for OsStr {
@@ -34,24 +56,24 @@ impl OsStrExtLmdb for OsStr {
 ///
 /// 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.
+    #[allow(clippy::new_ret_no_self)]
     pub fn new() -> EnvironmentBuilder {
         EnvironmentBuilder {
             flags: EnvironmentFlags::empty(),
             max_readers: None,
             max_dbs: None,
-            map_size: 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 {
@@ -90,32 +112,29 @@ impl Environment {
     /// 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> {
+    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> {
+    pub fn get_db_flags(&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())
     }
 
@@ -132,17 +151,24 @@ impl Environment {
 
     /// 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 }))
+            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.
@@ -234,33 +260,29 @@ impl Environment {
     ///   a size smaller than the space already consumed by the environment will
     ///   be silently changed to the current size of the used space.
     ///
     /// * In the multi-process case, once a process resizes the map, other
     ///   processes need to either re-open the environment, or call set_map_size
     ///   with size 0 to update the environment. Otherwise, new transaction creation
     ///   will fail with `Error::MapResized`.
     pub fn set_map_size(&self, size: size_t) -> Result<()> {
-        unsafe {
-            lmdb_result(ffi::mdb_env_set_mapsize(self.env(), size))
-        }
+        unsafe { lmdb_result(ffi::mdb_env_set_mapsize(self.env(), size)) }
     }
 }
 
 /// Environment statistics.
 ///
 /// Contains information about the size and layout of an LMDB environment or database.
 pub struct Stat(ffi::MDB_stat);
 
 impl Stat {
     /// Create a new Stat with zero'd inner struct `ffi::MDB_stat`.
     pub(crate) fn new() -> Stat {
-        unsafe {
-            Stat(mem::zeroed())
-        }
+        unsafe { Stat(mem::zeroed()) }
     }
 
     /// Returns a mut pointer to `ffi::MDB_stat`.
     pub(crate) fn mdb_stat(&mut self) -> *mut ffi::MDB_stat {
         &mut self.0
     }
 }
 
@@ -363,17 +385,16 @@ impl Drop for Environment {
 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, Windows UNC (Uniform Naming Convention)
     /// paths are not supported either.
     pub fn open(&self, path: &Path) -> Result<Environment> {
         self.open_with_permissions(path, 0o644)
@@ -385,36 +406,37 @@ impl EnvironmentBuilder {
     ///
     /// The path may not contain the null character, Windows UNC (Uniform Naming Convention)
     /// paths are not supported either.
     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))
+                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))
+                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))
+                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));
+            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(()) })
-
+        Ok(Environment {
+            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
     }
 
@@ -434,18 +456,18 @@ impl EnvironmentBuilder {
     ///
     /// 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);
+    pub fn set_max_dbs(&mut self, max_dbs: c_uint) -> &mut EnvironmentBuilder {
+        self.max_dbs = Some(max_dbs);
         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
     /// 1048576 bytes. The size of the memory map is also the maximum size
     /// of the database. The value should be chosen as large as possible,
@@ -460,106 +482,100 @@ impl EnvironmentBuilder {
     }
 }
 
 #[cfg(test)]
 mod test {
 
     extern crate byteorder;
 
+    use self::byteorder::{
+        ByteOrder,
+        LittleEndian,
+    };
     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());
+        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());
+        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
+        {
+            // 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();
+        {
+            // 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();
+        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();
+        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 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); }
+        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();
+        }
+        {
+            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();
@@ -593,20 +609,17 @@ mod test {
         assert_eq!(stat.overflow_pages(), 0);
         assert_eq!(stat.entries(), 64);
     }
 
     #[test]
     fn test_info() {
         let map_size = 1024 * 1024;
         let dir = TempDir::new("test").unwrap();
-        let env = Environment::new()
-            .set_map_size(map_size)
-            .open(dir.path())
-            .unwrap();
+        let env = Environment::new().set_map_size(map_size).open(dir.path()).unwrap();
 
         let info = env.info().unwrap();
         assert_eq!(info.map_size(), map_size);
         assert_eq!(info.last_pgno(), 1);
         assert_eq!(info.last_txnid(), 0);
         // The default max readers is 126.
         assert_eq!(info.max_readers(), 126);
         assert_eq!(info.num_readers(), 0);
--- a/third_party/rust/lmdb-rkv/src/error.rs
+++ b/third_party/rust/lmdb-rkv/src/error.rs
@@ -1,13 +1,17 @@
 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 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,
@@ -49,67 +53,67 @@ pub enum Error {
     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_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),
+            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.
+    #[allow(clippy::trivially_copy_pass_by_ref)]
     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::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::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())
@@ -141,14 +145,12 @@ pub fn lmdb_result(err_code: c_int) -> R
 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());
+        assert_eq!("Permission denied", Error::from_err_code(13).description());
+        assert_eq!("MDB_NOTFOUND: No matching key/data pair found", Error::NotFound.description());
     }
 }
--- a/third_party/rust/lmdb-rkv/src/lib.rs
+++ b/third_party/rust/lmdb-rkv/src/lib.rs
@@ -1,106 +1,88 @@
 //! 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.11.4")]
+#![doc(html_root_url = "https://docs.rs/lmdb-rkv/0.12.3")]
 
+extern crate byteorder;
 extern crate libc;
-extern crate lmdb_rkv_sys as ffi;
-extern crate byteorder;
+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;
+#[cfg(test)]
+extern crate tempdir;
+#[macro_use]
+extern crate bitflags;
 
 pub use cursor::{
     Cursor,
+    Iter,
+    IterDup,
     RoCursor,
     RwCursor,
-    Iter,
-    IterDup,
 };
 pub use database::Database;
 pub use environment::{
     Environment,
     EnvironmentBuilder,
     Info,
     Stat,
 };
-pub use error::{Error, Result};
+pub use error::{
+    Error,
+    Result,
+};
 pub use flags::*;
 pub use transaction::{
     InactiveTransaction,
     RoTransaction,
     RwTransaction,
     Transaction,
 };
 
 macro_rules! lmdb_try {
-    ($expr:expr) => ({
+    ($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) => ({
+    ($expr:expr, $cleanup:expr) => {{
         match $expr {
             ::ffi::MDB_SUCCESS => (),
             err_code => {
                 let _ = $cleanup;
-                return Err(::Error::from_err_code(err_code))
+                return Err(::Error::from_err_code(err_code));
             },
         }
-    })
+    }};
 }
 
-mod flags;
 mod cursor;
 mod database;
 mod environment;
 mod error;
+mod flags;
 mod transaction;
 
 #[cfg(test)]
 mod test_utils {
 
-    use byteorder::{ByteOrder, LittleEndian};
+    use 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();
@@ -112,16 +94,13 @@ mod test_utils {
             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.put(index, &HEIGHT_KEY, &value, WriteFlags::empty()).expect("tx.put");
             tx.commit().expect("tx.commit")
         }
     }
 }
--- a/third_party/rust/lmdb-rkv/src/transaction.rs
+++ b/third_party/rust/lmdb-rkv/src/transaction.rs
@@ -1,25 +1,48 @@
-use libc::{c_uint, c_void, size_t};
-use std::{fmt, mem, ptr, result, slice};
-use std::marker::PhantomData ;
+use libc::{
+    c_uint,
+    c_void,
+    size_t,
+};
+use std::marker::PhantomData;
+use std::{
+    fmt,
+    mem,
+    ptr,
+    result,
+    slice,
+};
 
 use ffi;
 
-use cursor::{RoCursor, RwCursor};
-use environment::{Environment, Stat};
+use cursor::{
+    RoCursor,
+    RwCursor,
+};
 use database::Database;
-use error::{Error, Result, lmdb_result};
-use flags::{DatabaseFlags, EnvironmentFlags, WriteFlags};
+use environment::{
+    Environment,
+    Stat,
+};
+use error::{
+    lmdb_result,
+    Error,
+    Result,
+};
+use flags::{
+    DatabaseFlags,
+    EnvironmentFlags,
+    WriteFlags,
+};
 
 /// An LMDB transaction.
 ///
 /// All database operations require a transaction.
-pub trait Transaction : Sized {
-
+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.
     ///
@@ -63,32 +86,32 @@ pub trait Transaction : Sized {
     /// 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]> {
+    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() };
+        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))
-                },
+                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)
@@ -114,37 +137,39 @@ pub trait Transaction : Sized {
 }
 
 /// An LMDB read-only transaction.
 pub struct RoTransaction<'env> {
     txn: *mut ffi::MDB_txn,
     _marker: PhantomData<&'env ()>,
 }
 
-impl <'env> fmt::Debug for RoTransaction<'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> {
+impl<'env> Drop for RoTransaction<'env> {
     fn drop(&mut self) {
         unsafe { ffi::mdb_txn_abort(self.txn) }
     }
 }
 
-impl <'env> RoTransaction<'env> {
-
+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 })
+            Ok(RoTransaction {
+                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
@@ -156,91 +181,95 @@ impl <'env> RoTransaction<'env> {
     /// 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 }
+        InactiveTransaction {
+            txn,
+            _marker: PhantomData,
+        }
     }
 }
 
-impl <'env> Transaction for RoTransaction<'env> {
+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> {
+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> {
+impl<'env> Drop for InactiveTransaction<'env> {
     fn drop(&mut self) {
         unsafe { ffi::mdb_txn_abort(self.txn) }
     }
 }
 
-impl <'env> InactiveTransaction<'env> {
-
+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 })
+        Ok(RoTransaction {
+            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> {
+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> {
+impl<'env> Drop for RwTransaction<'env> {
     fn drop(&mut self) {
         unsafe { ffi::mdb_txn_abort(self.txn) }
     }
 }
 
-impl <'env> RwTransaction<'env> {
-
+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 })
+            lmdb_result(ffi::mdb_txn_begin(env.env(), ptr::null_mut(), EnvironmentFlags::empty().bits(), &mut txn))?;
+            Ok(RwTransaction {
+                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
@@ -266,102 +295,96 @@ impl <'env> RwTransaction<'env> {
     }
 
     /// 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]> {
+    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()))
-        }
+        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]> {
+    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>() };
+        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))
+            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]> {
+    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 });
+        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,
+        });
 
         if let Some(mut d) = data_val {
-            unsafe {
-                lmdb_result(ffi::mdb_del(self.txn(),
-                                         database.dbi(),
-                                         &mut key_val,
-                                         &mut d))
-
-            }
+            unsafe { lmdb_result(ffi::mdb_del(self.txn(), database.dbi(), &mut key_val, &mut d)) }
         } else {
-            unsafe {
-                lmdb_result(ffi::mdb_del(self.txn(),
-                                         database.dbi(),
-                                         &mut key_val,
-                                         ptr::null_mut()))
-            }
+            unsafe { lmdb_result(ffi::mdb_del(self.txn(), database.dbi(), &mut key_val, 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)) }
     }
 
@@ -377,46 +400,48 @@ impl <'env> RwTransaction<'env> {
 
     /// 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 })
+        Ok(RwTransaction {
+            txn: nested,
+            _marker: PhantomData,
+        })
     }
 }
 
-impl <'env> Transaction for RwTransaction<'env> {
+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 std::sync::{
+        Arc,
+        Barrier,
+    };
+    use std::thread::{
+        self,
+        JoinHandle,
+    };
 
     use tempdir::TempDir;
 
-    use environment::*;
+    use super::*;
+    use cursor::Cursor;
     use error::*;
-    use ffi::*;
     use flags::*;
-    use super::*;
-    use test_utils::*;
-    use cursor::Cursor;
 
     #[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();
@@ -452,41 +477,39 @@ mod test {
         txn.put(db, b"key3", b"val2", WriteFlags::empty()).unwrap();
         txn.put(db, b"key3", b"val3", WriteFlags::empty()).unwrap();
         txn.commit().unwrap();
 
         let txn = env.begin_rw_txn().unwrap();
         {
             let mut cur = txn.open_ro_cursor(db).unwrap();
             let iter = cur.iter_dup_of(b"key1");
-            let vals = iter.map(|x| x.unwrap()).map(|(_,x)| x).collect::<Vec<_>>();
+            let vals = iter.map(|x| x.unwrap()).map(|(_, x)| x).collect::<Vec<_>>();
             assert_eq!(vals, vec![b"val1", b"val2", b"val3"]);
-
         }
         txn.commit().unwrap();
 
         let mut txn = env.begin_rw_txn().unwrap();
         txn.del(db, b"key1", Some(b"val2")).unwrap();
         txn.del(db, b"key2", None).unwrap();
         txn.commit().unwrap();
 
         let txn = env.begin_rw_txn().unwrap();
         {
             let mut cur = txn.open_ro_cursor(db).unwrap();
             let iter = cur.iter_dup_of(b"key1");
-            let vals = iter.map(|x| x.unwrap()).map(|(_,x)| x).collect::<Vec<_>>();
+            let vals = iter.map(|x| x.unwrap()).map(|(_, x)| x).collect::<Vec<_>>();
             assert_eq!(vals, vec![b"val1", b"val3"]);
 
             let iter = cur.iter_dup_of(b"key2");
             assert_eq!(0, iter.count());
         }
         txn.commit().unwrap();
     }
 
-
     #[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();
         {
@@ -558,32 +581,32 @@ mod test {
             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 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(); }
+            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() {
@@ -596,17 +619,17 @@ mod test {
 
         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|| {
+            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();
@@ -636,35 +659,30 @@ mod test {
         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|| {
+            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.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());
+            assert_eq!(format!("{}{}", val, i).as_bytes(), txn.get(db, &format!("{}{}", key, i)).unwrap());
         }
     }
 
     #[test]
     fn test_stat() {
         let dir = TempDir::new("test").unwrap();
         let env = Environment::new().open(dir.path()).unwrap();
         let db = env.create_db(None, DatabaseFlags::empty()).unwrap();
@@ -747,110 +765,9 @@ mod test {
         txn.commit().unwrap();
 
         {
             let txn = env.begin_ro_txn().unwrap();
             let stat = txn.stat(db).unwrap();
             assert_eq!(stat.entries(), 8);
         }
     }
-
-    #[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/proc-macro2-0.4.27/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{"Cargo.toml":"b523856472549844b4bf20eca0473d955a7e5eeb95c70eddd31a05ac455427bb","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"89857eaaa305afe540abcf56fabae0194dfb4e7906a8098b7206acb23ed11ce8","build.rs":"36fa668f3bf309f243d0e977e8428446cc424303139c1f63410b3c2e30445aec","src/fallback.rs":"e4d1bcb1e92383a2285e6c947dd74b0e34144904948db68127faea627f5dd6ff","src/lib.rs":"896a1d212e30902ff051313808007406ca4471c27880a6ef19508f0ebb8333ee","src/strnom.rs":"60f5380106dbe568cca7abd09877e133c874fbee95d502e4830425c4613a640d","src/wrapper.rs":"0d7fe28ab2b7ee02b8eb8c5a636da364c60f6704b23e7db0a1ddd57c742f54b1","tests/marker.rs":"0227d07bbc7f2e2ad34662a6acb65668b7dc2f79141c4faa672703a04e27bea0","tests/test.rs":"166d35835355bdaa85bcf69de4dfb56ccddd8acf2e1a8cbc506782632b151674"},"package":"4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915"}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/proc-macro2-0.4.27/Cargo.toml
@@ -0,0 +1,39 @@
+# 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 = "proc-macro2"
+version = "0.4.27"
+authors = ["Alex Crichton <alex@alexcrichton.com>"]
+build = "build.rs"
+description = "A stable implementation of the upcoming new `proc_macro` API. Comes with an\noption, off by default, to also reimplement itself in terms of the upstream\nunstable API.\n"
+homepage = "https://github.com/alexcrichton/proc-macro2"
+documentation = "https://docs.rs/proc-macro2"
+readme = "README.md"
+keywords = ["macros"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/alexcrichton/proc-macro2"
+[package.metadata.docs.rs]
+rustc-args = ["--cfg", "procmacro2_semver_exempt"]
+rustdoc-args = ["--cfg", "procmacro2_semver_exempt"]
+[dependencies.unicode-xid]
+version = "0.1"
+[dev-dependencies.quote]
+version = "0.6"
+
+[features]
+default = ["proc-macro"]
+nightly = []
+proc-macro = []
+span-locations = []
+[badges.travis-ci]
+repository = "alexcrichton/proc-macro2"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/proc-macro2-0.4.27/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/proc-macro2-0.4.27/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2014 Alex Crichton
+
+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/proc-macro2-0.4.27/README.md
@@ -0,0 +1,100 @@
+# proc-macro2
+
+[![Build Status](https://api.travis-ci.com/alexcrichton/proc-macro2.svg?branch=master)](https://travis-ci.com/alexcrichton/proc-macro2)
+[![Latest Version](https://img.shields.io/crates/v/proc-macro2.svg)](https://crates.io/crates/proc-macro2)
+[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/proc-macro2)
+
+A wrapper around the procedural macro API of the compiler's `proc_macro` crate.
+This library serves three purposes:
+
+- **Bring proc-macro-like functionality to other contexts like build.rs and
+  main.rs.** Types from `proc_macro` are entirely specific to procedural macros
+  and cannot ever exist in code outside of a procedural macro. Meanwhile
+  `proc_macro2` types may exist anywhere including non-macro code. By developing
+  foundational libraries like [syn] and [quote] against `proc_macro2` rather
+  than `proc_macro`, the procedural macro ecosystem becomes easily applicable to
+  many other use cases and we avoid reimplementing non-macro equivalents of
+  those libraries.
+
+- **Make procedural macros unit testable.** As a consequence of being specific
+  to procedural macros, nothing that uses `proc_macro` can be executed from a
+  unit test. In order for helper libraries or components of a macro to be
+  testable in isolation, they must be implemented using `proc_macro2`.
+
+- **Provide the latest and greatest APIs across all compiler versions.**
+  Procedural macros were first introduced to Rust in 1.15.0 with an extremely
+  minimal interface. Since then, many improvements have landed to make macros
+  more flexible and easier to write. This library tracks the procedural macro
+  API of the most recent stable compiler but employs a polyfill to provide that
+  API consistently across any compiler since 1.15.0.
+
+[syn]: https://github.com/dtolnay/syn
+[quote]: https://github.com/dtolnay/quote
+
+## Usage
+
+```toml
+[dependencies]
+proc-macro2 = "0.4"
+```
+
+The skeleton of a typical procedural macro typically looks like this:
+
+```rust
+extern crate proc_macro;
+
+#[proc_macro_derive(MyDerive)]
+pub fn my_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+    let input = proc_macro2::TokenStream::from(input);
+
+    let output: proc_macro2::TokenStream = {
+        /* transform input */
+    };
+
+    proc_macro::TokenStream::from(output)
+}
+```
+
+If parsing with [Syn], you'll use [`parse_macro_input!`] instead to propagate
+parse errors correctly back to the compiler when parsing fails.
+
+[`parse_macro_input!`]: https://docs.rs/syn/0.15/syn/macro.parse_macro_input.html
+
+## Unstable features
+
+The default feature set of proc-macro2 tracks the most recent stable compiler
+API. Functionality in `proc_macro` that is not yet stable is not exposed by
+proc-macro2 by default.
+
+To opt into the additional APIs available in the most recent nightly compiler,
+the `procmacro2_semver_exempt` config flag must be passed to rustc. As usual, we
+will polyfill those nightly-only APIs all the way back to Rust 1.15.0. As these
+are unstable APIs that track the nightly compiler, minor versions of proc-macro2
+may make breaking changes to them at any time.
+
+```
+RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build
+```
+
+Note that this must not only be done for your crate, but for any crate that
+depends on your crate. This infectious nature is intentional, as it serves as a
+reminder that you are outside of the normal semver guarantees.
+
+Semver exempt methods are marked as such in the proc-macro2 documentation.
+
+# License
+
+This project is licensed under either of
+
+ * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
+   http://www.apache.org/licenses/LICENSE-2.0)
+ * MIT license ([LICENSE-MIT](LICENSE-MIT) or
+   http://opensource.org/licenses/MIT)
+
+at your option.
+
+### Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in Serde by you, as defined in the Apache-2.0 license, shall be
+dual licensed as above, without any additional terms or conditions.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/proc-macro2-0.4.27/build.rs
@@ -0,0 +1,133 @@
+// rustc-cfg emitted by the build script:
+//
+// "u128"
+//     Include u128 and i128 constructors for proc_macro2::Literal. Enabled on
+//     any compiler 1.26+.
+//
+// "use_proc_macro"
+//     Link to extern crate proc_macro. Available on any compiler and any target
+//     except wasm32. Requires "proc-macro" Cargo cfg to be enabled (default is
+//     enabled). On wasm32 we never link to proc_macro even if "proc-macro" cfg
+//     is enabled.
+//
+// "wrap_proc_macro"
+//     Wrap types from libproc_macro rather than polyfilling the whole API.
+//     Enabled on rustc 1.29+ as long as procmacro2_semver_exempt is not set,
+//     because we can't emulate the unstable API without emulating everything
+//     else. Also enabled unconditionally on nightly, in which case the
+//     procmacro2_semver_exempt surface area is implemented by using the
+//     nightly-only proc_macro API.
+//
+// "slow_extend"
+//     Fallback when `impl Extend for TokenStream` is not available. These impls
+//     were added one version later than the rest of the proc_macro token API.
+//     Enabled on rustc 1.29 only.
+//
+// "nightly"
+//     Enable the Span::unwrap method. This is to support proc_macro_span and
+//     proc_macro_diagnostic use on the nightly channel without requiring the
+//     semver exemption opt-in. Enabled when building with nightly.
+//
+// "super_unstable"
+//     Implement the semver exempt API in terms of the nightly-only proc_macro
+//     API. Enabled when using procmacro2_semver_exempt on a nightly compiler.
+//
+// "span_locations"
+//     Provide methods Span::start and Span::end which give the line/column
+//     location of a token. Enabled by procmacro2_semver_exempt or the
+//     "span-locations" Cargo cfg. This is behind a cfg because tracking
+//     location inside spans is a performance hit.
+
+use std::env;
+use std::process::Command;
+use std::str;
+
+fn main() {
+    println!("cargo:rerun-if-changed=build.rs");
+
+    let target = env::var("TARGET").unwrap();
+
+    let version = match rustc_version() {
+        Some(version) => version,
+        None => return,
+    };
+
+    if version.minor >= 26 {
+        println!("cargo:rustc-cfg=u128");
+    }
+
+    let semver_exempt = cfg!(procmacro2_semver_exempt);
+    if semver_exempt {
+        // https://github.com/alexcrichton/proc-macro2/issues/147
+        println!("cargo:rustc-cfg=procmacro2_semver_exempt");
+    }
+
+    if semver_exempt || cfg!(feature = "span-locations") {
+        println!("cargo:rustc-cfg=span_locations");
+    }
+
+    if !enable_use_proc_macro(&target) {
+        return;
+    }
+
+    println!("cargo:rustc-cfg=use_proc_macro");
+
+    // Rust 1.29 stabilized the necessary APIs in the `proc_macro` crate
+    if version.nightly || version.minor >= 29 && !semver_exempt {
+        println!("cargo:rustc-cfg=wrap_proc_macro");
+    }
+
+    if version.minor == 29 {
+        println!("cargo:rustc-cfg=slow_extend");
+    }
+
+    if version.nightly {
+        println!("cargo:rustc-cfg=nightly");
+    }
+
+    if semver_exempt && version.nightly {
+        println!("cargo:rustc-cfg=super_unstable");
+    }
+}
+
+fn enable_use_proc_macro(target: &str) -> bool {
+    // wasm targets don't have the `proc_macro` crate, disable this feature.
+    if target.contains("wasm32") {
+        return false;
+    }
+
+    // Otherwise, only enable it if our feature is actually enabled.
+    cfg!(feature = "proc-macro")
+}
+
+struct RustcVersion {
+    minor: u32,
+    nightly: bool,
+}
+
+fn rustc_version() -> Option<RustcVersion> {
+    macro_rules! otry {
+        ($e:expr) => {
+            match $e {
+                Some(e) => e,
+                None => return None,
+            }
+        };
+    }
+
+    let rustc = otry!(env::var_os("RUSTC"));
+    let output = otry!(Command::new(rustc).arg("--version").output().ok());
+    let version = otry!(str::from_utf8(&output.stdout).ok());
+    let nightly = version.contains("nightly");
+    let mut pieces = version.split('.');
+    if pieces.next() != Some("rustc 1") {
+        return None;
+    }
+    let minor = otry!(pieces.next());
+    let minor = otry!(minor.parse().ok());
+
+    Some(RustcVersion {
+        minor: minor,
+        nightly: nightly,
+    })
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/proc-macro2-0.4.27/src/fallback.rs
@@ -0,0 +1,1421 @@
+#[cfg(span_locations)]
+use std::cell::RefCell;
+#[cfg(procmacro2_semver_exempt)]
+use std::cmp;
+use std::fmt;
+use std::iter;
+#[cfg(procmacro2_semver_exempt)]
+use std::path::Path;
+use std::path::PathBuf;
+use std::str::FromStr;
+use std::vec;
+
+use strnom::{block_comment, skip_whitespace, whitespace, word_break, Cursor, PResult};
+use unicode_xid::UnicodeXID;
+
+use {Delimiter, Punct, Spacing, TokenTree};
+
+#[derive(Clone)]
+pub struct TokenStream {
+    inner: Vec<TokenTree>,
+}
+
+#[derive(Debug)]
+pub struct LexError;
+
+impl TokenStream {
+    pub fn new() -> TokenStream {
+        TokenStream { inner: Vec::new() }
+    }
+
+    pub fn is_empty(&self) -> bool {
+        self.inner.len() == 0
+    }
+}
+
+#[cfg(span_locations)]
+fn get_cursor(src: &str) -> Cursor {
+    // Create a dummy file & add it to the codemap
+    CODEMAP.with(|cm| {
+        let mut cm = cm.borrow_mut();
+        let name = format!("<parsed string {}>", cm.files.len());
+        let span = cm.add_file(&name, src);
+        Cursor {
+            rest: src,
+            off: span.lo,
+        }
+    })
+}
+
+#[cfg(not(span_locations))]
+fn get_cursor(src: &str) -> Cursor {
+    Cursor { rest: src }
+}
+
+impl FromStr for TokenStream {
+    type Err = LexError;
+
+    fn from_str(src: &str) -> Result<TokenStream, LexError> {
+        // Create a dummy file & add it to the codemap
+        let cursor = get_cursor(src);
+
+        match token_stream(cursor) {
+            Ok((input, output)) => {
+                if skip_whitespace(input).len() != 0 {
+                    Err(LexError)
+                } else {
+                    Ok(output)
+                }
+            }
+            Err(LexError) => Err(LexError),
+        }
+    }
+}
+
+impl fmt::Display for TokenStream {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let mut joint = false;
+        for (i, tt) in self.inner.iter().enumerate() {
+            if i != 0 && !joint {
+                write!(f, " ")?;
+            }
+            joint = false;
+            match *tt {
+                TokenTree::Group(ref tt) => {
+                    let (start, end) = match tt.delimiter() {
+                        Delimiter::Parenthesis => ("(", ")"),
+                        Delimiter::Brace => ("{", "}"),
+                        Delimiter::Bracket => ("[", "]"),
+                        Delimiter::None => ("", ""),
+                    };
+                    if tt.stream().into_iter().next().is_none() {
+                        write!(f, "{} {}", start, end)?
+                    } else {
+                        write!(f, "{} {} {}", start, tt.stream(), end)?
+                    }
+                }
+                TokenTree::Ident(ref tt) => write!(f, "{}", tt)?,
+                TokenTree::Punct(ref tt) => {
+                    write!(f, "{}", tt.as_char())?;
+                    match tt.spacing() {
+                        Spacing::Alone => {}
+                        Spacing::Joint => joint = true,
+                    }
+                }
+                TokenTree::Literal(ref tt) => write!(f, "{}", tt)?,
+            }
+        }
+
+        Ok(())
+    }
+}
+
+impl fmt::Debug for TokenStream {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.write_str("TokenStream ")?;
+        f.debug_list().entries(self.clone()).finish()
+    }
+}
+
+#[cfg(use_proc_macro)]
+impl From<::proc_macro::TokenStream> for TokenStream {
+    fn from(inner: ::proc_macro::TokenStream) -> TokenStream {
+        inner
+            .to_string()
+            .parse()
+            .expect("compiler token stream parse failed")
+    }
+}
+
+#[cfg(use_proc_macro)]
+impl From<TokenStream> for ::proc_macro::TokenStream {
+    fn from(inner: TokenStream) -> ::proc_macro::TokenStream {
+        inner
+            .to_string()
+            .parse()
+            .expect("failed to parse to compiler tokens")
+    }
+}
+
+impl From<TokenTree> for TokenStream {
+    fn from(tree: TokenTree) -> TokenStream {
+        TokenStream { inner: vec![tree] }
+    }
+}
+
+impl iter::FromIterator<TokenTree> for TokenStream {
+    fn from_iter<I: IntoIterator<Item = TokenTree>>(streams: I) -> Self {
+        let mut v = Vec::new();
+
+        for token in streams.into_iter() {
+            v.push(token);
+        }
+
+        TokenStream { inner: v }
+    }
+}
+
+impl iter::FromIterator<TokenStream> for TokenStream {
+    fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
+        let mut v = Vec::new();
+
+        for stream in streams.into_iter() {
+            v.extend(stream.inner);
+        }
+
+        TokenStream { inner: v }
+    }
+}
+
+impl Extend<TokenTree> for TokenStream {
+    fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, streams: I) {
+        self.inner.extend(streams);
+    }
+}
+
+impl Extend<TokenStream> for TokenStream {
+    fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
+        self.inner
+            .extend(streams.into_iter().flat_map(|stream| stream));
+    }
+}
+
+pub type TokenTreeIter = vec::IntoIter<TokenTree>;
+
+impl IntoIterator for TokenStream {
+    type Item = TokenTree;
+    type IntoIter = TokenTreeIter;
+
+    fn into_iter(self) -> TokenTreeIter {
+        self.inner.into_iter()
+    }
+}
+
+#[derive(Clone, PartialEq, Eq)]
+pub struct SourceFile {
+    path: PathBuf,
+}
+
+impl SourceFile {
+    /// Get the path to this source file as a string.
+    pub fn path(&self) -> PathBuf {
+        self.path.clone()
+    }
+
+    pub fn is_real(&self) -> bool {
+        // XXX(nika): Support real files in the future?
+        false
+    }
+}
+
+impl fmt::Debug for SourceFile {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("SourceFile")
+            .field("path", &self.path())
+            .field("is_real", &self.is_real())
+            .finish()
+    }
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub struct LineColumn {
+    pub line: usize,
+    pub column: usize,
+}
+
+#[cfg(span_locations)]
+thread_local! {
+    static CODEMAP: RefCell<Codemap> = RefCell::new(Codemap {
+        // NOTE: We start with a single dummy file which all call_site() and
+        // def_site() spans reference.
+        files: vec![{
+            #[cfg(procmacro2_semver_exempt)]
+            {
+                FileInfo {
+                    name: "<unspecified>".to_owned(),
+                    span: Span { lo: 0, hi: 0 },
+                    lines: vec![0],
+                }
+            }
+
+            #[cfg(not(procmacro2_semver_exempt))]
+            {
+                FileInfo {
+                    span: Span { lo: 0, hi: 0 },
+                    lines: vec![0],
+                }
+            }
+        }],
+    });
+}
+
+#[cfg(span_locations)]
+struct FileInfo {
+    #[cfg(procmacro2_semver_exempt)]
+    name: String,
+    span: Span,
+    lines: Vec<usize>,
+}
+
+#[cfg(span_locations)]
+impl FileInfo {
+    fn offset_line_column(&self, offset: usize) -> LineColumn {
+        assert!(self.span_within(Span {
+            lo: offset as u32,
+            hi: offset as u32
+        }));
+        let offset = offset - self.span.lo as usize;
+        match self.lines.binary_search(&offset) {
+            Ok(found) => LineColumn {
+                line: found + 1,
+                column: 0,
+            },
+            Err(idx) => LineColumn {
+                line: idx,
+                column: offset - self.lines[idx - 1],
+            },
+        }
+    }
+
+    fn span_within(&self, span: Span) -> bool {
+        span.lo >= self.span.lo && span.hi <= self.span.hi
+    }
+}
+
+/// Computesthe offsets of each line in the given source string.
+#[cfg(span_locations)]
+fn lines_offsets(s: &str) -> Vec<usize> {
+    let mut lines = vec![0];
+    let mut prev = 0;
+    while let Some(len) = s[prev..].find('\n') {
+        prev += len + 1;
+        lines.push(prev);
+    }
+    lines
+}
+
+#[cfg(span_locations)]
+struct Codemap {
+    files: Vec<FileInfo>,
+}
+
+#[cfg(span_locations)]
+impl Codemap {
+    fn next_start_pos(&self) -> u32 {
+        // Add 1 so there's always space between files.
+        //
+        // We'll always have at least 1 file, as we initialize our files list
+        // with a dummy file.
+        self.files.last().unwrap().span.hi + 1
+    }
+
+    fn add_file(&mut self, name: &str, src: &str) -> Span {
+        let lines = lines_offsets(src);
+        let lo = self.next_start_pos();
+        // XXX(nika): Shouild we bother doing a checked cast or checked add here?
+        let span = Span {
+            lo: lo,
+            hi: lo + (src.len() as u32),
+        };
+
+        #[cfg(procmacro2_semver_exempt)]
+        self.files.push(FileInfo {
+            name: name.to_owned(),
+            span: span,
+            lines: lines,
+        });
+
+        #[cfg(not(procmacro2_semver_exempt))]
+        self.files.push(FileInfo {
+            span: span,
+            lines: lines,
+        });
+        let _ = name;
+
+        span
+    }
+
+    fn fileinfo(&self, span: Span) -> &FileInfo {
+        for file in &self.files {
+            if file.span_within(span) {
+                return file;
+            }
+        }
+        panic!("Invalid span with no related FileInfo!");
+    }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub struct Span {
+    #[cfg(span_locations)]
+    lo: u32,
+    #[cfg(span_locations)]
+    hi: u32,
+}
+
+impl Span {
+    #[cfg(not(span_locations))]
+    pub fn call_site() -> Span {
+        Span {}
+    }
+
+    #[cfg(span_locations)]
+    pub fn call_site() -> Span {
+        Span { lo: 0, hi: 0 }
+    }
+
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn def_site() -> Span {
+        Span::call_site()
+    }
+
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn resolved_at(&self, _other: Span) -> Span {
+        // Stable spans consist only of line/column information, so
+        // `resolved_at` and `located_at` only select which span the
+        // caller wants line/column information from.
+        *self
+    }
+
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn located_at(&self, other: Span) -> Span {
+        other
+    }
+
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn source_file(&self) -> SourceFile {
+        CODEMAP.with(|cm| {
+            let cm = cm.borrow();
+            let fi = cm.fileinfo(*self);
+            SourceFile {
+                path: Path::new(&fi.name).to_owned(),
+            }
+        })
+    }
+
+    #[cfg(span_locations)]
+    pub fn start(&self) -> LineColumn {
+        CODEMAP.with(|cm| {
+            let cm = cm.borrow();
+            let fi = cm.fileinfo(*self);
+            fi.offset_line_column(self.lo as usize)
+        })
+    }
+
+    #[cfg(span_locations)]
+    pub fn end(&self) -> LineColumn {
+        CODEMAP.with(|cm| {
+            let cm = cm.borrow();
+            let fi = cm.fileinfo(*self);
+            fi.offset_line_column(self.hi as usize)
+        })
+    }
+
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn join(&self, other: Span) -> Option<Span> {
+        CODEMAP.with(|cm| {
+            let cm = cm.borrow();
+            // If `other` is not within the same FileInfo as us, return None.
+            if !cm.fileinfo(*self).span_within(other) {
+                return None;
+            }
+            Some(Span {
+                lo: cmp::min(self.lo, other.lo),
+                hi: cmp::max(self.hi, other.hi),
+            })
+        })
+    }
+}
+
+impl fmt::Debug for Span {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        #[cfg(procmacro2_semver_exempt)]
+        return write!(f, "bytes({}..{})", self.lo, self.hi);
+
+        #[cfg(not(procmacro2_semver_exempt))]
+        write!(f, "Span")
+    }
+}
+
+pub fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) {
+    if cfg!(procmacro2_semver_exempt) {
+        debug.field("span", &span);
+    }
+}
+
+#[derive(Clone)]
+pub struct Group {
+    delimiter: Delimiter,
+    stream: TokenStream,
+    span: Span,
+}
+
+impl Group {
+    pub fn new(delimiter: Delimiter, stream: TokenStream) -> Group {
+        Group {
+            delimiter: delimiter,
+            stream: stream,
+            span: Span::call_site(),
+        }
+    }
+
+    pub fn delimiter(&self) -> Delimiter {
+        self.delimiter
+    }
+
+    pub fn stream(&self) -> TokenStream {
+        self.stream.clone()
+    }
+
+    pub fn span(&self) -> Span {
+        self.span
+    }
+
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn span_open(&self) -> Span {
+        self.span
+    }
+
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn span_close(&self) -> Span {
+        self.span
+    }
+
+    pub fn set_span(&mut self, span: Span) {
+        self.span = span;
+    }
+}
+
+impl fmt::Display for Group {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let (left, right) = match self.delimiter {
+            Delimiter::Parenthesis => ("(", ")"),
+            Delimiter::Brace => ("{", "}"),
+            Delimiter::Bracket => ("[", "]"),
+            Delimiter::None => ("", ""),
+        };
+
+        f.write_str(left)?;
+        self.stream.fmt(f)?;
+        f.write_str(right)?;
+
+        Ok(())
+    }
+}
+
+impl fmt::Debug for Group {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        let mut debug = fmt.debug_struct("Group");
+        debug.field("delimiter", &self.delimiter);
+        debug.field("stream", &self.stream);
+        #[cfg(procmacro2_semver_exempt)]
+        debug.field("span", &self.span);
+        debug.finish()
+    }
+}
+
+#[derive(Clone)]
+pub struct Ident {
+    sym: String,
+    span: Span,
+    raw: bool,
+}
+
+impl Ident {
+    fn _new(string: &str, raw: bool, span: Span) -> Ident {
+        validate_term(string);
+
+        Ident {
+            sym: string.to_owned(),
+            span: span,
+            raw: raw,
+        }
+    }
+
+    pub fn new(string: &str, span: Span) -> Ident {
+        Ident::_new(string, false, span)
+    }
+
+    pub fn new_raw(string: &str, span: Span) -> Ident {
+        Ident::_new(string, true, span)
+    }
+
+    pub fn span(&self) -> Span {
+        self.span
+    }
+
+    pub fn set_span(&mut self, span: Span) {
+        self.span = span;
+    }
+}
+
+#[inline]
+fn is_ident_start(c: char) -> bool {
+    ('a' <= c && c <= 'z')
+        || ('A' <= c && c <= 'Z')
+        || c == '_'
+        || (c > '\x7f' && UnicodeXID::is_xid_start(c))
+}
+
+#[inline]
+fn is_ident_continue(c: char) -> bool {
+    ('a' <= c && c <= 'z')
+        || ('A' <= c && c <= 'Z')
+        || c == '_'
+        || ('0' <= c && c <= '9')
+        || (c > '\x7f' && UnicodeXID::is_xid_continue(c))
+}
+
+fn validate_term(string: &str) {
+    let validate = string;
+    if validate.is_empty() {
+        panic!("Ident is not allowed to be empty; use Option<Ident>");
+    }
+
+    if validate.bytes().all(|digit| digit >= b'0' && digit <= b'9') {
+        panic!("Ident cannot be a number; use Literal instead");
+    }
+
+    fn ident_ok(string: &str) -> bool {
+        let mut chars = string.chars();
+        let first = chars.next().unwrap();
+        if !is_ident_start(first) {
+            return false;
+        }
+        for ch in chars {
+            if !is_ident_continue(ch) {
+                return false;
+            }
+        }
+        true
+    }
+
+    if !ident_ok(validate) {
+        panic!("{:?} is not a valid Ident", string);
+    }
+}
+
+impl PartialEq for Ident {
+    fn eq(&self, other: &Ident) -> bool {
+        self.sym == other.sym && self.raw == other.raw
+    }
+}
+
+impl<T> PartialEq<T> for Ident
+where
+    T: ?Sized + AsRef<str>,
+{
+    fn eq(&self, other: &T) -> bool {
+        let other = other.as_ref();
+        if self.raw {
+            other.starts_with("r#") && self.sym == other[2..]
+        } else {
+            self.sym == other
+        }
+    }
+}
+
+impl fmt::Display for Ident {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        if self.raw {
+            "r#".fmt(f)?;
+        }
+        self.sym.fmt(f)
+    }
+}
+
+impl fmt::Debug for Ident {
+    // Ident(proc_macro), Ident(r#union)
+    #[cfg(not(procmacro2_semver_exempt))]
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let mut debug = f.debug_tuple("Ident");
+        debug.field(&format_args!("{}", self));
+        debug.finish()
+    }
+
+    // Ident {
+    //     sym: proc_macro,
+    //     span: bytes(128..138)
+    // }
+    #[cfg(procmacro2_semver_exempt)]
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let mut debug = f.debug_struct("Ident");
+        debug.field("sym", &format_args!("{}", self));
+        debug.field("span", &self.span);
+        debug.finish()
+    }
+}
+
+#[derive(Clone)]
+pub struct Literal {
+    text: String,
+    span: Span,
+}
+
+macro_rules! suffixed_numbers {
+    ($($name:ident => $kind:ident,)*) => ($(
+        pub fn $name(n: $kind) -> Literal {
+            Literal::_new(format!(concat!("{}", stringify!($kind)), n))
+        }
+    )*)
+}
+
+macro_rules! unsuffixed_numbers {
+    ($($name:ident => $kind:ident,)*) => ($(
+        pub fn $name(n: $kind) -> Literal {
+            Literal::_new(n.to_string())
+        }
+    )*)
+}
+
+impl Literal {
+    fn _new(text: String) -> Literal {
+        Literal {
+            text: text,
+            span: Span::call_site(),
+        }
+    }
+
+    suffixed_numbers! {
+        u8_suffixed => u8,
+        u16_suffixed => u16,
+        u32_suffixed => u32,
+        u64_suffixed => u64,
+        usize_suffixed => usize,
+        i8_suffixed => i8,
+        i16_suffixed => i16,
+        i32_suffixed => i32,
+        i64_suffixed => i64,
+        isize_suffixed => isize,
+
+        f32_suffixed => f32,
+        f64_suffixed => f64,
+    }
+
+    #[cfg(u128)]
+    suffixed_numbers! {
+        u128_suffixed => u128,
+        i128_suffixed => i128,
+    }
+
+    unsuffixed_numbers! {
+        u8_unsuffixed => u8,
+        u16_unsuffixed => u16,
+        u32_unsuffixed => u32,
+        u64_unsuffixed => u64,
+        usize_unsuffixed => usize,
+        i8_unsuffixed => i8,
+        i16_unsuffixed => i16,
+        i32_unsuffixed => i32,
+        i64_unsuffixed => i64,
+        isize_unsuffixed => isize,
+    }
+
+    #[cfg(u128)]
+    unsuffixed_numbers! {
+        u128_unsuffixed => u128,
+        i128_unsuffixed => i128,
+    }
+
+    pub fn f32_unsuffixed(f: f32) -> Literal {
+        let mut s = f.to_string();
+        if !s.contains(".") {
+            s.push_str(".0");
+        }
+        Literal::_new(s)
+    }
+
+    pub fn f64_unsuffixed(f: f64) -> Literal {
+        let mut s = f.to_string();
+        if !s.contains(".") {
+            s.push_str(".0");
+        }
+        Literal::_new(s)
+    }
+
+    pub fn string(t: &str) -> Literal {
+        let mut s = t
+            .chars()
+            .flat_map(|c| c.escape_default())
+            .collect::<String>();
+        s.push('"');
+        s.insert(0, '"');
+        Literal::_new(s)
+    }
+
+    pub fn character(t: char) -> Literal {
+        Literal::_new(format!("'{}'", t.escape_default().collect::<String>()))
+    }
+
+    pub fn byte_string(bytes: &[u8]) -> Literal {
+        let mut escaped = "b\"".to_string();
+        for b in bytes {
+            match *b {
+                b'\0' => escaped.push_str(r"\0"),
+                b'\t' => escaped.push_str(r"\t"),
+                b'\n' => escaped.push_str(r"\n"),
+                b'\r' => escaped.push_str(r"\r"),
+                b'"' => escaped.push_str("\\\""),
+                b'\\' => escaped.push_str("\\\\"),
+                b'\x20'...b'\x7E' => escaped.push(*b as char),
+                _ => escaped.push_str(&format!("\\x{:02X}", b)),
+            }
+        }
+        escaped.push('"');
+        Literal::_new(escaped)
+    }
+
+    pub fn span(&self) -> Span {
+        self.span
+    }
+
+    pub fn set_span(&mut self, span: Span) {
+        self.span = span;
+    }
+}
+
+impl fmt::Display for Literal {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.text.fmt(f)
+    }
+}
+
+impl fmt::Debug for Literal {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        let mut debug = fmt.debug_struct("Literal");
+        debug.field("lit", &format_args!("{}", self.text));
+        #[cfg(procmacro2_semver_exempt)]
+        debug.field("span", &self.span);
+        debug.finish()
+    }
+}
+
+fn token_stream(mut input: Cursor) -> PResult<TokenStream> {
+    let mut trees = Vec::new();
+    loop {
+        let input_no_ws = skip_whitespace(input);
+        if input_no_ws.rest.len() == 0 {
+            break;
+        }
+        if let Ok((a, tokens)) = doc_comment(input_no_ws) {
+            input = a;
+            trees.extend(tokens);
+            continue;
+        }
+
+        let (a, tt) = match token_tree(input_no_ws) {
+            Ok(p) => p,
+            Err(_) => break,
+        };
+        trees.push(tt);
+        input = a;
+    }
+    Ok((input, TokenStream { inner: trees }))
+}
+
+#[cfg(not(span_locations))]
+fn spanned<'a, T>(
+    input: Cursor<'a>,
+    f: fn(Cursor<'a>) -> PResult<'a, T>,
+) -> PResult<'a, (T, ::Span)> {
+    let (a, b) = f(skip_whitespace(input))?;
+    Ok((a, ((b, ::Span::_new_stable(Span::call_site())))))
+}
+
+#[cfg(span_locations)]
+fn spanned<'a, T>(
+    input: Cursor<'a>,
+    f: fn(Cursor<'a>) -> PResult<'a, T>,
+) -> PResult<'a, (T, ::Span)> {
+    let input = skip_whitespace(input);
+    let lo = input.off;
+    let (a, b) = f(input)?;
+    let hi = a.off;
+    let span = ::Span::_new_stable(Span { lo: lo, hi: hi });
+    Ok((a, (b, span)))
+}
+
+fn token_tree(input: Cursor) -> PResult<TokenTree> {
+    let (rest, (mut tt, span)) = spanned(input, token_kind)?;
+    tt.set_span(span);
+    Ok((rest, tt))
+}
+
+named!(token_kind -> TokenTree, alt!(
+    map!(group, |g| TokenTree::Group(::Group::_new_stable(g)))
+    |
+    map!(literal, |l| TokenTree::Literal(::Literal::_new_stable(l))) // must be before symbol
+    |
+    map!(op, TokenTree::Punct)
+    |
+    symbol_leading_ws
+));
+
+named!(group -> Group, alt!(
+    delimited!(
+        punct!("("),
+        token_stream,
+        punct!(")")
+    ) => { |ts| Group::new(Delimiter::Parenthesis, ts) }
+    |
+    delimited!(
+        punct!("["),
+        token_stream,
+        punct!("]")
+    ) => { |ts| Group::new(Delimiter::Bracket, ts) }
+    |
+    delimited!(
+        punct!("{"),
+        token_stream,
+        punct!("}")
+    ) => { |ts| Group::new(Delimiter::Brace, ts) }
+));
+
+fn symbol_leading_ws(input: Cursor) -> PResult<TokenTree> {
+    symbol(skip_whitespace(input))
+}
+
+fn symbol(input: Cursor) -> PResult<TokenTree> {
+    let mut chars = input.char_indices();
+
+    let raw = input.starts_with("r#");
+    if raw {
+        chars.next();
+        chars.next();
+    }
+
+    match chars.next() {
+        Some((_, ch)) if is_ident_start(ch) => {}
+        _ => return Err(LexError),
+    }
+
+    let mut end = input.len();
+    for (i, ch) in chars {
+        if !is_ident_continue(ch) {
+            end = i;
+            break;
+        }
+    }
+
+    let a = &input.rest[..end];
+    if a == "r#_" {
+        Err(LexError)
+    } else {
+        let ident = if raw {
+            ::Ident::_new_raw(&a[2..], ::Span::call_site())
+        } else {
+            ::Ident::new(a, ::Span::call_site())
+        };
+        Ok((input.advance(end), ident.into()))
+    }
+}
+
+fn literal(input: Cursor) -> PResult<Literal> {
+    let input_no_ws = skip_whitespace(input);
+
+    match literal_nocapture(input_no_ws) {
+        Ok((a, ())) => {
+            let start = input.len() - input_no_ws.len();
+            let len = input_no_ws.len() - a.len();
+            let end = start + len;
+            Ok((a, Literal::_new(input.rest[start..end].to_string())))
+        }
+        Err(LexError) => Err(LexError),
+    }
+}
+
+named!(literal_nocapture -> (), alt!(
+    string
+    |
+    byte_string
+    |
+    byte
+    |
+    character
+    |
+    float
+    |
+    int
+));
+
+named!(string -> (), alt!(
+    quoted_string
+    |
+    preceded!(
+        punct!("r"),
+        raw_string
+    ) => { |_| () }
+));
+
+named!(quoted_string -> (), delimited!(
+    punct!("\""),
+    cooked_string,
+    tag!("\"")
+));
+
+fn cooked_string(input: Cursor) -> PResult<()> {
+    let mut chars = input.char_indices().peekable();
+    while let Some((byte_offset, ch)) = chars.next() {
+        match ch {
+            '"' => {
+                return Ok((input.advance(byte_offset), ()));
+            }
+            '\r' => {
+                if let Some((_, '\n')) = chars.next() {
+                    // ...
+                } else {
+                    break;
+                }
+            }
+            '\\' => match chars.next() {
+                Some((_, 'x')) => {
+                    if !backslash_x_char(&mut chars) {
+                        break;
+                    }
+                }
+                Some((_, 'n')) | Some((_, 'r')) | Some((_, 't')) | Some((_, '\\'))
+                | Some((_, '\'')) | Some((_, '"')) | Some((_, '0')) => {}
+                Some((_, 'u')) => {
+                    if !backslash_u(&mut chars) {
+                        break;
+                    }
+                }
+                Some((_, '\n')) | Some((_, '\r')) => {
+                    while let Some(&(_, ch)) = chars.peek() {
+                        if ch.is_whitespace() {
+                            chars.next();
+                        } else {
+                            break;
+                        }
+                    }
+                }
+                _ => break,
+            },
+            _ch => {}
+        }
+    }
+    Err(LexError)
+}
+
+named!(byte_string -> (), alt!(
+    delimited!(
+        punct!("b\""),
+        cooked_byte_string,
+        tag!("\"")
+    ) => { |_| () }
+    |
+    preceded!(
+        punct!("br"),
+        raw_string
+    ) => { |_| () }
+));
+
+fn cooked_byte_string(mut input: Cursor) -> PResult<()> {
+    let mut bytes = input.bytes().enumerate();
+    'outer: while let Some((offset, b)) = bytes.next() {
+        match b {
+            b'"' => {
+                return Ok((input.advance(offset), ()));
+            }
+            b'\r' => {
+                if let Some((_, b'\n')) = bytes.next() {
+                    // ...
+                } else {
+                    break;
+                }
+            }
+            b'\\' => match bytes.next() {
+                Some((_, b'x')) => {
+                    if !backslash_x_byte(&mut bytes) {
+                        break;
+                    }
+                }
+                Some((_, b'n')) | Some((_, b'r')) | Some((_, b't')) | Some((_, b'\\'))
+                | Some((_, b'0')) | Some((_, b'\'')) | Some((_, b'"')) => {}
+                Some((newline, b'\n')) | Some((newline, b'\r')) => {
+                    let rest = input.advance(newline + 1);
+                    for (offset, ch) in rest.char_indices() {
+                        if !ch.is_whitespace() {
+                            input = rest.advance(offset);
+                            bytes = input.bytes().enumerate();
+                            continue 'outer;
+                        }
+                    }
+                    break;
+                }
+                _ => break,
+            },
+            b if b < 0x80 => {}
+            _ => break,
+        }
+    }
+    Err(LexError)
+}
+
+fn raw_string(input: Cursor) -> PResult<()> {
+    let mut chars = input.char_indices();
+    let mut n = 0;
+    while let Some((byte_offset, ch)) = chars.next() {
+        match ch {
+            '"' => {
+                n = byte_offset;
+                break;
+            }
+            '#' => {}
+            _ => return Err(LexError),
+        }
+    }
+    for (byte_offset, ch) in chars {
+        match ch {
+            '"' if input.advance(byte_offset + 1).starts_with(&input.rest[..n]) => {
+                let rest = input.advance(byte_offset + 1 + n);
+                return Ok((rest, ()));
+            }
+            '\r' => {}
+            _ => {}
+        }
+    }
+    Err(LexError)
+}
+
+named!(byte -> (), do_parse!(
+    punct!("b") >>
+    tag!("'") >>
+    cooked_byte >>
+    tag!("'") >>
+    (())
+));
+
+fn cooked_byte(input: Cursor) -> PResult<()> {
+    let mut bytes = input.bytes().enumerate();
+    let ok = match bytes.next().map(|(_, b)| b) {
+        Some(b'\\') => match bytes.next().map(|(_, b)| b) {
+            Some(b'x') => backslash_x_byte(&mut bytes),
+            Some(b'n') | Some(b'r') | Some(b't') | Some(b'\\') | Some(b'0') | Some(b'\'')
+            | Some(b'"') => true,
+            _ => false,
+        },
+        b => b.is_some(),
+    };
+    if ok {
+        match bytes.next() {
+            Some((offset, _)) => {
+                if input.chars().as_str().is_char_boundary(offset) {
+                    Ok((input.advance(offset), ()))
+                } else {
+                    Err(LexError)
+                }
+            }
+            None => Ok((input.advance(input.len()), ())),
+        }
+    } else {
+        Err(LexError)
+    }
+}
+
+named!(character -> (), do_parse!(
+    punct!("'") >>
+    cooked_char >>
+    tag!("'") >>
+    (())
+));
+
+fn cooked_char(input: Cursor) -> PResult<()> {
+    let mut chars = input.char_indices();
+    let ok = match chars.next().map(|(_, ch)| ch) {
+        Some('\\') => match chars.next().map(|(_, ch)| ch) {
+            Some('x') => backslash_x_char(&mut chars),
+            Some('u') => backslash_u(&mut chars),
+            Some('n') | Some('r') | Some('t') | Some('\\') | Some('0') | Some('\'') | Some('"') => {
+                true
+            }
+            _ => false,
+        },
+        ch => ch.is_some(),
+    };
+    if ok {
+        match chars.next() {
+            Some((idx, _)) => Ok((input.advance(idx), ())),
+            None => Ok((input.advance(input.len()), ())),
+        }
+    } else {
+        Err(LexError)
+    }
+}
+
+macro_rules! next_ch {
+    ($chars:ident @ $pat:pat $(| $rest:pat)*) => {
+        match $chars.next() {
+            Some((_, ch)) => match ch {
+                $pat $(| $rest)*  => ch,
+                _ => return false,
+            },
+            None => return false
+        }
+    };
+}
+
+fn backslash_x_char<I>(chars: &mut I) -> bool
+where
+    I: Iterator<Item = (usize, char)>,
+{
+    next_ch!(chars @ '0'...'7');
+    next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F');
+    true
+}
+
+fn backslash_x_byte<I>(chars: &mut I) -> bool
+where
+    I: Iterator<Item = (usize, u8)>,
+{
+    next_ch!(chars @ b'0'...b'9' | b'a'...b'f' | b'A'...b'F');
+    next_ch!(chars @ b'0'...b'9' | b'a'...b'f' | b'A'...b'F');
+    true
+}
+
+fn backslash_u<I>(chars: &mut I) -> bool
+where
+    I: Iterator<Item = (usize, char)>,
+{
+    next_ch!(chars @ '{');
+    next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F');
+    loop {
+        let c = next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F' | '_' | '}');
+        if c == '}' {
+            return true;
+        }
+    }
+}
+
+fn float(input: Cursor) -> PResult<()> {
+    let (rest, ()) = float_digits(input)?;
+    for suffix in &["f32", "f64"] {
+        if rest.starts_with(suffix) {
+            return word_break(rest.advance(suffix.len()));
+        }
+    }
+    word_break(rest)
+}
+
+fn float_digits(input: Cursor) -> PResult<()> {
+    let mut chars = input.chars().peekable();
+    match chars.next() {
+        Some(ch) if ch >= '0' && ch <= '9' => {}
+        _ => return Err(LexError),
+    }
+
+    let mut len = 1;
+    let mut has_dot = false;
+    let mut has_exp = false;
+    while let Some(&ch) = chars.peek() {
+        match ch {
+            '0'...'9' | '_' => {
+                chars.next();
+                len += 1;
+            }
+            '.' => {
+                if has_dot {
+                    break;
+                }
+                chars.next();
+                if chars
+                    .peek()
+                    .map(|&ch| ch == '.' || UnicodeXID::is_xid_start(ch))
+                    .unwrap_or(false)
+                {
+                    return Err(LexError);
+                }
+                len += 1;
+                has_dot = true;
+            }
+            'e' | 'E' => {
+                chars.next();
+                len += 1;
+                has_exp = true;
+                break;
+            }
+            _ => break,
+        }
+    }
+
+    let rest = input.advance(len);
+    if !(has_dot || has_exp || rest.starts_with("f32") || rest.starts_with("f64")) {
+        return Err(LexError);
+    }
+
+    if has_exp {
+        let mut has_exp_value = false;
+        while let Some(&ch) = chars.peek() {
+            match ch {
+                '+' | '-' => {
+                    if has_exp_value {
+                        break;
+                    }
+                    chars.next();
+                    len += 1;
+                }
+                '0'...'9' => {
+                    chars.next();
+                    len += 1;
+                    has_exp_value = true;
+                }
+                '_' => {
+                    chars.next();
+                    len += 1;
+                }
+                _ => break,
+            }
+        }
+        if !has_exp_value {
+            return Err(LexError);
+        }
+    }
+
+    Ok((input.advance(len), ()))
+}
+
+fn int(input: Cursor) -> PResult<()> {
+    let (rest, ()) = digits(input)?;
+    for suffix in &[
+        "isize", "i8", "i16", "i32", "i64", "i128", "usize", "u8", "u16", "u32", "u64", "u128",
+    ] {
+        if rest.starts_with(suffix) {
+            return word_break(rest.advance(suffix.len()));
+        }
+    }
+    word_break(rest)
+}
+
+fn digits(mut input: Cursor) -> PResult<()> {
+    let base = if input.starts_with("0x") {
+        input = input.advance(2);
+        16
+    } else if input.starts_with("0o") {
+        input = input.advance(2);
+        8
+    } else if input.starts_with("0b") {
+        input = input.advance(2);
+        2
+    } else {
+        10
+    };
+
+    let mut len = 0;
+    let mut empty = true;
+    for b in input.bytes() {
+        let digit = match b {
+            b'0'...b'9' => (b - b'0') as u64,
+            b'a'...b'f' => 10 + (b - b'a') as u64,
+            b'A'...b'F' => 10 + (b - b'A') as u64,
+            b'_' => {
+                if empty && base == 10 {
+                    return Err(LexError);
+                }
+                len += 1;
+                continue;
+            }
+            _ => break,
+        };
+        if digit >= base {
+            return Err(LexError);
+        }
+        len += 1;
+        empty = false;
+    }
+    if empty {
+        Err(LexError)
+    } else {
+        Ok((input.advance(len), ()))
+    }
+}
+
+fn op(input: Cursor) -> PResult<Punct> {
+    let input = skip_whitespace(input);
+    match op_char(input) {
+        Ok((rest, '\'')) => {
+            symbol(rest)?;
+            Ok((rest, Punct::new('\'', Spacing::Joint)))
+        }
+        Ok((rest, ch)) => {
+            let kind = match op_char(rest) {
+                Ok(_) => Spacing::Joint,
+                Err(LexError) => Spacing::Alone,
+            };
+            Ok((rest, Punct::new(ch, kind)))
+        }
+        Err(LexError) => Err(LexError),
+    }
+}
+
+fn op_char(input: Cursor) -> PResult<char> {
+    if input.starts_with("//") || input.starts_with("/*") {
+        // Do not accept `/` of a comment as an op.
+        return Err(LexError);
+    }
+
+    let mut chars = input.chars();
+    let first = match chars.next() {
+        Some(ch) => ch,
+        None => {
+            return Err(LexError);
+        }
+    };
+    let recognized = "~!@#$%^&*-=+|;:,<.>/?'";
+    if recognized.contains(first) {
+        Ok((input.advance(first.len_utf8()), first))
+    } else {
+        Err(LexError)
+    }
+}
+
+fn doc_comment(input: Cursor) -> PResult<Vec<TokenTree>> {
+    let mut trees = Vec::new();
+    let (rest, ((comment, inner), span)) = spanned(input, doc_comment_contents)?;
+    trees.push(TokenTree::Punct(Punct::new('#', Spacing::Alone)));
+    if inner {
+        trees.push(Punct::new('!', Spacing::Alone).into());
+    }
+    let mut stream = vec![
+        TokenTree::Ident(::Ident::new("doc", span)),
+        TokenTree::Punct(Punct::new('=', Spacing::Alone)),
+        TokenTree::Literal(::Literal::string(comment)),
+    ];
+    for tt in stream.iter_mut() {
+        tt.set_span(span);
+    }
+    let group = Group::new(Delimiter::Bracket, stream.into_iter().collect());
+    trees.push(::Group::_new_stable(group).into());
+    for tt in trees.iter_mut() {
+        tt.set_span(span);
+    }
+    Ok((rest, trees))
+}
+
+named!(doc_comment_contents -> (&str, bool), alt!(
+    do_parse!(
+        punct!("//!") >>
+        s: take_until_newline_or_eof!() >>
+        ((s, true))
+    )
+    |
+    do_parse!(
+        option!(whitespace) >>
+        peek!(tag!("/*!")) >>
+        s: block_comment >>
+        ((s, true))
+    )
+    |
+    do_parse!(
+        punct!("///") >>
+        not!(tag!("/")) >>
+        s: take_until_newline_or_eof!() >>
+        ((s, false))
+    )
+    |
+    do_parse!(
+        option!(whitespace) >>
+        peek!(tuple!(tag!("/**"), not!(tag!("*")))) >>
+        s: block_comment >>
+        ((s, false))
+    )
+));
new file mode 100644
--- /dev/null
+++ b/third_party/rust/proc-macro2-0.4.27/src/lib.rs
@@ -0,0 +1,1149 @@
+//! A wrapper around the procedural macro API of the compiler's [`proc_macro`]
+//! crate. This library serves three purposes:
+//!
+//! [`proc_macro`]: https://doc.rust-lang.org/proc_macro/
+//!
+//! - **Bring proc-macro-like functionality to other contexts like build.rs and
+//!   main.rs.** Types from `proc_macro` are entirely specific to procedural
+//!   macros and cannot ever exist in code outside of a procedural macro.
+//!   Meanwhile `proc_macro2` types may exist anywhere including non-macro code.
+//!   By developing foundational libraries like [syn] and [quote] against
+//!   `proc_macro2` rather than `proc_macro`, the procedural macro ecosystem
+//!   becomes easily applicable to many other use cases and we avoid
+//!   reimplementing non-macro equivalents of those libraries.
+//!
+//! - **Make procedural macros unit testable.** As a consequence of being
+//!   specific to procedural macros, nothing that uses `proc_macro` can be
+//!   executed from a unit test. In order for helper libraries or components of
+//!   a macro to be testable in isolation, they must be implemented using
+//!   `proc_macro2`.
+//!
+//! - **Provide the latest and greatest APIs across all compiler versions.**
+//!   Procedural macros were first introduced to Rust in 1.15.0 with an
+//!   extremely minimal interface. Since then, many improvements have landed to
+//!   make macros more flexible and easier to write. This library tracks the
+//!   procedural macro API of the most recent stable compiler but employs a
+//!   polyfill to provide that API consistently across any compiler since
+//!   1.15.0.
+//!
+//! [syn]: https://github.com/dtolnay/syn
+//! [quote]: https://github.com/dtolnay/quote
+//!
+//! # Usage
+//!
+//! The skeleton of a typical procedural macro typically looks like this:
+//!
+//! ```edition2018
+//! extern crate proc_macro;
+//!
+//! # const IGNORE: &str = stringify! {
+//! #[proc_macro_derive(MyDerive)]
+//! # };
+//! pub fn my_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+//!     let input = proc_macro2::TokenStream::from(input);
+//!
+//!     let output: proc_macro2::TokenStream = {
+//!         /* transform input */
+//!         # input
+//!     };
+//!
+//!     proc_macro::TokenStream::from(output)
+//! }
+//! ```
+//!
+//! If parsing with [Syn], you'll use [`parse_macro_input!`] instead to
+//! propagate parse errors correctly back to the compiler when parsing fails.
+//!
+//! [`parse_macro_input!`]: https://docs.rs/syn/0.15/syn/macro.parse_macro_input.html
+//!
+//! # Unstable features
+//!
+//! The default feature set of proc-macro2 tracks the most recent stable
+//! compiler API. Functionality in `proc_macro` that is not yet stable is not
+//! exposed by proc-macro2 by default.
+//!
+//! To opt into the additional APIs available in the most recent nightly
+//! compiler, the `procmacro2_semver_exempt` config flag must be passed to
+//! rustc. As usual, we will polyfill those nightly-only APIs all the way back
+//! to Rust 1.15.0. As these are unstable APIs that track the nightly compiler,
+//! minor versions of proc-macro2 may make breaking changes to them at any time.
+//!
+//! ```sh
+//! RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build
+//! ```
+//!
+//! Note that this must not only be done for your crate, but for any crate that
+//! depends on your crate. This infectious nature is intentional, as it serves
+//! as a reminder that you are outside of the normal semver guarantees.
+//!
+//! Semver exempt methods are marked as such in the proc-macro2 documentation.
+
+// Proc-macro2 types in rustdoc of other crates get linked to here.
+#![doc(html_root_url = "https://docs.rs/proc-macro2/0.4.27")]
+#![cfg_attr(nightly, feature(proc_macro_span))]
+#![cfg_attr(super_unstable, feature(proc_macro_raw_ident, proc_macro_def_site))]
+
+#[cfg(use_proc_macro)]
+extern crate proc_macro;
+extern crate unicode_xid;
+
+use std::cmp::Ordering;
+use std::fmt;
+use std::hash::{Hash, Hasher};
+use std::iter::FromIterator;
+use std::marker;
+#[cfg(procmacro2_semver_exempt)]
+use std::path::PathBuf;
+use std::rc::Rc;
+use std::str::FromStr;
+
+#[macro_use]
+mod strnom;
+mod fallback;
+
+#[cfg(not(wrap_proc_macro))]
+use fallback as imp;
+#[path = "wrapper.rs"]
+#[cfg(wrap_proc_macro)]
+mod imp;
+
+/// An abstract stream of tokens, or more concretely a sequence of token trees.
+///
+/// This type provides interfaces for iterating over token trees and for
+/// collecting token trees into one stream.
+///
+/// Token stream is both the input and output of `#[proc_macro]`,
+/// `#[proc_macro_attribute]` and `#[proc_macro_derive]` definitions.
+#[derive(Clone)]
+pub struct TokenStream {
+    inner: imp::TokenStream,
+    _marker: marker::PhantomData<Rc<()>>,
+}
+
+/// Error returned from `TokenStream::from_str`.
+pub struct LexError {
+    inner: imp::LexError,
+    _marker: marker::PhantomData<Rc<()>>,
+}
+
+impl TokenStream {
+    fn _new(inner: imp::TokenStream) -> TokenStream {
+        TokenStream {
+            inner: inner,
+            _marker: marker::PhantomData,
+        }
+    }
+
+    fn _new_stable(inner: fallback::TokenStream) -> TokenStream {
+        TokenStream {
+            inner: inner.into(),
+            _marker: marker::PhantomData,
+        }
+    }
+
+    /// Returns an empty `TokenStream` containing no token trees.
+    pub fn new() -> TokenStream {
+        TokenStream::_new(imp::TokenStream::new())
+    }
+
+    #[deprecated(since = "0.4.4", note = "please use TokenStream::new")]
+    pub fn empty() -> TokenStream {
+        TokenStream::new()
+    }
+
+    /// Checks if this `TokenStream` is empty.
+    pub fn is_empty(&self) -> bool {
+        self.inner.is_empty()
+    }
+}
+
+/// `TokenStream::default()` returns an empty stream,
+/// i.e. this is equivalent with `TokenStream::new()`.
+impl Default for TokenStream {
+    fn default() -> Self {
+        TokenStream::new()
+    }
+}
+
+/// Attempts to break the string into tokens and parse those tokens into a token
+/// stream.
+///
+/// May fail for a number of reasons, for example, if the string contains
+/// unbalanced delimiters or characters not existing in the language.
+///
+/// NOTE: Some errors may cause panics instead of returning `LexError`. We
+/// reserve the right to change these errors into `LexError`s later.
+impl FromStr for TokenStream {
+    type Err = LexError;
+
+    fn from_str(src: &str) -> Result<TokenStream, LexError> {
+        let e = src.parse().map_err(|e| LexError {
+            inner: e,
+            _marker: marker::PhantomData,
+        })?;
+        Ok(TokenStream::_new(e))
+    }
+}
+
+#[cfg(use_proc_macro)]
+impl From<proc_macro::TokenStream> for TokenStream {
+    fn from(inner: proc_macro::TokenStream) -> TokenStream {
+        TokenStream::_new(inner.into())
+    }
+}
+
+#[cfg(use_proc_macro)]
+impl From<TokenStream> for proc_macro::TokenStream {
+    fn from(inner: TokenStream) -> proc_macro::TokenStream {
+        inner.inner.into()
+    }
+}
+
+impl Extend<TokenTree> for TokenStream {
+    fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, streams: I) {
+        self.inner.extend(streams)
+    }
+}
+
+impl Extend<TokenStream> for TokenStream {
+    fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
+        self.inner
+            .extend(streams.into_iter().map(|stream| stream.inner))
+    }
+}
+
+/// Collects a number of token trees into a single stream.
+impl FromIterator<TokenTree> for TokenStream {
+    fn from_iter<I: IntoIterator<Item = TokenTree>>(streams: I) -> Self {
+        TokenStream::_new(streams.into_iter().collect())
+    }
+}
+impl FromIterator<TokenStream> for TokenStream {
+    fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
+        TokenStream::_new(streams.into_iter().map(|i| i.inner).collect())
+    }
+}
+
+/// Prints the token stream as a string that is supposed to be losslessly
+/// convertible back into the same token stream (modulo spans), except for
+/// possibly `TokenTree::Group`s with `Delimiter::None` delimiters and negative
+/// numeric literals.
+impl fmt::Display for TokenStream {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.inner.fmt(f)
+    }
+}
+
+/// Prints token in a form convenient for debugging.
+impl fmt::Debug for TokenStream {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.inner.fmt(f)
+    }
+}
+
+impl fmt::Debug for LexError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.inner.fmt(f)
+    }
+}
+
+/// The source file of a given `Span`.
+///
+/// This type is semver exempt and not exposed by default.
+#[cfg(procmacro2_semver_exempt)]
+#[derive(Clone, PartialEq, Eq)]
+pub struct SourceFile {
+    inner: imp::SourceFile,
+    _marker: marker::PhantomData<Rc<()>>,
+}
+
+#[cfg(procmacro2_semver_exempt)]
+impl SourceFile {
+    fn _new(inner: imp::SourceFile) -> Self {
+        SourceFile {
+            inner: inner,
+            _marker: marker::PhantomData,
+        }
+    }
+
+    /// Get the path to this source file.
+    ///
+    /// ### Note
+    ///
+    /// If the code span associated with this `SourceFile` was generated by an
+    /// external macro, this may not be an actual path on the filesystem. Use
+    /// [`is_real`] to check.
+    ///
+    /// Also note that even if `is_real` returns `true`, if
+    /// `--remap-path-prefix` was passed on the command line, the path as given
+    /// may not actually be valid.
+    ///
+    /// [`is_real`]: #method.is_real
+    pub fn path(&self) -> PathBuf {
+        self.inner.path()
+    }
+
+    /// Returns `true` if this source file is a real source file, and not
+    /// generated by an external macro's expansion.
+    pub fn is_real(&self) -> bool {
+        self.inner.is_real()
+    }
+}
+
+#[cfg(procmacro2_semver_exempt)]
+impl fmt::Debug for SourceFile {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.inner.fmt(f)
+    }
+}
+
+/// A line-column pair representing the start or end of a `Span`.
+///
+/// This type is semver exempt and not exposed by default.
+#[cfg(span_locations)]
+pub struct LineColumn {
+    /// The 1-indexed line in the source file on which the span starts or ends
+    /// (inclusive).
+    pub line: usize,
+    /// The 0-indexed column (in UTF-8 characters) in the source file on which
+    /// the span starts or ends (inclusive).
+    pub column: usize,
+}
+
+/// A region of source code, along with macro expansion information.
+#[derive(Copy, Clone)]
+pub struct Span {
+    inner: imp::Span,
+    _marker: marker::PhantomData<Rc<()>>,
+}
+
+impl Span {
+    fn _new(inner: imp::Span) -> Span {
+        Span {
+            inner: inner,
+            _marker: marker::PhantomData,
+        }
+    }
+
+    fn _new_stable(inner: fallback::Span) -> Span {
+        Span {
+            inner: inner.into(),
+            _marker: marker::PhantomData,
+        }
+    }
+
+    /// The span of the invocation of the current procedural macro.
+    ///
+    /// Identifiers created with this span will be resolved as if they were
+    /// written directly at the macro call location (call-site hygiene) and
+    /// other code at the macro call site will be able to refer to them as well.
+    pub fn call_site() -> Span {
+        Span::_new(imp::Span::call_site())
+    }
+
+    /// A span that resolves at the macro definition site.
+    ///
+    /// This method is semver exempt and not exposed by default.
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn def_site() -> Span {
+        Span::_new(imp::Span::def_site())
+    }
+
+    /// Creates a new span with the same line/column information as `self` but
+    /// that resolves symbols as though it were at `other`.
+    ///
+    /// This method is semver exempt and not exposed by default.
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn resolved_at(&self, other: Span) -> Span {
+        Span::_new(self.inner.resolved_at(other.inner))
+    }
+
+    /// Creates a new span with the same name resolution behavior as `self` but
+    /// with the line/column information of `other`.
+    ///
+    /// This method is semver exempt and not exposed by default.
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn located_at(&self, other: Span) -> Span {
+        Span::_new(self.inner.located_at(other.inner))
+    }
+
+    /// Convert `proc_macro2::Span` to `proc_macro::Span`.
+    ///
+    /// This method is available when building with a nightly compiler, or when
+    /// building with rustc 1.29+ *without* semver exempt features.
+    ///
+    /// # Panics
+    ///
+    /// Panics if called from outside of a procedural macro. Unlike
+    /// `proc_macro2::Span`, the `proc_macro::Span` type can only exist within
+    /// the context of a procedural macro invocation.
+    #[cfg(wrap_proc_macro)]
+    pub fn unwrap(self) -> proc_macro::Span {
+        self.inner.unwrap()
+    }
+
+    // Soft deprecated. Please use Span::unwrap.
+    #[cfg(wrap_proc_macro)]
+    #[doc(hidden)]
+    pub fn unstable(self) -> proc_macro::Span {
+        self.unwrap()
+    }
+
+    /// The original source file into which this span points.
+    ///
+    /// This method is semver exempt and not exposed by default.
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn source_file(&self) -> SourceFile {
+        SourceFile::_new(self.inner.source_file())
+    }
+
+    /// Get the starting line/column in the source file for this span.
+    ///
+    /// This method requires the `"span-locations"` feature to be enabled.
+    #[cfg(span_locations)]
+    pub fn start(&self) -> LineColumn {
+        let imp::LineColumn { line, column } = self.inner.start();
+        LineColumn {
+            line: line,
+            column: column,
+        }
+    }
+
+    /// Get the ending line/column in the source file for this span.
+    ///
+    /// This method requires the `"span-locations"` feature to be enabled.
+    #[cfg(span_locations)]
+    pub fn end(&self) -> LineColumn {
+        let imp::LineColumn { line, column } = self.inner.end();
+        LineColumn {
+            line: line,
+            column: column,
+        }
+    }
+
+    /// Create a new span encompassing `self` and `other`.
+    ///
+    /// Returns `None` if `self` and `other` are from different files.
+    ///
+    /// This method is semver exempt and not exposed by default.
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn join(&self, other: Span) -> Option<Span> {
+        self.inner.join(other.inner).map(Span::_new)
+    }
+
+    /// Compares to spans to see if they're equal.
+    ///
+    /// This method is semver exempt and not exposed by default.
+    #[cfg(procmacro2_semver_exempt)]
+    pub fn eq(&self, other: &Span) -> bool {
+        self.inner.eq(&other.inner)
+    }
+}
+
+/// Prints a span in a form convenient for debugging.
+impl fmt::Debug for Span {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.inner.fmt(f)
+    }
+}
+
+/// A single token or a delimited sequence of token trees (e.g. `[1, (), ..]`).
+#[derive(Clone)]
+pub enum TokenTree {
+    /// A token stream surrounded by bracket delimiters.
+    Group(Group),
+    /// An identifier.
+    Ident(Ident),
+    /// A single punctuation character (`+`, `,`, `$`, etc.).
+    Punct(Punct),
+    /// A literal character (`'a'`), string (`"hello"`), number (`2.3`), etc.
+    Literal(Literal),
+}
+
+impl TokenTree {
+    /// Returns the span of this tree, delegating to the `span` method of
+    /// the contained token or a delimited stream.
+    pub fn span(&self) -> Span {
+        match *self {
+            TokenTree::Group(ref t) => t.span(),
+            TokenTree::Ident(ref t) => t.span(),
+            TokenTree::Punct(ref t) => t.span(),
+            TokenTree::Literal(ref t) => t.span(),
+        }
+    }
+
+    /// Configures the span for *only this token*.
+    ///
+    /// Note that if this token is a `Group` then this method will not configure
+    /// the span of each of the internal tokens, this will simply delegate to
+    /// the `set_span` method of each variant.
+    pub fn set_span(&mut self, span: Span) {
+        match *self {
+            TokenTree::Group(ref mut t) => t.set_span(span),
+            TokenTree::Ident(ref mut t) => t.set_span(span),
+            TokenTree::Punct(ref mut t) => t.set_span(span),
+            TokenTree::Literal(ref mut t) => t.set_span(span),
+        }
+    }
+}
+
+impl From<Group> for TokenTree {
+    fn from(g: Group) -> TokenTree {
+        TokenTree::Group(g)
+    }
+}
+
+impl From<Ident> for TokenTree {
+    fn from(g: Ident) -> TokenTree {
+        TokenTree::Ident(g)
+    }
+}
+
+impl From<Punct> for TokenTree {
+    fn from(g: Punct) -> TokenTree {
+        TokenTree::Punct(g)
+    }
+}
+
+impl From<Literal> for TokenTree {
+    fn from(g: Literal) -> TokenTree {
+        TokenTree::Literal(g)
+    }
+}
+
+/// Prints the token tree as a string that is supposed to be losslessly
+/// convertible back into the same token tree (modulo spans), except for
+/// possibly `TokenTree::Group`s with `Delimiter::None` delimiters and negative
+/// numeric literals.
+impl fmt::Display for TokenTree {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            TokenTree::Group(ref t) => t.fmt(f),
+            TokenTree::Ident(ref t) => t.fmt(f),
+            TokenTree::Punct(ref t) => t.fmt(f),
+            TokenTree::Literal(ref t) => t.fmt(f),
+        }
+    }
+}
+
+/// Prints token tree in a form convenient for debugging.
+impl fmt::Debug for TokenTree {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        // Each of these has the name in the struct type in the derived debug,
+        // so don't bother with an extra layer of indirection
+        match *self {
+            TokenTree::Group(ref t) => t.fmt(f),
+            TokenTree::Ident(ref t) => {
+                let mut debug = f.debug_struct("Ident");
+                debug.field("sym", &format_args!("{}", t));
+                imp::debug_span_field_if_nontrivial(&mut debug, t.span().inner);
+                debug.finish()
+            }
+            TokenTree::Punct(ref t) => t.fmt(f),
+            TokenTree::Literal(ref t) => t.fmt(f),
+        }
+    }
+}
+
+/// A delimited token stream.
+///
+/// A `Group` internally contains a `TokenStream` which is surrounded by
+/// `Delimiter`s.
+#[derive(Clone)]
+pub struct Group {
+    inner: imp::Group,
+}
+
+/// Describes how a sequence of token trees is delimited.
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub enum Delimiter {
+    /// `( ... )`
+    Parenthesis,
+    /// `{ ... }`
+    Brace,
+    /// `[ ... ]`
+    Bracket,
+    /// `Ø ... Ø`
+    ///
+    /// An implicit delimiter, that may, for example, appear around tokens
+    /// coming from a "macro variable" `$var`. It is important to preserve
+    /// operator priorities in cases like `$var * 3` where `$var` is `1 + 2`.
+    /// Implicit delimiters may not survive roundtrip of a token stream through
+    /// a string.
+    None,
+}
+
+impl Group {
+    fn _new(inner: imp::Group) -> Self {
+        Group { inner: inner }
+    }
+
+    fn _new_stable(inner: fallback::Group) -> Self {
+        Group {
+            inner: inner.into(),
+        }
+    }
+
+    /// Creates a new `Group` with the given delimiter and token stream.
+    ///
+    /// This constructor will set the span for this group to
+    /// `Span::call_site()`. To change the span you can use the `set_span`
+    /// method below.
+    pub fn new(delimiter: Delimiter, stream: TokenStream) -> Group {
+        Group {
+            inner: imp::Group::new(delimiter, stream.inner),
+        }
+    }
+
+    /// Returns the delimiter of this `Group`
+    pub fn delimiter(&self) -> Delimiter {
+        self.inner.delimiter()
+    }
+
+    /// Returns the `TokenStream` of tokens that are delimited in this `Group`.
+    ///
+    /// Note that the retur