diff --git a/.cargo/config.in b/.cargo/config.in
index f4157cdc1c3f4ebc23fbe53cc7d94c857654f422..42d3688b3c377e749e881a85f43eb769d5af966f 100644
--- a/.cargo/config.in
+++ b/.cargo/config.in
@@ -30,7 +30,7 @@ tag = "v0.4.21"
 [source."https://github.com/mozilla/mp4parse-rust"]
 git = "https://github.com/mozilla/mp4parse-rust"
 replace-with = "vendored-sources"
-rev = "3d9efdc868ce8c5767cea28708fa6512c0ab6d17"
+rev = "3011a2b923c8b0f1b392bcdd008cd8b95ffd846b"
 
 [source."https://github.com/mozilla/application-services"]
 git = "https://github.com/mozilla/application-services"
diff --git a/Cargo.lock b/Cargo.lock
index fa9d1e8844f3a2ecef1e74e6b01a0e0bd003d86f..8a66c953884608c881b0b08f6d1fdeb608f159d4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -223,7 +223,7 @@ dependencies = [
  "bindgen",
  "cranelift-codegen",
  "cranelift-wasm",
- "env_logger 0.8.2",
+ "env_logger",
  "log",
  "smallvec",
 ]
@@ -1310,19 +1310,6 @@ dependencies = [
  "packed_simd",
 ]
 
-[[package]]
-name = "env_logger"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
-dependencies = [
- "atty",
- "humantime 1.3.0",
- "log",
- "regex",
- "termcolor",
-]
-
 [[package]]
 name = "env_logger"
 version = "0.8.2"
@@ -1330,7 +1317,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f26ecb66b4bdca6c1409b40fb255eefc2bd4f6d135dab3c3124f80ffa2a9661e"
 dependencies = [
  "atty",
- "humantime 2.0.1",
+ "humantime",
  "log",
  "regex",
  "termcolor",
@@ -1790,7 +1777,7 @@ name = "gecko_logger"
 version = "0.1.0"
 dependencies = [
  "app_services_logger",
- "env_logger 0.8.2",
+ "env_logger",
  "lazy_static",
  "log",
 ]
@@ -2389,15 +2376,6 @@ version = "1.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83"
 
-[[package]]
-name = "humantime"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
-dependencies = [
- "quick-error",
-]
-
 [[package]]
 name = "humantime"
 version = "2.0.1"
@@ -2583,7 +2561,7 @@ version = "0.1.4"
 dependencies = [
  "bindgen",
  "cmake",
- "env_logger 0.8.2",
+ "env_logger",
  "glob",
  "lazy_static",
  "libc",
@@ -3334,12 +3312,12 @@ dependencies = [
 
 [[package]]
 name = "mp4parse"
-version = "0.11.4"
-source = "git+https://github.com/mozilla/mp4parse-rust?rev=3d9efdc868ce8c5767cea28708fa6512c0ab6d17#3d9efdc868ce8c5767cea28708fa6512c0ab6d17"
+version = "0.11.5"
+source = "git+https://github.com/mozilla/mp4parse-rust?rev=3011a2b923c8b0f1b392bcdd008cd8b95ffd846b#3011a2b923c8b0f1b392bcdd008cd8b95ffd846b"
 dependencies = [
  "bitreader",
  "byteorder",
- "env_logger 0.7.1",
+ "env_logger",
  "fallible_collections",
  "hashbrown",
  "log",
@@ -3353,8 +3331,8 @@ version = "0.1.0"
 
 [[package]]
 name = "mp4parse_capi"
-version = "0.11.4"
-source = "git+https://github.com/mozilla/mp4parse-rust?rev=3d9efdc868ce8c5767cea28708fa6512c0ab6d17#3d9efdc868ce8c5767cea28708fa6512c0ab6d17"
+version = "0.11.5"
+source = "git+https://github.com/mozilla/mp4parse-rust?rev=3011a2b923c8b0f1b392bcdd008cd8b95ffd846b#3011a2b923c8b0f1b392bcdd008cd8b95ffd846b"
 dependencies = [
  "byteorder",
  "fallible_collections",
@@ -3399,7 +3377,7 @@ version = "0.4.21"
 source = "git+https://github.com/mozilla/neqo?tag=v0.4.21#0e6040cd6385c038f8b7f604bcb09ad74d29e0d6"
 dependencies = [
  "chrono",
- "env_logger 0.8.2",
+ "env_logger",
  "lazy_static",
  "log",
  "qlog",
@@ -3638,11 +3616,11 @@ dependencies = [
 
 [[package]]
 name = "num-traits"
-version = "0.2.10"
+version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4"
+checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
 dependencies = [
- "autocfg 0.1.6",
+ "autocfg 1.0.1",
 ]
 
 [[package]]
@@ -3715,7 +3693,7 @@ version = "0.1.4"
 dependencies = [
  "byteorder",
  "core-foundation",
- "env_logger 0.8.2",
+ "env_logger",
  "lazy_static",
  "libloading 0.5.2",
  "log",
@@ -3991,7 +3969,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "50ce7c785e06e3a9e6f546c1a30d3d59111a31a21bc294fb1496241a572c9a00"
 dependencies = [
  "base64 0.10.1",
- "humantime 2.0.1",
+ "humantime",
  "indexmap",
  "line-wrap",
  "serde",
@@ -4814,7 +4792,7 @@ name = "smoosh"
 version = "0.1.0"
 dependencies = [
  "bumpalo",
- "env_logger 0.8.2",
+ "env_logger",
  "jsparagus",
  "log",
 ]
@@ -5014,7 +4992,7 @@ dependencies = [
  "atomic_refcell",
  "cssparser",
  "cstr",
- "env_logger 0.8.2",
+ "env_logger",
  "geckoservo",
  "libc",
  "log",
diff --git a/third_party/rust/env_logger-0.7.1/.cargo-checksum.json b/third_party/rust/env_logger-0.7.1/.cargo-checksum.json
deleted file mode 100644
index f7fcd9e6bc2391b18cc1a06baec87d679d4a33ce..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"CHANGELOG.md":"7c044d74477515ab39287a4caff27eb96daebaed8b9f9b6a1d1c081a7b42d4a7","Cargo.lock":"b1394b6c58241027832cc714a0754902d82aa1f6923ab478c318739462e565ca","Cargo.toml":"2961879155d753ba90ecd98c17875c82007a6973c95867e86bc1ec5bd4f5db41","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"0bf17650e07b88f1486f033643c1e82517caa69410e6faeaa352782d9231d63e","examples/custom_default_format.rs":"ae18cd0e765cf1f16568f9879925861d6f004481f955b58af5ed8fd04b0fca99","examples/custom_format.rs":"b0f41b7a3e6fe7582871281f4244c62c66b0d724bfc678907f67185a784e82b4","examples/custom_logger.rs":"6eeef506681a46925117e8f89395cdf4fea60a0d1f6a420e51768e790272dcde","examples/default.rs":"7ed1c6a8a8fe457a86676bd3a75c07d4ec7fb54147cf2825c9d299a5878a24cd","examples/direct_logger.rs":"ee20c25379c396e5e74e963290a4d8773a86f3fe10193f61fb1efd1c7271faf4","examples/filters_from_code.rs":"7f007b0dfa5a3964f839134824dc3684bf2f3c3d7b4c36c580cd029df5f9308b","src/filter/mod.rs":"5da7e51e7b77efdd4d2b5445e5d0264be2c897909d0f86eb553e16611307aed2","src/filter/regex.rs":"bdf875bac25e089e1e462f5dd01a88678067c24118ecd6268561c6a6af39747d","src/filter/string.rs":"fac54d51189fc0b5d2bff334b7a7e465177b431e3428299e345e1f90062d832e","src/fmt/humantime/extern_impl.rs":"f3087b29eedb8b4d5573621ad206e48a2eac72a77277be3b0e631d7dc9fb7a2e","src/fmt/humantime/mod.rs":"f4111c26cf2ffb85c1d639bd7674d55af7e1736e7e98c52f7be3070046a3253f","src/fmt/humantime/shim_impl.rs":"cce9a252abd5952fa109a72b1dfb85a593d237e22606b2b608a32c69184560e9","src/fmt/mod.rs":"4ab11971a73eb5fe9b40f0bca6dfc404321dd9e2ffcf87d911408e7183dc8362","src/fmt/writer/atty.rs":"69d9dd26c430000cd2d40f9c68b2e77cd492fec22921dd2c16864301252583e0","src/fmt/writer/mod.rs":"1e0feb4dee3ee86c4c24f49566673e99ec85765869105a07a2fc7436d7640cfe","src/fmt/writer/termcolor/extern_impl.rs":"89e9f2e66b914ddc960ad9a4355265a5db5d7be410b139cf2b54ca99207374a7","src/fmt/writer/termcolor/mod.rs":"a790f9391a50cd52be6823e3e55942de13a8d12e23d63765342ae9e8dd6d091c","src/fmt/writer/termcolor/shim_impl.rs":"d93786671d6a89fc2912f77f04b8cb0b82d67277d255d15ac31bfc1bc4464e30","src/lib.rs":"3cbc4f4d3fe51c43fc45a2f435c141f0de5b40b65ba0d2c7d16bb58c04d10898","tests/init-twice-retains-filter.rs":"be5cd2132342d89ede1f5c4266173bb3c4d51cc22a1847f133d299a1c5430ccb","tests/log-in-log.rs":"29fecc65c1e0d1c22d79c97e7ca843ad44a91f27934148d7a05c48899a3f39d8","tests/log_tls_dtors.rs":"7320667d774a9b05037f7bf273fb2574dec0705707692a9cd2f46f4cd5bc68dd","tests/regexp_filter.rs":"a84263c995b534b6479a1d0abadf63f4f0264958ff86d9173d6b2139b82c4dc5"},"package":"44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"}
\ No newline at end of file
diff --git a/third_party/rust/env_logger-0.7.1/CHANGELOG.md b/third_party/rust/env_logger-0.7.1/CHANGELOG.md
deleted file mode 100644
index f849eefff6eb3083c89745a73778b34a4a1bd763..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/CHANGELOG.md
+++ /dev/null
@@ -1,3 +0,0 @@
-Changes to this crate are tracked via [GitHub Releases][releases].
-
-[releases]: https://github.com/sebasmagri/env_logger/releases
diff --git a/third_party/rust/env_logger-0.7.1/Cargo.lock b/third_party/rust/env_logger-0.7.1/Cargo.lock
deleted file mode 100644
index bf04607aae65c6c26c876f22c4d75e49d1ce4172..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/Cargo.lock
+++ /dev/null
@@ -1,212 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-[[package]]
-name = "aho-corasick"
-version = "0.6.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "atty"
-version = "0.2.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "libc 0.2.40 (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.4 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "cfg-if"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "env_logger"
-version = "0.7.1"
-dependencies = [
- "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "humantime"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "lazy_static"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "libc"
-version = "0.2.40"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "log"
-version = "0.4.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "memchr"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "version_check 0.1.5 (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 = "redox_syscall"
-version = "0.1.37"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "redox_termios"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "regex"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.6.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "termcolor"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "termion"
-version = "1.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "thread_local"
-version = "0.3.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "ucd-util"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "utf8-ranges"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "version_check"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "winapi"
-version = "0.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "winapi-util"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "wincolor"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[metadata]
-"checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e"
-"checksum atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "af80143d6f7608d746df1520709e5d141c96f240b0e62b0aa41bdfb53374d9d4"
-"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
-"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
-"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
-"checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b"
-"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
-"checksum memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16"
-"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
-"checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd"
-"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
-"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f"
-"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861"
-"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 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 utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
-"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
-"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
-"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-"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 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-"checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba"
diff --git a/third_party/rust/env_logger-0.7.1/Cargo.toml b/third_party/rust/env_logger-0.7.1/Cargo.toml
deleted file mode 100644
index c34a1ee2391d0cc60b691f36a9b6e38f35315aa8..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/Cargo.toml
+++ /dev/null
@@ -1,62 +0,0 @@
-# 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]
-edition = "2018"
-name = "env_logger"
-version = "0.7.1"
-authors = ["The Rust Project Developers"]
-description = "A logging implementation for `log` which is configured via an environment\nvariable.\n"
-documentation = "https://docs.rs/env_logger"
-readme = "README.md"
-keywords = ["logging", "log", "logger"]
-categories = ["development-tools::debugging"]
-license = "MIT/Apache-2.0"
-repository = "https://github.com/sebasmagri/env_logger/"
-
-[[test]]
-name = "regexp_filter"
-harness = false
-
-[[test]]
-name = "log-in-log"
-harness = false
-
-[[test]]
-name = "log_tls_dtors"
-harness = false
-
-[[test]]
-name = "init-twice-retains-filter"
-harness = false
-[dependencies.atty]
-version = "0.2.5"
-optional = true
-
-[dependencies.humantime]
-version = "1.3"
-optional = true
-
-[dependencies.log]
-version = "0.4.8"
-features = ["std"]
-
-[dependencies.regex]
-version = "1.0.3"
-optional = true
-
-[dependencies.termcolor]
-version = "1.0.2"
-optional = true
-
-[features]
-default = ["termcolor", "atty", "humantime", "regex"]
diff --git a/third_party/rust/env_logger-0.7.1/LICENSE-APACHE b/third_party/rust/env_logger-0.7.1/LICENSE-APACHE
deleted file mode 100644
index 16fe87b06e802f094b3fbb0894b137bca2b16ef1..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/LICENSE-APACHE
+++ /dev/null
@@ -1,201 +0,0 @@
-                              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.
diff --git a/third_party/rust/env_logger-0.7.1/LICENSE-MIT b/third_party/rust/env_logger-0.7.1/LICENSE-MIT
deleted file mode 100644
index 39d4bdb5acd313c1a92dbeaa1c379aaf0596a315..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/LICENSE-MIT
+++ /dev/null
@@ -1,25 +0,0 @@
-Copyright (c) 2014 The Rust Project Developers
-
-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.
diff --git a/third_party/rust/env_logger-0.7.1/README.md b/third_party/rust/env_logger-0.7.1/README.md
deleted file mode 100644
index 34e4194a88fbb6d42225eaf39047db67484fc3b6..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/README.md
+++ /dev/null
@@ -1,150 +0,0 @@
-env_logger [![Build Status](https://travis-ci.org/sebasmagri/env_logger.svg?branch=master)](https://travis-ci.org/sebasmagri/env_logger) [![Maintenance](https://img.shields.io/badge/maintenance-actively%20maintained-brightgreen.svg)](https://github.com/sebasmagri/env_logger) [![crates.io](https://img.shields.io/crates/v/env_logger.svg)](https://crates.io/crates/env_logger) [![Documentation](https://img.shields.io/badge/docs-current-blue.svg)](https://docs.rs/env_logger)
-==========
-
-Implements a logger that can be configured via environment variables.
-
-## Usage
-
-### In libraries
-
-`env_logger` makes sense when used in executables (binary projects). Libraries should use the [`log`](https://doc.rust-lang.org/log) crate instead.
-
-### In executables
-
-It must be added along with `log` to the project dependencies:
-
-```toml
-[dependencies]
-log = "0.4.0"
-env_logger = "0.7.1"
-```
-
-`env_logger` must be initialized as early as possible in the project. After it's initialized, you can use the `log` macros to do actual logging.
-
-```rust
-#[macro_use]
-extern crate log;
-
-fn main() {
-    env_logger::init();
-
-    info!("starting up");
-
-    // ...
-}
-```
-
-Then when running the executable, specify a value for the `RUST_LOG`
-environment variable that corresponds with the log messages you want to show.
-
-```bash
-$ RUST_LOG=info ./main
-[2018-11-03T06:09:06Z INFO  default] starting up
-```
-
-`env_logger` can be configured in other ways besides an environment variable. See [the examples](https://github.com/sebasmagri/env_logger/tree/master/examples) for more approaches.
-
-### In tests
-
-Tests can use the `env_logger` crate to see log messages generated during that test:
-
-```toml
-[dependencies]
-log = "0.4.0"
-
-[dev-dependencies]
-env_logger = "0.7.1"
-```
-
-```rust
-#[macro_use]
-extern crate log;
-
-fn add_one(num: i32) -> i32 {
-    info!("add_one called with {}", num);
-    num + 1
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    fn init() {
-        let _ = env_logger::builder().is_test(true).try_init();
-    }
-
-    #[test]
-    fn it_adds_one() {
-        init();
-
-        info!("can log from the test too");
-        assert_eq!(3, add_one(2));
-    }
-
-    #[test]
-    fn it_handles_negative_numbers() {
-        init();
-
-        info!("logging from another test");
-        assert_eq!(-7, add_one(-8));
-    }
-}
-```
-
-Assuming the module under test is called `my_lib`, running the tests with the
-`RUST_LOG` filtering to info messages from this module looks like:
-
-```bash
-$ RUST_LOG=my_lib=info cargo test
-     Running target/debug/my_lib-...
-
-running 2 tests
-[INFO my_lib::tests] logging from another test
-[INFO my_lib] add_one called with -8
-test tests::it_handles_negative_numbers ... ok
-[INFO my_lib::tests] can log from the test too
-[INFO my_lib] add_one called with 2
-test tests::it_adds_one ... ok
-
-test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured
-```
-
-Note that `env_logger::try_init()` needs to be called in each test in which you
-want to enable logging. Additionally, the default behavior of tests to
-run in parallel means that logging output may be interleaved with test output.
-Either run tests in a single thread by specifying `RUST_TEST_THREADS=1` or by
-running one test by specifying its name as an argument to the test binaries as
-directed by the `cargo test` help docs:
-
-```bash
-$ RUST_LOG=my_lib=info cargo test it_adds_one
-     Running target/debug/my_lib-...
-
-running 1 test
-[INFO my_lib::tests] can log from the test too
-[INFO my_lib] add_one called with 2
-test tests::it_adds_one ... ok
-
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
-```
-
-## Configuring log target
-
-By default, `env_logger` logs to stderr. If you want to log to stdout instead,
-you can use the `Builder` to change the log target:
-
-```rust
-use std::env;
-use env_logger::{Builder, Target};
-
-let mut builder = Builder::from_default_env();
-builder.target(Target::Stdout);
-
-builder.init();
-```
-
-## Stability of the default format
-
-The default format won't optimise for long-term stability, and explicitly makes no guarantees about the stability of its output across major, minor or patch version bumps during `0.x`.
-
-If you want to capture or interpret the output of `env_logger` programmatically then you should use a custom format.
diff --git a/third_party/rust/env_logger-0.7.1/examples/custom_default_format.rs b/third_party/rust/env_logger-0.7.1/examples/custom_default_format.rs
deleted file mode 100644
index 43979247ca5b66d677e35fb1f5d59686d010f7c9..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/examples/custom_default_format.rs
+++ /dev/null
@@ -1,41 +0,0 @@
-/*!
-Disabling parts of the default format.
-
-Before running this example, try setting the `MY_LOG_LEVEL` environment variable to `info`:
-
-```no_run,shell
-$ export MY_LOG_LEVEL='info'
-```
-
-Also try setting the `MY_LOG_STYLE` environment variable to `never` to disable colors
-or `auto` to enable them:
-
-```no_run,shell
-$ export MY_LOG_STYLE=never
-```
-
-If you want to control the logging output completely, see the `custom_logger` example.
-*/
-
-#[macro_use]
-extern crate log;
-
-use env_logger::{Builder, Env};
-
-fn init_logger() {
-    let env = Env::default()
-        .filter("MY_LOG_LEVEL")
-        .write_style("MY_LOG_STYLE");
-
-    let mut builder = Builder::from_env(env);
-
-    builder.format_level(false).format_timestamp_nanos();
-
-    builder.init();
-}
-
-fn main() {
-    init_logger();
-
-    info!("a log from `MyLogger`");
-}
diff --git a/third_party/rust/env_logger-0.7.1/examples/custom_format.rs b/third_party/rust/env_logger-0.7.1/examples/custom_format.rs
deleted file mode 100644
index df5a8e5b9cd9d238937e93ed077d2bd9ea1d77a4..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/examples/custom_format.rs
+++ /dev/null
@@ -1,53 +0,0 @@
-/*!
-Changing the default logging format.
-
-Before running this example, try setting the `MY_LOG_LEVEL` environment variable to `info`:
-
-```no_run,shell
-$ export MY_LOG_LEVEL='info'
-```
-
-Also try setting the `MY_LOG_STYLE` environment variable to `never` to disable colors
-or `auto` to enable them:
-
-```no_run,shell
-$ export MY_LOG_STYLE=never
-```
-
-If you want to control the logging output completely, see the `custom_logger` example.
-*/
-
-#[cfg(all(feature = "termcolor", feature = "humantime"))]
-fn main() {
-    use env_logger::{fmt, Builder, Env};
-    use std::io::Write;
-
-    fn init_logger() {
-        let env = Env::default()
-            .filter("MY_LOG_LEVEL")
-            .write_style("MY_LOG_STYLE");
-
-        Builder::from_env(env)
-            .format(|buf, record| {
-                let mut style = buf.style();
-                style.set_bg(fmt::Color::Yellow).set_bold(true);
-
-                let timestamp = buf.timestamp();
-
-                writeln!(
-                    buf,
-                    "My formatted log ({}): {}",
-                    timestamp,
-                    style.value(record.args())
-                )
-            })
-            .init();
-    }
-
-    init_logger();
-
-    log::info!("a log from `MyLogger`");
-}
-
-#[cfg(not(all(feature = "termcolor", feature = "humantime")))]
-fn main() {}
diff --git a/third_party/rust/env_logger-0.7.1/examples/custom_logger.rs b/third_party/rust/env_logger-0.7.1/examples/custom_logger.rs
deleted file mode 100644
index 85de45b2d97d76fc779fe0c60c3fca3026eb49fe..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/examples/custom_logger.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-/*!
-Using `env_logger` to drive a custom logger.
-
-Before running this example, try setting the `MY_LOG_LEVEL` environment variable to `info`:
-
-```no_run,shell
-$ export MY_LOG_LEVEL='info'
-```
-
-If you only want to change the way logs are formatted, look at the `custom_format` example.
-*/
-
-#[macro_use]
-extern crate log;
-
-use env_logger::filter::Filter;
-use log::{Log, Metadata, Record, SetLoggerError};
-
-struct MyLogger {
-    inner: Filter,
-}
-
-impl MyLogger {
-    fn new() -> MyLogger {
-        use env_logger::filter::Builder;
-        let mut builder = Builder::from_env("MY_LOG_LEVEL");
-
-        MyLogger {
-            inner: builder.build(),
-        }
-    }
-
-    fn init() -> Result<(), SetLoggerError> {
-        let logger = Self::new();
-
-        log::set_max_level(logger.inner.filter());
-        log::set_boxed_logger(Box::new(logger))
-    }
-}
-
-impl Log for MyLogger {
-    fn enabled(&self, metadata: &Metadata) -> bool {
-        self.inner.enabled(metadata)
-    }
-
-    fn log(&self, record: &Record) {
-        // Check if the record is matched by the logger before logging
-        if self.inner.matches(record) {
-            println!("{} - {}", record.level(), record.args());
-        }
-    }
-
-    fn flush(&self) {}
-}
-
-fn main() {
-    MyLogger::init().unwrap();
-
-    info!("a log from `MyLogger`");
-}
diff --git a/third_party/rust/env_logger-0.7.1/examples/default.rs b/third_party/rust/env_logger-0.7.1/examples/default.rs
deleted file mode 100644
index 67bb030745e74aadb3526030d0076e05de66ee5c..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/examples/default.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-/*!
-Using `env_logger`.
-
-Before running this example, try setting the `MY_LOG_LEVEL` environment variable to `info`:
-
-```no_run,shell
-$ export MY_LOG_LEVEL='info'
-```
-
-Also try setting the `MY_LOG_STYLE` environment variable to `never` to disable colors
-or `auto` to enable them:
-
-```no_run,shell
-$ export MY_LOG_STYLE=never
-```
-*/
-
-#[macro_use]
-extern crate log;
-
-use env_logger::Env;
-
-fn main() {
-    // The `Env` lets us tweak what the environment
-    // variables to read are and what the default
-    // value is if they're missing
-    let env = Env::default()
-        .filter_or("MY_LOG_LEVEL", "trace")
-        .write_style_or("MY_LOG_STYLE", "always");
-
-    env_logger::init_from_env(env);
-
-    trace!("some trace log");
-    debug!("some debug log");
-    info!("some information log");
-    warn!("some warning log");
-    error!("some error log");
-}
diff --git a/third_party/rust/env_logger-0.7.1/examples/direct_logger.rs b/third_party/rust/env_logger-0.7.1/examples/direct_logger.rs
deleted file mode 100644
index 4ba023fae3bc6c79e64ca08a0c1c9a36957bf9c9..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/examples/direct_logger.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-/*!
-Using `env_logger::Logger` and the `log::Log` trait directly.
-
-This example doesn't rely on environment variables, or having a static logger installed.
-*/
-
-fn record() -> log::Record<'static> {
-    let error_metadata = log::MetadataBuilder::new()
-        .target("myApp")
-        .level(log::Level::Error)
-        .build();
-
-    log::Record::builder()
-        .metadata(error_metadata)
-        .args(format_args!("Error!"))
-        .line(Some(433))
-        .file(Some("app.rs"))
-        .module_path(Some("server"))
-        .build()
-}
-
-fn main() {
-    use log::Log;
-
-    let stylish_logger = env_logger::Builder::new()
-        .filter(None, log::LevelFilter::Error)
-        .write_style(env_logger::WriteStyle::Always)
-        .build();
-
-    let unstylish_logger = env_logger::Builder::new()
-        .filter(None, log::LevelFilter::Error)
-        .write_style(env_logger::WriteStyle::Never)
-        .build();
-
-    stylish_logger.log(&record());
-    unstylish_logger.log(&record());
-}
diff --git a/third_party/rust/env_logger-0.7.1/examples/filters_from_code.rs b/third_party/rust/env_logger-0.7.1/examples/filters_from_code.rs
deleted file mode 100644
index 4137c91898b03aef69225c80e283b4128d0efcea..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/examples/filters_from_code.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-/*!
-Specify logging filters in code instead of using an environment variable.
-*/
-
-#[macro_use]
-extern crate log;
-
-fn main() {
-    env_logger::builder()
-        .filter_level(log::LevelFilter::Trace)
-        .init();
-
-    trace!("some trace log");
-    debug!("some debug log");
-    info!("some information log");
-    warn!("some warning log");
-    error!("some error log");
-}
diff --git a/third_party/rust/env_logger-0.7.1/src/filter/mod.rs b/third_party/rust/env_logger-0.7.1/src/filter/mod.rs
deleted file mode 100644
index a994f4dc6cd69d8d15a314cd7e12f9e9fa71a86b..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/src/filter/mod.rs
+++ /dev/null
@@ -1,616 +0,0 @@
-//! Filtering for log records.
-//!
-//! This module contains the log filtering used by `env_logger` to match records.
-//! You can use the `Filter` type in your own logger implementation to use the same
-//! filter parsing and matching as `env_logger`. For more details about the format
-//! for directive strings see [Enabling Logging].
-//!
-//! ## Using `env_logger` in your own logger
-//!
-//! You can use `env_logger`'s filtering functionality with your own logger.
-//! Call [`Builder::parse`] to parse directives from a string when constructing
-//! your logger. Call [`Filter::matches`] to check whether a record should be
-//! logged based on the parsed filters when log records are received.
-//!
-//! ```
-//! extern crate log;
-//! extern crate env_logger;
-//! use env_logger::filter::Filter;
-//! use log::{Log, Metadata, Record};
-//!
-//! struct MyLogger {
-//!     filter: Filter
-//! }
-//!
-//! impl MyLogger {
-//!     fn new() -> MyLogger {
-//!         use env_logger::filter::Builder;
-//!         let mut builder = Builder::new();
-//!
-//!         // Parse a directives string from an environment variable
-//!         if let Ok(ref filter) = std::env::var("MY_LOG_LEVEL") {
-//!            builder.parse(filter);
-//!         }
-//!
-//!         MyLogger {
-//!             filter: builder.build()
-//!         }
-//!     }
-//! }
-//!
-//! impl Log for MyLogger {
-//!     fn enabled(&self, metadata: &Metadata) -> bool {
-//!         self.filter.enabled(metadata)
-//!     }
-//!
-//!     fn log(&self, record: &Record) {
-//!         // Check if the record is matched by the filter
-//!         if self.filter.matches(record) {
-//!             println!("{:?}", record);
-//!         }
-//!     }
-//!
-//!     fn flush(&self) {}
-//! }
-//! # fn main() {}
-//! ```
-//!
-//! [Enabling Logging]: ../index.html#enabling-logging
-//! [`Builder::parse`]: struct.Builder.html#method.parse
-//! [`Filter::matches`]: struct.Filter.html#method.matches
-
-use log::{Level, LevelFilter, Metadata, Record};
-use std::env;
-use std::fmt;
-use std::mem;
-
-#[cfg(feature = "regex")]
-#[path = "regex.rs"]
-mod inner;
-
-#[cfg(not(feature = "regex"))]
-#[path = "string.rs"]
-mod inner;
-
-/// A log filter.
-///
-/// This struct can be used to determine whether or not a log record
-/// should be written to the output.
-/// Use the [`Builder`] type to parse and construct a `Filter`.
-///
-/// [`Builder`]: struct.Builder.html
-pub struct Filter {
-    directives: Vec<Directive>,
-    filter: Option<inner::Filter>,
-}
-
-/// A builder for a log filter.
-///
-/// It can be used to parse a set of directives from a string before building
-/// a [`Filter`] instance.
-///
-/// ## Example
-///
-/// ```
-/// #[macro_use]
-/// extern crate log;
-/// extern crate env_logger;
-///
-/// use std::env;
-/// use std::io;
-/// use env_logger::filter::Builder;
-///
-/// fn main() {
-///     let mut builder = Builder::new();
-///
-///     // Parse a logging filter from an environment variable.
-///     if let Ok(rust_log) = env::var("RUST_LOG") {
-///        builder.parse(&rust_log);
-///     }
-///
-///     let filter = builder.build();
-/// }
-/// ```
-///
-/// [`Filter`]: struct.Filter.html
-pub struct Builder {
-    directives: Vec<Directive>,
-    filter: Option<inner::Filter>,
-    built: bool,
-}
-
-#[derive(Debug)]
-struct Directive {
-    name: Option<String>,
-    level: LevelFilter,
-}
-
-impl Filter {
-    /// Returns the maximum `LevelFilter` that this filter instance is
-    /// configured to output.
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// extern crate log;
-    /// extern crate env_logger;
-    ///
-    /// use log::LevelFilter;
-    /// use env_logger::filter::Builder;
-    ///
-    /// fn main() {
-    ///     let mut builder = Builder::new();
-    ///     builder.filter(Some("module1"), LevelFilter::Info);
-    ///     builder.filter(Some("module2"), LevelFilter::Error);
-    ///
-    ///     let filter = builder.build();
-    ///     assert_eq!(filter.filter(), LevelFilter::Info);
-    /// }
-    /// ```
-    pub fn filter(&self) -> LevelFilter {
-        self.directives
-            .iter()
-            .map(|d| d.level)
-            .max()
-            .unwrap_or(LevelFilter::Off)
-    }
-
-    /// Checks if this record matches the configured filter.
-    pub fn matches(&self, record: &Record) -> bool {
-        if !self.enabled(record.metadata()) {
-            return false;
-        }
-
-        if let Some(filter) = self.filter.as_ref() {
-            if !filter.is_match(&*record.args().to_string()) {
-                return false;
-            }
-        }
-
-        true
-    }
-
-    /// Determines if a log message with the specified metadata would be logged.
-    pub fn enabled(&self, metadata: &Metadata) -> bool {
-        let level = metadata.level();
-        let target = metadata.target();
-
-        enabled(&self.directives, level, target)
-    }
-}
-
-impl Builder {
-    /// Initializes the filter builder with defaults.
-    pub fn new() -> Builder {
-        Builder {
-            directives: Vec::new(),
-            filter: None,
-            built: false,
-        }
-    }
-
-    /// Initializes the filter builder from an environment.
-    pub fn from_env(env: &str) -> Builder {
-        let mut builder = Builder::new();
-
-        if let Ok(s) = env::var(env) {
-            builder.parse(&s);
-        }
-
-        builder
-    }
-
-    /// Adds a directive to the filter for a specific module.
-    pub fn filter_module(&mut self, module: &str, level: LevelFilter) -> &mut Self {
-        self.filter(Some(module), level)
-    }
-
-    /// Adds a directive to the filter for all modules.
-    pub fn filter_level(&mut self, level: LevelFilter) -> &mut Self {
-        self.filter(None, level)
-    }
-
-    /// Adds a directive to the filter.
-    ///
-    /// The given module (if any) will log at most the specified level provided.
-    /// If no module is provided then the filter will apply to all log messages.
-    pub fn filter(&mut self, module: Option<&str>, level: LevelFilter) -> &mut Self {
-        self.directives.push(Directive {
-            name: module.map(|s| s.to_string()),
-            level,
-        });
-        self
-    }
-
-    /// Parses the directives string.
-    ///
-    /// See the [Enabling Logging] section for more details.
-    ///
-    /// [Enabling Logging]: ../index.html#enabling-logging
-    pub fn parse(&mut self, filters: &str) -> &mut Self {
-        let (directives, filter) = parse_spec(filters);
-
-        self.filter = filter;
-
-        for directive in directives {
-            self.directives.push(directive);
-        }
-        self
-    }
-
-    /// Build a log filter.
-    pub fn build(&mut self) -> Filter {
-        assert!(!self.built, "attempt to re-use consumed builder");
-        self.built = true;
-
-        if self.directives.is_empty() {
-            // Adds the default filter if none exist
-            self.directives.push(Directive {
-                name: None,
-                level: LevelFilter::Error,
-            });
-        } else {
-            // Sort the directives by length of their name, this allows a
-            // little more efficient lookup at runtime.
-            self.directives.sort_by(|a, b| {
-                let alen = a.name.as_ref().map(|a| a.len()).unwrap_or(0);
-                let blen = b.name.as_ref().map(|b| b.len()).unwrap_or(0);
-                alen.cmp(&blen)
-            });
-        }
-
-        Filter {
-            directives: mem::replace(&mut self.directives, Vec::new()),
-            filter: mem::replace(&mut self.filter, None),
-        }
-    }
-}
-
-impl Default for Builder {
-    fn default() -> Self {
-        Builder::new()
-    }
-}
-
-impl fmt::Debug for Filter {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("Filter")
-            .field("filter", &self.filter)
-            .field("directives", &self.directives)
-            .finish()
-    }
-}
-
-impl fmt::Debug for Builder {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        if self.built {
-            f.debug_struct("Filter").field("built", &true).finish()
-        } else {
-            f.debug_struct("Filter")
-                .field("filter", &self.filter)
-                .field("directives", &self.directives)
-                .finish()
-        }
-    }
-}
-
-/// Parse a logging specification string (e.g: "crate1,crate2::mod3,crate3::x=error/foo")
-/// and return a vector with log directives.
-fn parse_spec(spec: &str) -> (Vec<Directive>, Option<inner::Filter>) {
-    let mut dirs = Vec::new();
-
-    let mut parts = spec.split('/');
-    let mods = parts.next();
-    let filter = parts.next();
-    if parts.next().is_some() {
-        eprintln!(
-            "warning: invalid logging spec '{}', \
-             ignoring it (too many '/'s)",
-            spec
-        );
-        return (dirs, None);
-    }
-    mods.map(|m| {
-        for s in m.split(',') {
-            if s.len() == 0 {
-                continue;
-            }
-            let mut parts = s.split('=');
-            let (log_level, name) =
-                match (parts.next(), parts.next().map(|s| s.trim()), parts.next()) {
-                    (Some(part0), None, None) => {
-                        // if the single argument is a log-level string or number,
-                        // treat that as a global fallback
-                        match part0.parse() {
-                            Ok(num) => (num, None),
-                            Err(_) => (LevelFilter::max(), Some(part0)),
-                        }
-                    }
-                    (Some(part0), Some(""), None) => (LevelFilter::max(), Some(part0)),
-                    (Some(part0), Some(part1), None) => match part1.parse() {
-                        Ok(num) => (num, Some(part0)),
-                        _ => {
-                            eprintln!(
-                                "warning: invalid logging spec '{}', \
-                                 ignoring it",
-                                part1
-                            );
-                            continue;
-                        }
-                    },
-                    _ => {
-                        eprintln!(
-                            "warning: invalid logging spec '{}', \
-                             ignoring it",
-                            s
-                        );
-                        continue;
-                    }
-                };
-            dirs.push(Directive {
-                name: name.map(|s| s.to_string()),
-                level: log_level,
-            });
-        }
-    });
-
-    let filter = filter.map_or(None, |filter| match inner::Filter::new(filter) {
-        Ok(re) => Some(re),
-        Err(e) => {
-            eprintln!("warning: invalid regex filter - {}", e);
-            None
-        }
-    });
-
-    return (dirs, filter);
-}
-
-// Check whether a level and target are enabled by the set of directives.
-fn enabled(directives: &[Directive], level: Level, target: &str) -> bool {
-    // Search for the longest match, the vector is assumed to be pre-sorted.
-    for directive in directives.iter().rev() {
-        match directive.name {
-            Some(ref name) if !target.starts_with(&**name) => {}
-            Some(..) | None => return level <= directive.level,
-        }
-    }
-    false
-}
-
-#[cfg(test)]
-mod tests {
-    use log::{Level, LevelFilter};
-
-    use super::{enabled, parse_spec, Builder, Directive, Filter};
-
-    fn make_logger_filter(dirs: Vec<Directive>) -> Filter {
-        let mut logger = Builder::new().build();
-        logger.directives = dirs;
-        logger
-    }
-
-    #[test]
-    fn filter_info() {
-        let logger = Builder::new().filter(None, LevelFilter::Info).build();
-        assert!(enabled(&logger.directives, Level::Info, "crate1"));
-        assert!(!enabled(&logger.directives, Level::Debug, "crate1"));
-    }
-
-    #[test]
-    fn filter_beginning_longest_match() {
-        let logger = Builder::new()
-            .filter(Some("crate2"), LevelFilter::Info)
-            .filter(Some("crate2::mod"), LevelFilter::Debug)
-            .filter(Some("crate1::mod1"), LevelFilter::Warn)
-            .build();
-        assert!(enabled(&logger.directives, Level::Debug, "crate2::mod1"));
-        assert!(!enabled(&logger.directives, Level::Debug, "crate2"));
-    }
-
-    #[test]
-    fn parse_default() {
-        let logger = Builder::new().parse("info,crate1::mod1=warn").build();
-        assert!(enabled(&logger.directives, Level::Warn, "crate1::mod1"));
-        assert!(enabled(&logger.directives, Level::Info, "crate2::mod2"));
-    }
-
-    #[test]
-    fn match_full_path() {
-        let logger = make_logger_filter(vec![
-            Directive {
-                name: Some("crate2".to_string()),
-                level: LevelFilter::Info,
-            },
-            Directive {
-                name: Some("crate1::mod1".to_string()),
-                level: LevelFilter::Warn,
-            },
-        ]);
-        assert!(enabled(&logger.directives, Level::Warn, "crate1::mod1"));
-        assert!(!enabled(&logger.directives, Level::Info, "crate1::mod1"));
-        assert!(enabled(&logger.directives, Level::Info, "crate2"));
-        assert!(!enabled(&logger.directives, Level::Debug, "crate2"));
-    }
-
-    #[test]
-    fn no_match() {
-        let logger = make_logger_filter(vec![
-            Directive {
-                name: Some("crate2".to_string()),
-                level: LevelFilter::Info,
-            },
-            Directive {
-                name: Some("crate1::mod1".to_string()),
-                level: LevelFilter::Warn,
-            },
-        ]);
-        assert!(!enabled(&logger.directives, Level::Warn, "crate3"));
-    }
-
-    #[test]
-    fn match_beginning() {
-        let logger = make_logger_filter(vec![
-            Directive {
-                name: Some("crate2".to_string()),
-                level: LevelFilter::Info,
-            },
-            Directive {
-                name: Some("crate1::mod1".to_string()),
-                level: LevelFilter::Warn,
-            },
-        ]);
-        assert!(enabled(&logger.directives, Level::Info, "crate2::mod1"));
-    }
-
-    #[test]
-    fn match_beginning_longest_match() {
-        let logger = make_logger_filter(vec![
-            Directive {
-                name: Some("crate2".to_string()),
-                level: LevelFilter::Info,
-            },
-            Directive {
-                name: Some("crate2::mod".to_string()),
-                level: LevelFilter::Debug,
-            },
-            Directive {
-                name: Some("crate1::mod1".to_string()),
-                level: LevelFilter::Warn,
-            },
-        ]);
-        assert!(enabled(&logger.directives, Level::Debug, "crate2::mod1"));
-        assert!(!enabled(&logger.directives, Level::Debug, "crate2"));
-    }
-
-    #[test]
-    fn match_default() {
-        let logger = make_logger_filter(vec![
-            Directive {
-                name: None,
-                level: LevelFilter::Info,
-            },
-            Directive {
-                name: Some("crate1::mod1".to_string()),
-                level: LevelFilter::Warn,
-            },
-        ]);
-        assert!(enabled(&logger.directives, Level::Warn, "crate1::mod1"));
-        assert!(enabled(&logger.directives, Level::Info, "crate2::mod2"));
-    }
-
-    #[test]
-    fn zero_level() {
-        let logger = make_logger_filter(vec![
-            Directive {
-                name: None,
-                level: LevelFilter::Info,
-            },
-            Directive {
-                name: Some("crate1::mod1".to_string()),
-                level: LevelFilter::Off,
-            },
-        ]);
-        assert!(!enabled(&logger.directives, Level::Error, "crate1::mod1"));
-        assert!(enabled(&logger.directives, Level::Info, "crate2::mod2"));
-    }
-
-    #[test]
-    fn parse_spec_valid() {
-        let (dirs, filter) = parse_spec("crate1::mod1=error,crate1::mod2,crate2=debug");
-        assert_eq!(dirs.len(), 3);
-        assert_eq!(dirs[0].name, Some("crate1::mod1".to_string()));
-        assert_eq!(dirs[0].level, LevelFilter::Error);
-
-        assert_eq!(dirs[1].name, Some("crate1::mod2".to_string()));
-        assert_eq!(dirs[1].level, LevelFilter::max());
-
-        assert_eq!(dirs[2].name, Some("crate2".to_string()));
-        assert_eq!(dirs[2].level, LevelFilter::Debug);
-        assert!(filter.is_none());
-    }
-
-    #[test]
-    fn parse_spec_invalid_crate() {
-        // test parse_spec with multiple = in specification
-        let (dirs, filter) = parse_spec("crate1::mod1=warn=info,crate2=debug");
-        assert_eq!(dirs.len(), 1);
-        assert_eq!(dirs[0].name, Some("crate2".to_string()));
-        assert_eq!(dirs[0].level, LevelFilter::Debug);
-        assert!(filter.is_none());
-    }
-
-    #[test]
-    fn parse_spec_invalid_level() {
-        // test parse_spec with 'noNumber' as log level
-        let (dirs, filter) = parse_spec("crate1::mod1=noNumber,crate2=debug");
-        assert_eq!(dirs.len(), 1);
-        assert_eq!(dirs[0].name, Some("crate2".to_string()));
-        assert_eq!(dirs[0].level, LevelFilter::Debug);
-        assert!(filter.is_none());
-    }
-
-    #[test]
-    fn parse_spec_string_level() {
-        // test parse_spec with 'warn' as log level
-        let (dirs, filter) = parse_spec("crate1::mod1=wrong,crate2=warn");
-        assert_eq!(dirs.len(), 1);
-        assert_eq!(dirs[0].name, Some("crate2".to_string()));
-        assert_eq!(dirs[0].level, LevelFilter::Warn);
-        assert!(filter.is_none());
-    }
-
-    #[test]
-    fn parse_spec_empty_level() {
-        // test parse_spec with '' as log level
-        let (dirs, filter) = parse_spec("crate1::mod1=wrong,crate2=");
-        assert_eq!(dirs.len(), 1);
-        assert_eq!(dirs[0].name, Some("crate2".to_string()));
-        assert_eq!(dirs[0].level, LevelFilter::max());
-        assert!(filter.is_none());
-    }
-
-    #[test]
-    fn parse_spec_global() {
-        // test parse_spec with no crate
-        let (dirs, filter) = parse_spec("warn,crate2=debug");
-        assert_eq!(dirs.len(), 2);
-        assert_eq!(dirs[0].name, None);
-        assert_eq!(dirs[0].level, LevelFilter::Warn);
-        assert_eq!(dirs[1].name, Some("crate2".to_string()));
-        assert_eq!(dirs[1].level, LevelFilter::Debug);
-        assert!(filter.is_none());
-    }
-
-    #[test]
-    fn parse_spec_valid_filter() {
-        let (dirs, filter) = parse_spec("crate1::mod1=error,crate1::mod2,crate2=debug/abc");
-        assert_eq!(dirs.len(), 3);
-        assert_eq!(dirs[0].name, Some("crate1::mod1".to_string()));
-        assert_eq!(dirs[0].level, LevelFilter::Error);
-
-        assert_eq!(dirs[1].name, Some("crate1::mod2".to_string()));
-        assert_eq!(dirs[1].level, LevelFilter::max());
-
-        assert_eq!(dirs[2].name, Some("crate2".to_string()));
-        assert_eq!(dirs[2].level, LevelFilter::Debug);
-        assert!(filter.is_some() && filter.unwrap().to_string() == "abc");
-    }
-
-    #[test]
-    fn parse_spec_invalid_crate_filter() {
-        let (dirs, filter) = parse_spec("crate1::mod1=error=warn,crate2=debug/a.c");
-        assert_eq!(dirs.len(), 1);
-        assert_eq!(dirs[0].name, Some("crate2".to_string()));
-        assert_eq!(dirs[0].level, LevelFilter::Debug);
-        assert!(filter.is_some() && filter.unwrap().to_string() == "a.c");
-    }
-
-    #[test]
-    fn parse_spec_empty_with_filter() {
-        let (dirs, filter) = parse_spec("crate1/a*c");
-        assert_eq!(dirs.len(), 1);
-        assert_eq!(dirs[0].name, Some("crate1".to_string()));
-        assert_eq!(dirs[0].level, LevelFilter::max());
-        assert!(filter.is_some() && filter.unwrap().to_string() == "a*c");
-    }
-}
diff --git a/third_party/rust/env_logger-0.7.1/src/filter/regex.rs b/third_party/rust/env_logger-0.7.1/src/filter/regex.rs
deleted file mode 100644
index fb21528a121614290b05e5dc61943916b46e1ecf..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/src/filter/regex.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-extern crate regex;
-
-use std::fmt;
-
-use self::regex::Regex;
-
-#[derive(Debug)]
-pub struct Filter {
-    inner: Regex,
-}
-
-impl Filter {
-    pub fn new(spec: &str) -> Result<Filter, String> {
-        match Regex::new(spec) {
-            Ok(r) => Ok(Filter { inner: r }),
-            Err(e) => Err(e.to_string()),
-        }
-    }
-
-    pub fn is_match(&self, s: &str) -> bool {
-        self.inner.is_match(s)
-    }
-}
-
-impl fmt::Display for Filter {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.inner.fmt(f)
-    }
-}
diff --git a/third_party/rust/env_logger-0.7.1/src/filter/string.rs b/third_party/rust/env_logger-0.7.1/src/filter/string.rs
deleted file mode 100644
index ea476e42f934fd80d1314f73737e320994281072..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/src/filter/string.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-use std::fmt;
-
-#[derive(Debug)]
-pub struct Filter {
-    inner: String,
-}
-
-impl Filter {
-    pub fn new(spec: &str) -> Result<Filter, String> {
-        Ok(Filter {
-            inner: spec.to_string(),
-        })
-    }
-
-    pub fn is_match(&self, s: &str) -> bool {
-        s.contains(&self.inner)
-    }
-}
-
-impl fmt::Display for Filter {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.inner.fmt(f)
-    }
-}
diff --git a/third_party/rust/env_logger-0.7.1/src/fmt/humantime/extern_impl.rs b/third_party/rust/env_logger-0.7.1/src/fmt/humantime/extern_impl.rs
deleted file mode 100644
index 19dec1b65d39065fcff5d88a8988619f3c08c1fc..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/src/fmt/humantime/extern_impl.rs
+++ /dev/null
@@ -1,118 +0,0 @@
-use std::fmt;
-use std::time::SystemTime;
-
-use humantime::{
-    format_rfc3339_micros, format_rfc3339_millis, format_rfc3339_nanos, format_rfc3339_seconds,
-};
-
-use crate::fmt::{Formatter, TimestampPrecision};
-
-pub(in crate::fmt) mod glob {
-    pub use super::*;
-}
-
-impl Formatter {
-    /// Get a [`Timestamp`] for the current date and time in UTC.
-    ///
-    /// # Examples
-    ///
-    /// Include the current timestamp with the log record:
-    ///
-    /// ```
-    /// use std::io::Write;
-    ///
-    /// let mut builder = env_logger::Builder::new();
-    ///
-    /// builder.format(|buf, record| {
-    ///     let ts = buf.timestamp();
-    ///
-    ///     writeln!(buf, "{}: {}: {}", ts, record.level(), record.args())
-    /// });
-    /// ```
-    ///
-    /// [`Timestamp`]: struct.Timestamp.html
-    pub fn timestamp(&self) -> Timestamp {
-        Timestamp {
-            time: SystemTime::now(),
-            precision: TimestampPrecision::Seconds,
-        }
-    }
-
-    /// Get a [`Timestamp`] for the current date and time in UTC with full
-    /// second precision.
-    pub fn timestamp_seconds(&self) -> Timestamp {
-        Timestamp {
-            time: SystemTime::now(),
-            precision: TimestampPrecision::Seconds,
-        }
-    }
-
-    /// Get a [`Timestamp`] for the current date and time in UTC with
-    /// millisecond precision.
-    pub fn timestamp_millis(&self) -> Timestamp {
-        Timestamp {
-            time: SystemTime::now(),
-            precision: TimestampPrecision::Millis,
-        }
-    }
-
-    /// Get a [`Timestamp`] for the current date and time in UTC with
-    /// microsecond precision.
-    pub fn timestamp_micros(&self) -> Timestamp {
-        Timestamp {
-            time: SystemTime::now(),
-            precision: TimestampPrecision::Micros,
-        }
-    }
-
-    /// Get a [`Timestamp`] for the current date and time in UTC with
-    /// nanosecond precision.
-    pub fn timestamp_nanos(&self) -> Timestamp {
-        Timestamp {
-            time: SystemTime::now(),
-            precision: TimestampPrecision::Nanos,
-        }
-    }
-}
-
-/// An [RFC3339] formatted timestamp.
-///
-/// The timestamp implements [`Display`] and can be written to a [`Formatter`].
-///
-/// [RFC3339]: https://www.ietf.org/rfc/rfc3339.txt
-/// [`Display`]: https://doc.rust-lang.org/stable/std/fmt/trait.Display.html
-/// [`Formatter`]: struct.Formatter.html
-pub struct Timestamp {
-    time: SystemTime,
-    precision: TimestampPrecision,
-}
-
-impl fmt::Debug for Timestamp {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        /// A `Debug` wrapper for `Timestamp` that uses the `Display` implementation.
-        struct TimestampValue<'a>(&'a Timestamp);
-
-        impl<'a> fmt::Debug for TimestampValue<'a> {
-            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-                fmt::Display::fmt(&self.0, f)
-            }
-        }
-
-        f.debug_tuple("Timestamp")
-            .field(&TimestampValue(&self))
-            .finish()
-    }
-}
-
-impl fmt::Display for Timestamp {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let formatter = match self.precision {
-            TimestampPrecision::Seconds => format_rfc3339_seconds,
-            TimestampPrecision::Millis => format_rfc3339_millis,
-            TimestampPrecision::Micros => format_rfc3339_micros,
-            TimestampPrecision::Nanos => format_rfc3339_nanos,
-        };
-
-        formatter(self.time).fmt(f)
-    }
-}
diff --git a/third_party/rust/env_logger-0.7.1/src/fmt/humantime/mod.rs b/third_party/rust/env_logger-0.7.1/src/fmt/humantime/mod.rs
deleted file mode 100644
index ac23ae2493f36637c5532bd008e5f755bc65ebfa..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/src/fmt/humantime/mod.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
-This internal module contains the timestamp implementation.
-
-Its public API is available when the `humantime` crate is available.
-*/
-
-#[cfg_attr(feature = "humantime", path = "extern_impl.rs")]
-#[cfg_attr(not(feature = "humantime"), path = "shim_impl.rs")]
-mod imp;
-
-pub(in crate::fmt) use self::imp::*;
diff --git a/third_party/rust/env_logger-0.7.1/src/fmt/humantime/shim_impl.rs b/third_party/rust/env_logger-0.7.1/src/fmt/humantime/shim_impl.rs
deleted file mode 100644
index 906bf9e4c1a6a96f284c413b450142f2621ce334..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/src/fmt/humantime/shim_impl.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
-Timestamps aren't available when we don't have a `humantime` dependency.
-*/
-
-pub(in crate::fmt) mod glob {}
diff --git a/third_party/rust/env_logger-0.7.1/src/fmt/mod.rs b/third_party/rust/env_logger-0.7.1/src/fmt/mod.rs
deleted file mode 100644
index e699e214d64b0aa76da8066a76eadaee21e04919..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/src/fmt/mod.rs
+++ /dev/null
@@ -1,489 +0,0 @@
-//! Formatting for log records.
-//!
-//! This module contains a [`Formatter`] that can be used to format log records
-//! into without needing temporary allocations. Usually you won't need to worry
-//! about the contents of this module and can use the `Formatter` like an ordinary
-//! [`Write`].
-//!
-//! # Formatting log records
-//!
-//! The format used to print log records can be customised using the [`Builder::format`]
-//! method.
-//! Custom formats can apply different color and weight to printed values using
-//! [`Style`] builders.
-//!
-//! ```
-//! use std::io::Write;
-//!
-//! let mut builder = env_logger::Builder::new();
-//!
-//! builder.format(|buf, record| {
-//!     writeln!(buf, "{}: {}",
-//!         record.level(),
-//!         record.args())
-//! });
-//! ```
-//!
-//! [`Formatter`]: struct.Formatter.html
-//! [`Style`]: struct.Style.html
-//! [`Builder::format`]: ../struct.Builder.html#method.format
-//! [`Write`]: https://doc.rust-lang.org/stable/std/io/trait.Write.html
-
-use std::cell::RefCell;
-use std::fmt::Display;
-use std::io::prelude::*;
-use std::rc::Rc;
-use std::{fmt, io, mem};
-
-use log::Record;
-
-mod humantime;
-pub(crate) mod writer;
-
-pub use self::humantime::glob::*;
-pub use self::writer::glob::*;
-
-use self::writer::{Buffer, Writer};
-
-pub(crate) mod glob {
-    pub use super::{Target, TimestampPrecision, WriteStyle};
-}
-
-/// Formatting precision of timestamps.
-///
-/// Seconds give precision of full seconds, milliseconds give thousands of a
-/// second (3 decimal digits), microseconds are millionth of a second (6 decimal
-/// digits) and nanoseconds are billionth of a second (9 decimal digits).
-#[derive(Copy, Clone, Debug)]
-pub enum TimestampPrecision {
-    /// Full second precision (0 decimal digits)
-    Seconds,
-    /// Millisecond precision (3 decimal digits)
-    Millis,
-    /// Microsecond precision (6 decimal digits)
-    Micros,
-    /// Nanosecond precision (9 decimal digits)
-    Nanos,
-}
-
-/// The default timestamp precision is seconds.
-impl Default for TimestampPrecision {
-    fn default() -> Self {
-        TimestampPrecision::Seconds
-    }
-}
-
-/// A formatter to write logs into.
-///
-/// `Formatter` implements the standard [`Write`] trait for writing log records.
-/// It also supports terminal colors, through the [`style`] method.
-///
-/// # Examples
-///
-/// Use the [`writeln`] macro to format a log record.
-/// An instance of a `Formatter` is passed to an `env_logger` format as `buf`:
-///
-/// ```
-/// use std::io::Write;
-///
-/// let mut builder = env_logger::Builder::new();
-///
-/// builder.format(|buf, record| writeln!(buf, "{}: {}", record.level(), record.args()));
-/// ```
-///
-/// [`Write`]: https://doc.rust-lang.org/stable/std/io/trait.Write.html
-/// [`writeln`]: https://doc.rust-lang.org/stable/std/macro.writeln.html
-/// [`style`]: #method.style
-pub struct Formatter {
-    buf: Rc<RefCell<Buffer>>,
-    write_style: WriteStyle,
-}
-
-impl Formatter {
-    pub(crate) fn new(writer: &Writer) -> Self {
-        Formatter {
-            buf: Rc::new(RefCell::new(writer.buffer())),
-            write_style: writer.write_style(),
-        }
-    }
-
-    pub(crate) fn write_style(&self) -> WriteStyle {
-        self.write_style
-    }
-
-    pub(crate) fn print(&self, writer: &Writer) -> io::Result<()> {
-        writer.print(&self.buf.borrow())
-    }
-
-    pub(crate) fn clear(&mut self) {
-        self.buf.borrow_mut().clear()
-    }
-}
-
-impl Write for Formatter {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        self.buf.borrow_mut().write(buf)
-    }
-
-    fn flush(&mut self) -> io::Result<()> {
-        self.buf.borrow_mut().flush()
-    }
-}
-
-impl fmt::Debug for Formatter {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("Formatter").finish()
-    }
-}
-
-pub(crate) struct Builder {
-    pub format_timestamp: Option<TimestampPrecision>,
-    pub format_module_path: bool,
-    pub format_level: bool,
-    pub format_indent: Option<usize>,
-    #[allow(unknown_lints, bare_trait_objects)]
-    pub custom_format: Option<Box<Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send>>,
-    built: bool,
-}
-
-impl Default for Builder {
-    fn default() -> Self {
-        Builder {
-            format_timestamp: Some(Default::default()),
-            format_module_path: true,
-            format_level: true,
-            format_indent: Some(4),
-            custom_format: None,
-            built: false,
-        }
-    }
-}
-
-impl Builder {
-    /// Convert the format into a callable function.
-    ///
-    /// If the `custom_format` is `Some`, then any `default_format` switches are ignored.
-    /// If the `custom_format` is `None`, then a default format is returned.
-    /// Any `default_format` switches set to `false` won't be written by the format.
-    #[allow(unknown_lints, bare_trait_objects)]
-    pub fn build(&mut self) -> Box<Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send> {
-        assert!(!self.built, "attempt to re-use consumed builder");
-
-        let built = mem::replace(
-            self,
-            Builder {
-                built: true,
-                ..Default::default()
-            },
-        );
-
-        if let Some(fmt) = built.custom_format {
-            fmt
-        } else {
-            Box::new(move |buf, record| {
-                let fmt = DefaultFormat {
-                    timestamp: built.format_timestamp,
-                    module_path: built.format_module_path,
-                    level: built.format_level,
-                    written_header_value: false,
-                    indent: built.format_indent,
-                    buf,
-                };
-
-                fmt.write(record)
-            })
-        }
-    }
-}
-
-#[cfg(feature = "termcolor")]
-type SubtleStyle = StyledValue<'static, &'static str>;
-#[cfg(not(feature = "termcolor"))]
-type SubtleStyle = &'static str;
-
-/// The default format.
-///
-/// This format needs to work with any combination of crate features.
-struct DefaultFormat<'a> {
-    timestamp: Option<TimestampPrecision>,
-    module_path: bool,
-    level: bool,
-    written_header_value: bool,
-    indent: Option<usize>,
-    buf: &'a mut Formatter,
-}
-
-impl<'a> DefaultFormat<'a> {
-    fn write(mut self, record: &Record) -> io::Result<()> {
-        self.write_timestamp()?;
-        self.write_level(record)?;
-        self.write_module_path(record)?;
-        self.finish_header()?;
-
-        self.write_args(record)
-    }
-
-    fn subtle_style(&self, text: &'static str) -> SubtleStyle {
-        #[cfg(feature = "termcolor")]
-        {
-            self.buf
-                .style()
-                .set_color(Color::Black)
-                .set_intense(true)
-                .into_value(text)
-        }
-        #[cfg(not(feature = "termcolor"))]
-        {
-            text
-        }
-    }
-
-    fn write_header_value<T>(&mut self, value: T) -> io::Result<()>
-    where
-        T: Display,
-    {
-        if !self.written_header_value {
-            self.written_header_value = true;
-
-            let open_brace = self.subtle_style("[");
-            write!(self.buf, "{}{}", open_brace, value)
-        } else {
-            write!(self.buf, " {}", value)
-        }
-    }
-
-    fn write_level(&mut self, record: &Record) -> io::Result<()> {
-        if !self.level {
-            return Ok(());
-        }
-
-        let level = {
-            #[cfg(feature = "termcolor")]
-            {
-                self.buf.default_styled_level(record.level())
-            }
-            #[cfg(not(feature = "termcolor"))]
-            {
-                record.level()
-            }
-        };
-
-        self.write_header_value(format_args!("{:<5}", level))
-    }
-
-    fn write_timestamp(&mut self) -> io::Result<()> {
-        #[cfg(feature = "humantime")]
-        {
-            use self::TimestampPrecision::*;
-            let ts = match self.timestamp {
-                None => return Ok(()),
-                Some(Seconds) => self.buf.timestamp_seconds(),
-                Some(Millis) => self.buf.timestamp_millis(),
-                Some(Micros) => self.buf.timestamp_micros(),
-                Some(Nanos) => self.buf.timestamp_nanos(),
-            };
-
-            self.write_header_value(ts)
-        }
-        #[cfg(not(feature = "humantime"))]
-        {
-            // Trick the compiler to think we have used self.timestamp
-            // Workaround for "field is never used: `timestamp`" compiler nag.
-            let _ = self.timestamp;
-            Ok(())
-        }
-    }
-
-    fn write_module_path(&mut self, record: &Record) -> io::Result<()> {
-        if !self.module_path {
-            return Ok(());
-        }
-
-        if let Some(module_path) = record.module_path() {
-            self.write_header_value(module_path)
-        } else {
-            Ok(())
-        }
-    }
-
-    fn finish_header(&mut self) -> io::Result<()> {
-        if self.written_header_value {
-            let close_brace = self.subtle_style("]");
-            write!(self.buf, "{} ", close_brace)
-        } else {
-            Ok(())
-        }
-    }
-
-    fn write_args(&mut self, record: &Record) -> io::Result<()> {
-        match self.indent {
-            // Fast path for no indentation
-            None => writeln!(self.buf, "{}", record.args()),
-
-            Some(indent_count) => {
-                // Create a wrapper around the buffer only if we have to actually indent the message
-
-                struct IndentWrapper<'a, 'b: 'a> {
-                    fmt: &'a mut DefaultFormat<'b>,
-                    indent_count: usize,
-                }
-
-                impl<'a, 'b> Write for IndentWrapper<'a, 'b> {
-                    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-                        let mut first = true;
-                        for chunk in buf.split(|&x| x == b'\n') {
-                            if !first {
-                                write!(self.fmt.buf, "\n{:width$}", "", width = self.indent_count)?;
-                            }
-                            self.fmt.buf.write_all(chunk)?;
-                            first = false;
-                        }
-
-                        Ok(buf.len())
-                    }
-
-                    fn flush(&mut self) -> io::Result<()> {
-                        self.fmt.buf.flush()
-                    }
-                }
-
-                // The explicit scope here is just to make older versions of Rust happy
-                {
-                    let mut wrapper = IndentWrapper {
-                        fmt: self,
-                        indent_count,
-                    };
-                    write!(wrapper, "{}", record.args())?;
-                }
-
-                writeln!(self.buf)?;
-
-                Ok(())
-            }
-        }
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    use log::{Level, Record};
-
-    fn write(fmt: DefaultFormat) -> String {
-        let buf = fmt.buf.buf.clone();
-
-        let record = Record::builder()
-            .args(format_args!("log\nmessage"))
-            .level(Level::Info)
-            .file(Some("test.rs"))
-            .line(Some(144))
-            .module_path(Some("test::path"))
-            .build();
-
-        fmt.write(&record).expect("failed to write record");
-
-        let buf = buf.borrow();
-        String::from_utf8(buf.bytes().to_vec()).expect("failed to read record")
-    }
-
-    #[test]
-    fn format_with_header() {
-        let writer = writer::Builder::new()
-            .write_style(WriteStyle::Never)
-            .build();
-
-        let mut f = Formatter::new(&writer);
-
-        let written = write(DefaultFormat {
-            timestamp: None,
-            module_path: true,
-            level: true,
-            written_header_value: false,
-            indent: None,
-            buf: &mut f,
-        });
-
-        assert_eq!("[INFO  test::path] log\nmessage\n", written);
-    }
-
-    #[test]
-    fn format_no_header() {
-        let writer = writer::Builder::new()
-            .write_style(WriteStyle::Never)
-            .build();
-
-        let mut f = Formatter::new(&writer);
-
-        let written = write(DefaultFormat {
-            timestamp: None,
-            module_path: false,
-            level: false,
-            written_header_value: false,
-            indent: None,
-            buf: &mut f,
-        });
-
-        assert_eq!("log\nmessage\n", written);
-    }
-
-    #[test]
-    fn format_indent_spaces() {
-        let writer = writer::Builder::new()
-            .write_style(WriteStyle::Never)
-            .build();
-
-        let mut f = Formatter::new(&writer);
-
-        let written = write(DefaultFormat {
-            timestamp: None,
-            module_path: true,
-            level: true,
-            written_header_value: false,
-            indent: Some(4),
-            buf: &mut f,
-        });
-
-        assert_eq!("[INFO  test::path] log\n    message\n", written);
-    }
-
-    #[test]
-    fn format_indent_zero_spaces() {
-        let writer = writer::Builder::new()
-            .write_style(WriteStyle::Never)
-            .build();
-
-        let mut f = Formatter::new(&writer);
-
-        let written = write(DefaultFormat {
-            timestamp: None,
-            module_path: true,
-            level: true,
-            written_header_value: false,
-            indent: Some(0),
-            buf: &mut f,
-        });
-
-        assert_eq!("[INFO  test::path] log\nmessage\n", written);
-    }
-
-    #[test]
-    fn format_indent_spaces_no_header() {
-        let writer = writer::Builder::new()
-            .write_style(WriteStyle::Never)
-            .build();
-
-        let mut f = Formatter::new(&writer);
-
-        let written = write(DefaultFormat {
-            timestamp: None,
-            module_path: false,
-            level: false,
-            written_header_value: false,
-            indent: Some(4),
-            buf: &mut f,
-        });
-
-        assert_eq!("log\n    message\n", written);
-    }
-}
diff --git a/third_party/rust/env_logger-0.7.1/src/fmt/writer/atty.rs b/third_party/rust/env_logger-0.7.1/src/fmt/writer/atty.rs
deleted file mode 100644
index f6718413f0d68cf09b15443134734529ca095903..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/src/fmt/writer/atty.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-This internal module contains the terminal detection implementation.
-
-If the `atty` crate is available then we use it to detect whether we're
-attached to a particular TTY. If the `atty` crate is not available we
-assume we're not attached to anything. This effectively prevents styles
-from being printed.
-*/
-
-#[cfg(feature = "atty")]
-mod imp {
-    use atty;
-
-    pub(in crate::fmt) fn is_stdout() -> bool {
-        atty::is(atty::Stream::Stdout)
-    }
-
-    pub(in crate::fmt) fn is_stderr() -> bool {
-        atty::is(atty::Stream::Stderr)
-    }
-}
-
-#[cfg(not(feature = "atty"))]
-mod imp {
-    pub(in crate::fmt) fn is_stdout() -> bool {
-        false
-    }
-
-    pub(in crate::fmt) fn is_stderr() -> bool {
-        false
-    }
-}
-
-pub(in crate::fmt) use self::imp::*;
diff --git a/third_party/rust/env_logger-0.7.1/src/fmt/writer/mod.rs b/third_party/rust/env_logger-0.7.1/src/fmt/writer/mod.rs
deleted file mode 100644
index 6ee63a39811c1d979b4274019a8563b6b8c81163..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/src/fmt/writer/mod.rs
+++ /dev/null
@@ -1,201 +0,0 @@
-mod atty;
-mod termcolor;
-
-use self::atty::{is_stderr, is_stdout};
-use self::termcolor::BufferWriter;
-use std::{fmt, io};
-
-pub(in crate::fmt) mod glob {
-    pub use super::termcolor::glob::*;
-    pub use super::*;
-}
-
-pub(in crate::fmt) use self::termcolor::Buffer;
-
-/// Log target, either `stdout` or `stderr`.
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub enum Target {
-    /// Logs will be sent to standard output.
-    Stdout,
-    /// Logs will be sent to standard error.
-    Stderr,
-}
-
-impl Default for Target {
-    fn default() -> Self {
-        Target::Stderr
-    }
-}
-
-/// Whether or not to print styles to the target.
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub enum WriteStyle {
-    /// Try to print styles, but don't force the issue.
-    Auto,
-    /// Try very hard to print styles.
-    Always,
-    /// Never print styles.
-    Never,
-}
-
-impl Default for WriteStyle {
-    fn default() -> Self {
-        WriteStyle::Auto
-    }
-}
-
-/// A terminal target with color awareness.
-pub(crate) struct Writer {
-    inner: BufferWriter,
-    write_style: WriteStyle,
-}
-
-impl Writer {
-    pub fn write_style(&self) -> WriteStyle {
-        self.write_style
-    }
-
-    pub(in crate::fmt) fn buffer(&self) -> Buffer {
-        self.inner.buffer()
-    }
-
-    pub(in crate::fmt) fn print(&self, buf: &Buffer) -> io::Result<()> {
-        self.inner.print(buf)
-    }
-}
-
-/// A builder for a terminal writer.
-///
-/// The target and style choice can be configured before building.
-pub(crate) struct Builder {
-    target: Target,
-    write_style: WriteStyle,
-    is_test: bool,
-    built: bool,
-}
-
-impl Builder {
-    /// Initialize the writer builder with defaults.
-    pub(crate) fn new() -> Self {
-        Builder {
-            target: Default::default(),
-            write_style: Default::default(),
-            is_test: false,
-            built: false,
-        }
-    }
-
-    /// Set the target to write to.
-    pub(crate) fn target(&mut self, target: Target) -> &mut Self {
-        self.target = target;
-        self
-    }
-
-    /// Parses a style choice string.
-    ///
-    /// See the [Disabling colors] section for more details.
-    ///
-    /// [Disabling colors]: ../index.html#disabling-colors
-    pub(crate) fn parse_write_style(&mut self, write_style: &str) -> &mut Self {
-        self.write_style(parse_write_style(write_style))
-    }
-
-    /// Whether or not to print style characters when writing.
-    pub(crate) fn write_style(&mut self, write_style: WriteStyle) -> &mut Self {
-        self.write_style = write_style;
-        self
-    }
-
-    /// Whether or not to capture logs for `cargo test`.
-    pub(crate) fn is_test(&mut self, is_test: bool) -> &mut Self {
-        self.is_test = is_test;
-        self
-    }
-
-    /// Build a terminal writer.
-    pub(crate) fn build(&mut self) -> Writer {
-        assert!(!self.built, "attempt to re-use consumed builder");
-        self.built = true;
-
-        let color_choice = match self.write_style {
-            WriteStyle::Auto => {
-                if match self.target {
-                    Target::Stderr => is_stderr(),
-                    Target::Stdout => is_stdout(),
-                } {
-                    WriteStyle::Auto
-                } else {
-                    WriteStyle::Never
-                }
-            }
-            color_choice => color_choice,
-        };
-
-        let writer = match self.target {
-            Target::Stderr => BufferWriter::stderr(self.is_test, color_choice),
-            Target::Stdout => BufferWriter::stdout(self.is_test, color_choice),
-        };
-
-        Writer {
-            inner: writer,
-            write_style: self.write_style,
-        }
-    }
-}
-
-impl Default for Builder {
-    fn default() -> Self {
-        Builder::new()
-    }
-}
-
-impl fmt::Debug for Builder {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("Logger")
-            .field("target", &self.target)
-            .field("write_style", &self.write_style)
-            .finish()
-    }
-}
-
-impl fmt::Debug for Writer {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("Writer").finish()
-    }
-}
-
-fn parse_write_style(spec: &str) -> WriteStyle {
-    match spec {
-        "auto" => WriteStyle::Auto,
-        "always" => WriteStyle::Always,
-        "never" => WriteStyle::Never,
-        _ => Default::default(),
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    fn parse_write_style_valid() {
-        let inputs = vec![
-            ("auto", WriteStyle::Auto),
-            ("always", WriteStyle::Always),
-            ("never", WriteStyle::Never),
-        ];
-
-        for (input, expected) in inputs {
-            assert_eq!(expected, parse_write_style(input));
-        }
-    }
-
-    #[test]
-    fn parse_write_style_invalid() {
-        let inputs = vec!["", "true", "false", "NEVER!!"];
-
-        for input in inputs {
-            assert_eq!(WriteStyle::Auto, parse_write_style(input));
-        }
-    }
-}
diff --git a/third_party/rust/env_logger-0.7.1/src/fmt/writer/termcolor/extern_impl.rs b/third_party/rust/env_logger-0.7.1/src/fmt/writer/termcolor/extern_impl.rs
deleted file mode 100644
index 2d38e375aaf412b45f85061313b9b2818ce96ad4..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/src/fmt/writer/termcolor/extern_impl.rs
+++ /dev/null
@@ -1,486 +0,0 @@
-use std::borrow::Cow;
-use std::cell::RefCell;
-use std::fmt;
-use std::io::{self, Write};
-use std::rc::Rc;
-
-use log::Level;
-use termcolor::{self, ColorChoice, ColorSpec, WriteColor};
-
-use crate::fmt::{Formatter, Target, WriteStyle};
-
-pub(in crate::fmt::writer) mod glob {
-    pub use super::*;
-}
-
-impl Formatter {
-    /// Begin a new [`Style`].
-    ///
-    /// # Examples
-    ///
-    /// Create a bold, red colored style and use it to print the log level:
-    ///
-    /// ```
-    /// use std::io::Write;
-    /// use env_logger::fmt::Color;
-    ///
-    /// let mut builder = env_logger::Builder::new();
-    ///
-    /// builder.format(|buf, record| {
-    ///     let mut level_style = buf.style();
-    ///
-    ///     level_style.set_color(Color::Red).set_bold(true);
-    ///
-    ///     writeln!(buf, "{}: {}",
-    ///         level_style.value(record.level()),
-    ///         record.args())
-    /// });
-    /// ```
-    ///
-    /// [`Style`]: struct.Style.html
-    pub fn style(&self) -> Style {
-        Style {
-            buf: self.buf.clone(),
-            spec: ColorSpec::new(),
-        }
-    }
-
-    /// Get the default [`Style`] for the given level.
-    ///
-    /// The style can be used to print other values besides the level.
-    pub fn default_level_style(&self, level: Level) -> Style {
-        let mut level_style = self.style();
-        match level {
-            Level::Trace => level_style.set_color(Color::Black).set_intense(true),
-            Level::Debug => level_style.set_color(Color::White),
-            Level::Info => level_style.set_color(Color::Green),
-            Level::Warn => level_style.set_color(Color::Yellow),
-            Level::Error => level_style.set_color(Color::Red).set_bold(true),
-        };
-        level_style
-    }
-
-    /// Get a printable [`Style`] for the given level.
-    ///
-    /// The style can only be used to print the level.
-    pub fn default_styled_level(&self, level: Level) -> StyledValue<'static, Level> {
-        self.default_level_style(level).into_value(level)
-    }
-}
-
-pub(in crate::fmt::writer) struct BufferWriter {
-    inner: termcolor::BufferWriter,
-    test_target: Option<Target>,
-}
-
-pub(in crate::fmt) struct Buffer {
-    inner: termcolor::Buffer,
-    test_target: Option<Target>,
-}
-
-impl BufferWriter {
-    pub(in crate::fmt::writer) fn stderr(is_test: bool, write_style: WriteStyle) -> Self {
-        BufferWriter {
-            inner: termcolor::BufferWriter::stderr(write_style.into_color_choice()),
-            test_target: if is_test { Some(Target::Stderr) } else { None },
-        }
-    }
-
-    pub(in crate::fmt::writer) fn stdout(is_test: bool, write_style: WriteStyle) -> Self {
-        BufferWriter {
-            inner: termcolor::BufferWriter::stdout(write_style.into_color_choice()),
-            test_target: if is_test { Some(Target::Stdout) } else { None },
-        }
-    }
-
-    pub(in crate::fmt::writer) fn buffer(&self) -> Buffer {
-        Buffer {
-            inner: self.inner.buffer(),
-            test_target: self.test_target,
-        }
-    }
-
-    pub(in crate::fmt::writer) fn print(&self, buf: &Buffer) -> io::Result<()> {
-        if let Some(target) = self.test_target {
-            // This impl uses the `eprint` and `print` macros
-            // instead of `termcolor`'s buffer.
-            // This is so their output can be captured by `cargo test`
-            let log = String::from_utf8_lossy(buf.bytes());
-
-            match target {
-                Target::Stderr => eprint!("{}", log),
-                Target::Stdout => print!("{}", log),
-            }
-
-            Ok(())
-        } else {
-            self.inner.print(&buf.inner)
-        }
-    }
-}
-
-impl Buffer {
-    pub(in crate::fmt) fn clear(&mut self) {
-        self.inner.clear()
-    }
-
-    pub(in crate::fmt) fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        self.inner.write(buf)
-    }
-
-    pub(in crate::fmt) fn flush(&mut self) -> io::Result<()> {
-        self.inner.flush()
-    }
-
-    pub(in crate::fmt) fn bytes(&self) -> &[u8] {
-        self.inner.as_slice()
-    }
-
-    fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> {
-        // Ignore styles for test captured logs because they can't be printed
-        if self.test_target.is_none() {
-            self.inner.set_color(spec)
-        } else {
-            Ok(())
-        }
-    }
-
-    fn reset(&mut self) -> io::Result<()> {
-        // Ignore styles for test captured logs because they can't be printed
-        if self.test_target.is_none() {
-            self.inner.reset()
-        } else {
-            Ok(())
-        }
-    }
-}
-
-impl WriteStyle {
-    fn into_color_choice(self) -> ColorChoice {
-        match self {
-            WriteStyle::Always => ColorChoice::Always,
-            WriteStyle::Auto => ColorChoice::Auto,
-            WriteStyle::Never => ColorChoice::Never,
-        }
-    }
-}
-
-/// A set of styles to apply to the terminal output.
-///
-/// Call [`Formatter::style`] to get a `Style` and use the builder methods to
-/// set styling properties, like [color] and [weight].
-/// To print a value using the style, wrap it in a call to [`value`] when the log
-/// record is formatted.
-///
-/// # Examples
-///
-/// Create a bold, red colored style and use it to print the log level:
-///
-/// ```
-/// use std::io::Write;
-/// use env_logger::fmt::Color;
-///
-/// let mut builder = env_logger::Builder::new();
-///
-/// builder.format(|buf, record| {
-///     let mut level_style = buf.style();
-///
-///     level_style.set_color(Color::Red).set_bold(true);
-///
-///     writeln!(buf, "{}: {}",
-///         level_style.value(record.level()),
-///         record.args())
-/// });
-/// ```
-///
-/// Styles can be re-used to output multiple values:
-///
-/// ```
-/// use std::io::Write;
-/// use env_logger::fmt::Color;
-///
-/// let mut builder = env_logger::Builder::new();
-///
-/// builder.format(|buf, record| {
-///     let mut bold = buf.style();
-///
-///     bold.set_bold(true);
-///
-///     writeln!(buf, "{}: {} {}",
-///         bold.value(record.level()),
-///         bold.value("some bold text"),
-///         record.args())
-/// });
-/// ```
-///
-/// [`Formatter::style`]: struct.Formatter.html#method.style
-/// [color]: #method.set_color
-/// [weight]: #method.set_bold
-/// [`value`]: #method.value
-#[derive(Clone)]
-pub struct Style {
-    buf: Rc<RefCell<Buffer>>,
-    spec: ColorSpec,
-}
-
-/// A value that can be printed using the given styles.
-///
-/// It is the result of calling [`Style::value`].
-///
-/// [`Style::value`]: struct.Style.html#method.value
-pub struct StyledValue<'a, T> {
-    style: Cow<'a, Style>,
-    value: T,
-}
-
-impl Style {
-    /// Set the text color.
-    ///
-    /// # Examples
-    ///
-    /// Create a style with red text:
-    ///
-    /// ```
-    /// use std::io::Write;
-    /// use env_logger::fmt::Color;
-    ///
-    /// let mut builder = env_logger::Builder::new();
-    ///
-    /// builder.format(|buf, record| {
-    ///     let mut style = buf.style();
-    ///
-    ///     style.set_color(Color::Red);
-    ///
-    ///     writeln!(buf, "{}", style.value(record.args()))
-    /// });
-    /// ```
-    pub fn set_color(&mut self, color: Color) -> &mut Style {
-        self.spec.set_fg(color.into_termcolor());
-        self
-    }
-
-    /// Set the text weight.
-    ///
-    /// If `yes` is true then text will be written in bold.
-    /// If `yes` is false then text will be written in the default weight.
-    ///
-    /// # Examples
-    ///
-    /// Create a style with bold text:
-    ///
-    /// ```
-    /// use std::io::Write;
-    ///
-    /// let mut builder = env_logger::Builder::new();
-    ///
-    /// builder.format(|buf, record| {
-    ///     let mut style = buf.style();
-    ///
-    ///     style.set_bold(true);
-    ///
-    ///     writeln!(buf, "{}", style.value(record.args()))
-    /// });
-    /// ```
-    pub fn set_bold(&mut self, yes: bool) -> &mut Style {
-        self.spec.set_bold(yes);
-        self
-    }
-
-    /// Set the text intensity.
-    ///
-    /// If `yes` is true then text will be written in a brighter color.
-    /// If `yes` is false then text will be written in the default color.
-    ///
-    /// # Examples
-    ///
-    /// Create a style with intense text:
-    ///
-    /// ```
-    /// use std::io::Write;
-    ///
-    /// let mut builder = env_logger::Builder::new();
-    ///
-    /// builder.format(|buf, record| {
-    ///     let mut style = buf.style();
-    ///
-    ///     style.set_intense(true);
-    ///
-    ///     writeln!(buf, "{}", style.value(record.args()))
-    /// });
-    /// ```
-    pub fn set_intense(&mut self, yes: bool) -> &mut Style {
-        self.spec.set_intense(yes);
-        self
-    }
-
-    /// Set the background color.
-    ///
-    /// # Examples
-    ///
-    /// Create a style with a yellow background:
-    ///
-    /// ```
-    /// use std::io::Write;
-    /// use env_logger::fmt::Color;
-    ///
-    /// let mut builder = env_logger::Builder::new();
-    ///
-    /// builder.format(|buf, record| {
-    ///     let mut style = buf.style();
-    ///
-    ///     style.set_bg(Color::Yellow);
-    ///
-    ///     writeln!(buf, "{}", style.value(record.args()))
-    /// });
-    /// ```
-    pub fn set_bg(&mut self, color: Color) -> &mut Style {
-        self.spec.set_bg(color.into_termcolor());
-        self
-    }
-
-    /// Wrap a value in the style.
-    ///
-    /// The same `Style` can be used to print multiple different values.
-    ///
-    /// # Examples
-    ///
-    /// Create a bold, red colored style and use it to print the log level:
-    ///
-    /// ```
-    /// use std::io::Write;
-    /// use env_logger::fmt::Color;
-    ///
-    /// let mut builder = env_logger::Builder::new();
-    ///
-    /// builder.format(|buf, record| {
-    ///     let mut style = buf.style();
-    ///
-    ///     style.set_color(Color::Red).set_bold(true);
-    ///
-    ///     writeln!(buf, "{}: {}",
-    ///         style.value(record.level()),
-    ///         record.args())
-    /// });
-    /// ```
-    pub fn value<T>(&self, value: T) -> StyledValue<T> {
-        StyledValue {
-            style: Cow::Borrowed(self),
-            value,
-        }
-    }
-
-    /// Wrap a value in the style by taking ownership of it.
-    pub(crate) fn into_value<T>(&mut self, value: T) -> StyledValue<'static, T> {
-        StyledValue {
-            style: Cow::Owned(self.clone()),
-            value,
-        }
-    }
-}
-
-impl<'a, T> StyledValue<'a, T> {
-    fn write_fmt<F>(&self, f: F) -> fmt::Result
-    where
-        F: FnOnce() -> fmt::Result,
-    {
-        self.style
-            .buf
-            .borrow_mut()
-            .set_color(&self.style.spec)
-            .map_err(|_| fmt::Error)?;
-
-        // Always try to reset the terminal style, even if writing failed
-        let write = f();
-        let reset = self.style.buf.borrow_mut().reset().map_err(|_| fmt::Error);
-
-        write.and(reset)
-    }
-}
-
-impl fmt::Debug for Style {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("Style").field("spec", &self.spec).finish()
-    }
-}
-
-macro_rules! impl_styled_value_fmt {
-    ($($fmt_trait:path),*) => {
-        $(
-            impl<'a, T: $fmt_trait> $fmt_trait for StyledValue<'a, T> {
-                fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result {
-                    self.write_fmt(|| T::fmt(&self.value, f))
-                }
-            }
-        )*
-    };
-}
-
-impl_styled_value_fmt!(
-    fmt::Debug,
-    fmt::Display,
-    fmt::Pointer,
-    fmt::Octal,
-    fmt::Binary,
-    fmt::UpperHex,
-    fmt::LowerHex,
-    fmt::UpperExp,
-    fmt::LowerExp
-);
-
-// The `Color` type is copied from https://github.com/BurntSushi/ripgrep/tree/master/termcolor
-
-/// The set of available colors for the terminal foreground/background.
-///
-/// The `Ansi256` and `Rgb` colors will only output the correct codes when
-/// paired with the `Ansi` `WriteColor` implementation.
-///
-/// The `Ansi256` and `Rgb` color types are not supported when writing colors
-/// on Windows using the console. If they are used on Windows, then they are
-/// silently ignored and no colors will be emitted.
-///
-/// This set may expand over time.
-///
-/// This type has a `FromStr` impl that can parse colors from their human
-/// readable form. The format is as follows:
-///
-/// 1. Any of the explicitly listed colors in English. They are matched
-///    case insensitively.
-/// 2. A single 8-bit integer, in either decimal or hexadecimal format.
-/// 3. A triple of 8-bit integers separated by a comma, where each integer is
-///    in decimal or hexadecimal format.
-///
-/// Hexadecimal numbers are written with a `0x` prefix.
-#[allow(missing_docs)]
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub enum Color {
-    Black,
-    Blue,
-    Green,
-    Red,
-    Cyan,
-    Magenta,
-    Yellow,
-    White,
-    Ansi256(u8),
-    Rgb(u8, u8, u8),
-    #[doc(hidden)]
-    __Nonexhaustive,
-}
-
-impl Color {
-    fn into_termcolor(self) -> Option<termcolor::Color> {
-        match self {
-            Color::Black => Some(termcolor::Color::Black),
-            Color::Blue => Some(termcolor::Color::Blue),
-            Color::Green => Some(termcolor::Color::Green),
-            Color::Red => Some(termcolor::Color::Red),
-            Color::Cyan => Some(termcolor::Color::Cyan),
-            Color::Magenta => Some(termcolor::Color::Magenta),
-            Color::Yellow => Some(termcolor::Color::Yellow),
-            Color::White => Some(termcolor::Color::White),
-            Color::Ansi256(value) => Some(termcolor::Color::Ansi256(value)),
-            Color::Rgb(r, g, b) => Some(termcolor::Color::Rgb(r, g, b)),
-            _ => None,
-        }
-    }
-}
diff --git a/third_party/rust/env_logger-0.7.1/src/fmt/writer/termcolor/mod.rs b/third_party/rust/env_logger-0.7.1/src/fmt/writer/termcolor/mod.rs
deleted file mode 100644
index f3e6768cd05103cbdd21c0dbcd743c952550c2f9..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/src/fmt/writer/termcolor/mod.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
-This internal module contains the style and terminal writing implementation.
-
-Its public API is available when the `termcolor` crate is available.
-The terminal printing is shimmed when the `termcolor` crate is not available.
-*/
-
-#[cfg_attr(feature = "termcolor", path = "extern_impl.rs")]
-#[cfg_attr(not(feature = "termcolor"), path = "shim_impl.rs")]
-mod imp;
-
-pub(in crate::fmt) use self::imp::*;
diff --git a/third_party/rust/env_logger-0.7.1/src/fmt/writer/termcolor/shim_impl.rs b/third_party/rust/env_logger-0.7.1/src/fmt/writer/termcolor/shim_impl.rs
deleted file mode 100644
index 563f8ad4ffd797313478a2cec3110dedc76ef970..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/src/fmt/writer/termcolor/shim_impl.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-use std::io;
-
-use crate::fmt::{Target, WriteStyle};
-
-pub(in crate::fmt::writer) mod glob {}
-
-pub(in crate::fmt::writer) struct BufferWriter {
-    target: Target,
-}
-
-pub(in crate::fmt) struct Buffer(Vec<u8>);
-
-impl BufferWriter {
-    pub(in crate::fmt::writer) fn stderr(_is_test: bool, _write_style: WriteStyle) -> Self {
-        BufferWriter {
-            target: Target::Stderr,
-        }
-    }
-
-    pub(in crate::fmt::writer) fn stdout(_is_test: bool, _write_style: WriteStyle) -> Self {
-        BufferWriter {
-            target: Target::Stdout,
-        }
-    }
-
-    pub(in crate::fmt::writer) fn buffer(&self) -> Buffer {
-        Buffer(Vec::new())
-    }
-
-    pub(in crate::fmt::writer) fn print(&self, buf: &Buffer) -> io::Result<()> {
-        // This impl uses the `eprint` and `print` macros
-        // instead of using the streams directly.
-        // This is so their output can be captured by `cargo test`
-        let log = String::from_utf8_lossy(&buf.0);
-
-        match self.target {
-            Target::Stderr => eprint!("{}", log),
-            Target::Stdout => print!("{}", log),
-        }
-
-        Ok(())
-    }
-}
-
-impl Buffer {
-    pub(in crate::fmt) fn clear(&mut self) {
-        self.0.clear();
-    }
-
-    pub(in crate::fmt) fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        self.0.extend(buf);
-        Ok(buf.len())
-    }
-
-    pub(in crate::fmt) fn flush(&mut self) -> io::Result<()> {
-        Ok(())
-    }
-
-    #[cfg(test)]
-    pub(in crate::fmt) fn bytes(&self) -> &[u8] {
-        &self.0
-    }
-}
diff --git a/third_party/rust/env_logger-0.7.1/src/lib.rs b/third_party/rust/env_logger-0.7.1/src/lib.rs
deleted file mode 100644
index 415183600b268af5a539c3d9b67b94a2240d81b6..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/src/lib.rs
+++ /dev/null
@@ -1,1177 +0,0 @@
-// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! A simple logger configured via environment variables which writes
-//! to stdout or stderr, for use with the logging facade exposed by the
-//! [`log` crate][log-crate-url].
-//!
-//! ## Example
-//!
-//! ```
-//! #[macro_use] extern crate log;
-//!
-//! use log::Level;
-//!
-//! fn main() {
-//!     env_logger::init();
-//!
-//!     debug!("this is a debug {}", "message");
-//!     error!("this is printed by default");
-//!
-//!     if log_enabled!(Level::Info) {
-//!         let x = 3 * 4; // expensive computation
-//!         info!("the answer was: {}", x);
-//!     }
-//! }
-//! ```
-//!
-//! Assumes the binary is `main`:
-//!
-//! ```{.bash}
-//! $ RUST_LOG=error ./main
-//! [2017-11-09T02:12:24Z ERROR main] this is printed by default
-//! ```
-//!
-//! ```{.bash}
-//! $ RUST_LOG=info ./main
-//! [2017-11-09T02:12:24Z ERROR main] this is printed by default
-//! [2017-11-09T02:12:24Z INFO main] the answer was: 12
-//! ```
-//!
-//! ```{.bash}
-//! $ RUST_LOG=debug ./main
-//! [2017-11-09T02:12:24Z DEBUG main] this is a debug message
-//! [2017-11-09T02:12:24Z ERROR main] this is printed by default
-//! [2017-11-09T02:12:24Z INFO main] the answer was: 12
-//! ```
-//!
-//! You can also set the log level on a per module basis:
-//!
-//! ```{.bash}
-//! $ RUST_LOG=main=info ./main
-//! [2017-11-09T02:12:24Z ERROR main] this is printed by default
-//! [2017-11-09T02:12:24Z INFO main] the answer was: 12
-//! ```
-//!
-//! And enable all logging:
-//!
-//! ```{.bash}
-//! $ RUST_LOG=main ./main
-//! [2017-11-09T02:12:24Z DEBUG main] this is a debug message
-//! [2017-11-09T02:12:24Z ERROR main] this is printed by default
-//! [2017-11-09T02:12:24Z INFO main] the answer was: 12
-//! ```
-//!
-//! If the binary name contains hyphens, you will need to replace
-//! them with underscores:
-//!
-//! ```{.bash}
-//! $ RUST_LOG=my_app ./my-app
-//! [2017-11-09T02:12:24Z DEBUG my_app] this is a debug message
-//! [2017-11-09T02:12:24Z ERROR my_app] this is printed by default
-//! [2017-11-09T02:12:24Z INFO my_app] the answer was: 12
-//! ```
-//!
-//! This is because Rust modules and crates cannot contain hyphens
-//! in their name, although `cargo` continues to accept them.
-//!
-//! See the documentation for the [`log` crate][log-crate-url] for more
-//! information about its API.
-//!
-//! ## Enabling logging
-//!
-//! Log levels are controlled on a per-module basis, and by default all logging
-//! is disabled except for `error!`. Logging is controlled via the `RUST_LOG`
-//! environment variable. The value of this environment variable is a
-//! comma-separated list of logging directives. A logging directive is of the
-//! form:
-//!
-//! ```text
-//! path::to::module=level
-//! ```
-//!
-//! The path to the module is rooted in the name of the crate it was compiled
-//! for, so if your program is contained in a file `hello.rs`, for example, to
-//! turn on logging for this file you would use a value of `RUST_LOG=hello`.
-//! Furthermore, this path is a prefix-search, so all modules nested in the
-//! specified module will also have logging enabled.
-//!
-//! The actual `level` is optional to specify. If omitted, all logging will
-//! be enabled. If specified, it must be one of the strings `debug`, `error`,
-//! `info`, `warn`, or `trace`.
-//!
-//! As the log level for a module is optional, the module to enable logging for
-//! is also optional. If only a `level` is provided, then the global log
-//! level for all modules is set to this value.
-//!
-//! Some examples of valid values of `RUST_LOG` are:
-//!
-//! * `hello` turns on all logging for the 'hello' module
-//! * `info` turns on all info logging
-//! * `hello=debug` turns on debug logging for 'hello'
-//! * `hello,std::option` turns on hello, and std's option logging
-//! * `error,hello=warn` turn on global error logging and also warn for hello
-//!
-//! ## Filtering results
-//!
-//! A `RUST_LOG` directive may include a regex filter. The syntax is to append `/`
-//! followed by a regex. Each message is checked against the regex, and is only
-//! logged if it matches. Note that the matching is done after formatting the
-//! log string but before adding any logging meta-data. There is a single filter
-//! for all modules.
-//!
-//! Some examples:
-//!
-//! * `hello/foo` turns on all logging for the 'hello' module where the log
-//!   message includes 'foo'.
-//! * `info/f.o` turns on all info logging where the log message includes 'foo',
-//!   'f1o', 'fao', etc.
-//! * `hello=debug/foo*foo` turns on debug logging for 'hello' where the log
-//!   message includes 'foofoo' or 'fofoo' or 'fooooooofoo', etc.
-//! * `error,hello=warn/[0-9]scopes` turn on global error logging and also
-//!   warn for hello. In both cases the log message must include a single digit
-//!   number followed by 'scopes'.
-//!
-//! ## Capturing logs in tests
-//!
-//! Records logged during `cargo test` will not be captured by the test harness by default.
-//! The [`Builder::is_test`] method can be used in unit tests to ensure logs will be captured:
-//!
-//! ```
-//! # #[macro_use] extern crate log;
-//! # fn main() {}
-//! #[cfg(test)]
-//! mod tests {
-//!     fn init() {
-//!         let _ = env_logger::builder().is_test(true).try_init();
-//!     }
-//!
-//!     #[test]
-//!     fn it_works() {
-//!         init();
-//!
-//!         info!("This record will be captured by `cargo test`");
-//!
-//!         assert_eq!(2, 1 + 1);
-//!     }
-//! }
-//! ```
-//!
-//! Enabling test capturing comes at the expense of color and other style support
-//! and may have performance implications.
-//!
-//! ## Disabling colors
-//!
-//! Colors and other styles can be configured with the `RUST_LOG_STYLE`
-//! environment variable. It accepts the following values:
-//!
-//! * `auto` (default) will attempt to print style characters, but don't force the issue.
-//! If the console isn't available on Windows, or if TERM=dumb, for example, then don't print colors.
-//! * `always` will always print style characters even if they aren't supported by the terminal.
-//! This includes emitting ANSI colors on Windows if the console API is unavailable.
-//! * `never` will never print style characters.
-//!
-//! ## Tweaking the default format
-//!
-//! Parts of the default format can be excluded from the log output using the [`Builder`].
-//! The following example excludes the timestamp from the log output:
-//!
-//! ```
-//! env_logger::builder()
-//!     .format_timestamp(None)
-//!     .init();
-//! ```
-//!
-//! ### Stability of the default format
-//!
-//! The default format won't optimise for long-term stability, and explicitly makes no
-//! guarantees about the stability of its output across major, minor or patch version
-//! bumps during `0.x`.
-//!
-//! If you want to capture or interpret the output of `env_logger` programmatically
-//! then you should use a custom format.
-//!
-//! ### Using a custom format
-//!
-//! Custom formats can be provided as closures to the [`Builder`].
-//! These closures take a [`Formatter`] and `log::Record` as arguments:
-//!
-//! ```
-//! use std::io::Write;
-//!
-//! env_logger::builder()
-//!     .format(|buf, record| {
-//!         writeln!(buf, "{}: {}", record.level(), record.args())
-//!     })
-//!     .init();
-//! ```
-//!
-//! See the [`fmt`] module for more details about custom formats.
-//!
-//! ## Specifying defaults for environment variables
-//!
-//! `env_logger` can read configuration from environment variables.
-//! If these variables aren't present, the default value to use can be tweaked with the [`Env`] type.
-//! The following example defaults to log `warn` and above if the `RUST_LOG` environment variable
-//! isn't set:
-//!
-//! ```
-//! use env_logger::Env;
-//!
-//! env_logger::from_env(Env::default().default_filter_or("warn")).init();
-//! ```
-//!
-//! [log-crate-url]: https://docs.rs/log/
-//! [`Builder`]: struct.Builder.html
-//! [`Builder::is_test`]: struct.Builder.html#method.is_test
-//! [`Env`]: struct.Env.html
-//! [`fmt`]: fmt/index.html
-
-#![doc(
-    html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-    html_favicon_url = "https://www.rust-lang.org/static/images/favicon.ico",
-    html_root_url = "https://docs.rs/env_logger/0.7.1"
-)]
-#![cfg_attr(test, deny(warnings))]
-// When compiled for the rustc compiler itself we want to make sure that this is
-// an unstable crate
-#![cfg_attr(rustbuild, feature(staged_api, rustc_private))]
-#![cfg_attr(rustbuild, unstable(feature = "rustc_private", issue = "27812"))]
-#![deny(missing_debug_implementations, missing_docs, warnings)]
-
-use std::{borrow::Cow, cell::RefCell, env, io};
-
-use log::{LevelFilter, Log, Metadata, Record, SetLoggerError};
-
-pub mod filter;
-pub mod fmt;
-
-pub use self::fmt::glob::*;
-
-use self::filter::Filter;
-use self::fmt::writer::{self, Writer};
-use self::fmt::Formatter;
-
-/// The default name for the environment variable to read filters from.
-pub const DEFAULT_FILTER_ENV: &'static str = "RUST_LOG";
-
-/// The default name for the environment variable to read style preferences from.
-pub const DEFAULT_WRITE_STYLE_ENV: &'static str = "RUST_LOG_STYLE";
-
-/// Set of environment variables to configure from.
-///
-/// # Default environment variables
-///
-/// By default, the `Env` will read the following environment variables:
-///
-/// - `RUST_LOG`: the level filter
-/// - `RUST_LOG_STYLE`: whether or not to print styles with records.
-///
-/// These sources can be configured using the builder methods on `Env`.
-#[derive(Debug)]
-pub struct Env<'a> {
-    filter: Var<'a>,
-    write_style: Var<'a>,
-}
-
-#[derive(Debug)]
-struct Var<'a> {
-    name: Cow<'a, str>,
-    default: Option<Cow<'a, str>>,
-}
-
-/// The env logger.
-///
-/// This struct implements the `Log` trait from the [`log` crate][log-crate-url],
-/// which allows it to act as a logger.
-///
-/// The [`init()`], [`try_init()`], [`Builder::init()`] and [`Builder::try_init()`]
-/// methods will each construct a `Logger` and immediately initialize it as the
-/// default global logger.
-///
-/// If you'd instead need access to the constructed `Logger`, you can use
-/// the associated [`Builder`] and install it with the
-/// [`log` crate][log-crate-url] directly.
-///
-/// [log-crate-url]: https://docs.rs/log/
-/// [`init()`]: fn.init.html
-/// [`try_init()`]: fn.try_init.html
-/// [`Builder::init()`]: struct.Builder.html#method.init
-/// [`Builder::try_init()`]: struct.Builder.html#method.try_init
-/// [`Builder`]: struct.Builder.html
-pub struct Logger {
-    writer: Writer,
-    filter: Filter,
-    #[allow(unknown_lints, bare_trait_objects)]
-    format: Box<Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send>,
-}
-
-/// `Builder` acts as builder for initializing a `Logger`.
-///
-/// It can be used to customize the log format, change the environment variable used
-/// to provide the logging directives and also set the default log level filter.
-///
-/// # Examples
-///
-/// ```
-/// #[macro_use] extern crate log;
-///
-/// use std::env;
-/// use std::io::Write;
-/// use log::LevelFilter;
-/// use env_logger::Builder;
-///
-/// fn main() {
-///     let mut builder = Builder::from_default_env();
-///
-///     builder.format(|buf, record| writeln!(buf, "{} - {}", record.level(), record.args()))
-///            .filter(None, LevelFilter::Info)
-///            .init();
-///
-///     error!("error message");
-///     info!("info message");
-/// }
-/// ```
-#[derive(Default)]
-pub struct Builder {
-    filter: filter::Builder,
-    writer: writer::Builder,
-    format: fmt::Builder,
-    built: bool,
-}
-
-impl Builder {
-    /// Initializes the log builder with defaults.
-    ///
-    /// **NOTE:** This method won't read from any environment variables.
-    /// Use the [`filter`] and [`write_style`] methods to configure the builder
-    /// or use [`from_env`] or [`from_default_env`] instead.
-    ///
-    /// # Examples
-    ///
-    /// Create a new builder and configure filters and style:
-    ///
-    /// ```
-    /// # fn main() {
-    /// use log::LevelFilter;
-    /// use env_logger::{Builder, WriteStyle};
-    ///
-    /// let mut builder = Builder::new();
-    ///
-    /// builder.filter(None, LevelFilter::Info)
-    ///        .write_style(WriteStyle::Always)
-    ///        .init();
-    /// # }
-    /// ```
-    ///
-    /// [`filter`]: #method.filter
-    /// [`write_style`]: #method.write_style
-    /// [`from_env`]: #method.from_env
-    /// [`from_default_env`]: #method.from_default_env
-    pub fn new() -> Builder {
-        Default::default()
-    }
-
-    /// Initializes the log builder from the environment.
-    ///
-    /// The variables used to read configuration from can be tweaked before
-    /// passing in.
-    ///
-    /// # Examples
-    ///
-    /// Initialise a logger reading the log filter from an environment variable
-    /// called `MY_LOG`:
-    ///
-    /// ```
-    /// use env_logger::Builder;
-    ///
-    /// let mut builder = Builder::from_env("MY_LOG");
-    /// builder.init();
-    /// ```
-    ///
-    /// Initialise a logger using the `MY_LOG` variable for filtering and
-    /// `MY_LOG_STYLE` for whether or not to write styles:
-    ///
-    /// ```
-    /// use env_logger::{Builder, Env};
-    ///
-    /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
-    ///
-    /// let mut builder = Builder::from_env(env);
-    /// builder.init();
-    /// ```
-    pub fn from_env<'a, E>(env: E) -> Self
-    where
-        E: Into<Env<'a>>,
-    {
-        let mut builder = Builder::new();
-        let env = env.into();
-
-        if let Some(s) = env.get_filter() {
-            builder.parse_filters(&s);
-        }
-
-        if let Some(s) = env.get_write_style() {
-            builder.parse_write_style(&s);
-        }
-
-        builder
-    }
-
-    /// Initializes the log builder from the environment using default variable names.
-    ///
-    /// This method is a convenient way to call `from_env(Env::default())` without
-    /// having to use the `Env` type explicitly. The builder will use the
-    /// [default environment variables].
-    ///
-    /// # Examples
-    ///
-    /// Initialise a logger using the default environment variables:
-    ///
-    /// ```
-    /// use env_logger::Builder;
-    ///
-    /// let mut builder = Builder::from_default_env();
-    /// builder.init();
-    /// ```
-    ///
-    /// [default environment variables]: struct.Env.html#default-environment-variables
-    pub fn from_default_env() -> Self {
-        Self::from_env(Env::default())
-    }
-
-    /// Sets the format function for formatting the log output.
-    ///
-    /// This function is called on each record logged and should format the
-    /// log record and output it to the given [`Formatter`].
-    ///
-    /// The format function is expected to output the string directly to the
-    /// `Formatter` so that implementations can use the [`std::fmt`] macros
-    /// to format and output without intermediate heap allocations. The default
-    /// `env_logger` formatter takes advantage of this.
-    ///
-    /// # Examples
-    ///
-    /// Use a custom format to write only the log message:
-    ///
-    /// ```
-    /// use std::io::Write;
-    /// use env_logger::Builder;
-    ///
-    /// let mut builder = Builder::new();
-    ///
-    /// builder.format(|buf, record| writeln!(buf, "{}", record.args()));
-    /// ```
-    ///
-    /// [`Formatter`]: fmt/struct.Formatter.html
-    /// [`String`]: https://doc.rust-lang.org/stable/std/string/struct.String.html
-    /// [`std::fmt`]: https://doc.rust-lang.org/std/fmt/index.html
-    pub fn format<F: 'static>(&mut self, format: F) -> &mut Self
-    where
-        F: Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send,
-    {
-        self.format.custom_format = Some(Box::new(format));
-        self
-    }
-
-    /// Use the default format.
-    ///
-    /// This method will clear any custom format set on the builder.
-    pub fn default_format(&mut self) -> &mut Self {
-        self.format = Default::default();
-        self
-    }
-
-    /// Whether or not to write the level in the default format.
-    pub fn format_level(&mut self, write: bool) -> &mut Self {
-        self.format.format_level = write;
-        self
-    }
-
-    /// Whether or not to write the module path in the default format.
-    pub fn format_module_path(&mut self, write: bool) -> &mut Self {
-        self.format.format_module_path = write;
-        self
-    }
-
-    /// Configures the amount of spaces to use to indent multiline log records.
-    /// A value of `None` disables any kind of indentation.
-    pub fn format_indent(&mut self, indent: Option<usize>) -> &mut Self {
-        self.format.format_indent = indent;
-        self
-    }
-
-    /// Configures if timestamp should be included and in what precision.
-    pub fn format_timestamp(&mut self, timestamp: Option<fmt::TimestampPrecision>) -> &mut Self {
-        self.format.format_timestamp = timestamp;
-        self
-    }
-
-    /// Configures the timestamp to use second precision.
-    pub fn format_timestamp_secs(&mut self) -> &mut Self {
-        self.format_timestamp(Some(fmt::TimestampPrecision::Seconds))
-    }
-
-    /// Configures the timestamp to use millisecond precision.
-    pub fn format_timestamp_millis(&mut self) -> &mut Self {
-        self.format_timestamp(Some(fmt::TimestampPrecision::Millis))
-    }
-
-    /// Configures the timestamp to use microsecond precision.
-    pub fn format_timestamp_micros(&mut self) -> &mut Self {
-        self.format_timestamp(Some(fmt::TimestampPrecision::Micros))
-    }
-
-    /// Configures the timestamp to use nanosecond precision.
-    pub fn format_timestamp_nanos(&mut self) -> &mut Self {
-        self.format_timestamp(Some(fmt::TimestampPrecision::Nanos))
-    }
-
-    /// Adds a directive to the filter for a specific module.
-    ///
-    /// # Examples
-    ///
-    /// Only include messages for warning and above for logs in `path::to::module`:
-    ///
-    /// ```
-    /// # fn main() {
-    /// use log::LevelFilter;
-    /// use env_logger::Builder;
-    ///
-    /// let mut builder = Builder::new();
-    ///
-    /// builder.filter_module("path::to::module", LevelFilter::Info);
-    /// # }
-    /// ```
-    pub fn filter_module(&mut self, module: &str, level: LevelFilter) -> &mut Self {
-        self.filter.filter_module(module, level);
-        self
-    }
-
-    /// Adds a directive to the filter for all modules.
-    ///
-    /// # Examples
-    ///
-    /// Only include messages for warning and above for logs in `path::to::module`:
-    ///
-    /// ```
-    /// # fn main() {
-    /// use log::LevelFilter;
-    /// use env_logger::Builder;
-    ///
-    /// let mut builder = Builder::new();
-    ///
-    /// builder.filter_level(LevelFilter::Info);
-    /// # }
-    /// ```
-    pub fn filter_level(&mut self, level: LevelFilter) -> &mut Self {
-        self.filter.filter_level(level);
-        self
-    }
-
-    /// Adds filters to the logger.
-    ///
-    /// The given module (if any) will log at most the specified level provided.
-    /// If no module is provided then the filter will apply to all log messages.
-    ///
-    /// # Examples
-    ///
-    /// Only include messages for warning and above for logs in `path::to::module`:
-    ///
-    /// ```
-    /// # fn main() {
-    /// use log::LevelFilter;
-    /// use env_logger::Builder;
-    ///
-    /// let mut builder = Builder::new();
-    ///
-    /// builder.filter(Some("path::to::module"), LevelFilter::Info);
-    /// # }
-    /// ```
-    pub fn filter(&mut self, module: Option<&str>, level: LevelFilter) -> &mut Self {
-        self.filter.filter(module, level);
-        self
-    }
-
-    /// Parses the directives string in the same form as the `RUST_LOG`
-    /// environment variable.
-    ///
-    /// See the module documentation for more details.
-    pub fn parse_filters(&mut self, filters: &str) -> &mut Self {
-        self.filter.parse(filters);
-        self
-    }
-
-    /// Sets the target for the log output.
-    ///
-    /// Env logger can log to either stdout or stderr. The default is stderr.
-    ///
-    /// # Examples
-    ///
-    /// Write log message to `stdout`:
-    ///
-    /// ```
-    /// use env_logger::{Builder, Target};
-    ///
-    /// let mut builder = Builder::new();
-    ///
-    /// builder.target(Target::Stdout);
-    /// ```
-    pub fn target(&mut self, target: fmt::Target) -> &mut Self {
-        self.writer.target(target);
-        self
-    }
-
-    /// Sets whether or not styles will be written.
-    ///
-    /// This can be useful in environments that don't support control characters
-    /// for setting colors.
-    ///
-    /// # Examples
-    ///
-    /// Never attempt to write styles:
-    ///
-    /// ```
-    /// use env_logger::{Builder, WriteStyle};
-    ///
-    /// let mut builder = Builder::new();
-    ///
-    /// builder.write_style(WriteStyle::Never);
-    /// ```
-    pub fn write_style(&mut self, write_style: fmt::WriteStyle) -> &mut Self {
-        self.writer.write_style(write_style);
-        self
-    }
-
-    /// Parses whether or not to write styles in the same form as the `RUST_LOG_STYLE`
-    /// environment variable.
-    ///
-    /// See the module documentation for more details.
-    pub fn parse_write_style(&mut self, write_style: &str) -> &mut Self {
-        self.writer.parse_write_style(write_style);
-        self
-    }
-
-    /// Sets whether or not the logger will be used in unit tests.
-    ///
-    /// If `is_test` is `true` then the logger will allow the testing framework to
-    /// capture log records rather than printing them to the terminal directly.
-    pub fn is_test(&mut self, is_test: bool) -> &mut Self {
-        self.writer.is_test(is_test);
-        self
-    }
-
-    /// Initializes the global logger with the built env logger.
-    ///
-    /// This should be called early in the execution of a Rust program. Any log
-    /// events that occur before initialization will be ignored.
-    ///
-    /// # Errors
-    ///
-    /// This function will fail if it is called more than once, or if another
-    /// library has already initialized a global logger.
-    pub fn try_init(&mut self) -> Result<(), SetLoggerError> {
-        let logger = self.build();
-
-        let max_level = logger.filter();
-        let r = log::set_boxed_logger(Box::new(logger));
-
-        if r.is_ok() {
-            log::set_max_level(max_level);
-        }
-
-        r
-    }
-
-    /// Initializes the global logger with the built env logger.
-    ///
-    /// This should be called early in the execution of a Rust program. Any log
-    /// events that occur before initialization will be ignored.
-    ///
-    /// # Panics
-    ///
-    /// This function will panic if it is called more than once, or if another
-    /// library has already initialized a global logger.
-    pub fn init(&mut self) {
-        self.try_init()
-            .expect("Builder::init should not be called after logger initialized");
-    }
-
-    /// Build an env logger.
-    ///
-    /// The returned logger implements the `Log` trait and can be installed manually
-    /// or nested within another logger.
-    pub fn build(&mut self) -> Logger {
-        assert!(!self.built, "attempt to re-use consumed builder");
-        self.built = true;
-
-        Logger {
-            writer: self.writer.build(),
-            filter: self.filter.build(),
-            format: self.format.build(),
-        }
-    }
-}
-
-impl Logger {
-    /// Creates the logger from the environment.
-    ///
-    /// The variables used to read configuration from can be tweaked before
-    /// passing in.
-    ///
-    /// # Examples
-    ///
-    /// Create a logger reading the log filter from an environment variable
-    /// called `MY_LOG`:
-    ///
-    /// ```
-    /// use env_logger::Logger;
-    ///
-    /// let logger = Logger::from_env("MY_LOG");
-    /// ```
-    ///
-    /// Create a logger using the `MY_LOG` variable for filtering and
-    /// `MY_LOG_STYLE` for whether or not to write styles:
-    ///
-    /// ```
-    /// use env_logger::{Logger, Env};
-    ///
-    /// let env = Env::new().filter_or("MY_LOG", "info").write_style_or("MY_LOG_STYLE", "always");
-    ///
-    /// let logger = Logger::from_env(env);
-    /// ```
-    pub fn from_env<'a, E>(env: E) -> Self
-    where
-        E: Into<Env<'a>>,
-    {
-        Builder::from_env(env).build()
-    }
-
-    /// Creates the logger from the environment using default variable names.
-    ///
-    /// This method is a convenient way to call `from_env(Env::default())` without
-    /// having to use the `Env` type explicitly. The logger will use the
-    /// [default environment variables].
-    ///
-    /// # Examples
-    ///
-    /// Creates a logger using the default environment variables:
-    ///
-    /// ```
-    /// use env_logger::Logger;
-    ///
-    /// let logger = Logger::from_default_env();
-    /// ```
-    ///
-    /// [default environment variables]: struct.Env.html#default-environment-variables
-    pub fn from_default_env() -> Self {
-        Builder::from_default_env().build()
-    }
-
-    /// Returns the maximum `LevelFilter` that this env logger instance is
-    /// configured to output.
-    pub fn filter(&self) -> LevelFilter {
-        self.filter.filter()
-    }
-
-    /// Checks if this record matches the configured filter.
-    pub fn matches(&self, record: &Record) -> bool {
-        self.filter.matches(record)
-    }
-}
-
-impl Log for Logger {
-    fn enabled(&self, metadata: &Metadata) -> bool {
-        self.filter.enabled(metadata)
-    }
-
-    fn log(&self, record: &Record) {
-        if self.matches(record) {
-            // Log records are written to a thread-local buffer before being printed
-            // to the terminal. We clear these buffers afterwards, but they aren't shrinked
-            // so will always at least have capacity for the largest log record formatted
-            // on that thread.
-            //
-            // If multiple `Logger`s are used by the same threads then the thread-local
-            // formatter might have different color support. If this is the case the
-            // formatter and its buffer are discarded and recreated.
-
-            thread_local! {
-                static FORMATTER: RefCell<Option<Formatter>> = RefCell::new(None);
-            }
-
-            let print = |formatter: &mut Formatter, record: &Record| {
-                let _ =
-                    (self.format)(formatter, record).and_then(|_| formatter.print(&self.writer));
-
-                // Always clear the buffer afterwards
-                formatter.clear();
-            };
-
-            let printed = FORMATTER
-                .try_with(|tl_buf| {
-                    match tl_buf.try_borrow_mut() {
-                        // There are no active borrows of the buffer
-                        Ok(mut tl_buf) => match *tl_buf {
-                            // We have a previously set formatter
-                            Some(ref mut formatter) => {
-                                // Check the buffer style. If it's different from the logger's
-                                // style then drop the buffer and recreate it.
-                                if formatter.write_style() != self.writer.write_style() {
-                                    *formatter = Formatter::new(&self.writer);
-                                }
-
-                                print(formatter, record);
-                            }
-                            // We don't have a previously set formatter
-                            None => {
-                                let mut formatter = Formatter::new(&self.writer);
-                                print(&mut formatter, record);
-
-                                *tl_buf = Some(formatter);
-                            }
-                        },
-                        // There's already an active borrow of the buffer (due to re-entrancy)
-                        Err(_) => {
-                            print(&mut Formatter::new(&self.writer), record);
-                        }
-                    }
-                })
-                .is_ok();
-
-            if !printed {
-                // The thread-local storage was not available (because its
-                // destructor has already run). Create a new single-use
-                // Formatter on the stack for this call.
-                print(&mut Formatter::new(&self.writer), record);
-            }
-        }
-    }
-
-    fn flush(&self) {}
-}
-
-impl<'a> Env<'a> {
-    /// Get a default set of environment variables.
-    pub fn new() -> Self {
-        Self::default()
-    }
-
-    /// Specify an environment variable to read the filter from.
-    pub fn filter<E>(mut self, filter_env: E) -> Self
-    where
-        E: Into<Cow<'a, str>>,
-    {
-        self.filter = Var::new(filter_env);
-
-        self
-    }
-
-    /// Specify an environment variable to read the filter from.
-    ///
-    /// If the variable is not set, the default value will be used.
-    pub fn filter_or<E, V>(mut self, filter_env: E, default: V) -> Self
-    where
-        E: Into<Cow<'a, str>>,
-        V: Into<Cow<'a, str>>,
-    {
-        self.filter = Var::new_with_default(filter_env, default);
-
-        self
-    }
-
-    /// Use the default environment variable to read the filter from.
-    ///
-    /// If the variable is not set, the default value will be used.
-    pub fn default_filter_or<V>(mut self, default: V) -> Self
-    where
-        V: Into<Cow<'a, str>>,
-    {
-        self.filter = Var::new_with_default(DEFAULT_FILTER_ENV, default);
-
-        self
-    }
-
-    fn get_filter(&self) -> Option<String> {
-        self.filter.get()
-    }
-
-    /// Specify an environment variable to read the style from.
-    pub fn write_style<E>(mut self, write_style_env: E) -> Self
-    where
-        E: Into<Cow<'a, str>>,
-    {
-        self.write_style = Var::new(write_style_env);
-
-        self
-    }
-
-    /// Specify an environment variable to read the style from.
-    ///
-    /// If the variable is not set, the default value will be used.
-    pub fn write_style_or<E, V>(mut self, write_style_env: E, default: V) -> Self
-    where
-        E: Into<Cow<'a, str>>,
-        V: Into<Cow<'a, str>>,
-    {
-        self.write_style = Var::new_with_default(write_style_env, default);
-
-        self
-    }
-
-    /// Use the default environment variable to read the style from.
-    ///
-    /// If the variable is not set, the default value will be used.
-    pub fn default_write_style_or<V>(mut self, default: V) -> Self
-    where
-        V: Into<Cow<'a, str>>,
-    {
-        self.write_style = Var::new_with_default(DEFAULT_WRITE_STYLE_ENV, default);
-
-        self
-    }
-
-    fn get_write_style(&self) -> Option<String> {
-        self.write_style.get()
-    }
-}
-
-impl<'a> Var<'a> {
-    fn new<E>(name: E) -> Self
-    where
-        E: Into<Cow<'a, str>>,
-    {
-        Var {
-            name: name.into(),
-            default: None,
-        }
-    }
-
-    fn new_with_default<E, V>(name: E, default: V) -> Self
-    where
-        E: Into<Cow<'a, str>>,
-        V: Into<Cow<'a, str>>,
-    {
-        Var {
-            name: name.into(),
-            default: Some(default.into()),
-        }
-    }
-
-    fn get(&self) -> Option<String> {
-        env::var(&*self.name)
-            .ok()
-            .or_else(|| self.default.to_owned().map(|v| v.into_owned()))
-    }
-}
-
-impl<'a, T> From<T> for Env<'a>
-where
-    T: Into<Cow<'a, str>>,
-{
-    fn from(filter_env: T) -> Self {
-        Env::default().filter(filter_env.into())
-    }
-}
-
-impl<'a> Default for Env<'a> {
-    fn default() -> Self {
-        Env {
-            filter: Var::new(DEFAULT_FILTER_ENV),
-            write_style: Var::new(DEFAULT_WRITE_STYLE_ENV),
-        }
-    }
-}
-
-mod std_fmt_impls {
-    use super::*;
-    use std::fmt;
-
-    impl fmt::Debug for Logger {
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-            f.debug_struct("Logger")
-                .field("filter", &self.filter)
-                .finish()
-        }
-    }
-
-    impl fmt::Debug for Builder {
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-            if self.built {
-                f.debug_struct("Logger").field("built", &true).finish()
-            } else {
-                f.debug_struct("Logger")
-                    .field("filter", &self.filter)
-                    .field("writer", &self.writer)
-                    .finish()
-            }
-        }
-    }
-}
-
-/// Attempts to initialize the global logger with an env logger.
-///
-/// This should be called early in the execution of a Rust program. Any log
-/// events that occur before initialization will be ignored.
-///
-/// # Errors
-///
-/// This function will fail if it is called more than once, or if another
-/// library has already initialized a global logger.
-pub fn try_init() -> Result<(), SetLoggerError> {
-    try_init_from_env(Env::default())
-}
-
-/// Initializes the global logger with an env logger.
-///
-/// This should be called early in the execution of a Rust program. Any log
-/// events that occur before initialization will be ignored.
-///
-/// # Panics
-///
-/// This function will panic if it is called more than once, or if another
-/// library has already initialized a global logger.
-pub fn init() {
-    try_init().expect("env_logger::init should not be called after logger initialized");
-}
-
-/// Attempts to initialize the global logger with an env logger from the given
-/// environment variables.
-///
-/// This should be called early in the execution of a Rust program. Any log
-/// events that occur before initialization will be ignored.
-///
-/// # Examples
-///
-/// Initialise a logger using the `MY_LOG` environment variable for filters
-/// and `MY_LOG_STYLE` for writing colors:
-///
-/// ```
-/// # extern crate env_logger;
-/// use env_logger::{Builder, Env};
-///
-/// # fn run() -> Result<(), Box<::std::error::Error>> {
-/// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
-///
-/// env_logger::try_init_from_env(env)?;
-///
-/// Ok(())
-/// # }
-/// # fn main() { run().unwrap(); }
-/// ```
-///
-/// # Errors
-///
-/// This function will fail if it is called more than once, or if another
-/// library has already initialized a global logger.
-pub fn try_init_from_env<'a, E>(env: E) -> Result<(), SetLoggerError>
-where
-    E: Into<Env<'a>>,
-{
-    let mut builder = Builder::from_env(env);
-
-    builder.try_init()
-}
-
-/// Initializes the global logger with an env logger from the given environment
-/// variables.
-///
-/// This should be called early in the execution of a Rust program. Any log
-/// events that occur before initialization will be ignored.
-///
-/// # Examples
-///
-/// Initialise a logger using the `MY_LOG` environment variable for filters
-/// and `MY_LOG_STYLE` for writing colors:
-///
-/// ```
-/// use env_logger::{Builder, Env};
-///
-/// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE");
-///
-/// env_logger::init_from_env(env);
-/// ```
-///
-/// # Panics
-///
-/// This function will panic if it is called more than once, or if another
-/// library has already initialized a global logger.
-pub fn init_from_env<'a, E>(env: E)
-where
-    E: Into<Env<'a>>,
-{
-    try_init_from_env(env)
-        .expect("env_logger::init_from_env should not be called after logger initialized");
-}
-
-/// Create a new builder with the default environment variables.
-///
-/// The builder can be configured before being initialized.
-pub fn builder() -> Builder {
-    Builder::from_default_env()
-}
-
-/// Create a builder from the given environment variables.
-///
-/// The builder can be configured before being initialized.
-pub fn from_env<'a, E>(env: E) -> Builder
-where
-    E: Into<Env<'a>>,
-{
-    Builder::from_env(env)
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    fn env_get_filter_reads_from_var_if_set() {
-        env::set_var("env_get_filter_reads_from_var_if_set", "from var");
-
-        let env = Env::new().filter_or("env_get_filter_reads_from_var_if_set", "from default");
-
-        assert_eq!(Some("from var".to_owned()), env.get_filter());
-    }
-
-    #[test]
-    fn env_get_filter_reads_from_default_if_var_not_set() {
-        env::remove_var("env_get_filter_reads_from_default_if_var_not_set");
-
-        let env = Env::new().filter_or(
-            "env_get_filter_reads_from_default_if_var_not_set",
-            "from default",
-        );
-
-        assert_eq!(Some("from default".to_owned()), env.get_filter());
-    }
-
-    #[test]
-    fn env_get_write_style_reads_from_var_if_set() {
-        env::set_var("env_get_write_style_reads_from_var_if_set", "from var");
-
-        let env =
-            Env::new().write_style_or("env_get_write_style_reads_from_var_if_set", "from default");
-
-        assert_eq!(Some("from var".to_owned()), env.get_write_style());
-    }
-
-    #[test]
-    fn env_get_write_style_reads_from_default_if_var_not_set() {
-        env::remove_var("env_get_write_style_reads_from_default_if_var_not_set");
-
-        let env = Env::new().write_style_or(
-            "env_get_write_style_reads_from_default_if_var_not_set",
-            "from default",
-        );
-
-        assert_eq!(Some("from default".to_owned()), env.get_write_style());
-    }
-}
diff --git a/third_party/rust/env_logger-0.7.1/tests/init-twice-retains-filter.rs b/third_party/rust/env_logger-0.7.1/tests/init-twice-retains-filter.rs
deleted file mode 100644
index 673da3fd287995c1fe80593370c9b6d659d0d654..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/tests/init-twice-retains-filter.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-extern crate env_logger;
-extern crate log;
-
-use std::env;
-use std::process;
-use std::str;
-
-fn main() {
-    if env::var("YOU_ARE_TESTING_NOW").is_ok() {
-        // Init from the env (which should set the max level to `Debug`)
-        env_logger::init();
-
-        assert_eq!(log::LevelFilter::Debug, log::max_level());
-
-        // Init again using a different max level
-        // This shouldn't clobber the level that was previously set
-        env_logger::Builder::new()
-            .parse_filters("info")
-            .try_init()
-            .unwrap_err();
-
-        assert_eq!(log::LevelFilter::Debug, log::max_level());
-        return;
-    }
-
-    let exe = env::current_exe().unwrap();
-    let out = process::Command::new(exe)
-        .env("YOU_ARE_TESTING_NOW", "1")
-        .env("RUST_LOG", "debug")
-        .output()
-        .unwrap_or_else(|e| panic!("Unable to start child process: {}", e));
-    if out.status.success() {
-        return;
-    }
-
-    println!("test failed: {}", out.status);
-    println!("--- stdout\n{}", str::from_utf8(&out.stdout).unwrap());
-    println!("--- stderr\n{}", str::from_utf8(&out.stderr).unwrap());
-    process::exit(1);
-}
diff --git a/third_party/rust/env_logger-0.7.1/tests/log-in-log.rs b/third_party/rust/env_logger-0.7.1/tests/log-in-log.rs
deleted file mode 100644
index 89517ff36236e1d86d2b56cb102cf3c33933cb9b..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/tests/log-in-log.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-#[macro_use]
-extern crate log;
-extern crate env_logger;
-
-use std::env;
-use std::fmt;
-use std::process;
-use std::str;
-
-struct Foo;
-
-impl fmt::Display for Foo {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        info!("test");
-        f.write_str("bar")
-    }
-}
-
-fn main() {
-    env_logger::init();
-    if env::var("YOU_ARE_TESTING_NOW").is_ok() {
-        return info!("{}", Foo);
-    }
-
-    let exe = env::current_exe().unwrap();
-    let out = process::Command::new(exe)
-        .env("YOU_ARE_TESTING_NOW", "1")
-        .env("RUST_LOG", "debug")
-        .output()
-        .unwrap_or_else(|e| panic!("Unable to start child process: {}", e));
-    if out.status.success() {
-        return;
-    }
-
-    println!("test failed: {}", out.status);
-    println!("--- stdout\n{}", str::from_utf8(&out.stdout).unwrap());
-    println!("--- stderr\n{}", str::from_utf8(&out.stderr).unwrap());
-    process::exit(1);
-}
diff --git a/third_party/rust/env_logger-0.7.1/tests/log_tls_dtors.rs b/third_party/rust/env_logger-0.7.1/tests/log_tls_dtors.rs
deleted file mode 100644
index 5db87bd6c59a98bc9e1675f04d546d548f185e59..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/tests/log_tls_dtors.rs
+++ /dev/null
@@ -1,66 +0,0 @@
-#[macro_use]
-extern crate log;
-extern crate env_logger;
-
-use std::env;
-use std::process;
-use std::str;
-use std::thread;
-
-struct DropMe;
-
-impl Drop for DropMe {
-    fn drop(&mut self) {
-        debug!("Dropping now");
-    }
-}
-
-fn run() {
-    // Use multiple thread local values to increase the chance that our TLS
-    // value will get destroyed after the FORMATTER key in the library
-    thread_local! {
-        static DROP_ME_0: DropMe = DropMe;
-        static DROP_ME_1: DropMe = DropMe;
-        static DROP_ME_2: DropMe = DropMe;
-        static DROP_ME_3: DropMe = DropMe;
-        static DROP_ME_4: DropMe = DropMe;
-        static DROP_ME_5: DropMe = DropMe;
-        static DROP_ME_6: DropMe = DropMe;
-        static DROP_ME_7: DropMe = DropMe;
-        static DROP_ME_8: DropMe = DropMe;
-        static DROP_ME_9: DropMe = DropMe;
-    }
-    DROP_ME_0.with(|_| {});
-    DROP_ME_1.with(|_| {});
-    DROP_ME_2.with(|_| {});
-    DROP_ME_3.with(|_| {});
-    DROP_ME_4.with(|_| {});
-    DROP_ME_5.with(|_| {});
-    DROP_ME_6.with(|_| {});
-    DROP_ME_7.with(|_| {});
-    DROP_ME_8.with(|_| {});
-    DROP_ME_9.with(|_| {});
-}
-
-fn main() {
-    env_logger::init();
-    if env::var("YOU_ARE_TESTING_NOW").is_ok() {
-        // Run on a separate thread because TLS values on the main thread
-        // won't have their destructors run if pthread is used.
-        // https://doc.rust-lang.org/std/thread/struct.LocalKey.html#platform-specific-behavior
-        thread::spawn(run).join().unwrap();
-    } else {
-        let exe = env::current_exe().unwrap();
-        let out = process::Command::new(exe)
-            .env("YOU_ARE_TESTING_NOW", "1")
-            .env("RUST_LOG", "debug")
-            .output()
-            .unwrap_or_else(|e| panic!("Unable to start child process: {}", e));
-        if !out.status.success() {
-            println!("test failed: {}", out.status);
-            println!("--- stdout\n{}", str::from_utf8(&out.stdout).unwrap());
-            println!("--- stderr\n{}", str::from_utf8(&out.stderr).unwrap());
-            process::exit(1);
-        }
-    }
-}
diff --git a/third_party/rust/env_logger-0.7.1/tests/regexp_filter.rs b/third_party/rust/env_logger-0.7.1/tests/regexp_filter.rs
deleted file mode 100644
index 40178bac7fdcf2f3b0581adee07d4cd458e73417..0000000000000000000000000000000000000000
--- a/third_party/rust/env_logger-0.7.1/tests/regexp_filter.rs
+++ /dev/null
@@ -1,57 +0,0 @@
-#[macro_use]
-extern crate log;
-extern crate env_logger;
-
-use std::env;
-use std::process;
-use std::str;
-
-fn main() {
-    if env::var("LOG_REGEXP_TEST").ok() == Some(String::from("1")) {
-        child_main();
-    } else {
-        parent_main()
-    }
-}
-
-fn child_main() {
-    env_logger::init();
-    info!("XYZ Message");
-}
-
-fn run_child(rust_log: String) -> bool {
-    let exe = env::current_exe().unwrap();
-    let out = process::Command::new(exe)
-        .env("LOG_REGEXP_TEST", "1")
-        .env("RUST_LOG", rust_log)
-        .output()
-        .unwrap_or_else(|e| panic!("Unable to start child process: {}", e));
-    str::from_utf8(out.stderr.as_ref())
-        .unwrap()
-        .contains("XYZ Message")
-}
-
-fn assert_message_printed(rust_log: &str) {
-    if !run_child(rust_log.to_string()) {
-        panic!("RUST_LOG={} should allow the test log message", rust_log)
-    }
-}
-
-fn assert_message_not_printed(rust_log: &str) {
-    if run_child(rust_log.to_string()) {
-        panic!(
-            "RUST_LOG={} should not allow the test log message",
-            rust_log
-        )
-    }
-}
-
-fn parent_main() {
-    // test normal log severity levels
-    assert_message_printed("info");
-    assert_message_not_printed("warn");
-
-    // test of regular expression filters
-    assert_message_printed("info/XYZ");
-    assert_message_not_printed("info/XXX");
-}
diff --git a/third_party/rust/humantime-1.3.0/.cargo-checksum.json b/third_party/rust/humantime-1.3.0/.cargo-checksum.json
deleted file mode 100644
index 2ffd8f042d502518c989ffeca5fdced847cb76a7..0000000000000000000000000000000000000000
--- a/third_party/rust/humantime-1.3.0/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"Cargo.toml":"ae7f884d13f5d849afd58b5db15510396832df7f648b0095e43bfdfa600b2ba3","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"f6deca8261a8f4a3403dc74c725c46051157fd36c27cd4b100277eb1f303ad11","README.md":"e4bb65f28ddffb11d7eb337e9585947651f2fc11a5e4290f0ca126e21c582c1e","benches/datetime_format.rs":"a44c7ffb3c9515e92828564df8f91a86470343a2fa7e1a08bc2bc7397ba2591c","benches/datetime_parse.rs":"336a241755ccfa546d1840e56a40218c4f98f22d7d274829c5102ec280f2d963","bulk.yaml":"17c2548388e0cd3a63473021a2f1e4ddedee082d79d9167cb31ad06a1890d3fc","src/date.rs":"ea9924869a2484e333df2a845009593dd0062bb3b3e1a5ef9cefc05ec0a41196","src/duration.rs":"a5d4756451f495a3d5df0c872caa6304dd81ae075f0e204c8145c11c7c8f698b","src/lib.rs":"59dcc8a1ed89ecde199d59a7f71e550b461f87858b4becffb0a183994bafdd7c","src/wrapper.rs":"5bbdaf43256b445a8ca3a6b3eded9dd4fa8fb4dadf3683a5bac9648d91117396","vagga.yaml":"59761e5138a3015ef5654fec095ac8f1587cd23529b37822dd540b866fe4cd5b"},"package":"df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"}
\ No newline at end of file
diff --git a/third_party/rust/humantime-1.3.0/Cargo.toml b/third_party/rust/humantime-1.3.0/Cargo.toml
deleted file mode 100644
index 53bdcfd2cf7e4fceb9b7d315ac05e7ba4103b12d..0000000000000000000000000000000000000000
--- a/third_party/rust/humantime-1.3.0/Cargo.toml
+++ /dev/null
@@ -1,37 +0,0 @@
-# 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 = "humantime"
-version = "1.3.0"
-authors = ["Paul Colomiets <paul@colomiets.name>"]
-description = "    A parser and formatter for std::time::{Duration, SystemTime}\n"
-homepage = "https://github.com/tailhook/humantime"
-documentation = "https://docs.rs/humantime"
-readme = "README.md"
-keywords = ["time", "human", "human-friendly", "parser", "duration"]
-categories = ["date-and-time"]
-license = "MIT/Apache-2.0"
-
-[lib]
-name = "humantime"
-path = "src/lib.rs"
-[dependencies.quick-error]
-version = "1.0.0"
-[dev-dependencies.chrono]
-version = "0.4.0"
-
-[dev-dependencies.rand]
-version = "0.4.2"
-
-[dev-dependencies.time]
-version = "0.1.39"
diff --git a/third_party/rust/humantime-1.3.0/LICENSE-APACHE b/third_party/rust/humantime-1.3.0/LICENSE-APACHE
deleted file mode 100644
index 8f71f43fee3f78649d238238cbde51e6d7055c82..0000000000000000000000000000000000000000
--- a/third_party/rust/humantime-1.3.0/LICENSE-APACHE
+++ /dev/null
@@ -1,202 +0,0 @@
-                                 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.
-
diff --git a/third_party/rust/humantime-1.3.0/LICENSE-MIT b/third_party/rust/humantime-1.3.0/LICENSE-MIT
deleted file mode 100644
index a099fbade45d90157884a272ac125787ba4c5225..0000000000000000000000000000000000000000
--- a/third_party/rust/humantime-1.3.0/LICENSE-MIT
+++ /dev/null
@@ -1,26 +0,0 @@
-Copyright (c) 2016 The humantime Developers
-
-Includes parts of http date with the following copyright:
-Copyright (c) 2016 Pyfisch
-
-Includes portions of musl libc with the following copyright:
-Copyright © 2005-2013 Rich Felker
-
-
-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.
diff --git a/third_party/rust/humantime-1.3.0/README.md b/third_party/rust/humantime-1.3.0/README.md
deleted file mode 100644
index 39156dcdc9411b55fa20bcb8ac558eda9e515cf5..0000000000000000000000000000000000000000
--- a/third_party/rust/humantime-1.3.0/README.md
+++ /dev/null
@@ -1,68 +0,0 @@
-Human Time
-==========
-
-**Status: stable**
-
-[Documentation](https://docs.rs/humantime) |
-[Github](https://github.com/tailhook/humantime) |
-[Crate](https://crates.io/crates/humantime)
-
-
-Features:
-
-* Parses durations in free form like `15days 2min 2s`
-* Formats durations in similar form `2years 2min 12us`
-* Parses and formats timestamp in `rfc3339` format: `2018-01-01T12:53:00Z`
-* Parses timestamps in a weaker format: `2018-01-01 12:53:00`
-
-Timestamp parsing/formatting is super-fast because format is basically
-fixed.
-
-Here are some micro-benchmarks:
-
-```
-test result: ok. 0 passed; 0 failed; 26 ignored; 0 measured; 0 filtered out
-
-     Running target/release/deps/datetime_format-8facb4ac832d9770
-
-running 2 tests
-test rfc3339_chrono            ... bench:         737 ns/iter (+/- 37)
-test rfc3339_humantime_seconds ... bench:          73 ns/iter (+/- 2)
-
-test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured; 0 filtered out
-
-     Running target/release/deps/datetime_parse-342628f877d7867c
-
-running 6 tests
-test datetime_utc_parse_millis  ... bench:         228 ns/iter (+/- 11)
-test datetime_utc_parse_nanos   ... bench:         236 ns/iter (+/- 10)
-test datetime_utc_parse_seconds ... bench:         204 ns/iter (+/- 18)
-test rfc3339_humantime_millis   ... bench:          28 ns/iter (+/- 1)
-test rfc3339_humantime_nanos    ... bench:          36 ns/iter (+/- 2)
-test rfc3339_humantime_seconds  ... bench:          24 ns/iter (+/- 1)
-
-test result: ok. 0 passed; 0 failed; 0 ignored; 6 measured; 0 filtered out
-```
-
-See [humantime-serde] for serde integration (previous crate [serde-humantime] looks unmaintained).
-
-[serde-humantime]: https://docs.rs/serde-humantime/0.1.1/serde_humantime/
-[humantime-serde]: https://docs.rs/humantime-serde
-
-License
-=======
-
-Licensed under either of
-
-* Apache License, Version 2.0, (./LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
-* MIT license (./LICENSE-MIT or http://opensource.org/licenses/MIT)
-
-at your option.
-
-Contribution
-------------
-
-Unless you explicitly state otherwise, any contribution intentionally
-submitted for inclusion in the work by you, as defined in the Apache-2.0
-license, shall be dual licensed as above, without any additional terms or
-conditions.
diff --git a/third_party/rust/humantime-1.3.0/benches/datetime_format.rs b/third_party/rust/humantime-1.3.0/benches/datetime_format.rs
deleted file mode 100644
index 7f6dca79c58d016164b904508a8c05ed67b9f91c..0000000000000000000000000000000000000000
--- a/third_party/rust/humantime-1.3.0/benches/datetime_format.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-#![feature(test)]
-extern crate chrono;
-extern crate humantime;
-extern crate test;
-
-use std::io::Write;
-use std::time::{Duration, UNIX_EPOCH};
-use humantime::format_rfc3339;
-
-
-#[bench]
-fn rfc3339_humantime_seconds(b: &mut test::Bencher) {
-    let time = UNIX_EPOCH + Duration::new(1483228799, 0);
-    let mut buf = Vec::with_capacity(100);
-    b.iter(|| {
-        buf.truncate(0);
-        write!(&mut buf, "{}", format_rfc3339(time)).unwrap()
-    });
-}
-
-#[bench]
-fn rfc3339_chrono(b: &mut test::Bencher) {
-    use chrono::{DateTime, NaiveDateTime, Utc};
-    use chrono::format::Item;
-    use chrono::format::Item::*;
-    use chrono::format::Numeric::*;
-    use chrono::format::Fixed::*;
-    use chrono::format::Pad::*;
-
-    let time = DateTime::<Utc>::from_utc(
-        NaiveDateTime::from_timestamp(1483228799, 0), Utc);
-    let mut buf = Vec::with_capacity(100);
-
-    // formatting code from env_logger
-    const ITEMS: &'static [Item<'static>] = {
-        &[
-            Numeric(Year, Zero),
-            Literal("-"),
-            Numeric(Month, Zero),
-            Literal("-"),
-            Numeric(Day, Zero),
-            Literal("T"),
-            Numeric(Hour, Zero),
-            Literal(":"),
-            Numeric(Minute, Zero),
-            Literal(":"),
-            Numeric(Second, Zero),
-            Fixed(TimezoneOffsetZ),
-        ]
-    };
-
-
-    b.iter(|| {
-        buf.truncate(0);
-        write!(&mut buf, "{}", time.format_with_items(ITEMS.iter().cloned()))
-            .unwrap()
-    });
-}
diff --git a/third_party/rust/humantime-1.3.0/benches/datetime_parse.rs b/third_party/rust/humantime-1.3.0/benches/datetime_parse.rs
deleted file mode 100644
index 785d713d3f5a9bdc7cf59a087ca0bd1b74037cc4..0000000000000000000000000000000000000000
--- a/third_party/rust/humantime-1.3.0/benches/datetime_parse.rs
+++ /dev/null
@@ -1,50 +0,0 @@
-#![feature(test)]
-extern crate chrono;
-extern crate humantime;
-extern crate test;
-
-use chrono::{DateTime};
-use humantime::parse_rfc3339;
-
-
-#[bench]
-fn rfc3339_humantime_seconds(b: &mut test::Bencher) {
-    b.iter(|| {
-        parse_rfc3339("2018-02-13T23:08:32Z").unwrap()
-    });
-}
-
-#[bench]
-fn datetime_utc_parse_seconds(b: &mut test::Bencher) {
-    b.iter(|| {
-        DateTime::parse_from_rfc3339("2018-02-13T23:08:32Z").unwrap()
-    });
-}
-
-#[bench]
-fn rfc3339_humantime_millis(b: &mut test::Bencher) {
-    b.iter(|| {
-        parse_rfc3339("2018-02-13T23:08:32.123Z").unwrap()
-    });
-}
-
-#[bench]
-fn datetime_utc_parse_millis(b: &mut test::Bencher) {
-    b.iter(|| {
-        DateTime::parse_from_rfc3339("2018-02-13T23:08:32.123Z").unwrap()
-    });
-}
-
-#[bench]
-fn rfc3339_humantime_nanos(b: &mut test::Bencher) {
-    b.iter(|| {
-        parse_rfc3339("2018-02-13T23:08:32.123456983Z").unwrap()
-    });
-}
-
-#[bench]
-fn datetime_utc_parse_nanos(b: &mut test::Bencher) {
-    b.iter(|| {
-        DateTime::parse_from_rfc3339("2018-02-13T23:08:32.123456983Z").unwrap()
-    });
-}
diff --git a/third_party/rust/humantime-1.3.0/bulk.yaml b/third_party/rust/humantime-1.3.0/bulk.yaml
deleted file mode 100644
index cdb9763b67d6d788e5ba82752493fba020ffb298..0000000000000000000000000000000000000000
--- a/third_party/rust/humantime-1.3.0/bulk.yaml
+++ /dev/null
@@ -1,8 +0,0 @@
-minimum-bulk: v0.4.5
-
-versions:
-
-- file: Cargo.toml
-  block-start: ^\[package\]
-  block-end: ^\[.*\]
-  regex: ^version\s*=\s*"(\S+)"
diff --git a/third_party/rust/humantime-1.3.0/src/date.rs b/third_party/rust/humantime-1.3.0/src/date.rs
deleted file mode 100644
index d5bc82cf6c1097d728b1fcf69999ffb04508a638..0000000000000000000000000000000000000000
--- a/third_party/rust/humantime-1.3.0/src/date.rs
+++ /dev/null
@@ -1,614 +0,0 @@
-use std::fmt;
-use std::str;
-use std::time::{SystemTime, Duration, UNIX_EPOCH};
-
-#[cfg(target_os="cloudabi")]
-mod max {
-    pub const SECONDS: u64 = ::std::u64::MAX / 1_000_000_000;
-    #[allow(unused)]
-    pub const TIMESTAMP: &'static str = "2554-07-21T23:34:33Z";
-}
-#[cfg(all(
-    target_pointer_width="32",
-    not(target_os="cloudabi"),
-    not(target_os="windows"),
-    not(all(target_arch="wasm32", not(target_os="emscripten")))
-))]
-mod max {
-    pub const SECONDS: u64 = ::std::i32::MAX as u64;
-    #[allow(unused)]
-    pub const TIMESTAMP: &'static str = "2038-01-19T03:14:07Z";
-}
-
-#[cfg(any(
-    target_pointer_width="64",
-    target_os="windows",
-    all(target_arch="wasm32", not(target_os="emscripten")),
-))]
-mod max {
-    pub const SECONDS: u64 = 253402300800-1;  // last second of year 9999
-    #[allow(unused)]
-    pub const TIMESTAMP: &'static str = "9999-12-31T23:59:59Z";
-}
-
-quick_error! {
-    /// Error parsing datetime (timestamp)
-    #[derive(Debug, PartialEq, Clone, Copy)]
-    pub enum Error {
-        /// Numeric component is out of range
-        OutOfRange {
-            display("numeric component is out of range")
-        }
-        /// Bad character where digit is expected
-        InvalidDigit {
-            display("bad character where digit is expected")
-        }
-        /// Other formatting errors
-        InvalidFormat {
-            display("timestamp format is invalid")
-        }
-    }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-enum Precision {
-    Smart,
-    Seconds,
-    Millis,
-    Micros,
-    Nanos,
-}
-
-/// A wrapper type that allows you to Display a SystemTime
-#[derive(Debug, Clone)]
-pub struct Rfc3339Timestamp(SystemTime, Precision);
-
-#[inline]
-fn two_digits(b1: u8, b2: u8) -> Result<u64, Error> {
-    if b1 < b'0' || b2 < b'0' || b1 > b'9' || b2 > b'9' {
-        return Err(Error::InvalidDigit);
-    }
-    Ok(((b1 - b'0')*10 + (b2 - b'0')) as u64)
-}
-
-/// Parse RFC3339 timestamp `2018-02-14T00:28:07Z`
-///
-/// Supported feature: any precision of fractional
-/// digits `2018-02-14T00:28:07.133Z`.
-///
-/// Unsupported feature: localized timestamps. Only UTC is supported.
-pub fn parse_rfc3339(s: &str) -> Result<SystemTime, Error> {
-    if s.len() < "2018-02-14T00:28:07Z".len() {
-        return Err(Error::InvalidFormat);
-    }
-    let b = s.as_bytes();
-    if b[10] != b'T' || b[b.len()-1] != b'Z' {
-        return Err(Error::InvalidFormat);
-    }
-    return parse_rfc3339_weak(s);
-}
-
-/// Parse RFC3339-like timestamp `2018-02-14 00:28:07`
-///
-/// Supported features:
-///
-/// 1. Any precision of fractional digits `2018-02-14 00:28:07.133`.
-/// 2. Supports timestamp with or without either of `T` or `Z`
-/// 3. Anything valid for `parse_3339` is valid for this function
-///
-/// Unsupported feature: localized timestamps. Only UTC is supported, even if
-/// `Z` is not specified.
-///
-/// This function is intended to use for parsing human input. Whereas
-/// `parse_rfc3339` is for strings generated programmatically.
-pub fn parse_rfc3339_weak(s: &str) -> Result<SystemTime, Error> {
-    if s.len() < "2018-02-14T00:28:07".len() {
-        return Err(Error::InvalidFormat);
-    }
-    let b = s.as_bytes();  // for careless slicing
-    if b[4] != b'-' || b[7] != b'-' || (b[10] != b'T' && b[10] != b' ') ||
-       b[13] != b':' || b[16] != b':'
-    {
-        return Err(Error::InvalidFormat);
-    }
-    let year = two_digits(b[0], b[1])? * 100 + two_digits(b[2], b[3])?;
-    let month = two_digits(b[5], b[6])?;
-    let day = two_digits(b[8], b[9])?;
-    let hour = two_digits(b[11], b[12])?;
-    let minute = two_digits(b[14], b[15])?;
-    let mut second = two_digits(b[17], b[18])?;
-
-    if year < 1970 || hour > 23 || minute > 59 || second > 60 {
-        return Err(Error::OutOfRange);
-    }
-    // TODO(tailhook) should we check that leaps second is only on midnight ?
-    if second == 60 {
-        second = 59
-    };
-    let leap_years = ((year - 1) - 1968) / 4 - ((year - 1) - 1900) / 100 +
-                     ((year - 1) - 1600) / 400;
-    let leap = is_leap_year(year);
-    let (mut ydays, mdays) = match month {
-        1 => (0, 31),
-        2 if leap => (31, 29),
-        2 => (31, 28),
-        3 => (59, 31),
-        4 => (90, 30),
-        5 => (120, 31),
-        6 => (151, 30),
-        7 => (181, 31),
-        8 => (212, 31),
-        9 => (243, 30),
-        10 => (273, 31),
-        11 => (304, 30),
-        12 => (334, 31),
-        _ => return Err(Error::OutOfRange),
-    };
-    if day > mdays || day == 0 {
-        return Err(Error::OutOfRange);
-    }
-    ydays += day - 1;
-    if leap && month > 2 {
-        ydays += 1;
-    }
-    let days = (year - 1970) * 365 + leap_years + ydays;
-
-    let time = second + minute * 60 + hour * 3600;
-
-    let mut nanos = 0;
-    let mut mult = 100_000_000;
-    if b.get(19) == Some(&b'.') {
-        for idx in 20..b.len() {
-            if b[idx] == b'Z' {
-                if idx == b.len()-1 {
-                    break;
-                } else {
-                    return Err(Error::InvalidDigit);
-                }
-            }
-            if b[idx] < b'0' || b[idx] > b'9' {
-                return Err(Error::InvalidDigit);
-            }
-            nanos += mult * (b[idx] - b'0') as u32;
-            mult /= 10;
-        }
-    } else {
-        if b.len() != 19 && (b.len() > 20 || b[19] != b'Z') {
-            return Err(Error::InvalidFormat);
-        }
-    }
-
-    let total_seconds = time + days * 86400;
-    if total_seconds > max::SECONDS {
-        return Err(Error::OutOfRange);
-    }
-
-    return Ok(UNIX_EPOCH + Duration::new(total_seconds, nanos));
-}
-
-fn is_leap_year(y: u64) -> bool {
-    y % 4 == 0 && (!(y % 100 == 0) || y % 400 == 0)
-}
-
-/// Format an RFC3339 timestamp `2018-02-14T00:28:07Z`
-///
-/// This function formats timestamp with smart precision: i.e. if it has no
-/// fractional seconds, they aren't written at all. And up to nine digits if
-/// they are.
-///
-/// The value is always UTC and ignores system timezone.
-pub fn format_rfc3339(system_time: SystemTime) -> Rfc3339Timestamp {
-    return Rfc3339Timestamp(system_time, Precision::Smart);
-}
-
-/// Format an RFC3339 timestamp `2018-02-14T00:28:07Z`
-///
-/// This format always shows timestamp without fractional seconds.
-///
-/// The value is always UTC and ignores system timezone.
-pub fn format_rfc3339_seconds(system_time: SystemTime) -> Rfc3339Timestamp {
-    return Rfc3339Timestamp(system_time, Precision::Seconds);
-}
-
-/// Format an RFC3339 timestamp `2018-02-14T00:28:07.000Z`
-///
-/// This format always shows milliseconds even if millisecond value is zero.
-///
-/// The value is always UTC and ignores system timezone.
-pub fn format_rfc3339_millis(system_time: SystemTime) -> Rfc3339Timestamp {
-    return Rfc3339Timestamp(system_time, Precision::Millis);
-}
-
-/// Format an RFC3339 timestamp `2018-02-14T00:28:07.000000Z`
-///
-/// This format always shows microseconds even if microsecond value is zero.
-///
-/// The value is always UTC and ignores system timezone.
-pub fn format_rfc3339_micros(system_time: SystemTime) -> Rfc3339Timestamp {
-    return Rfc3339Timestamp(system_time, Precision::Micros);
-}
-
-/// Format an RFC3339 timestamp `2018-02-14T00:28:07.000000000Z`
-///
-/// This format always shows nanoseconds even if nanosecond value is zero.
-///
-/// The value is always UTC and ignores system timezone.
-pub fn format_rfc3339_nanos(system_time: SystemTime) -> Rfc3339Timestamp {
-    return Rfc3339Timestamp(system_time, Precision::Nanos);
-}
-
-impl fmt::Display for Rfc3339Timestamp {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        use self::Precision::*;
-
-        let dur = self.0.duration_since(UNIX_EPOCH)
-            .expect("all times should be after the epoch");
-        let secs_since_epoch = dur.as_secs();
-        let nanos = dur.subsec_nanos();
-
-        if secs_since_epoch >= 253402300800 { // year 9999
-            return Err(fmt::Error);
-        }
-
-        /* 2000-03-01 (mod 400 year, immediately after feb29 */
-        const LEAPOCH: i64 = 11017;
-        const DAYS_PER_400Y: i64 = 365*400 + 97;
-        const DAYS_PER_100Y: i64 = 365*100 + 24;
-        const DAYS_PER_4Y: i64 = 365*4 + 1;
-
-        let days = (secs_since_epoch / 86400) as i64 - LEAPOCH;
-        let secs_of_day = secs_since_epoch % 86400;
-
-        let mut qc_cycles = days / DAYS_PER_400Y;
-        let mut remdays = days % DAYS_PER_400Y;
-
-        if remdays < 0 {
-            remdays += DAYS_PER_400Y;
-            qc_cycles -= 1;
-        }
-
-        let mut c_cycles = remdays / DAYS_PER_100Y;
-        if c_cycles == 4 { c_cycles -= 1; }
-        remdays -= c_cycles * DAYS_PER_100Y;
-
-        let mut q_cycles = remdays / DAYS_PER_4Y;
-        if q_cycles == 25 { q_cycles -= 1; }
-        remdays -= q_cycles * DAYS_PER_4Y;
-
-        let mut remyears = remdays / 365;
-        if remyears == 4 { remyears -= 1; }
-        remdays -= remyears * 365;
-
-        let mut year = 2000 +
-            remyears + 4*q_cycles + 100*c_cycles + 400*qc_cycles;
-
-        let months = [31,30,31,30,31,31,30,31,30,31,31,29];
-        let mut mon = 0;
-        for mon_len in months.iter() {
-            mon += 1;
-            if remdays < *mon_len {
-                break;
-            }
-            remdays -= *mon_len;
-        }
-        let mday = remdays+1;
-        let mon = if mon + 2 > 12 {
-            year += 1;
-            mon - 10
-        } else {
-            mon + 2
-        };
-
-        let mut buf: [u8; 30] = [
-            // Too long to write as: b"0000-00-00T00:00:00.000000000Z"
-            b'0', b'0', b'0', b'0', b'-', b'0', b'0', b'-', b'0', b'0', b'T',
-            b'0', b'0', b':', b'0', b'0', b':', b'0', b'0',
-            b'.', b'0', b'0', b'0', b'0', b'0', b'0', b'0', b'0', b'0', b'Z',
-        ];
-        buf[0] = b'0' + (year / 1000) as u8;
-        buf[1] = b'0' + (year / 100 % 10) as u8;
-        buf[2] = b'0' + (year / 10 % 10) as u8;
-        buf[3] = b'0' + (year % 10) as u8;
-        buf[5] = b'0' + (mon / 10) as u8;
-        buf[6] = b'0' + (mon % 10) as u8;
-        buf[8] = b'0' + (mday / 10) as u8;
-        buf[9] = b'0' + (mday % 10) as u8;
-        buf[11] = b'0' + (secs_of_day / 3600 / 10) as u8;
-        buf[12] = b'0' + (secs_of_day / 3600 % 10) as u8;
-        buf[14] = b'0' + (secs_of_day / 60 / 10 % 6) as u8;
-        buf[15] = b'0' + (secs_of_day / 60 % 10) as u8;
-        buf[17] = b'0' + (secs_of_day / 10 % 6) as u8;
-        buf[18] = b'0' + (secs_of_day % 10) as u8;
-
-        let offset = if self.1 == Seconds || nanos == 0 && self.1 == Smart {
-            buf[19] = b'Z';
-            19
-        } else if self.1 == Millis {
-            buf[20] = b'0' + (nanos / 100_000_000) as u8;
-            buf[21] = b'0' + (nanos / 10_000_000 % 10) as u8;
-            buf[22] = b'0' + (nanos / 1_000_000 % 10) as u8;
-            buf[23] = b'Z';
-            23
-        } else if self.1 == Micros {
-            buf[20] = b'0' + (nanos / 100_000_000) as u8;
-            buf[21] = b'0' + (nanos / 10_000_000 % 10) as u8;
-            buf[22] = b'0' + (nanos / 1_000_000 % 10) as u8;
-            buf[23] = b'0' + (nanos / 100_000 % 10) as u8;
-            buf[24] = b'0' + (nanos / 10_000 % 10) as u8;
-            buf[25] = b'0' + (nanos / 1_000 % 10) as u8;
-            buf[26] = b'Z';
-            26
-        } else {
-            buf[20] = b'0' + (nanos / 100_000_000) as u8;
-            buf[21] = b'0' + (nanos / 10_000_000 % 10) as u8;
-            buf[22] = b'0' + (nanos / 1_000_000 % 10) as u8;
-            buf[23] = b'0' + (nanos / 100_000 % 10) as u8;
-            buf[24] = b'0' + (nanos / 10_000 % 10) as u8;
-            buf[25] = b'0' + (nanos / 1_000 % 10) as u8;
-            buf[26] = b'0' + (nanos / 100 % 10) as u8;
-            buf[27] = b'0' + (nanos / 10 % 10) as u8;
-            buf[28] = b'0' + (nanos / 1 % 10) as u8;
-            // 29th is 'Z'
-            29
-        };
-
-        // we know our chars are all ascii
-        f.write_str(unsafe { str::from_utf8_unchecked(&buf[..offset+1]) })
-    }
-}
-
-#[cfg(test)]
-mod test {
-    extern crate time;
-    extern crate rand;
-
-    use std::str::from_utf8;
-    use self::rand::Rng;
-    use std::time::{UNIX_EPOCH, SystemTime, Duration};
-    use super::{parse_rfc3339, parse_rfc3339_weak, format_rfc3339};
-    use super::{format_rfc3339_millis, format_rfc3339_micros};
-    use super::{format_rfc3339_nanos};
-    use super::max;
-
-    fn from_sec(sec: u64) -> (String, SystemTime) {
-        let s = time::at_utc(time::Timespec { sec: sec as i64, nsec: 0 })
-                  .rfc3339().to_string();
-        let time = UNIX_EPOCH + Duration::new(sec, 0);
-        return (s, time)
-    }
-
-    #[test]
-    #[cfg(all(target_pointer_width="32", target_os="linux"))]
-    fn year_after_2038_fails_gracefully() {
-        // next second
-        assert_eq!(parse_rfc3339("2038-01-19T03:14:08Z").unwrap_err(),
-                   super::Error::OutOfRange);
-        assert_eq!(parse_rfc3339("9999-12-31T23:59:59Z").unwrap_err(),
-                   super::Error::OutOfRange);
-    }
-
-    #[test]
-    fn smoke_tests_parse() {
-        assert_eq!(parse_rfc3339("1970-01-01T00:00:00Z").unwrap(),
-                   UNIX_EPOCH + Duration::new(0, 0));
-        assert_eq!(parse_rfc3339("1970-01-01T00:00:01Z").unwrap(),
-                   UNIX_EPOCH + Duration::new(1, 0));
-        assert_eq!(parse_rfc3339("2018-02-13T23:08:32Z").unwrap(),
-                   UNIX_EPOCH + Duration::new(1518563312, 0));
-        assert_eq!(parse_rfc3339("2012-01-01T00:00:00Z").unwrap(),
-                   UNIX_EPOCH + Duration::new(1325376000, 0));
-    }
-
-    #[test]
-    fn smoke_tests_format() {
-        assert_eq!(
-            format_rfc3339(UNIX_EPOCH + Duration::new(0, 0)).to_string(),
-            "1970-01-01T00:00:00Z");
-        assert_eq!(
-            format_rfc3339(UNIX_EPOCH + Duration::new(1, 0)).to_string(),
-            "1970-01-01T00:00:01Z");
-        assert_eq!(
-            format_rfc3339(UNIX_EPOCH + Duration::new(1518563312, 0)).to_string(),
-            "2018-02-13T23:08:32Z");
-        assert_eq!(
-            format_rfc3339(UNIX_EPOCH + Duration::new(1325376000, 0)).to_string(),
-            "2012-01-01T00:00:00Z");
-    }
-
-    #[test]
-    fn smoke_tests_format_millis() {
-        assert_eq!(
-            format_rfc3339_millis(UNIX_EPOCH +
-                Duration::new(0, 0)).to_string(),
-            "1970-01-01T00:00:00.000Z");
-        assert_eq!(
-            format_rfc3339_millis(UNIX_EPOCH +
-                Duration::new(1518563312, 123_000_000)).to_string(),
-            "2018-02-13T23:08:32.123Z");
-    }
-
-    #[test]
-    fn smoke_tests_format_micros() {
-        assert_eq!(
-            format_rfc3339_micros(UNIX_EPOCH +
-                Duration::new(0, 0)).to_string(),
-            "1970-01-01T00:00:00.000000Z");
-        assert_eq!(
-            format_rfc3339_micros(UNIX_EPOCH +
-                Duration::new(1518563312, 123_000_000)).to_string(),
-            "2018-02-13T23:08:32.123000Z");
-        assert_eq!(
-            format_rfc3339_micros(UNIX_EPOCH +
-                Duration::new(1518563312, 456_123_000)).to_string(),
-            "2018-02-13T23:08:32.456123Z");
-    }
-
-    #[test]
-    fn smoke_tests_format_nanos() {
-        assert_eq!(
-            format_rfc3339_nanos(UNIX_EPOCH +
-                Duration::new(0, 0)).to_string(),
-            "1970-01-01T00:00:00.000000000Z");
-        assert_eq!(
-            format_rfc3339_nanos(UNIX_EPOCH +
-                Duration::new(1518563312, 123_000_000)).to_string(),
-            "2018-02-13T23:08:32.123000000Z");
-        assert_eq!(
-            format_rfc3339_nanos(UNIX_EPOCH +
-                Duration::new(1518563312, 789_456_123)).to_string(),
-            "2018-02-13T23:08:32.789456123Z");
-    }
-
-    #[test]
-    fn upper_bound() {
-        let max = UNIX_EPOCH + Duration::new(max::SECONDS, 0);
-        assert_eq!(parse_rfc3339(&max::TIMESTAMP).unwrap(), max);
-        assert_eq!(format_rfc3339(max).to_string(), max::TIMESTAMP);
-    }
-
-    #[test]
-    fn leap_second() {
-        assert_eq!(parse_rfc3339("2016-12-31T23:59:60Z").unwrap(),
-                   UNIX_EPOCH + Duration::new(1483228799, 0));
-    }
-
-    #[test]
-    fn first_731_days() {
-        let year_start = 0;  // 1970
-        for day in 0.. (365 * 2 + 1) {  // scan leap year and non-leap year
-            let (s, time) = from_sec(year_start + day * 86400);
-            assert_eq!(parse_rfc3339(&s).unwrap(), time);
-            assert_eq!(format_rfc3339(time).to_string(), s);
-        }
-    }
-
-    #[test]
-    fn the_731_consecutive_days() {
-        let year_start = 1325376000;  // 2012
-        for day in 0.. (365 * 2 + 1) {  // scan leap year and non-leap year
-            let (s, time) = from_sec(year_start + day * 86400);
-            assert_eq!(parse_rfc3339(&s).unwrap(), time);
-            assert_eq!(format_rfc3339(time).to_string(), s);
-        }
-    }
-
-    #[test]
-    fn all_86400_seconds() {
-        let day_start = 1325376000;
-        for second in 0..86400 {  // scan leap year and non-leap year
-            let (s, time) = from_sec(day_start + second);
-            assert_eq!(parse_rfc3339(&s).unwrap(), time);
-            assert_eq!(format_rfc3339(time).to_string(), s);
-        }
-    }
-
-    #[test]
-    fn random_past() {
-        let upper = SystemTime::now().duration_since(UNIX_EPOCH).unwrap()
-            .as_secs();
-        for _ in 0..10000 {
-            let sec = rand::thread_rng().gen_range(0, upper);
-            let (s, time) = from_sec(sec);
-            assert_eq!(parse_rfc3339(&s).unwrap(), time);
-            assert_eq!(format_rfc3339(time).to_string(), s);
-        }
-    }
-
-    #[test]
-    fn random_wide_range() {
-        for _ in 0..100000 {
-            let sec = rand::thread_rng().gen_range(0, max::SECONDS);
-            let (s, time) = from_sec(sec);
-            assert_eq!(parse_rfc3339(&s).unwrap(), time);
-            assert_eq!(format_rfc3339(time).to_string(), s);
-        }
-    }
-
-    #[test]
-    fn milliseconds() {
-        assert_eq!(parse_rfc3339("1970-01-01T00:00:00.123Z").unwrap(),
-                   UNIX_EPOCH + Duration::new(0, 123000000));
-        assert_eq!(format_rfc3339(UNIX_EPOCH + Duration::new(0, 123000000))
-            .to_string(), "1970-01-01T00:00:00.123000000Z");
-    }
-
-    #[test]
-    #[should_panic(expected="OutOfRange")]
-    fn zero_month() {
-        parse_rfc3339("1970-00-01T00:00:00Z").unwrap();
-    }
-
-    #[test]
-    #[should_panic(expected="OutOfRange")]
-    fn big_month() {
-        parse_rfc3339("1970-32-01T00:00:00Z").unwrap();
-    }
-
-    #[test]
-    #[should_panic(expected="OutOfRange")]
-    fn zero_day() {
-        parse_rfc3339("1970-01-00T00:00:00Z").unwrap();
-    }
-
-    #[test]
-    #[should_panic(expected="OutOfRange")]
-    fn big_day() {
-        parse_rfc3339("1970-12-35T00:00:00Z").unwrap();
-    }
-
-    #[test]
-    #[should_panic(expected="OutOfRange")]
-    fn big_day2() {
-        parse_rfc3339("1970-02-30T00:00:00Z").unwrap();
-    }
-
-    #[test]
-    #[should_panic(expected="OutOfRange")]
-    fn big_second() {
-        parse_rfc3339("1970-12-30T00:00:78Z").unwrap();
-    }
-
-    #[test]
-    #[should_panic(expected="OutOfRange")]
-    fn big_minute() {
-        parse_rfc3339("1970-12-30T00:78:00Z").unwrap();
-    }
-
-    #[test]
-    #[should_panic(expected="OutOfRange")]
-    fn big_hour() {
-        parse_rfc3339("1970-12-30T24:00:00Z").unwrap();
-    }
-
-    #[test]
-    fn break_data() {
-        for pos in 0.."2016-12-31T23:59:60Z".len() {
-            let mut s = b"2016-12-31T23:59:60Z".to_vec();
-            s[pos] = b'x';
-            parse_rfc3339(from_utf8(&s).unwrap()).unwrap_err();
-        }
-    }
-
-    #[test]
-    fn weak_smoke_tests() {
-        assert_eq!(parse_rfc3339_weak("1970-01-01 00:00:00").unwrap(),
-                   UNIX_EPOCH + Duration::new(0, 0));
-        parse_rfc3339("1970-01-01 00:00:00").unwrap_err();
-
-        assert_eq!(parse_rfc3339_weak("1970-01-01 00:00:00.000123").unwrap(),
-                   UNIX_EPOCH + Duration::new(0, 123000));
-        parse_rfc3339("1970-01-01 00:00:00.000123").unwrap_err();
-
-        assert_eq!(parse_rfc3339_weak("1970-01-01T00:00:00.000123").unwrap(),
-                   UNIX_EPOCH + Duration::new(0, 123000));
-        parse_rfc3339("1970-01-01T00:00:00.000123").unwrap_err();
-
-        assert_eq!(parse_rfc3339_weak("1970-01-01 00:00:00.000123Z").unwrap(),
-                   UNIX_EPOCH + Duration::new(0, 123000));
-        parse_rfc3339("1970-01-01 00:00:00.000123Z").unwrap_err();
-
-        assert_eq!(parse_rfc3339_weak("1970-01-01 00:00:00Z").unwrap(),
-                   UNIX_EPOCH + Duration::new(0, 0));
-        parse_rfc3339("1970-01-01 00:00:00Z").unwrap_err();
-    }
-}
diff --git a/third_party/rust/humantime-1.3.0/src/duration.rs b/third_party/rust/humantime-1.3.0/src/duration.rs
deleted file mode 100644
index 9fafa84bdca8bc18e6e163fb58dc781412c2ad64..0000000000000000000000000000000000000000
--- a/third_party/rust/humantime-1.3.0/src/duration.rs
+++ /dev/null
@@ -1,411 +0,0 @@
-use std::fmt;
-use std::str::Chars;
-use std::time::Duration;
-use std::error::Error as StdError;
-
-quick_error! {
-    /// Error parsing human-friendly duration
-    #[derive(Debug, PartialEq, Clone, Copy)]
-    pub enum Error {
-        /// Invalid character during parsing
-        ///
-        /// More specifically anything that is not alphanumeric is prohibited
-        ///
-        /// The field is an byte offset of the character in the string.
-        InvalidCharacter(offset: usize) {
-            display("invalid character at {}", offset)
-            description("invalid character")
-        }
-        /// Non-numeric value where number is expected
-        ///
-        /// This usually means that either time unit is broken into words,
-        /// e.g. `m sec` instead of `msec`, or just number is omitted,
-        /// for example `2 hours min` instead of `2 hours 1 min`
-        ///
-        /// The field is an byte offset of the errorneous character
-        /// in the string.
-        NumberExpected(offset: usize) {
-            display("expected number at {}", offset)
-            description("expected number")
-        }
-        /// Unit in the number is not one of allowed units
-        ///
-        /// See documentation of `parse_duration` for the list of supported
-        /// time units.
-        ///
-        /// The two fields are start and end (exclusive) of the slice from
-        /// the original string, containing errorneous value
-        UnknownUnit(start: usize, end: usize) {
-            display("unknown unit at {}-{}", start, end)
-            description("unknown unit")
-        }
-        /// The numeric value is too large
-        ///
-        /// Usually this means value is too large to be useful. If user writes
-        /// data in subsecond units, then the maximum is about 3k years. When
-        /// using seconds, or larger units, the limit is even larger.
-        NumberOverflow {
-            display(self_) -> ("{}", self_.description())
-            description("number is too large")
-        }
-        /// The value was an empty string (or consists only whitespace)
-        Empty {
-            display(self_) -> ("{}", self_.description())
-            description("value was empty")
-        }
-    }
-
-}
-
-/// A wrapper type that allows you to Display a Duration
-#[derive(Debug, Clone)]
-pub struct FormattedDuration(Duration);
-
-trait OverflowOp: Sized {
-    fn mul(self, other: Self) -> Result<Self, Error>;
-    fn add(self, other: Self) -> Result<Self, Error>;
-}
-
-impl OverflowOp for u64 {
-    fn mul(self, other: Self) -> Result<Self, Error> {
-        self.checked_mul(other).ok_or(Error::NumberOverflow)
-    }
-    fn add(self, other: Self) -> Result<Self, Error> {
-        self.checked_add(other).ok_or(Error::NumberOverflow)
-    }
-}
-
-struct Parser<'a> {
-    iter: Chars<'a>,
-    src: &'a str,
-    current: (u64, u64),
-}
-
-impl<'a> Parser<'a> {
-    fn off(&self) -> usize {
-        self.src.len() - self.iter.as_str().len()
-    }
-
-    fn parse_first_char(&mut self) -> Result<Option<u64>, Error> {
-        let off = self.off();
-        for c in self.iter.by_ref() {
-            match c {
-                '0'...'9' => {
-                    return Ok(Some(c as u64 - '0' as u64));
-                }
-                c if c.is_whitespace() => continue,
-                _ => {
-                    return Err(Error::NumberExpected(off));
-                }
-            }
-        }
-        return Ok(None);
-    }
-    fn parse_unit(&mut self, n: u64, start: usize, end: usize)
-        -> Result<(), Error>
-    {
-        let (mut sec, nsec) = match &self.src[start..end] {
-            "nanos" | "nsec" | "ns" => (0u64, n),
-            "usec" | "us" => (0u64, try!(n.mul(1000))),
-            "millis" | "msec" | "ms" => (0u64, try!(n.mul(1000_000))),
-            "seconds" | "second" | "secs" | "sec" | "s" => (n, 0),
-            "minutes" | "minute" | "min" | "mins" | "m"
-            => (try!(n.mul(60)), 0),
-            "hours" | "hour" | "hr" | "hrs" | "h" => (try!(n.mul(3600)), 0),
-            "days" | "day" | "d" => (try!(n.mul(86400)), 0),
-            "weeks" | "week" | "w" => (try!(n.mul(86400*7)), 0),
-            "months" | "month" | "M" => (try!(n.mul(2630016)), 0), // 30.44d
-            "years" | "year" | "y" => (try!(n.mul(31557600)), 0), // 365.25d
-            _ => return Err(Error::UnknownUnit(start, end)),
-        };
-        let mut nsec = try!(self.current.1.add(nsec));
-        if nsec > 1000_000_000 {
-            sec = try!(sec.add(nsec / 1000_000_000));
-            nsec %= 1000_000_000;
-        }
-        sec = try!(self.current.0.add(sec));
-        self.current = (sec, nsec);
-        Ok(())
-    }
-
-    fn parse(mut self) -> Result<Duration, Error> {
-        let mut n = try!(try!(self.parse_first_char()).ok_or(Error::Empty));
-        'outer: loop {
-            let mut off = self.off();
-            while let Some(c) = self.iter.next() {
-                match c {
-                    '0'...'9' => {
-                        n = try!(n.checked_mul(10)
-                            .and_then(|x| x.checked_add(c as u64 - '0' as u64))
-                            .ok_or(Error::NumberOverflow));
-                    }
-                    c if c.is_whitespace() => {}
-                    'a'...'z' | 'A'...'Z' => {
-                        break;
-                    }
-                    _ => {
-                        return Err(Error::InvalidCharacter(off));
-                    }
-                }
-                off = self.off();
-            }
-            let start = off;
-            let mut off = self.off();
-            while let Some(c) = self.iter.next() {
-                match c {
-                    '0'...'9' => {
-                        try!(self.parse_unit(n, start, off));
-                        n = c as u64 - '0' as u64;
-                        continue 'outer;
-                    }
-                    c if c.is_whitespace() => break,
-                    'a'...'z' | 'A'...'Z' => {}
-                    _ => {
-                        return Err(Error::InvalidCharacter(off));
-                    }
-                }
-                off = self.off();
-            }
-            try!(self.parse_unit(n, start, off));
-            n = match try!(self.parse_first_char()) {
-                Some(n) => n,
-                None => return Ok(
-                    Duration::new(self.current.0, self.current.1 as u32)),
-            };
-        }
-    }
-
-}
-
-/// Parse duration object `1hour 12min 5s`
-///
-/// The duration object is a concatenation of time spans. Where each time
-/// span is an integer number and a suffix. Supported suffixes:
-///
-/// * `nsec`, `ns` -- microseconds
-/// * `usec`, `us` -- microseconds
-/// * `msec`, `ms` -- milliseconds
-/// * `seconds`, `second`, `sec`, `s`
-/// * `minutes`, `minute`, `min`, `m`
-/// * `hours`, `hour`, `hr`, `h`
-/// * `days`, `day`, `d`
-/// * `weeks`, `week`, `w`
-/// * `months`, `month`, `M` -- defined as 30.44 days
-/// * `years`, `year`, `y` -- defined as 365.25 days
-///
-/// # Examples
-///
-/// ```
-/// use std::time::Duration;
-/// use humantime::parse_duration;
-///
-/// assert_eq!(parse_duration("2h 37min"), Ok(Duration::new(9420, 0)));
-/// assert_eq!(parse_duration("32ms"), Ok(Duration::new(0, 32_000_000)));
-/// ```
-pub fn parse_duration(s: &str) -> Result<Duration, Error> {
-    Parser {
-        iter: s.chars(),
-        src: s,
-        current: (0, 0),
-    }.parse()
-}
-
-/// Formats duration into a human-readable string
-///
-/// Note: this format is guaranteed to have same value when using
-/// parse_duration, but we can change some details of the exact composition
-/// of the value.
-///
-/// # Examples
-///
-/// ```
-/// use std::time::Duration;
-/// use humantime::format_duration;
-///
-/// let val1 = Duration::new(9420, 0);
-/// assert_eq!(format_duration(val1).to_string(), "2h 37m");
-/// let val2 = Duration::new(0, 32_000_000);
-/// assert_eq!(format_duration(val2).to_string(), "32ms");
-/// ```
-pub fn format_duration(val: Duration) -> FormattedDuration {
-    FormattedDuration(val)
-}
-
-fn item_plural(f: &mut fmt::Formatter, started: &mut bool,
-    name: &str, value: u64)
-    -> fmt::Result
-{
-    if value > 0 {
-        if *started {
-            f.write_str(" ")?;
-        }
-        write!(f, "{}{}", value, name)?;
-        if value > 1 {
-            f.write_str("s")?;
-        }
-        *started = true;
-    }
-    Ok(())
-}
-fn item(f: &mut fmt::Formatter, started: &mut bool, name: &str, value: u32)
-    -> fmt::Result
-{
-    if value > 0 {
-        if *started {
-            f.write_str(" ")?;
-        }
-        write!(f, "{}{}", value, name)?;
-        *started = true;
-    }
-    Ok(())
-}
-
-impl fmt::Display for FormattedDuration {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let secs = self.0.as_secs();
-        let nanos = self.0.subsec_nanos();
-
-        if secs == 0 && nanos == 0 {
-            f.write_str("0s")?;
-            return Ok(());
-        }
-
-        let years = secs / 31557600;  // 365.25d
-        let ydays = secs % 31557600;
-        let months = ydays / 2630016;  // 30.44d
-        let mdays = ydays % 2630016;
-        let days = mdays / 86400;
-        let day_secs = mdays % 86400;
-        let hours = day_secs / 3600;
-        let minutes = day_secs % 3600 / 60;
-        let seconds = day_secs % 60;
-
-        let millis = nanos / 1_000_000;
-        let micros = nanos / 1000 % 1000;
-        let nanosec = nanos % 1000;
-
-        let ref mut started = false;
-        item_plural(f, started, "year", years)?;
-        item_plural(f, started, "month", months)?;
-        item_plural(f, started, "day", days)?;
-        item(f, started, "h", hours as u32)?;
-        item(f, started, "m", minutes as u32)?;
-        item(f, started, "s", seconds as u32)?;
-        item(f, started, "ms", millis)?;
-        item(f, started, "us", micros)?;
-        item(f, started, "ns", nanosec)?;
-        Ok(())
-    }
-}
-
-#[cfg(test)]
-mod test {
-    extern crate rand;
-
-    use std::time::Duration;
-    use self::rand::Rng;
-    use super::{parse_duration, format_duration};
-    use super::Error;
-
-    #[test]
-    fn test_units() {
-        assert_eq!(parse_duration("17nsec"), Ok(Duration::new(0, 17)));
-        assert_eq!(parse_duration("17nanos"), Ok(Duration::new(0, 17)));
-        assert_eq!(parse_duration("33ns"), Ok(Duration::new(0, 33)));
-        assert_eq!(parse_duration("3usec"), Ok(Duration::new(0, 3000)));
-        assert_eq!(parse_duration("78us"), Ok(Duration::new(0, 78000)));
-        assert_eq!(parse_duration("31msec"), Ok(Duration::new(0, 31000000)));
-        assert_eq!(parse_duration("31millis"), Ok(Duration::new(0, 31000000)));
-        assert_eq!(parse_duration("6ms"), Ok(Duration::new(0, 6000000)));
-        assert_eq!(parse_duration("3000s"), Ok(Duration::new(3000, 0)));
-        assert_eq!(parse_duration("300sec"), Ok(Duration::new(300, 0)));
-        assert_eq!(parse_duration("300secs"), Ok(Duration::new(300, 0)));
-        assert_eq!(parse_duration("50seconds"), Ok(Duration::new(50, 0)));
-        assert_eq!(parse_duration("1second"), Ok(Duration::new(1, 0)));
-        assert_eq!(parse_duration("100m"), Ok(Duration::new(6000, 0)));
-        assert_eq!(parse_duration("12min"), Ok(Duration::new(720, 0)));
-        assert_eq!(parse_duration("12mins"), Ok(Duration::new(720, 0)));
-        assert_eq!(parse_duration("1minute"), Ok(Duration::new(60, 0)));
-        assert_eq!(parse_duration("7minutes"), Ok(Duration::new(420, 0)));
-        assert_eq!(parse_duration("2h"), Ok(Duration::new(7200, 0)));
-        assert_eq!(parse_duration("7hr"), Ok(Duration::new(25200, 0)));
-        assert_eq!(parse_duration("7hrs"), Ok(Duration::new(25200, 0)));
-        assert_eq!(parse_duration("1hour"), Ok(Duration::new(3600, 0)));
-        assert_eq!(parse_duration("24hours"), Ok(Duration::new(86400, 0)));
-        assert_eq!(parse_duration("1day"), Ok(Duration::new(86400, 0)));
-        assert_eq!(parse_duration("2days"), Ok(Duration::new(172800, 0)));
-        assert_eq!(parse_duration("365d"), Ok(Duration::new(31536000, 0)));
-        assert_eq!(parse_duration("1week"), Ok(Duration::new(604800, 0)));
-        assert_eq!(parse_duration("7weeks"), Ok(Duration::new(4233600, 0)));
-        assert_eq!(parse_duration("52w"), Ok(Duration::new(31449600, 0)));
-        assert_eq!(parse_duration("1month"), Ok(Duration::new(2630016, 0)));
-        assert_eq!(parse_duration("3months"), Ok(Duration::new(3*2630016, 0)));
-        assert_eq!(parse_duration("12M"), Ok(Duration::new(31560192, 0)));
-        assert_eq!(parse_duration("1year"), Ok(Duration::new(31557600, 0)));
-        assert_eq!(parse_duration("7years"), Ok(Duration::new(7*31557600, 0)));
-        assert_eq!(parse_duration("17y"), Ok(Duration::new(536479200, 0)));
-    }
-
-    #[test]
-    fn test_combo() {
-        assert_eq!(parse_duration("20 min 17 nsec "), Ok(Duration::new(1200, 17)));
-        assert_eq!(parse_duration("2h 15m"), Ok(Duration::new(8100, 0)));
-    }
-
-    #[test]
-    fn all_86400_seconds() {
-        for second in 0..86400 {  // scan leap year and non-leap year
-            let d = Duration::new(second, 0);
-            assert_eq!(d,
-                parse_duration(&format_duration(d).to_string()).unwrap());
-        }
-    }
-
-    #[test]
-    fn random_second() {
-        for _ in 0..10000 {
-            let sec = rand::thread_rng().gen_range(0, 253370764800);
-            let d = Duration::new(sec, 0);
-            assert_eq!(d,
-                parse_duration(&format_duration(d).to_string()).unwrap());
-        }
-    }
-
-    #[test]
-    fn random_any() {
-        for _ in 0..10000 {
-            let sec = rand::thread_rng().gen_range(0, 253370764800);
-            let nanos = rand::thread_rng().gen_range(0, 1_000_000_000);
-            let d = Duration::new(sec, nanos);
-            assert_eq!(d,
-                parse_duration(&format_duration(d).to_string()).unwrap());
-        }
-    }
-
-    #[test]
-    fn test_overlow() {
-        // Overflow on subseconds is earlier because of how we do conversion
-        // we could fix it, but I don't see any good reason for this
-        assert_eq!(parse_duration("100000000000000000000ns"),
-            Err(Error::NumberOverflow));
-        assert_eq!(parse_duration("100000000000000000us"),
-            Err(Error::NumberOverflow));
-        assert_eq!(parse_duration("100000000000000ms"),
-            Err(Error::NumberOverflow));
-
-        assert_eq!(parse_duration("100000000000000000000s"),
-            Err(Error::NumberOverflow));
-        assert_eq!(parse_duration("10000000000000000000m"),
-            Err(Error::NumberOverflow));
-        assert_eq!(parse_duration("1000000000000000000h"),
-            Err(Error::NumberOverflow));
-        assert_eq!(parse_duration("100000000000000000d"),
-            Err(Error::NumberOverflow));
-        assert_eq!(parse_duration("10000000000000000w"),
-            Err(Error::NumberOverflow));
-        assert_eq!(parse_duration("1000000000000000M"),
-            Err(Error::NumberOverflow));
-        assert_eq!(parse_duration("10000000000000y"),
-            Err(Error::NumberOverflow));
-    }
-}
diff --git a/third_party/rust/humantime-1.3.0/src/lib.rs b/third_party/rust/humantime-1.3.0/src/lib.rs
deleted file mode 100644
index 6d6c707e1d5dafb72b18b1ea1b100544de3a9d53..0000000000000000000000000000000000000000
--- a/third_party/rust/humantime-1.3.0/src/lib.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-//! Human-friendly time parser and formatter
-//!
-//! Features:
-//!
-//! * Parses durations in free form like `15days 2min 2s`
-//! * Formats durations in similar form `2years 2min 12us`
-//! * Parses and formats timestamp in `rfc3339` format: `2018-01-01T12:53:00Z`
-//! * Parses timestamps in a weaker format: `2018-01-01 12:53:00`
-//!
-//! Timestamp parsing/formatting is super-fast because format is basically
-//! fixed.
-//!
-//! See [serde-humantime] for serde integration.
-//!
-//! [serde-humantime]: https://docs.rs/serde-humantime/0.1.1/serde_humantime/
-#![warn(missing_debug_implementations)]
-#![warn(missing_docs)]
-
-#[macro_use] extern crate quick_error;
-
-mod duration;
-mod wrapper;
-mod date;
-
-pub use duration::{parse_duration, Error as DurationError};
-pub use duration::{format_duration, FormattedDuration};
-pub use wrapper::{Duration, Timestamp};
-pub use date::{parse_rfc3339, parse_rfc3339_weak, Error as TimestampError};
-pub use date::{
-    format_rfc3339, format_rfc3339_micros, format_rfc3339_millis, format_rfc3339_nanos,
-    format_rfc3339_seconds,
-};
-pub use date::{Rfc3339Timestamp};
diff --git a/third_party/rust/humantime-1.3.0/src/wrapper.rs b/third_party/rust/humantime-1.3.0/src/wrapper.rs
deleted file mode 100644
index df01d791a8193880a62a9e454574f7622e077168..0000000000000000000000000000000000000000
--- a/third_party/rust/humantime-1.3.0/src/wrapper.rs
+++ /dev/null
@@ -1,107 +0,0 @@
-use std::str::FromStr;
-use std::ops::Deref;
-use std::fmt;
-use std::time::{Duration as StdDuration, SystemTime};
-
-use duration::{self, parse_duration, format_duration};
-use date::{self, parse_rfc3339_weak, format_rfc3339};
-
-/// A wrapper for duration that has `FromStr` implementation
-///
-/// This is useful if you want to use it somewhere where `FromStr` is
-/// expected.
-///
-/// See `parse_duration` for the description of the format.
-///
-/// # Example
-///
-/// ```
-/// use std::time::Duration;
-/// let x: Duration;
-/// x = "12h 5min 2ns".parse::<humantime::Duration>().unwrap().into();
-/// assert_eq!(x, Duration::new(12*3600 + 5*60, 2))
-/// ```
-///
-#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
-pub struct Duration(StdDuration);
-
-/// A wrapper for SystemTime that has `FromStr` implementation
-///
-/// This is useful if you want to use it somewhere where `FromStr` is
-/// expected.
-///
-/// See `parse_rfc3339_weak` for the description of the format. The "weak"
-/// format is used as it's more pemissive for human input as this is the
-/// expected use of the type (e.g. command-line parsing).
-///
-/// # Example
-///
-/// ```
-/// use std::time::SystemTime;
-/// let x: SystemTime;
-/// x = "2018-02-16T00:31:37Z".parse::<humantime::Timestamp>().unwrap().into();
-/// assert_eq!(humantime::format_rfc3339(x).to_string(), "2018-02-16T00:31:37Z");
-/// ```
-///
-#[derive(Debug, PartialEq, Eq, Clone)]
-pub struct Timestamp(SystemTime);
-
-impl AsRef<StdDuration> for Duration {
-    fn as_ref(&self) -> &StdDuration { &self.0 }
-}
-
-impl Deref for Duration {
-    type Target = StdDuration;
-    fn deref(&self) -> &StdDuration { &self.0 }
-}
-
-impl Into<StdDuration> for Duration {
-    fn into(self) -> StdDuration { self.0 }
-}
-
-impl From<StdDuration> for Duration {
-    fn from(dur: StdDuration) -> Duration { Duration(dur) }
-}
-
-impl FromStr for Duration {
-    type Err = duration::Error;
-    fn from_str(s: &str) -> Result<Duration, Self::Err> {
-        parse_duration(s).map(Duration)
-    }
-}
-
-impl fmt::Display for Duration {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        format_duration(self.0).fmt(f)
-    }
-}
-
-impl AsRef<SystemTime> for Timestamp {
-    fn as_ref(&self) -> &SystemTime { &self.0 }
-}
-
-impl Deref for Timestamp {
-    type Target = SystemTime;
-    fn deref(&self) -> &SystemTime { &self.0 }
-}
-
-impl Into<SystemTime> for Timestamp {
-    fn into(self) -> SystemTime { self.0 }
-}
-
-impl From<SystemTime> for Timestamp {
-    fn from(dur: SystemTime) -> Timestamp { Timestamp(dur) }
-}
-
-impl FromStr for Timestamp {
-    type Err = date::Error;
-    fn from_str(s: &str) -> Result<Timestamp, Self::Err> {
-        parse_rfc3339_weak(s).map(Timestamp)
-    }
-}
-
-impl fmt::Display for Timestamp {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        format_rfc3339(self.0).fmt(f)
-    }
-}
diff --git a/third_party/rust/humantime-1.3.0/vagga.yaml b/third_party/rust/humantime-1.3.0/vagga.yaml
deleted file mode 100644
index b5d6b8b7c00506bd27e1d04b07f6a3ac979a1c77..0000000000000000000000000000000000000000
--- a/third_party/rust/humantime-1.3.0/vagga.yaml
+++ /dev/null
@@ -1,92 +0,0 @@
-commands:
-
-  cargo: !Command
-    description: Run any cargo command
-    container: ubuntu
-    run: [cargo]
-
-  make: !Command
-    description: Build the library
-    container: ubuntu
-    run: [cargo, build]
-
-  test64: !Command
-    description: Test the 64bit library
-    container: ubuntu
-    environ: { RUST_BACKTRACE: 1 }
-    run: [cargo, test]
-
-  test32: !Command
-    description: Test the 32bit library
-    container: ubuntu32
-    environ: { RUST_BACKTRACE: 1 }
-    run: [cargo, test]
-
-  test: !Command
-    description: Test the 64bit library
-    container: ubuntu
-    environ: { RUST_BACKTRACE: 1 }
-    prerequisites: [test64, test32]
-    run: [echo, okay]
-
-  bench: !Command
-    description: Run benchmarks
-    container: bench
-    environ: { RUST_BACKTRACE: 1 }
-    run: [cargo, bench]
-
-  _bulk: !Command
-    description: Run `bulk` command (for version bookkeeping)
-    container: ubuntu
-    run: [bulk]
-
-containers:
-
-  ubuntu:
-    setup:
-    - !Ubuntu xenial
-    - !UbuntuUniverse
-    - !Install [ca-certificates, build-essential, vim]
-
-    - !TarInstall
-      url: "https://static.rust-lang.org/dist/rust-1.24.0-x86_64-unknown-linux-gnu.tar.gz"
-      script: "./install.sh --prefix=/usr \
-               --components=rustc,rust-std-x86_64-unknown-linux-gnu,cargo"
-    - &bulk !Tar
-      url: "https://github.com/tailhook/bulk/releases/download/v0.4.10/bulk-v0.4.10.tar.gz"
-      sha256: 481513f8a0306a9857d045497fb5b50b50a51e9ff748909ecf7d2bda1de275ab
-      path: /
-
-    environ:
-      HOME: /work/target
-      USER: pc
-
-  ubuntu32:
-    setup:
-    - !UbuntuRelease
-      codename: xenial
-      arch: i386
-    - !UbuntuUniverse
-    - !Install [ca-certificates, build-essential, vim]
-
-    - !TarInstall
-      url: "https://static.rust-lang.org/dist/rust-1.24.0-i686-unknown-linux-gnu.tar.gz"
-      script: "./install.sh --prefix=/usr \
-               --components=rustc,rust-std-i686-unknown-linux-gnu,cargo"
-
-    environ:
-      HOME: /work/target
-      USER: pc
-
-  bench:
-    setup:
-    - !Ubuntu xenial
-    - !Install [ca-certificates, wget, build-essential]
-    - !TarInstall
-      url: https://static.rust-lang.org/dist/rust-nightly-x86_64-unknown-linux-gnu.tar.gz
-      script: |
-        ./install.sh --prefix=/usr \
-          --components=rustc,rust-std-x86_64-unknown-linux-gnu,cargo
-    environ:
-      HOME: /work/target
-      USER: pc
diff --git a/third_party/rust/mp4parse/.cargo-checksum.json b/third_party/rust/mp4parse/.cargo-checksum.json
index 94fbb7ab48a177c1eda9e2a94ebb9b9516d97352..a754b45852e9f79e85944e355ccdf2cd6d676d55 100644
--- a/third_party/rust/mp4parse/.cargo-checksum.json
+++ b/third_party/rust/mp4parse/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"105033ac7475000fc0d13cb51973a6fe439a167d05ef79d7db1aa0f82618dedd","benches/avif_benchmark.rs":"e4bdd69c7b434448ef7080bbf488b2f64c2c88121fe1c1f7e9d9c8def3d648ae","src/boxes.rs":"756a3d3638d91fc8e2e58a3e41e663b46d6381539ec12b2e7b6980b205ef4ed2","src/lib.rs":"27ec213bc309ca3701dd0f4d0e5f4af3668c108a4c7f7863285024960c05eae2","src/macros.rs":"76c840f9299797527fe71aa5b378ffb01312767372b45cc62deddb19775400ae","src/tests.rs":"7598fba59c47dc0f713c5a71fa477d046b595ba6362c6e32d775e33197770055","tests/bug-1661347.avif":"a4741189d897401c746492d780bccf4c42dddde8f46d01a791f9656aac2ab164","tests/corrupt/bad-ipma-flags.avif":"ecde7997b97db1910b9dcc7ca8e3c8957da0e83681ea9008c66dc9f12b78ad19","tests/corrupt/bad-ipma-version.avif":"7f9a1a0b4ebbf8d800d22eaae5ff78970cc6b811317db6c1467c6883952b7c9b","tests/corrupt/bug-1655846.avif":"e0a5a06225800fadf05f5352503a4cec11af73eef705c43b4acab5f4a99dea50","tests/corrupt/bug-1661347.avif":"31c26561e1d9eafb60f7c5968b82a0859d203d73f17f26b29276256acee12966","tests/kodim-extents.avif":"e4de6d124535206c3daca797e64cccc6a5b439f93733af52a95b1e82d581a78b","tests/overflow.rs":"16b591d8def1a155b3b997622f6ea255536870d99c3d8f97c51755b77a50de3c","tests/public.rs":"cfc9f440d828d504dfbbb327395c88f92e6685198ef161cd1215188480286d3b"},"package":null}
\ No newline at end of file
+{"files":{"Cargo.toml":"20d60a51a713582d285ab994d13014f101450a359f5ada589b82ea97615ae2e8","benches/avif_benchmark.rs":"e4bdd69c7b434448ef7080bbf488b2f64c2c88121fe1c1f7e9d9c8def3d648ae","src/boxes.rs":"756a3d3638d91fc8e2e58a3e41e663b46d6381539ec12b2e7b6980b205ef4ed2","src/lib.rs":"5cc2731dff15507d7b9a3c2e88ea1682dc40ca75901b69f35c9a6e71898c323b","src/macros.rs":"76c840f9299797527fe71aa5b378ffb01312767372b45cc62deddb19775400ae","src/tests.rs":"7598fba59c47dc0f713c5a71fa477d046b595ba6362c6e32d775e33197770055","tests/bug-1661347.avif":"a4741189d897401c746492d780bccf4c42dddde8f46d01a791f9656aac2ab164","tests/corrupt/bad-ipma-flags.avif":"ecde7997b97db1910b9dcc7ca8e3c8957da0e83681ea9008c66dc9f12b78ad19","tests/corrupt/bad-ipma-version.avif":"7f9a1a0b4ebbf8d800d22eaae5ff78970cc6b811317db6c1467c6883952b7c9b","tests/corrupt/bug-1655846.avif":"e0a5a06225800fadf05f5352503a4cec11af73eef705c43b4acab5f4a99dea50","tests/corrupt/bug-1661347.avif":"31c26561e1d9eafb60f7c5968b82a0859d203d73f17f26b29276256acee12966","tests/kodim-extents.avif":"e4de6d124535206c3daca797e64cccc6a5b439f93733af52a95b1e82d581a78b","tests/overflow.rs":"16b591d8def1a155b3b997622f6ea255536870d99c3d8f97c51755b77a50de3c","tests/public.rs":"bee907c7183040b3a2842312d13e20ac005e880d33d2b2c9067d5a48db3d6514"},"package":null}
\ No newline at end of file
diff --git a/third_party/rust/mp4parse/Cargo.toml b/third_party/rust/mp4parse/Cargo.toml
index 02754e6c8fe3a35eb953646fa86d7ef64d289d37..123930f64882d608d485ff4ba0cbd20d42fd6e06 100644
--- a/third_party/rust/mp4parse/Cargo.toml
+++ b/third_party/rust/mp4parse/Cargo.toml
@@ -1,11 +1,12 @@
 [package]
 name = "mp4parse"
-version = "0.11.4"
+version = "0.11.5"
 authors = [
   "Ralph Giles <giles@mozilla.com>",
   "Matthew Gregan <kinetik@flim.org>",
   "Alfredo Yang <ayang@mozilla.com>",
   "Jon Bauman <jbauman@mozilla.com>",
+  "Bryce Seager van Dyk <bvandyk@mozilla.com>",
 ]
 
 description = "Parser for ISO base media file format (mp4)"
@@ -27,10 +28,10 @@ travis-ci = { repository = "https://github.com/mozilla/mp4parse-rust" }
 [dependencies]
 byteorder = "1.2.1"
 bitreader = { version = "0.3.2" }
-env_logger = "0.7.1"
+env_logger = "0.8"
 fallible_collections = { version = "0.3", features = ["std_io"] }
 hashbrown = "0.9"
-num-traits = "=0.2.10"
+num-traits = "0.2.14"
 log = "0.4"
 static_assertions = "1.1.0"
 
diff --git a/third_party/rust/mp4parse/src/lib.rs b/third_party/rust/mp4parse/src/lib.rs
index 5a2ffece835de7dd65a09a4d2150499ff6e23c13..a50e311a711eb9d8f2fcf0fba310563bdb321189 100644
--- a/third_party/rust/mp4parse/src/lib.rs
+++ b/third_party/rust/mp4parse/src/lib.rs
@@ -2344,6 +2344,11 @@ fn read_moov<T: Read>(f: &mut BMFFBox<T>, context: Option<MediaContext>) -> Resu
             BoxType::UserdataBox => {
                 userdata = Some(read_udta(&mut b));
                 debug!("{:?}", userdata);
+                if let Some(Err(_)) = userdata {
+                    // There was an error parsing userdata. Such failures are not fatal to overall
+                    // parsing, just skip the rest of the box.
+                    skip_box_remain(&mut b)?;
+                }
             }
             _ => skip_box_content(&mut b)?,
         };
diff --git a/third_party/rust/mp4parse/tests/public.rs b/third_party/rust/mp4parse/tests/public.rs
index 42a4c42b075c44099631364fe718c37c4aca626c..5bdd301c665bced31176004bd345d825407ea564 100644
--- a/third_party/rust/mp4parse/tests/public.rs
+++ b/third_party/rust/mp4parse/tests/public.rs
@@ -28,6 +28,9 @@ static VIDEO_EME_CENC_MP4: &str = "tests/bipbop_480wp_1001kbps-cenc-video-key1-i
 static AUDIO_EME_CBCS_MP4: &str = "tests/bipbop_cbcs_audio_init.mp4";
 static VIDEO_EME_CBCS_MP4: &str = "tests/bipbop_cbcs_video_init.mp4";
 static VIDEO_AV1_MP4: &str = "tests/tiny_av1.mp4";
+// This file contains invalid userdata in its copyright userdata. See
+// https://bugzilla.mozilla.org/show_bug.cgi?id=1687357 for more information.
+static VIDEO_INVALID_USERDATA: &str = "tests/invalid_userdata.mp4";
 static IMAGE_AVIF: &str = "av1-avif/testFiles/Microsoft/Monochrome.avif";
 static IMAGE_AVIF_EXTENTS: &str = "tests/kodim-extents.avif";
 static IMAGE_AVIF_ALPHA: &str = "tests/bug-1661347.avif";
@@ -41,7 +44,6 @@ static AVIF_CORRUPT_IMAGES: &str = "tests/corrupt";
 
 // Adapted from https://github.com/GuillaumeGomez/audio-video-metadata/blob/9dff40f565af71d5502e03a2e78ae63df95cfd40/src/metadata.rs#L53
 #[test]
-#[allow(clippy::cognitive_complexity)] // TODO: Consider simplifying this
 fn public_api() {
     let mut fd = File::open(MINI_MP4).expect("Unknown file");
     let mut buf = Vec::new();
@@ -161,7 +163,6 @@ fn public_api() {
 }
 
 #[test]
-#[allow(clippy::cognitive_complexity)] // TODO: Consider simplifying this
 fn public_metadata() {
     let mut fd = File::open(MINI_MP4_WITH_METADATA).expect("Unknown file");
     let mut buf = Vec::new();
@@ -228,7 +229,6 @@ fn public_metadata() {
 }
 
 #[test]
-#[allow(clippy::cognitive_complexity)] // TODO: Consider simplifying this
 fn public_metadata_gnre() {
     let mut fd = File::open(MINI_MP4_WITH_METADATA_STD_GENRE).expect("Unknown file");
     let mut buf = Vec::new();
@@ -291,6 +291,46 @@ fn public_metadata_gnre() {
     assert_eq!(u32::from_le_bytes(bytes), 0x00ff_d8ff);
 }
 
+#[test]
+fn public_invalid_metadata() {
+    // Test that reading userdata containing invalid metadata is not fatal to parsing and that
+    // expected values are still found.
+    let mut fd = File::open(VIDEO_INVALID_USERDATA).expect("Unknown file");
+    let mut buf = Vec::new();
+    fd.read_to_end(&mut buf).expect("File error");
+
+    let mut c = Cursor::new(&buf);
+    let context = mp4::read_mp4(&mut c).expect("read_mp4 failed");
+    // Should have userdata.
+    assert!(context.userdata.is_some());
+    // But it should contain an error.
+    assert!(context.userdata.unwrap().is_err());
+    // Smoke test that other data has been parsed. Don't check everything, just make sure some
+    // values are as expected.
+    assert_eq!(context.tracks.len(), 2);
+    for track in context.tracks {
+        match track.track_type {
+            mp4::TrackType::Video => {
+                // Check some of the values in the video tkhd.
+                let tkhd = track.tkhd.unwrap();
+                assert_eq!(tkhd.disabled, false);
+                assert_eq!(tkhd.duration, 231232);
+                assert_eq!(tkhd.width, 83_886_080);
+                assert_eq!(tkhd.height, 47_185_920);
+            }
+            mp4::TrackType::Audio => {
+                // Check some of the values in the audio tkhd.
+                let tkhd = track.tkhd.unwrap();
+                assert_eq!(tkhd.disabled, false);
+                assert_eq!(tkhd.duration, 231338);
+                assert_eq!(tkhd.width, 0);
+                assert_eq!(tkhd.height, 0);
+            }
+            _ => panic!("File should not contain other tracks."),
+        }
+    }
+}
+
 #[test]
 fn public_audio_tenc() {
     let kid = vec![
@@ -486,7 +526,6 @@ fn public_audio_cbcs() {
 }
 
 #[test]
-#[allow(clippy::cognitive_complexity)] // TODO: Consider simplifying this
 fn public_video_cbcs() {
     let system_id = vec![
         0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, 0xac, 0xe3, 0x3c, 0x1e, 0x52, 0xe2, 0xfb,
@@ -567,7 +606,6 @@ fn public_video_cbcs() {
 }
 
 #[test]
-#[allow(clippy::cognitive_complexity)] // TODO: Consider simplifying this
 fn public_video_av1() {
     let mut fd = File::open(VIDEO_AV1_MP4).expect("Unknown file");
     let mut buf = Vec::new();
diff --git a/third_party/rust/mp4parse_capi/.cargo-checksum.json b/third_party/rust/mp4parse_capi/.cargo-checksum.json
index e59d87b754566752b21df056b6177d6ae061499c..925858c835b41136b9d7996e1fe22e57d68b63b8 100644
--- a/third_party/rust/mp4parse_capi/.cargo-checksum.json
+++ b/third_party/rust/mp4parse_capi/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"ba144343a4d38fe6918dd61bb6723e46ac297f506a27370c1d10b49bd8123572","cbindgen.toml":"5c9429f271d6e914d81b63e6509c04ffe84cab11ed3a53a2ed4715e5d5ace80e","examples/dump.rs":"83462422315c22e496960bae922edb23105c0aa272d2b106edd7574ff068513a","src/lib.rs":"d25c2e010186ada3524801e8f1ecdbe42cc4f961880ccca11ba9bdddd42363f7","tests/test_chunk_out_of_range.rs":"b5da583218d98027ed973a29c67434a91a1306f2d2fb39ec4d640d4824c308ce","tests/test_encryption.rs":"ca98516ff423c03b5fcc17b05f993f13b32485e4cf3ba86faf1bea72681d75ce","tests/test_fragment.rs":"e90eb5a4418d30002655466c0c4b3125c7fd70a74b6871471eaa172f1def9db8","tests/test_rotation.rs":"fb43c2f2dfa496d151c33bdd46c0fd3252387c23cc71e2cac9ed0234de715a81","tests/test_sample_table.rs":"185755909b2f4e0ea99604bb423a07623d614a180accdaebd1c98aef2c2e3ae6","tests/test_workaround_stsc.rs":"7dd419f3d55b9a3a039cac57e58a9240a9c8166bcd4356c24f69f731c3ced83b"},"package":null}
\ No newline at end of file
+{"files":{"Cargo.toml":"9f188cfbdda3daf4dc36638f136f3640c21cad5eef8df60f66826f06cf2cc0e0","cbindgen.toml":"5c9429f271d6e914d81b63e6509c04ffe84cab11ed3a53a2ed4715e5d5ace80e","examples/dump.rs":"83462422315c22e496960bae922edb23105c0aa272d2b106edd7574ff068513a","src/lib.rs":"d25c2e010186ada3524801e8f1ecdbe42cc4f961880ccca11ba9bdddd42363f7","tests/test_chunk_out_of_range.rs":"b5da583218d98027ed973a29c67434a91a1306f2d2fb39ec4d640d4824c308ce","tests/test_encryption.rs":"f1b4dc5a726f067f6a6049ec43bc93733131e7e25b0d7344251e1fdd02dcbbcd","tests/test_fragment.rs":"e90eb5a4418d30002655466c0c4b3125c7fd70a74b6871471eaa172f1def9db8","tests/test_rotation.rs":"fb43c2f2dfa496d151c33bdd46c0fd3252387c23cc71e2cac9ed0234de715a81","tests/test_sample_table.rs":"185755909b2f4e0ea99604bb423a07623d614a180accdaebd1c98aef2c2e3ae6","tests/test_workaround_stsc.rs":"7dd419f3d55b9a3a039cac57e58a9240a9c8166bcd4356c24f69f731c3ced83b"},"package":null}
\ No newline at end of file
diff --git a/third_party/rust/mp4parse_capi/Cargo.toml b/third_party/rust/mp4parse_capi/Cargo.toml
index b4ede98c93e75e15d2bef63d1ccf3b83ce51e6d6..b49e90b291c91d2433c9110f5b78623adb996de2 100644
--- a/third_party/rust/mp4parse_capi/Cargo.toml
+++ b/third_party/rust/mp4parse_capi/Cargo.toml
@@ -1,11 +1,12 @@
 [package]
 name = "mp4parse_capi"
-version = "0.11.4"
+version = "0.11.5"
 authors = [
   "Ralph Giles <giles@mozilla.com>",
   "Matthew Gregan <kinetik@flim.org>",
   "Alfredo Yang <ayang@mozilla.com>",
   "Jon Bauman <jbauman@mozilla.com>",
+  "Bryce Seager van Dyk <bvandyk@mozilla.com>",
 ]
 
 description = "Parser for ISO base media file format (mp4)"
@@ -26,8 +27,8 @@ travis-ci = { repository = "https://github.com/mozilla/mp4parse-rust" }
 byteorder = "1.2.1"
 fallible_collections = { version = "0.3", features = ["std_io"] }
 log = "0.4"
-mp4parse = {version = "0.11.2", path = "../mp4parse"}
-num-traits = "=0.2.10"
+mp4parse = {version = "0.11.5", path = "../mp4parse"}
+num-traits = "0.2.14"
 
 [dev-dependencies]
-env_logger = "0.7.1"
+env_logger = "0.8"
diff --git a/third_party/rust/mp4parse_capi/tests/test_encryption.rs b/third_party/rust/mp4parse_capi/tests/test_encryption.rs
index 33c9c6d9f97d0ab5b4aea3b3ccbf42ed43405f93..fe9114039d35fdffd457895d52524e4390daf2b0 100644
--- a/third_party/rust/mp4parse_capi/tests/test_encryption.rs
+++ b/third_party/rust/mp4parse_capi/tests/test_encryption.rs
@@ -12,7 +12,6 @@ extern "C" fn buf_read(buf: *mut u8, size: usize, userdata: *mut std::os::raw::c
 }
 
 #[test]
-#[allow(clippy::cognitive_complexity)] // TODO: Consider simplifying this
 fn parse_cenc() {
     let mut file = std::fs::File::open("tests/short-cenc.mp4").expect("Unknown file");
     let io = Mp4parseIo {
diff --git a/third_party/rust/num-traits/.cargo-checksum.json b/third_party/rust/num-traits/.cargo-checksum.json
index 9338f632f4c1ba97061998277868ed8355de6f02..01ee2a6feca78edb42a8f6b97c194b7565939bff 100644
--- a/third_party/rust/num-traits/.cargo-checksum.json
+++ b/third_party/rust/num-traits/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"35c48122af67e382695600a6af69d73c0dd907afb31914aee049eebc88c871a5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"b442afb73953744a9d2134442845d3e960984ac5be2a058e5064ae851624d67f","RELEASES.md":"683c12fd04a3185fcbfa1915d1fbce8051077c5bdf07c3bfade4606bdd92d0e4","build.rs":"b4b2d0df90ca7570a339ca4d84a72e4ef00d9dced8927350424e666790c752d7","src/bounds.rs":"4fbc6bf3550e4da7ef55c9eb96466c6e0aee7f7542d7c85cfd742f16e3b4729f","src/cast.rs":"2eae0873cbe11fa0d1a012e304f48dea6a0802c0ee738dc25683779cf15b18fb","src/float.rs":"5c1a11e4218d376cd531aff0d6546c2b590d687bda5825f8c27dc6d6f974fb9b","src/identities.rs":"5b6238ebd52e1fadd5b405bc40ad81e45346bcb1c4b46cf1f0496a30be7c9bc4","src/int.rs":"bbc014a02998848170430abf60ab80fa46d7835be3a5e8bf7d28e1c5318068ae","src/lib.rs":"beb207aa3f791811b043d7aa0daa34a2f8f3a52e0555bda8eb32e3359203a129","src/macros.rs":"b589a98c2468ca98131c641a058601964c4e82d75129b1c16fdc17aca8779eca","src/ops/checked.rs":"b6dfae21fe1a5ce41e92074c57d204284975ec56d45e63cac5f0136b8c3643b4","src/ops/inv.rs":"dd80b9bd48d815f17855a25842287942317fa49d1fdcdd655b61bd20ef927cda","src/ops/mod.rs":"036b2a1900dc8e7295a91060e660184b2bd98f33b5db81a62b08cf8d3df726cf","src/ops/mul_add.rs":"368bdebb40b16f3b4b85cf50235954268ff601ec7a458a3a83fe433f47f86f6d","src/ops/saturating.rs":"81c34038ec88fe49f4286e6e1213a1da831c5e66caac651f0a61506a4534c9ce","src/ops/wrapping.rs":"8d334dd2b8128e640bff6c3e93ea301182241987b3ed1fc158268292827bbd0c","src/pow.rs":"9f78cb9c4d5987b59e16f4141723a33ff689781cc352f357b0cc0111d22cde3a","src/real.rs":"b5115bb2cfb752a59426bb3fcbabf9cff15521a00a3f8b5ef4dfc0b0b31bb1f4","src/sign.rs":"81b1116300b5787546852d9d04f0375fa24342f85c34f5bc1ce5360b53fa411a","tests/cast.rs":"2c4b4f2185ec0d687e1bde292731dbc5efec527ab393478b5adf26f6e1352231"},"package":"d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4"}
\ No newline at end of file
+{"files":{"Cargo.toml":"25ae881cd00d94ea9f9cb7844f32e3e58871fc9e45769ead9820d8d40c342ddb","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"dd03422a366071c147d9dec73f01ba8299ccf963a0b038eb85520908d9cd028c","RELEASES.md":"8be8fef421245ea7d9e8a4ab89056307095bfbc9730ca175a75968e6d01b68e4","build.rs":"14cb861026b2493f7b39e0f72ced0ccb95c9a5fd0bdce3158f23a27dac7577e8","src/bounds.rs":"4fbc6bf3550e4da7ef55c9eb96466c6e0aee7f7542d7c85cfd742f16e3b4729f","src/cast.rs":"8c8384dcdfaf926b9331399d528278fc73851f8b5e1105dee343f4f19557e932","src/float.rs":"73cc27228e7578d537c00b9b46e124e365c569a53a7e160fe0d1ad1dacf54fc8","src/identities.rs":"5b6238ebd52e1fadd5b405bc40ad81e45346bcb1c4b46cf1f0496a30be7c9bc4","src/int.rs":"c6e042ac4614529f07b0009271a6b97378451d6d3998e1dc407e76f9a050aa2d","src/lib.rs":"5ff4c0694c7db0538fdca2eb8290ecca4a05e0357607dd4bd078b2b762241094","src/macros.rs":"b589a98c2468ca98131c641a058601964c4e82d75129b1c16fdc17aca8779eca","src/ops/checked.rs":"b6dfae21fe1a5ce41e92074c57d204284975ec56d45e63cac5f0136b8c3643b4","src/ops/inv.rs":"dd80b9bd48d815f17855a25842287942317fa49d1fdcdd655b61bd20ef927cda","src/ops/mod.rs":"fd33030d6e5bd50b9797112b63d14e49ce53a61dd9cc88205c942fa79cb18cf5","src/ops/mul_add.rs":"368bdebb40b16f3b4b85cf50235954268ff601ec7a458a3a83fe433f47f86f6d","src/ops/overflowing.rs":"1b92882a5a738ea4cafdb0971101dc438be9043f540e1246f58f7c9ecf6348dc","src/ops/saturating.rs":"6fb4b2a2c78d9202152a84586d7b068444b78d3caed4b293980832672a234d4b","src/ops/wrapping.rs":"0acf88c0e5fc81a3c6790b31986ab9be5b16c720c9e27461fe5d69b710ffcaba","src/pow.rs":"9f78cb9c4d5987b59e16f4141723a33ff689781cc352f357b0cc0111d22cde3a","src/real.rs":"b5115bb2cfb752a59426bb3fcbabf9cff15521a00a3f8b5ef4dfc0b0b31bb1f4","src/sign.rs":"83562caa3501c6873558eb64c9e3bfe25b4b20d38562a7aa7cc9adafcb3ff037","tests/cast.rs":"0a41785611b3909ecb4a88d6d5264a85564f6de8fbfc761436d3c8baafc8e3d0"},"package":"9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"}
\ No newline at end of file
diff --git a/third_party/rust/num-traits/Cargo.toml b/third_party/rust/num-traits/Cargo.toml
index 5b7b0ada1e7ae4c0447e30d2fbe585b471733478..685a784c0fdb6cff8cd1602b7db3d739f03a6201 100644
--- a/third_party/rust/num-traits/Cargo.toml
+++ b/third_party/rust/num-traits/Cargo.toml
@@ -12,17 +12,17 @@
 
 [package]
 name = "num-traits"
-version = "0.2.10"
+version = "0.2.14"
 authors = ["The Rust Project Developers"]
 build = "build.rs"
-exclude = ["/ci/*", "/.travis.yml", "/bors.toml"]
+exclude = ["/bors.toml", "/ci/*", "/.github/*"]
 description = "Numeric traits for generic mathematics"
 homepage = "https://github.com/rust-num/num-traits"
 documentation = "https://docs.rs/num-traits"
 readme = "README.md"
 keywords = ["mathematics", "numerics"]
 categories = ["algorithms", "science", "no-std"]
-license = "MIT/Apache-2.0"
+license = "MIT OR Apache-2.0"
 repository = "https://github.com/rust-num/num-traits"
 [package.metadata.docs.rs]
 features = ["std"]
@@ -30,7 +30,7 @@ features = ["std"]
 version = "0.2.0"
 optional = true
 [build-dependencies.autocfg]
-version = "0.1.3"
+version = "1"
 
 [features]
 default = ["std"]
diff --git a/third_party/rust/num-traits/README.md b/third_party/rust/num-traits/README.md
index 43335b1341bf52ba26b73dae9972f3169fe9ceee..1ee1e1e9d85b78bde529e7acd450c900beda7824 100644
--- a/third_party/rust/num-traits/README.md
+++ b/third_party/rust/num-traits/README.md
@@ -2,8 +2,8 @@
 
 [![crate](https://img.shields.io/crates/v/num-traits.svg)](https://crates.io/crates/num-traits)
 [![documentation](https://docs.rs/num-traits/badge.svg)](https://docs.rs/num-traits)
-![minimum rustc 1.8](https://img.shields.io/badge/rustc-1.8+-red.svg)
-[![Travis status](https://travis-ci.org/rust-num/num-traits.svg?branch=master)](https://travis-ci.org/rust-num/num-traits)
+[![minimum rustc 1.8](https://img.shields.io/badge/rustc-1.8+-red.svg)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html)
+[![build status](https://github.com/rust-num/num-traits/workflows/master/badge.svg)](https://github.com/rust-num/num-traits/actions)
 
 Numeric traits for generic mathematics in Rust.
 
@@ -52,3 +52,18 @@ Release notes are available in [RELEASES.md](RELEASES.md).
 ## Compatibility
 
 The `num-traits` crate is tested for rustc 1.8 and greater.
+
+## License
+
+Licensed under either of
+
+ * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0)
+ * [MIT license](http://opensource.org/licenses/MIT)
+
+at your option.
+
+### Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
+dual licensed as above, without any additional terms or conditions.
diff --git a/third_party/rust/num-traits/RELEASES.md b/third_party/rust/num-traits/RELEASES.md
index 18879d8a5e5514e0ef3b2af22d85b84ae55c12ad..94449d694a801c7381b36ad2798ea4ca668136ec 100644
--- a/third_party/rust/num-traits/RELEASES.md
+++ b/third_party/rust/num-traits/RELEASES.md
@@ -1,3 +1,56 @@
+# Release 0.2.14 (2020-10-29)
+
+- Clarify the license specification as "MIT OR Apache-2.0".
+
+**Contributors**: @cuviper
+
+# Release 0.2.13 (2020-10-29)
+
+- [The new `OverflowingAdd`, `OverflowingSub`, and `OverflowingMul` traits][180]
+  return a tuple with the operation result and a `bool` indicating overflow.
+- [The "i128" feature now overrides compiler probes for that support][185].
+  This may fix scenarios where `autocfg` probing doesn't work properly.
+- [Casts from large `f64` values to `f32` now saturate to infinity][186]. They
+  previously returned `None` because that was once thought to be undefined
+  behavior, but [rust#15536] resolved that such casts are fine.
+- [`Num::from_str_radix` documents requirements for radix support][192], which
+  are now more relaxed than previously implied. It is suggested to accept at
+  least `2..=36` without panicking, but `Err` may be returned otherwise.
+
+**Contributors**: @cuviper, @Enet4, @KaczuH, @martin-t, @newpavlov
+
+[180]: https://github.com/rust-num/num-traits/pull/180
+[185]: https://github.com/rust-num/num-traits/pull/185
+[186]: https://github.com/rust-num/num-traits/pull/186
+[192]: https://github.com/rust-num/num-traits/issues/192
+[rust#15536]: https://github.com/rust-lang/rust/issues/15536
+
+# Release 0.2.12 (2020-06-11)
+
+- [The new `WrappingNeg` trait][153] will wrap the result if it exceeds the
+  boundary of the type, e.g. `i32::MIN.wrapping_neg() == i32::MIN`.
+- [The new `SaturatingAdd`, `SaturatingSub`, and `SaturatingMul` traits][165]
+  will saturate at the numeric bounds if the operation would overflow. These
+  soft-deprecate the existing `Saturating` trait that only has addition and
+  subtraction methods.
+- [Added new constants for logarithms, `FloatConst::{LOG10_2, LOG2_10}`][171].
+
+**Contributors**: @cuviper, @ocstl, @trepetti, @vallentin
+
+[153]: https://github.com/rust-num/num-traits/pull/153
+[165]: https://github.com/rust-num/num-traits/pull/165
+[171]: https://github.com/rust-num/num-traits/pull/171
+
+# Release 0.2.11 (2020-01-09)
+
+- [Added the full circle constant Ï„ as `FloatConst::TAU`][145].
+- [Updated the `autocfg` build dependency to 1.0][148].
+
+**Contributors**: @cuviper, @m-ou-se
+
+[145]: https://github.com/rust-num/num-traits/pull/145
+[148]: https://github.com/rust-num/num-traits/pull/148
+
 # Release 0.2.10 (2019-11-22)
 
 - [Updated the `libm` dependency to 0.2][144].
diff --git a/third_party/rust/num-traits/build.rs b/third_party/rust/num-traits/build.rs
index e483c15fd7f68536573d1b44bf9c8c7e2b568448..816ddadd721196a1c9838daa01e31c9844fc9046 100644
--- a/third_party/rust/num-traits/build.rs
+++ b/third_party/rust/num-traits/build.rs
@@ -4,11 +4,17 @@ use std::env;
 
 fn main() {
     let ac = autocfg::new();
-    if ac.probe_type("i128") {
-        println!("cargo:rustc-cfg=has_i128");
-    } else if env::var_os("CARGO_FEATURE_I128").is_some() {
-        panic!("i128 support was not detected!");
+
+    // If the "i128" feature is explicity requested, don't bother probing for it.
+    // It will still cause a build error if that was set improperly.
+    if env::var_os("CARGO_FEATURE_I128").is_some() || ac.probe_type("i128") {
+        autocfg::emit("has_i128");
     }
 
+    ac.emit_expression_cfg(
+        "unsafe { 1f64.to_int_unchecked::<i32>() }",
+        "has_to_int_unchecked",
+    );
+
     autocfg::rerun_path("build.rs");
 }
diff --git a/third_party/rust/num-traits/src/cast.rs b/third_party/rust/num-traits/src/cast.rs
index cd66ae964ffcad8a765d25adf0564a5252d2bf4d..d38c338156b19bc8c218e2a55fcb88a611047ad0 100644
--- a/third_party/rust/num-traits/src/cast.rs
+++ b/third_party/rust/num-traits/src/cast.rs
@@ -6,9 +6,16 @@ use core::{i128, u128};
 use core::{i16, i32, i64, i8, isize};
 use core::{u16, u32, u64, u8, usize};
 
-use float::FloatCore;
-
 /// A generic trait for converting a value to a number.
+///
+/// A value can be represented by the target type when it lies within
+/// the range of scalars supported by the target type.
+/// For example, a negative integer cannot be represented by an unsigned
+/// integer type, and an `i64` with a very high magnitude might not be
+/// convertible to an `i32`.
+/// On the other hand, conversions with possible precision loss or truncation
+/// are admitted, like an `f32` with a decimal part to an integer type, or
+/// even a large `f64` saturating to `f32` infinity.
 pub trait ToPrimitive {
     /// Converts the value of `self` to an `isize`. If the value cannot be
     /// represented by an `isize`, then `None` is returned.
@@ -94,7 +101,7 @@ pub trait ToPrimitive {
     ///
     /// This method is only available with feature `i128` enabled on Rust >= 1.26.
     ///
-    /// The default implementation converts through `to_u64()`.  Types implementing
+    /// The default implementation converts through `to_u64()`. Types implementing
     /// this trait should override this method if they can represent a greater range.
     #[inline]
     #[cfg(has_i128)]
@@ -102,15 +109,21 @@ pub trait ToPrimitive {
         self.to_u64().map(From::from)
     }
 
-    /// Converts the value of `self` to an `f32`. If the value cannot be
-    /// represented by an `f32`, then `None` is returned.
+    /// Converts the value of `self` to an `f32`. Overflows may map to positive
+    /// or negative inifinity, otherwise `None` is returned if the value cannot
+    /// be represented by an `f32`.
     #[inline]
     fn to_f32(&self) -> Option<f32> {
         self.to_f64().as_ref().and_then(ToPrimitive::to_f32)
     }
 
-    /// Converts the value of `self` to an `f64`. If the value cannot be
-    /// represented by an `f64`, then `None` is returned.
+    /// Converts the value of `self` to an `f64`. Overflows may map to positive
+    /// or negative inifinity, otherwise `None` is returned if the value cannot
+    /// be represented by an `f64`.
+    ///
+    /// The default implementation tries to convert through `to_i64()`, and
+    /// failing that through `to_u64()`. Types implementing this trait should
+    /// override this method if they can represent a greater range.
     #[inline]
     fn to_f64(&self) -> Option<f64> {
         match self.to_i64() {
@@ -271,19 +284,29 @@ macro_rules! impl_to_primitive_float_to_float {
     ($SrcT:ident : $( fn $method:ident -> $DstT:ident ; )*) => {$(
         #[inline]
         fn $method(&self) -> Option<$DstT> {
-            // Only finite values that are reducing size need to worry about overflow.
-            if size_of::<$SrcT>() > size_of::<$DstT>() && FloatCore::is_finite(*self) {
-                let n = *self as f64;
-                if n < $DstT::MIN as f64 || n > $DstT::MAX as f64 {
-                    return None;
-                }
-            }
-            // We can safely cast NaN, +-inf, and finite values in range.
+            // We can safely cast all values, whether NaN, +-inf, or finite.
+            // Finite values that are reducing size may saturate to +-inf.
             Some(*self as $DstT)
         }
     )*}
 }
 
+#[cfg(has_to_int_unchecked)]
+macro_rules! float_to_int_unchecked {
+    // SAFETY: Must not be NaN or infinite; must be representable as the integer after truncating.
+    // We already checked that the float is in the exclusive range `(MIN-1, MAX+1)`.
+    ($float:expr => $int:ty) => {
+        unsafe { $float.to_int_unchecked::<$int>() }
+    };
+}
+
+#[cfg(not(has_to_int_unchecked))]
+macro_rules! float_to_int_unchecked {
+    ($float:expr => $int:ty) => {
+        $float as $int
+    };
+}
+
 macro_rules! impl_to_primitive_float_to_signed_int {
     ($f:ident : $( $(#[$cfg:meta])* fn $method:ident -> $i:ident ; )*) => {$(
         #[inline]
@@ -296,7 +319,7 @@ macro_rules! impl_to_primitive_float_to_signed_int {
                 const MIN_M1: $f = $i::MIN as $f - 1.0;
                 const MAX_P1: $f = $i::MAX as $f + 1.0;
                 if *self > MIN_M1 && *self < MAX_P1 {
-                    return Some(*self as $i);
+                    return Some(float_to_int_unchecked!(*self => $i));
                 }
             } else {
                 // We can't represent `MIN-1` exactly, but there's no fractional part
@@ -306,7 +329,7 @@ macro_rules! impl_to_primitive_float_to_signed_int {
                 // `MAX+1` (a power of two) when we cast it.
                 const MAX_P1: $f = $i::MAX as $f;
                 if *self >= MIN && *self < MAX_P1 {
-                    return Some(*self as $i);
+                    return Some(float_to_int_unchecked!(*self => $i));
                 }
             }
             None
@@ -325,7 +348,7 @@ macro_rules! impl_to_primitive_float_to_unsigned_int {
                 // With a larger size, we can represent the range exactly.
                 const MAX_P1: $f = $u::MAX as $f + 1.0;
                 if *self > -1.0 && *self < MAX_P1 {
-                    return Some(*self as $u);
+                    return Some(float_to_int_unchecked!(*self => $u));
                 }
             } else {
                 // We can't represent `MAX` exactly, but it will round up to exactly
@@ -333,7 +356,7 @@ macro_rules! impl_to_primitive_float_to_unsigned_int {
                 // (`u128::MAX as f32` is infinity, but this is still ok.)
                 const MAX_P1: $f = $u::MAX as $f;
                 if *self > -1.0 && *self < MAX_P1 {
-                    return Some(*self as $u);
+                    return Some(float_to_int_unchecked!(*self => $u));
                 }
             }
             None
@@ -376,6 +399,15 @@ impl_to_primitive_float!(f32);
 impl_to_primitive_float!(f64);
 
 /// A generic trait for converting a number to a value.
+///
+/// A value can be represented by the target type when it lies within
+/// the range of scalars supported by the target type.
+/// For example, a negative integer cannot be represented by an unsigned
+/// integer type, and an `i64` with a very high magnitude might not be
+/// convertible to an `i32`.
+/// On the other hand, conversions with possible precision loss or truncation
+/// are admitted, like an `f32` with a decimal part to an integer type, or
+/// even a large `f64` saturating to `f32` infinity.
 pub trait FromPrimitive: Sized {
     /// Converts an `isize` to return an optional value of this type. If the
     /// value cannot be represented by this type, then `None` is returned.
@@ -476,6 +508,10 @@ pub trait FromPrimitive: Sized {
 
     /// Converts a `f64` to return an optional value of this type. If the
     /// value cannot be represented by this type, then `None` is returned.
+    ///
+    /// The default implementation tries to convert through `from_i64()`, and
+    /// failing that through `from_u64()`. Types implementing this trait should
+    /// override this method if they can represent a greater range.
     #[inline]
     fn from_f64(n: f64) -> Option<Self> {
         match n.to_i64() {
@@ -656,6 +692,15 @@ pub trait NumCast: Sized + ToPrimitive {
     /// Creates a number from another value that can be converted into
     /// a primitive via the `ToPrimitive` trait. If the source value cannot be
     /// represented by the target type, then `None` is returned.
+    ///
+    /// A value can be represented by the target type when it lies within
+    /// the range of scalars supported by the target type.
+    /// For example, a negative integer cannot be represented by an unsigned
+    /// integer type, and an `i64` with a very high magnitude might not be
+    /// convertible to an `i32`.
+    /// On the other hand, conversions with possible precision loss or truncation
+    /// are admitted, like an `f32` with a decimal part to an integer type, or
+    /// even a large `f64` saturating to `f32` infinity.
     fn from<T: ToPrimitive>(n: T) -> Option<Self>;
 }
 
@@ -712,25 +757,16 @@ impl<T: NumCast> NumCast for Wrapping<T> {
 ///
 /// # Safety
 ///
-/// Currently, some uses of the `as` operator are not entirely safe.
-/// In particular, it is undefined behavior if:
-///
-/// - A truncated floating point value cannot fit in the target integer
-///   type ([#10184](https://github.com/rust-lang/rust/issues/10184));
+/// **In Rust versions before 1.45.0**, some uses of the `as` operator were not entirely safe.
+/// In particular, it was undefined behavior if
+/// a truncated floating point value could not fit in the target integer
+/// type ([#10184](https://github.com/rust-lang/rust/issues/10184)).
 ///
 /// ```ignore
 /// # use num_traits::AsPrimitive;
 /// let x: u8 = (1.04E+17).as_(); // UB
 /// ```
 ///
-/// - Or a floating point value does not fit in another floating
-///   point type ([#15536](https://github.com/rust-lang/rust/issues/15536)).
-///
-/// ```ignore
-/// # use num_traits::AsPrimitive;
-/// let x: f32 = (1e300f64).as_(); // UB
-/// ```
-///
 pub trait AsPrimitive<T>: 'static + Copy
 where
     T: 'static + Copy,
diff --git a/third_party/rust/num-traits/src/float.rs b/third_party/rust/num-traits/src/float.rs
index dd14bbe4ed9429bca58f2cb0f59be3b867704cf9..0e7b9db357f563616f594f06b9f24adfb42e045f 100644
--- a/third_party/rust/num-traits/src/float.rs
+++ b/third_party/rust/num-traits/src/float.rs
@@ -1,6 +1,6 @@
 use core::mem;
 use core::num::FpCategory;
-use core::ops::Neg;
+use core::ops::{Add, Div, Neg};
 
 use core::f32;
 use core::f64;
@@ -606,8 +606,8 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
     /// use num_traits::float::FloatCore;
     /// use std::{f32, f64};
     ///
-    /// fn check<T: FloatCore>(x: T, y: T, min: T) {
-    ///     assert!(x.max(y) == min);
+    /// fn check<T: FloatCore>(x: T, y: T, max: T) {
+    ///     assert!(x.max(y) == max);
     /// }
     ///
     /// check(1.0f32, 2.0, 2.0);
@@ -2247,6 +2247,21 @@ macro_rules! float_const_impl {
         #[allow(non_snake_case)]
         pub trait FloatConst {
             $(#[$doc] fn $constant() -> Self;)+
+            #[doc = "Return the full circle constant `Ï„`."]
+            #[inline]
+            fn TAU() -> Self where Self: Sized + Add<Self, Output = Self> {
+                Self::PI() + Self::PI()
+            }
+            #[doc = "Return `log10(2.0)`."]
+            #[inline]
+            fn LOG10_2() -> Self where Self: Sized + Div<Self, Output = Self> {
+                Self::LN_2() / Self::LN_10()
+            }
+            #[doc = "Return `log2(10.0)`."]
+            #[inline]
+            fn LOG2_10() -> Self where Self: Sized + Div<Self, Output = Self> {
+                Self::LN_10() / Self::LN_2()
+            }
         }
         float_const_impl! { @float f32, $($constant,)+ }
         float_const_impl! { @float f64, $($constant,)+ }
@@ -2255,6 +2270,9 @@ macro_rules! float_const_impl {
         impl FloatConst for $T {
             constant! {
                 $( $constant() -> $T::consts::$constant; )+
+                TAU() -> 6.28318530717958647692528676655900577;
+                LOG10_2() -> 0.301029995663981195213738894724493027;
+                LOG2_10() -> 3.32192809488736234787031942948939018;
             }
         }
     );
@@ -2289,7 +2307,7 @@ float_const_impl! {
     LOG10_E,
     #[doc = "Return `log2(e)`."]
     LOG2_E,
-    #[doc = "Return Archimedes’ constant."]
+    #[doc = "Return Archimedes’ constant `π`."]
     PI,
     #[doc = "Return `sqrt(2.0)`."]
     SQRT_2,
@@ -2350,4 +2368,23 @@ mod tests {
             57.2957795130823208767981548141051703
         );
     }
+
+    #[test]
+    #[cfg(any(feature = "std", feature = "libm"))]
+    fn extra_logs() {
+        use float::{Float, FloatConst};
+
+        fn check<F: Float + FloatConst>(diff: F) {
+            let _2 = F::from(2.0).unwrap();
+            assert!((F::LOG10_2() - F::log10(_2)).abs() < diff);
+            assert!((F::LOG10_2() - F::LN_2() / F::LN_10()).abs() < diff);
+
+            let _10 = F::from(10.0).unwrap();
+            assert!((F::LOG2_10() - F::log2(_10)).abs() < diff);
+            assert!((F::LOG2_10() - F::LN_10() / F::LN_2()).abs() < diff);
+        }
+
+        check::<f32>(1e-6);
+        check::<f64>(1e-12);
+    }
 }
diff --git a/third_party/rust/num-traits/src/int.rs b/third_party/rust/num-traits/src/int.rs
index 26d5a9a3970a621363ae4a8944aa22d06ddaea6a..10e751a9d4fdb6bf8f79f7c8f31c631543ed4c9d 100644
--- a/third_party/rust/num-traits/src/int.rs
+++ b/third_party/rust/num-traits/src/int.rs
@@ -106,7 +106,7 @@ pub trait PrimInt:
     /// ```
     fn trailing_zeros(self) -> u32;
 
-    /// Shifts the bits to the left by a specified amount amount, `n`, wrapping
+    /// Shifts the bits to the left by a specified amount, `n`, wrapping
     /// the truncated bits to the end of the resulting integer.
     ///
     /// # Examples
@@ -121,7 +121,7 @@ pub trait PrimInt:
     /// ```
     fn rotate_left(self, n: u32) -> Self;
 
-    /// Shifts the bits to the right by a specified amount amount, `n`, wrapping
+    /// Shifts the bits to the right by a specified amount, `n`, wrapping
     /// the truncated bits to the beginning of the resulting integer.
     ///
     /// # Examples
@@ -136,7 +136,7 @@ pub trait PrimInt:
     /// ```
     fn rotate_right(self, n: u32) -> Self;
 
-    /// Shifts the bits to the left by a specified amount amount, `n`, filling
+    /// Shifts the bits to the left by a specified amount, `n`, filling
     /// zeros in the least significant bits.
     ///
     /// This is bitwise equivalent to signed `Shl`.
@@ -153,7 +153,7 @@ pub trait PrimInt:
     /// ```
     fn signed_shl(self, n: u32) -> Self;
 
-    /// Shifts the bits to the right by a specified amount amount, `n`, copying
+    /// Shifts the bits to the right by a specified amount, `n`, copying
     /// the "sign bit" in the most significant bits even for unsigned types.
     ///
     /// This is bitwise equivalent to signed `Shr`.
@@ -170,7 +170,7 @@ pub trait PrimInt:
     /// ```
     fn signed_shr(self, n: u32) -> Self;
 
-    /// Shifts the bits to the left by a specified amount amount, `n`, filling
+    /// Shifts the bits to the left by a specified amount, `n`, filling
     /// zeros in the least significant bits.
     ///
     /// This is bitwise equivalent to unsigned `Shl`.
@@ -187,7 +187,7 @@ pub trait PrimInt:
     /// ```
     fn unsigned_shl(self, n: u32) -> Self;
 
-    /// Shifts the bits to the right by a specified amount amount, `n`, filling
+    /// Shifts the bits to the right by a specified amount, `n`, filling
     /// zeros in the most significant bits.
     ///
     /// This is bitwise equivalent to unsigned `Shr`.
diff --git a/third_party/rust/num-traits/src/lib.rs b/third_party/rust/num-traits/src/lib.rs
index 559a18cdf8f836bf0fb6aeded86fe9ec51745c04..a6c202c95eeb4393ed1e222e531ca94879a14011 100644
--- a/third_party/rust/num-traits/src/lib.rs
+++ b/third_party/rust/num-traits/src/lib.rs
@@ -42,8 +42,10 @@ pub use ops::checked::{
 };
 pub use ops::inv::Inv;
 pub use ops::mul_add::{MulAdd, MulAddAssign};
-pub use ops::saturating::Saturating;
-pub use ops::wrapping::{WrappingAdd, WrappingMul, WrappingShl, WrappingShr, WrappingSub};
+pub use ops::saturating::{Saturating, SaturatingAdd, SaturatingMul, SaturatingSub};
+pub use ops::wrapping::{
+    WrappingAdd, WrappingMul, WrappingNeg, WrappingShl, WrappingShr, WrappingSub,
+};
 pub use pow::{checked_pow, pow, Pow};
 pub use sign::{abs, abs_sub, signum, Signed, Unsigned};
 
@@ -65,7 +67,7 @@ pub mod sign;
 pub trait Num: PartialEq + Zero + One + NumOps {
     type FromStrRadixErr;
 
-    /// Convert from a string and radix <= 36.
+    /// Convert from a string and radix (typically `2..=36`).
     ///
     /// # Examples
     ///
@@ -78,6 +80,18 @@ pub trait Num: PartialEq + Zero + One + NumOps {
     /// let result = <i32 as Num>::from_str_radix("foo", 10);
     /// assert!(result.is_err());
     /// ```
+    ///
+    /// # Supported radices
+    ///
+    /// The exact range of supported radices is at the discretion of each type implementation. For
+    /// primitive integers, this is implemented by the inherent `from_str_radix` methods in the
+    /// standard library, which **panic** if the radix is not in the range from 2 to 36. The
+    /// implementation in this crate for primitive floats is similar.
+    ///
+    /// For third-party types, it is suggested that implementations should follow suit and at least
+    /// accept `2..=36` without panicking, but an `Err` may be returned for any unsupported radix.
+    /// It's possible that a type might not even support the common radix 10, nor any, if string
+    /// parsing doesn't make sense for that type.
     fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr>;
 }
 
diff --git a/third_party/rust/num-traits/src/ops/mod.rs b/third_party/rust/num-traits/src/ops/mod.rs
index fd1695d993823db5fdfd46362c919658c10f51b4..73c4f9025985a002170dfcc8ac8c8e3c6995e3f2 100644
--- a/third_party/rust/num-traits/src/ops/mod.rs
+++ b/third_party/rust/num-traits/src/ops/mod.rs
@@ -1,5 +1,6 @@
 pub mod checked;
 pub mod inv;
 pub mod mul_add;
+pub mod overflowing;
 pub mod saturating;
 pub mod wrapping;
diff --git a/third_party/rust/num-traits/src/ops/overflowing.rs b/third_party/rust/num-traits/src/ops/overflowing.rs
new file mode 100644
index 0000000000000000000000000000000000000000..56118a032b10bab1af911784fd74f7dcda6159ea
--- /dev/null
+++ b/third_party/rust/num-traits/src/ops/overflowing.rs
@@ -0,0 +1,104 @@
+use core::ops::{Add, Mul, Sub};
+#[cfg(has_i128)]
+use core::{i128, u128};
+use core::{i16, i32, i64, i8, isize};
+use core::{u16, u32, u64, u8, usize};
+
+macro_rules! overflowing_impl {
+    ($trait_name:ident, $method:ident, $t:ty) => {
+        impl $trait_name for $t {
+            #[inline]
+            fn $method(&self, v: &Self) -> (Self, bool) {
+                <$t>::$method(*self, *v)
+            }
+        }
+    };
+}
+
+/// Performs addition with a flag for overflow.
+pub trait OverflowingAdd: Sized + Add<Self, Output = Self> {
+    /// Returns a tuple of the sum along with a boolean indicating whether an arithmetic overflow would occur.
+    /// If an overflow would have occurred then the wrapped value is returned.
+    fn overflowing_add(&self, v: &Self) -> (Self, bool);
+}
+
+overflowing_impl!(OverflowingAdd, overflowing_add, u8);
+overflowing_impl!(OverflowingAdd, overflowing_add, u16);
+overflowing_impl!(OverflowingAdd, overflowing_add, u32);
+overflowing_impl!(OverflowingAdd, overflowing_add, u64);
+overflowing_impl!(OverflowingAdd, overflowing_add, usize);
+#[cfg(has_i128)]
+overflowing_impl!(OverflowingAdd, overflowing_add, u128);
+
+overflowing_impl!(OverflowingAdd, overflowing_add, i8);
+overflowing_impl!(OverflowingAdd, overflowing_add, i16);
+overflowing_impl!(OverflowingAdd, overflowing_add, i32);
+overflowing_impl!(OverflowingAdd, overflowing_add, i64);
+overflowing_impl!(OverflowingAdd, overflowing_add, isize);
+#[cfg(has_i128)]
+overflowing_impl!(OverflowingAdd, overflowing_add, i128);
+
+/// Performs substraction with a flag for overflow.
+pub trait OverflowingSub: Sized + Sub<Self, Output = Self> {
+    /// Returns a tuple of the difference along with a boolean indicating whether an arithmetic overflow would occur.
+    /// If an overflow would have occurred then the wrapped value is returned.
+    fn overflowing_sub(&self, v: &Self) -> (Self, bool);
+}
+
+overflowing_impl!(OverflowingSub, overflowing_sub, u8);
+overflowing_impl!(OverflowingSub, overflowing_sub, u16);
+overflowing_impl!(OverflowingSub, overflowing_sub, u32);
+overflowing_impl!(OverflowingSub, overflowing_sub, u64);
+overflowing_impl!(OverflowingSub, overflowing_sub, usize);
+#[cfg(has_i128)]
+overflowing_impl!(OverflowingSub, overflowing_sub, u128);
+
+overflowing_impl!(OverflowingSub, overflowing_sub, i8);
+overflowing_impl!(OverflowingSub, overflowing_sub, i16);
+overflowing_impl!(OverflowingSub, overflowing_sub, i32);
+overflowing_impl!(OverflowingSub, overflowing_sub, i64);
+overflowing_impl!(OverflowingSub, overflowing_sub, isize);
+#[cfg(has_i128)]
+overflowing_impl!(OverflowingSub, overflowing_sub, i128);
+
+/// Performs multiplication with a flag for overflow.
+pub trait OverflowingMul: Sized + Mul<Self, Output = Self> {
+    /// Returns a tuple of the product along with a boolean indicating whether an arithmetic overflow would occur.
+    /// If an overflow would have occurred then the wrapped value is returned.
+    fn overflowing_mul(&self, v: &Self) -> (Self, bool);
+}
+
+overflowing_impl!(OverflowingMul, overflowing_mul, u8);
+overflowing_impl!(OverflowingMul, overflowing_mul, u16);
+overflowing_impl!(OverflowingMul, overflowing_mul, u32);
+overflowing_impl!(OverflowingMul, overflowing_mul, u64);
+overflowing_impl!(OverflowingMul, overflowing_mul, usize);
+#[cfg(has_i128)]
+overflowing_impl!(OverflowingMul, overflowing_mul, u128);
+
+overflowing_impl!(OverflowingMul, overflowing_mul, i8);
+overflowing_impl!(OverflowingMul, overflowing_mul, i16);
+overflowing_impl!(OverflowingMul, overflowing_mul, i32);
+overflowing_impl!(OverflowingMul, overflowing_mul, i64);
+overflowing_impl!(OverflowingMul, overflowing_mul, isize);
+#[cfg(has_i128)]
+overflowing_impl!(OverflowingMul, overflowing_mul, i128);
+
+#[test]
+fn test_overflowing_traits() {
+    fn overflowing_add<T: OverflowingAdd>(a: T, b: T) -> (T, bool) {
+        a.overflowing_add(&b)
+    }
+    fn overflowing_sub<T: OverflowingSub>(a: T, b: T) -> (T, bool) {
+        a.overflowing_sub(&b)
+    }
+    fn overflowing_mul<T: OverflowingMul>(a: T, b: T) -> (T, bool) {
+        a.overflowing_mul(&b)
+    }
+    assert_eq!(overflowing_add(5i16, 2), (7, false));
+    assert_eq!(overflowing_add(i16::MAX, 1), (i16::MIN, true));
+    assert_eq!(overflowing_sub(5i16, 2), (3, false));
+    assert_eq!(overflowing_sub(i16::MIN, 1), (i16::MAX, true));
+    assert_eq!(overflowing_mul(5i16, 2), (10, false));
+    assert_eq!(overflowing_mul(1_000_000_000i32, 10), (1410065408, true));
+}
diff --git a/third_party/rust/num-traits/src/ops/saturating.rs b/third_party/rust/num-traits/src/ops/saturating.rs
index fdce18977c068d6a1540e126cfc6be59362d6524..e39cfd7b6c1abc2c0e9ac73147830ad305ded23d 100644
--- a/third_party/rust/num-traits/src/ops/saturating.rs
+++ b/third_party/rust/num-traits/src/ops/saturating.rs
@@ -1,4 +1,7 @@
-/// Saturating math operations
+use core::ops::{Add, Mul, Sub};
+
+/// Saturating math operations. Deprecated, use `SaturatingAdd`, `SaturatingSub` and
+/// `SaturatingMul` instead.
 pub trait Saturating {
     /// Saturating addition operator.
     /// Returns a+b, saturating at the numeric bounds instead of overflowing.
@@ -9,7 +12,7 @@ pub trait Saturating {
     fn saturating_sub(self, v: Self) -> Self;
 }
 
-macro_rules! saturating_impl {
+macro_rules! deprecated_saturating_impl {
     ($trait_name:ident for $($t:ty)*) => {$(
         impl $trait_name for $t {
             #[inline]
@@ -25,6 +28,110 @@ macro_rules! saturating_impl {
     )*}
 }
 
-saturating_impl!(Saturating for isize usize i8 u8 i16 u16 i32 u32 i64 u64);
+deprecated_saturating_impl!(Saturating for isize usize i8 u8 i16 u16 i32 u32 i64 u64);
+#[cfg(has_i128)]
+deprecated_saturating_impl!(Saturating for i128 u128);
+
+macro_rules! saturating_impl {
+    ($trait_name:ident, $method:ident, $t:ty) => {
+        impl $trait_name for $t {
+            #[inline]
+            fn $method(&self, v: &Self) -> Self {
+                <$t>::$method(*self, *v)
+            }
+        }
+    };
+}
+
+/// Performs addition that saturates at the numeric bounds instead of overflowing.
+pub trait SaturatingAdd: Sized + Add<Self, Output = Self> {
+    /// Saturating addition. Computes `self + other`, saturating at the relevant high or low boundary of
+    /// the type.
+    fn saturating_add(&self, v: &Self) -> Self;
+}
+
+saturating_impl!(SaturatingAdd, saturating_add, u8);
+saturating_impl!(SaturatingAdd, saturating_add, u16);
+saturating_impl!(SaturatingAdd, saturating_add, u32);
+saturating_impl!(SaturatingAdd, saturating_add, u64);
+saturating_impl!(SaturatingAdd, saturating_add, usize);
+#[cfg(has_i128)]
+saturating_impl!(SaturatingAdd, saturating_add, u128);
+
+saturating_impl!(SaturatingAdd, saturating_add, i8);
+saturating_impl!(SaturatingAdd, saturating_add, i16);
+saturating_impl!(SaturatingAdd, saturating_add, i32);
+saturating_impl!(SaturatingAdd, saturating_add, i64);
+saturating_impl!(SaturatingAdd, saturating_add, isize);
+#[cfg(has_i128)]
+saturating_impl!(SaturatingAdd, saturating_add, i128);
+
+/// Performs subtraction that saturates at the numeric bounds instead of overflowing.
+pub trait SaturatingSub: Sized + Sub<Self, Output = Self> {
+    /// Saturating subtraction. Computes `self - other`, saturating at the relevant high or low boundary of
+    /// the type.
+    fn saturating_sub(&self, v: &Self) -> Self;
+}
+
+saturating_impl!(SaturatingSub, saturating_sub, u8);
+saturating_impl!(SaturatingSub, saturating_sub, u16);
+saturating_impl!(SaturatingSub, saturating_sub, u32);
+saturating_impl!(SaturatingSub, saturating_sub, u64);
+saturating_impl!(SaturatingSub, saturating_sub, usize);
 #[cfg(has_i128)]
-saturating_impl!(Saturating for i128 u128);
+saturating_impl!(SaturatingSub, saturating_sub, u128);
+
+saturating_impl!(SaturatingSub, saturating_sub, i8);
+saturating_impl!(SaturatingSub, saturating_sub, i16);
+saturating_impl!(SaturatingSub, saturating_sub, i32);
+saturating_impl!(SaturatingSub, saturating_sub, i64);
+saturating_impl!(SaturatingSub, saturating_sub, isize);
+#[cfg(has_i128)]
+saturating_impl!(SaturatingSub, saturating_sub, i128);
+
+/// Performs multiplication that saturates at the numeric bounds instead of overflowing.
+pub trait SaturatingMul: Sized + Mul<Self, Output = Self> {
+    /// Saturating multiplication. Computes `self * other`, saturating at the relevant high or low boundary of
+    /// the type.
+    fn saturating_mul(&self, v: &Self) -> Self;
+}
+
+saturating_impl!(SaturatingMul, saturating_mul, u8);
+saturating_impl!(SaturatingMul, saturating_mul, u16);
+saturating_impl!(SaturatingMul, saturating_mul, u32);
+saturating_impl!(SaturatingMul, saturating_mul, u64);
+saturating_impl!(SaturatingMul, saturating_mul, usize);
+#[cfg(has_i128)]
+saturating_impl!(SaturatingMul, saturating_mul, u128);
+
+saturating_impl!(SaturatingMul, saturating_mul, i8);
+saturating_impl!(SaturatingMul, saturating_mul, i16);
+saturating_impl!(SaturatingMul, saturating_mul, i32);
+saturating_impl!(SaturatingMul, saturating_mul, i64);
+saturating_impl!(SaturatingMul, saturating_mul, isize);
+#[cfg(has_i128)]
+saturating_impl!(SaturatingMul, saturating_mul, i128);
+
+// TODO: add SaturatingNeg for signed integer primitives once the saturating_neg() API is stable.
+
+#[test]
+fn test_saturating_traits() {
+    fn saturating_add<T: SaturatingAdd>(a: T, b: T) -> T {
+        a.saturating_add(&b)
+    }
+    fn saturating_sub<T: SaturatingSub>(a: T, b: T) -> T {
+        a.saturating_sub(&b)
+    }
+    fn saturating_mul<T: SaturatingMul>(a: T, b: T) -> T {
+        a.saturating_mul(&b)
+    }
+    assert_eq!(saturating_add(255, 1), 255u8);
+    assert_eq!(saturating_add(127, 1), 127i8);
+    assert_eq!(saturating_add(-128, -1), -128i8);
+    assert_eq!(saturating_sub(0, 1), 0u8);
+    assert_eq!(saturating_sub(-128, 1), -128i8);
+    assert_eq!(saturating_sub(127, -1), 127i8);
+    assert_eq!(saturating_mul(255, 2), 255u8);
+    assert_eq!(saturating_mul(127, 2), 127i8);
+    assert_eq!(saturating_mul(-128, 2), -128i8);
+}
diff --git a/third_party/rust/num-traits/src/ops/wrapping.rs b/third_party/rust/num-traits/src/ops/wrapping.rs
index 5ce16af53fad3ff0317a90b3a400a4e991c71e8b..265b8f3bbc98f332d3642897d40e39642782e9f3 100644
--- a/third_party/rust/num-traits/src/ops/wrapping.rs
+++ b/third_party/rust/num-traits/src/ops/wrapping.rs
@@ -1,5 +1,5 @@
 use core::num::Wrapping;
-use core::ops::{Add, Mul, Shl, Shr, Sub};
+use core::ops::{Add, Mul, Neg, Shl, Shr, Sub};
 
 macro_rules! wrapping_impl {
     ($trait_name:ident, $method:ident, $t:ty) => {
@@ -89,6 +89,54 @@ wrapping_impl!(WrappingMul, wrapping_mul, isize);
 #[cfg(has_i128)]
 wrapping_impl!(WrappingMul, wrapping_mul, i128);
 
+macro_rules! wrapping_unary_impl {
+    ($trait_name:ident, $method:ident, $t:ty) => {
+        impl $trait_name for $t {
+            #[inline]
+            fn $method(&self) -> $t {
+                <$t>::$method(*self)
+            }
+        }
+    };
+}
+
+/// Performs a negation that does not panic.
+pub trait WrappingNeg: Sized {
+    /// Wrapping (modular) negation. Computes `-self`,
+    /// wrapping around at the boundary of the type.
+    ///
+    /// Since unsigned types do not have negative equivalents
+    /// all applications of this function will wrap (except for `-0`).
+    /// For values smaller than the corresponding signed type's maximum
+    /// the result is the same as casting the corresponding signed value.
+    /// Any larger values are equivalent to `MAX + 1 - (val - MAX - 1)` where
+    /// `MAX` is the corresponding signed type's maximum.
+    ///
+    /// ```
+    /// use num_traits::WrappingNeg;
+    ///
+    /// assert_eq!(100i8.wrapping_neg(), -100);
+    /// assert_eq!((-100i8).wrapping_neg(), 100);
+    /// assert_eq!((-128i8).wrapping_neg(), -128); // wrapped!
+    /// ```
+    fn wrapping_neg(&self) -> Self;
+}
+
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, u8);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, u16);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, u32);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, u64);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, usize);
+#[cfg(has_i128)]
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, u128);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, i8);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, i16);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, i32);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, i64);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, isize);
+#[cfg(has_i128)]
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, i128);
+
 macro_rules! wrapping_shift_impl {
     ($trait_name:ident, $method:ident, $t:ty) => {
         impl $trait_name for $t {
@@ -195,6 +243,14 @@ where
         Wrapping(self.0.wrapping_mul(&v.0))
     }
 }
+impl<T: WrappingNeg> WrappingNeg for Wrapping<T>
+where
+    Wrapping<T>: Neg<Output = Wrapping<T>>,
+{
+    fn wrapping_neg(&self) -> Self {
+        Wrapping(self.0.wrapping_neg())
+    }
+}
 impl<T: WrappingShl> WrappingShl for Wrapping<T>
 where
     Wrapping<T>: Shl<usize, Output = Wrapping<T>>,
@@ -223,6 +279,9 @@ fn test_wrapping_traits() {
     fn wrapping_mul<T: WrappingMul>(a: T, b: T) -> T {
         a.wrapping_mul(&b)
     }
+    fn wrapping_neg<T: WrappingNeg>(a: T) -> T {
+        a.wrapping_neg()
+    }
     fn wrapping_shl<T: WrappingShl>(a: T, b: u32) -> T {
         a.wrapping_shl(b)
     }
@@ -232,11 +291,14 @@ fn test_wrapping_traits() {
     assert_eq!(wrapping_add(255, 1), 0u8);
     assert_eq!(wrapping_sub(0, 1), 255u8);
     assert_eq!(wrapping_mul(255, 2), 254u8);
+    assert_eq!(wrapping_neg(255), 1u8);
     assert_eq!(wrapping_shl(255, 8), 255u8);
     assert_eq!(wrapping_shr(255, 8), 255u8);
     assert_eq!(wrapping_add(255, 1), (Wrapping(255u8) + Wrapping(1u8)).0);
     assert_eq!(wrapping_sub(0, 1), (Wrapping(0u8) - Wrapping(1u8)).0);
     assert_eq!(wrapping_mul(255, 2), (Wrapping(255u8) * Wrapping(2u8)).0);
+    // TODO: Test for Wrapping::Neg. Not possible yet since core::ops::Neg was
+    // only added to core::num::Wrapping<_> in Rust 1.10.
     assert_eq!(wrapping_shl(255, 8), (Wrapping(255u8) << 8).0);
     assert_eq!(wrapping_shr(255, 8), (Wrapping(255u8) >> 8).0);
 }
@@ -259,6 +321,9 @@ fn wrapping_is_wrappingmul() {
     require_wrappingmul(&Wrapping(42));
 }
 
+// TODO: Test for Wrapping::Neg. Not possible yet since core::ops::Neg was
+// only added to core::num::Wrapping<_> in Rust 1.10.
+
 #[test]
 fn wrapping_is_wrappingshl() {
     fn require_wrappingshl<T: WrappingShl>(_: &T) {}
diff --git a/third_party/rust/num-traits/src/sign.rs b/third_party/rust/num-traits/src/sign.rs
index 26d44c500f4c563252b6eefb97e694a751a14d05..5c32071c2395c0afdc913b36c762ed6a918e5a49 100644
--- a/third_party/rust/num-traits/src/sign.rs
+++ b/third_party/rust/num-traits/src/sign.rs
@@ -213,13 +213,12 @@ fn unsigned_wrapping_is_unsigned() {
     fn require_unsigned<T: Unsigned>(_: &T) {}
     require_unsigned(&Wrapping(42_u32));
 }
-/*
+
 // Commenting this out since it doesn't compile on Rust 1.8,
 // because on this version Wrapping doesn't implement Neg and therefore can't
 // implement Signed.
-#[test]
-fn signed_wrapping_is_signed() {
-    fn require_signed<T: Signed>(_: &T) {}
-    require_signed(&Wrapping(-42));
-}
-*/
+// #[test]
+// fn signed_wrapping_is_signed() {
+//     fn require_signed<T: Signed>(_: &T) {}
+//     require_signed(&Wrapping(-42));
+// }
diff --git a/third_party/rust/num-traits/tests/cast.rs b/third_party/rust/num-traits/tests/cast.rs
index b3f3108e7ad1276cb5be60f9332f7f706ccd6bbf..69310d0748703183c875e9e4902b56f48621a828 100644
--- a/third_party/rust/num-traits/tests/cast.rs
+++ b/third_party/rust/num-traits/tests/cast.rs
@@ -24,7 +24,8 @@ use core::num::Wrapping;
 #[test]
 fn to_primitive_float() {
     let f32_toolarge = 1e39f64;
-    assert_eq!(f32_toolarge.to_f32(), None);
+    assert_eq!(f32_toolarge.to_f32(), Some(f32::INFINITY));
+    assert_eq!((-f32_toolarge).to_f32(), Some(f32::NEG_INFINITY));
     assert_eq!((f32::MAX as f64).to_f32(), Some(f32::MAX));
     assert_eq!((-f32::MAX as f64).to_f32(), Some(-f32::MAX));
     assert_eq!(f64::INFINITY.to_f32(), Some(f32::INFINITY));
diff --git a/toolkit/library/rust/shared/Cargo.toml b/toolkit/library/rust/shared/Cargo.toml
index f408db74f5897681ffaa1cd7e4f025ba11b7ce27..3c7b4d882d0d0221fb92f99be7ae154f0deea333 100644
--- a/toolkit/library/rust/shared/Cargo.toml
+++ b/toolkit/library/rust/shared/Cargo.toml
@@ -9,7 +9,7 @@ description = "Shared Rust code for libxul"
 geckoservo = { path = "../../../../servo/ports/geckolib" }
 kvstore = { path = "../../../components/kvstore" }
 lmdb-rkv-sys = { version = "0.11", features = ["mdb_idl_logn_9"] }
-mp4parse_capi = { git = "https://github.com/mozilla/mp4parse-rust", rev = "3d9efdc868ce8c5767cea28708fa6512c0ab6d17" }
+mp4parse_capi = { git = "https://github.com/mozilla/mp4parse-rust", rev = "3011a2b923c8b0f1b392bcdd008cd8b95ffd846b" }
 nserror = { path = "../../../../xpcom/rust/nserror" }
 nsstring = { path = "../../../../xpcom/rust/nsstring" }
 netwerk_helper = { path = "../../../../netwerk/base/rust-helper" }