[third_party] Update handlebars crate to v3.5.4.

Also updated packages that depend on handlebars: fidldoc, create, intl.

Test: fx test fidldoc
      fx test create
      fx test intl

Fixed: 74027
Change-Id: I7bfd6ed7553005fa9ca8e0f0fc9e8ea984dcc73c
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/514109
Reviewed-by: James Tucker <raggi@google.com>
Commit-Queue: Claudio Cherubino <ccherubino@google.com>
diff --git a/src/lib/intl/strings/src/message_ids.rs b/src/lib/intl/strings/src/message_ids.rs
index f5d8e176..9912c6c 100644
--- a/src/lib/intl/strings/src/message_ids.rs
+++ b/src/lib/intl/strings/src/message_ids.rs
@@ -151,7 +151,7 @@
 enum MessageIds : uint64 {
   {{~#each constants~}}
   {{~#each comments}}
-    // {{this}}
+    // {{{this}}}
   {{~/each}}
     {{name}} = {{value}};
   {{~/each}}
diff --git a/third_party/rust_crates/BUILD.gn b/third_party/rust_crates/BUILD.gn
index 15fe875..512b350 100644
--- a/third_party/rust_crates/BUILD.gn
+++ b/third_party/rust_crates/BUILD.gn
@@ -262,7 +262,7 @@
 
 if (!(current_os == "fuchsia")) {
   group("handlebars") {
-    deps = [ ":handlebars-v2_0_0-beta_2" ]
+    deps = [ ":handlebars-v3_5_4" ]
   }
 }
 
@@ -3876,26 +3876,22 @@
   ]
 }
 
-rust_library("handlebars-v2_0_0-beta_2") {
+rust_library("handlebars-v3_5_4") {
   crate_name = "handlebars"
   crate_root = "//third_party/rust_crates/vendor/handlebars/src/lib.rs"
-  output_name = "handlebars-64c1f63c35898973"
+  output_name = "handlebars-57fc345ed0913234"
   configs -= [
     "//build/config/rust:edition_2018",
     "//build/config/rust:2018_idioms",
   ]
 
   deps = []
-  deps += [ ":hashbrown-v0_2_2" ]
-  deps += [ ":lazy_static-v1_4_0" ]
   deps += [ ":log-v0_4_11" ]
   deps += [ ":pest-v2_1_0" ]
   deps += [ ":pest_derive-v2_1_0($host_toolchain)" ]
-  deps += [ ":quick-error-v1_2_2" ]
-  deps += [ ":regex-v1_3_5" ]
+  deps += [ ":quick-error-v2_0_0" ]
   deps += [ ":serde-v1_0_116" ]
   deps += [ ":serde_json-v1_0_59" ]
-  deps += [ ":walkdir-v2_3_1" ]
 
   rustenv =
       [ "CARGO_MANIFEST_DIR=../../third_party/rust_crates/vendor/handlebars" ]
@@ -3903,37 +3899,9 @@
   rustflags = [
     "--cap-lints=allow",
     "--edition=2018",
-    "-Cmetadata=64c1f63c35898973",
-    "-Cextra-filename=-64c1f63c35898973",
+    "-Cmetadata=57fc345ed0913234",
+    "-Cextra-filename=-57fc345ed0913234",
     "--cfg=feature=\"default\"",
-    "--cfg=feature=\"dir_source\"",
-    "--cfg=feature=\"log\"",
-    "--cfg=feature=\"logging\"",
-    "--cfg=feature=\"walkdir\"",
-  ]
-}
-
-rust_library("hashbrown-v0_2_2") {
-  crate_name = "hashbrown"
-  crate_root = "//third_party/rust_crates/vendor/hashbrown/src/lib.rs"
-  output_name = "hashbrown-d251d5dab4b25374"
-  configs -= [
-    "//build/config/rust:edition_2018",
-    "//build/config/rust:2018_idioms",
-  ]
-
-  deps = []
-  deps += [ ":serde-v1_0_116" ]
-
-  rustenv = []
-
-  rustflags = [
-    "--cap-lints=allow",
-    "--edition=2018",
-    "-Cmetadata=d251d5dab4b25374",
-    "-Cextra-filename=-d251d5dab4b25374",
-    "--cfg=feature=\"default\"",
-    "--cfg=feature=\"serde\"",
   ]
 }
 
@@ -6678,7 +6646,7 @@
 
 rust_library("quick-error-v1_2_2") {
   crate_name = "quick_error"
-  crate_root = "//third_party/rust_crates/vendor/quick-error/src/lib.rs"
+  crate_root = "//third_party/rust_crates/vendor/quick-error-1.2.2/src/lib.rs"
   output_name = "quick_error-5bd842b4b1c97fb4"
   configs -= [
     "//build/config/rust:edition_2018",
@@ -6697,6 +6665,27 @@
   ]
 }
 
+rust_library("quick-error-v2_0_0") {
+  crate_name = "quick_error"
+  crate_root = "//third_party/rust_crates/vendor/quick-error/src/lib.rs"
+  output_name = "quick_error-3a3190e4aad267f3"
+  configs -= [
+    "//build/config/rust:edition_2018",
+    "//build/config/rust:2018_idioms",
+  ]
+
+  deps = []
+
+  rustenv = []
+
+  rustflags = [
+    "--cap-lints=allow",
+    "--edition=2018",
+    "-Cmetadata=3a3190e4aad267f3",
+    "-Cextra-filename=-3a3190e4aad267f3",
+  ]
+}
+
 rust_library("quote-v0_6_11") {
   crate_name = "quote"
   crate_root = "//third_party/rust_crates/vendor/quote-0.6.11/src/lib.rs"
diff --git a/third_party/rust_crates/Cargo.lock b/third_party/rust_crates/Cargo.lock
index b592f18..b7d1d86 100644
--- a/third_party/rust_crates/Cargo.lock
+++ b/third_party/rust_crates/Cargo.lock
@@ -1406,29 +1406,16 @@
 
 [[package]]
 name = "handlebars"
-version = "2.0.0-beta.2"
+version = "3.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cfcc4c7d5274ebfa5c5c1d9464b5bfa7a15c784a9f016d7c43b8aa71ad2631d2"
+checksum = "580b6f551b29a3a02436318aed09ba1c58eea177dc49e39beac627ad356730a5"
 dependencies = [
- "hashbrown",
- "lazy_static",
  "log 0.4.11",
  "pest",
  "pest_derive",
- "quick-error",
- "regex",
+ "quick-error 2.0.0",
  "serde",
  "serde_json",
- "walkdir",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61e4900fa4e80b3d15c78a08ec8a08433246063fa7577e7b2c6426b3b21b1f79"
-dependencies = [
- "serde",
 ]
 
 [[package]]
@@ -1849,7 +1836,7 @@
  "log 0.4.11",
  "mime",
  "mime_guess",
- "quick-error",
+ "quick-error 1.2.2",
  "rand 0.4.6",
  "safemem 0.3.0",
  "tempdir",
@@ -2445,7 +2432,7 @@
  "byteorder",
  "lazy_static",
  "num-traits",
- "quick-error",
+ "quick-error 1.2.2",
  "rand 0.6.5",
  "rand_chacha 0.1.1",
  "rand_xorshift",
@@ -2507,6 +2494,12 @@
 checksum = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
 
 [[package]]
+name = "quick-error"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ac73b1112776fc109b2e61909bc46c7e1bf0d7f690ffb1676553acce16d5cda"
+
+[[package]]
 name = "quote"
 version = "0.6.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3023,7 +3016,7 @@
 checksum = "9591f190d2852720b679c21f66ad929f9f1d7bb09d1193c26167586029d8489c"
 dependencies = [
  "fnv",
- "quick-error",
+ "quick-error 1.2.2",
  "tempfile",
  "wait-timeout",
 ]
diff --git a/third_party/rust_crates/Cargo.toml b/third_party/rust_crates/Cargo.toml
index 1c71cef..007be9c 100644
--- a/third_party/rust_crates/Cargo.toml
+++ b/third_party/rust_crates/Cargo.toml
@@ -213,7 +213,7 @@
 crossterm = "0.17.7"
 concurrent-queue = "1"
 easy-parallel = "3.1"
-handlebars = "2.0.0-beta.2"
+handlebars = "3.5.4"
 home = "0.5.3"
 hyper-rustls = { version = "0.20.0", default-features = false, features = ["rustls-native-certs"] }
 indoc = "0.3.3"
@@ -441,7 +441,7 @@
 #
 # Keep this sorted alphabetically, please.
 
-[gn.package.handlebars."2.0.0-beta.2"]
+[gn.package.handlebars."3.5.4"]
 # pest relies on this being set to find the grammar file
 env_vars = [ "CARGO_MANIFEST_DIR=../../third_party/rust_crates/vendor/handlebars" ]
 
diff --git a/third_party/rust_crates/vendor/handlebars/.cargo-checksum.json b/third_party/rust_crates/vendor/handlebars/.cargo-checksum.json
index f0b1014..2c3844c 100644
--- a/third_party/rust_crates/vendor/handlebars/.cargo-checksum.json
+++ b/third_party/rust_crates/vendor/handlebars/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"75189d9e3a11d63b0d788decd23fa97533311441c8e43bdab94615f50c6793d9","Cargo.toml":"46dddf5305e6bd0612f13b2d8bb1ef720da7ea949e4c95400e83a282730b5723","LICENSE":"63b308fad3db82dc12067a8d7ff4b672fae97d12d0b4b3bb59179e27d640b3a4","README.md":"61eb556c5dcd902a9db86f214d5dea36f92800d269cf578a1ed683515459538d","benches/bench.rs":"4afe02b450e02ca3f38f8a54b103f2d4575aeabf3e2cd1047c90f9543daef673","examples/decorator.rs":"ffe5969ce994044c56924028b6d852c7d63be97a13864c93cd34c485ce8edcb1","examples/decorator/template.hbs":"57a7a8a4243999de126e835c11ee3fd5ea5dc5b3495df6199bbee0e883afade6","examples/error.rs":"857be1fb4cc044d19ad403fe0160b828fe19d42320c23df1c0e2699650ca4ebe","examples/error/error.hbs":"4e8fac806d444a5bc41436fe0a51b4d7850c7645f8996db7a99a821c88622eef","examples/error/template.hbs":"67110cc252b7d74908db40aaf4c61c4e6a628596d25b7069d1f8de8fab578742","examples/partials.rs":"1f8759dab8777feb686d7f5ed2b37a04a24db105f093426226b1f7ed64246a71","examples/partials/base0.hbs":"3f9c9e5a27acf06ebbd53af99546165d7824cc26b3627ce4d06185f4152aa27f","examples/partials/base1.hbs":"1f32a70cbe0e992df23fb9072b11340ac38f130ff1495bb52bc75b0f040751de","examples/partials/template2.hbs":"0611352294d490b2827a85a9871aa42547d2f1a022ee67a357224546bff07bdd","examples/quick.rs":"55e86db6bbc6f4cdfdaa580cf8206ac4d3c8a56f52cade966272b89fc1318238","examples/render-cli.rs":"c99b8ce6857e5dbef923474821de8235eb1e5fab599843c036b8161468dc6fe4","examples/render.rs":"0bbca1cb1fe6bd44c5acef3e08c5eb2ce7d674750f1e75d5ba9dbfd1ddc161a8","examples/render/template.hbs":"c66f4cf729af7bc9250bb0154423ceb5228e56a384b90dd95fce018699fdfffb","examples/render_cli/simple.hbs":"a2e0df51e7c1a25c4e9e1bbe0f4911c7c86200d358fc6c9195b61e89adddc970","examples/render_file.rs":"a66c83feb388fce776e138dabe1800fbc32d47ad7ae2f46cfde82f6544cc7062","examples/render_file/template.hbs":"c66f4cf729af7bc9250bb0154423ceb5228e56a384b90dd95fce018699fdfffb","release.toml":"694d27b5ac02e1df8857f832dd277e9776124736694fae06f443cc64188e110e","rustfmt.toml":"8e99dabd6aadb112f9f9ed8709e7388b57bf43d19cd08342c093c870534a3f97","src/context.rs":"4acf92b1a6c596a473c176764cdf49129c7ce26685ca3db1de156d344461d7c1","src/directives/inline.rs":"06e2634cf9b6b09ff3032c1ef665b6f1e75718fe6fc824470e88efae26b94864","src/directives/mod.rs":"52b214f3a4fa4c0869c9a65da5891c3756b2f4629402697dca36ae22f2f93187","src/error.rs":"ad8d617db6aab8e28aa8aff251192313ec2a2bbcc34b068c3643b8727be3a5b4","src/grammar.pest":"e54160f437e90c39e7fb00b279425b2cd231cdcd716a0b835199b6f1390426c8","src/grammar.rs":"eefb9b7049a0ba7193308fb5d44df1e564504f03b6001e75a5d2f878c341f670","src/helpers/helper_boolean.rs":"01aa34e0fa81e51809ba8dcc45aaf831358404a8cc980a0353ab9f42cd70df46","src/helpers/helper_each.rs":"acd9e9821872062e4942f8a6663be20a572705b4928ec0a2e1f6a92281d89ed6","src/helpers/helper_if.rs":"d93f079618258a7697588e3ea2117419e7ce9bab73d54c13ce91d659d9f429c8","src/helpers/helper_log.rs":"08d861c08779224473f7d415df0dae5e82e1d6b18bfff5be909387ab21750c43","src/helpers/helper_lookup.rs":"506a4f7ea46c476045aebaf623517bab7ec696036c8180770d7f1a092b81d883","src/helpers/helper_raw.rs":"0c0305cb615db4fc7918f28e4448033c7a68748506dad44b55bbcee0f3cc4798","src/helpers/helper_with.rs":"4a21ec8eebbdc90edd75c61281adb90cb9e41e5c927520450982c0741dda085a","src/helpers/mod.rs":"3b53e32acf862aaea927bc7fe0584126734f59895126ed14e850891f2d491f3f","src/lib.rs":"c0cb93f2e20357c0e8d1b8c0c7f4dd6933fd46b0a66bc2c2b092ad89bebc1862","src/macros.rs":"ecbf4e13490fea911f197a2a158304fa05e7c92a9b0b920dbca0955a14b37ed0","src/output.rs":"523723cf788cbe16fb249c03bcef4e4d8d409f5151f6a295e847d6c20c906894","src/partial.rs":"5b56bc734ced3447ebd026bcc1e291d1cbe930aea8f91cba782e34ac68ab4dd4","src/registry.rs":"6ffabf64f3b73e871284f79d602d6003b42a42831da2ef2b05b8f359ea9ae462","src/render.rs":"ef2399cdb06d3da7dd79ef3c92e59100db436adde42c5bf05866af4240a0246e","src/support.rs":"239acce572354fc0748e6bb54220e292caf740877094722f2076c96deecd1a79","src/template.rs":"a022315597e1fbc789d7c4ced977c8f8ab4276e5f7bf8410e0214be2cca567bf","src/value.rs":"5b1a1ee3e94bf2786ae9068ce943f79a628188768f514b6fcab1c3d886578a65","tests/escape.rs":"d304435298125a296a43e4640a6d8b12ff6b8d8535c1acfe5dc51bd4d7639a11","tests/helper_macro.rs":"26b887048bb6f1b5830b17d9019d4a27c912f6f2d49f4e31da36abc81b31e17a","tests/root_var.rs":"fda5b30bac1e692fb010f9f98e052d5a525420fece9dcc3821a4e5aeee3a8841","tests/subexpression.rs":"2e4fe5086c55e23d2d0ac96f691803cdee64834b12796b6c51991e5aa8d8ca81"},"package":"cfcc4c7d5274ebfa5c5c1d9464b5bfa7a15c784a9f016d7c43b8aa71ad2631d2"}
\ No newline at end of file
+{"files":{"CHANGELOG.md":"1dfa6782b4f494d5fbeecb4e684910b6658c73a3307e3c7b3bddd6bb16536b50","Cargo.lock":"41c1c5e5de2be1d6cedae3a2f0e2667975afa5a64450b14d7ecfa31719264d5f","Cargo.toml":"ba3f18dff20a9e332be6734a679da627f8d178a766003031a09fb51db3ed55b1","LICENSE":"63b308fad3db82dc12067a8d7ff4b672fae97d12d0b4b3bb59179e27d640b3a4","README.md":"1c433ae3f8fd03b7911b8ab8e845503a49b670a5969bdacacd5f482c9cf95b95","benches/bench.rs":"d6c6d4040e5768beafc842ad58bff7210765da2eb3722f195b8c8248c622e82a","build-wasm.sh":"9f7226d7d0768fe0fba97f698642a4c13a600468ba7d57abcfad9285efd9f4ce","examples/decorator.rs":"010762d337c64a8ade120c66ccb97ac176653d2fc1265c6f77c35d2a7693176f","examples/decorator/template.hbs":"36fd28e0d11c90a34c32e045af9e45259b8750ade27800901b1f750171d0cbdd","examples/error.rs":"ddd25928acb652be5a9ea9164d630cbb395f1484228ccc471a9ed93ce4f22f2a","examples/error/error.hbs":"4e8fac806d444a5bc41436fe0a51b4d7850c7645f8996db7a99a821c88622eef","examples/error/template.hbs":"67110cc252b7d74908db40aaf4c61c4e6a628596d25b7069d1f8de8fab578742","examples/partials.rs":"e102f0bdacb80a08ac9ae3c92c415991095a1a2142d55420457706823a67fba0","examples/partials/base0.hbs":"3f9c9e5a27acf06ebbd53af99546165d7824cc26b3627ce4d06185f4152aa27f","examples/partials/base1.hbs":"1f32a70cbe0e992df23fb9072b11340ac38f130ff1495bb52bc75b0f040751de","examples/partials/template2.hbs":"0611352294d490b2827a85a9871aa42547d2f1a022ee67a357224546bff07bdd","examples/quick.rs":"96df03fc1742504afae34c6da9da05206adc41f771406da2825b41725329cb2d","examples/render.rs":"eadc1aff65d96c7f95c948fbccfb79981276075f83e19a22214fe0772ef17496","examples/render/template.hbs":"c66f4cf729af7bc9250bb0154423ceb5228e56a384b90dd95fce018699fdfffb","examples/render_cli/simple.hbs":"a2e0df51e7c1a25c4e9e1bbe0f4911c7c86200d358fc6c9195b61e89adddc970","examples/render_file.rs":"7865b720b0ae7b41f2c4944bbd3e78cd663392de1b9e6e7ee3ff6e850b6187d6","examples/render_file/template.hbs":"c66f4cf729af7bc9250bb0154423ceb5228e56a384b90dd95fce018699fdfffb","examples/script.rs":"df869a15d6cd8c478f74582018c54e20545b9451e84cdec2f8bb71c31a618da0","examples/script/goals.rhai":"1097bfaa9f341ea836cb7cbe0e9573767e5b40905802a9553a57de56149cb1b1","examples/script/template.hbs":"6f9f9c2532e50c3fbc300dd11b615bb7cd3fd132337d44878cdee5539eee16f2","profile.sh":"b8e80c59bc12fca93daa67c09001c1c045e594e532831cc957c9ac313f8b2390","release.toml":"968ff7e0a0f8b99d0b91a06cb007fcee55427ccbd05012b46202829336287151","rustfmt.toml":"8e99dabd6aadb112f9f9ed8709e7388b57bf43d19cd08342c093c870534a3f97","src/block.rs":"ef0225d1d5d8eaff25f85b8529a2a9d7d9231a0365cf3f9732ba1da5201b0d45","src/cli.rs":"a207fd7cc588329ccb176d7097813864f83dae16e3b0ba2abaf01931762cbb5e","src/context.rs":"d43f7d1da6dc65190e4b325a9e7bb9733b5643c1d94cf0687110a8f6824a2265","src/decorators/inline.rs":"a7892aecedb72773456e391719f047fc6ce0599c57c2e9b70a97e1d7fbe478d7","src/decorators/mod.rs":"322d4d692331a1e3a2806780cbe1e7a3a82b343486f1182d2e8a017a8bf11085","src/error.rs":"67fbc66041b83f4946f0474cecf5683a2eb8de14f790125cb9054daa53363597","src/grammar.pest":"359aa2750d08fcecf93ad1683af63bcb2a6f32e5097f00b74b5376f2f07361bf","src/grammar.rs":"f3a796f3d39bc23643d9e0d2551c858f6bc8730f1453f2a2066fd60f815e0386","src/helpers/block_util.rs":"b7acba8807e08222d930ec1899f83d7801754b29c7c07b5adf14966844f831c0","src/helpers/helper_boolean.rs":"690d8e3dac568d7c00296802c866659b250e03f90200a01517c0f2698eb8bb87","src/helpers/helper_each.rs":"4327544a5c43a1a8a2f69e0f8bff4ee3376ac291fdac21964ab25b336c9d75c0","src/helpers/helper_if.rs":"5b108aabcedc61d032e51d4166bc2132e2c4f4e55cd1c4f53a2ecc12bff12030","src/helpers/helper_log.rs":"272f7c1f873b97974cce156c04281f2bd8c44ccc885b4c59dd2b43e8d7cc6ef6","src/helpers/helper_lookup.rs":"79d0d8c970f32ada6c8b095c24d0e62fa075cc8c3882c4b7b94ddf791822e8d4","src/helpers/helper_raw.rs":"6b0b5b3774a1d5c3ebf30b1e0b8cac825f6ffb8a18cb9e08bd40786258e4b597","src/helpers/helper_with.rs":"5bd006ad12506dd41b4341b3e792a2267b46e79237e54d3daef99addbe4b5980","src/helpers/mod.rs":"814490533c480b8aa9dc9b3a0790e148344e45008b3729613536132d1b1416b3","src/helpers/scripting.rs":"8ea64a63393c8a0c445f0e6268a693a8f8d9fafbbb4536fef266f3f9995d25a2","src/json/mod.rs":"ef2fc8fe98e9761e2e2a4b2d2293bb29cdb689db2f44f939fc61c48c6b52f0a7","src/json/path.rs":"7edb20317b400356c1ad3f0a08f812f860dce71cf7ca1dd87dff5a1ec659f1ce","src/json/value.rs":"258cc143cdd082db6f24b0646960bfff0cdcaa7f8adf3feb6d291cc4eb4c79af","src/lib.rs":"fcad1a383bcab98ff84d9cfbc2526b0f0f7067282d250112c5f799b92b9664be","src/macros.rs":"6591fc9e1d92aebe9af1252966c11d1c0cf08443acbab2dc347c8341ab5a66dc","src/output.rs":"10c28874f78cddba70b24eb984a849c7750b207ac605f2aa46f2abe02846b3a2","src/partial.rs":"38b9d780c355f89c29173b9c6c086a00d1e435d20c93722c08508ecd90e2e007","src/registry.rs":"76dba9c103f8270aff47879aba3e3ec83de51d225c33cd26caf3183810fa549b","src/render.rs":"aa9362b87e4642dfdcfe47ff8f692db8e2fb1763bbf1e4e5eb020c2ae5df9107","src/support.rs":"b3d1d99440182548ff9bfcffbd9a7e08507f740ed68382f9c74ab0a92a79eab7","src/template.rs":"174ec4b910eb83f2883cd6e7ab4d0ac96eb4d6b8e900fd33a3aafc1df3f2ec40","src/util.rs":"2ebc845de5ca47455442a1b6bd664565a52e29928e82c526fbfe56ed5196410f","tests/block_context.rs":"4dce11312d2b6c0c5c2f3104516e5567e5a370611e08f4055fa3653293580385","tests/data_helper.rs":"a7f9d1d42d5415ba1dba459840067acc1294f6f6057d9a5a13d9f7e19469e850","tests/escape.rs":"d304435298125a296a43e4640a6d8b12ff6b8d8535c1acfe5dc51bd4d7639a11","tests/helper_function_lifetime.rs":"635cbd0b44742539bdf36e803a19c6a1a698399f8b765415d53f28df1acfbc2b","tests/helper_macro.rs":"dd16d7a75909a49b7409a56b8c22a54ec81e75fdbd89fe21424769de014332d4","tests/helper_with_space.rs":"c64952ea031f964e558cb323df1bf731bb7c0bf7b226142cea61afa2fd4efbfd","tests/root_var.rs":"fda5b30bac1e692fb010f9f98e052d5a525420fece9dcc3821a4e5aeee3a8841","tests/subexpression.rs":"2e4fe5086c55e23d2d0ac96f691803cdee64834b12796b6c51991e5aa8d8ca81","tests/template_names.rs":"4bbe6b48c974ae7ea1e61806794d846e2f0e8505e1568c5305fa2364dceef68a","wasm/LICENSE":"63b308fad3db82dc12067a8d7ff4b672fae97d12d0b4b3bb59179e27d640b3a4","wasm/README.md":"d67bad452550d34e9317fb8f4884b8bc07939fbb0dfdcf1be6bfce52a6851fa6","wasm/wapm.toml":"bdb286ccaa18c5c8aa0d2db25755aba9b0e3e83a59fc4d2334c1854933000ea1"},"package":"580b6f551b29a3a02436318aed09ba1c58eea177dc49e39beac627ad356730a5"}
\ No newline at end of file
diff --git a/third_party/rust_crates/vendor/handlebars/CHANGELOG.md b/third_party/rust_crates/vendor/handlebars/CHANGELOG.md
index 3b172a4e..130f2c1 100644
--- a/third_party/rust_crates/vendor/handlebars/CHANGELOG.md
+++ b/third_party/rust_crates/vendor/handlebars/CHANGELOG.md
@@ -1,6 +1,109 @@
 # Change Log
 
-## [2.0.0-beta.1](https://github.com/sunng87/handlebars-rust/compare/1.1.0...2.0.0-beta.1) - {{ 2019-03-16}}
+## [3.5.4](https://github.com/sunng87/handlebars-rust/compare/3.5.3...3.5.4) - 2021-03-27
+
+* [Fixed] Json string literal with escape char [#422]
+
+## [3.5.3](https://github.com/sunng87/handlebars-rust/compare/3.5.2...3.5.3) - 2021-02-20
+
+* [Fixed] value access issue when upper block has a base value [#419]
+
+## [3.5.2](https://github.com/sunng87/handlebars-rust/compare/3.5.1...3.5.2) - 2020-12-29
+
+* [Fixed] allow `/` as trailing separator on Windows, backported from master [#405]
+
+## [3.5.1](https://github.com/sunng87/handlebars-rust/compare/3.5.0...3.5.1) - 2020-10-25
+
+* [Fixed] dir source path separator bug on windows [#389]
+
+## [3.5.0](https://github.com/sunng87/handlebars-rust/compare/3.4.0...3.5.0) - 2020-09-23
+
+* [Changed] `#each` helper now renders else block for non-iterable data [#380]
+* [Fixed] reference starts with `null`, `true` and `false` were parsed incorrectly [#382]
+
+## [3.4.0](https://github.com/sunng87/handlebars-rust/compare/3.3.0...3.4.0) - 2020-08-14
+
+* [Added] Debug log that can be turned on by using envlog or other implementation, to trace data resolution during rendering [#369]
+* [Fixed] Derived value as block context base value [#343, #353]
+* [Fixed] Partial name aligned with handlebars.js, added support for `.`, escape `[]` and string `''` name
+* [Changed] HTML escape aligned with handlebars.js, added `=`, `\` and ``` [#366]
+* [Changed] Update rhai to 0.18 [#370]
+* [Fixed] Result of simple helper is now escaped [#373]
+
+## [3.3.0](https://github.com/sunng87/handlebars-rust/compare/3.2.1...3.3.0) - 2020-07-18
+
+* [Added] Added two new APIs to reuse `Context` for rendering [#352]
+* [Changed] Update rhai to 0.17 [#354]
+* [Fixed] Fixed mustache.js html expression support, which is "&" instead of "$"
+
+## [3.2.1](https://github.com/sunng87/handlebars-rust/compare/3.2.0...3.2.1) - 2020-06-28
+
+* [Fixed] block context leak introduced in 3.2.0, #346 [#349]
+
+## [3.2.0](https://github.com/sunng87/handlebars-rust/compare/3.1.0...3.2.0) - 2020-06-28
+
+* [Added] API to register an pre-processed template [#331]
+* [Added] Helper macro now has support for named argument and helepr hash [#338]
+* [Added] Added support for `$` expression that is part of mustache.js [#339]
+* [Changed] Update rhai to 0.15 [#330]
+* [Fixed] else block for `each` [#344]
+
+## [3.1.0](https://github.com/sunng87/handlebars-rust/compare/3.0.1...3.1.0) - 2020-06-01
+
+* [Added] All new rhai script helper
+* [Added] multiple parameter support for log helper
+* [Fixed] helper lookup priority
+* [Changed] `Send` and `Sync` are not required for RenderContext local helper [#319]
+* [Fixed] partial block when using path as name [#321]
+
+## [3.0.1](https://github.com/sunng87/handlebars-rust/compare/3.0.0...3.0.1) - 2020-01-25
+
+* [Fixed] Slash in partial path causing syntax error  #313
+
+## [3.0.0](https://github.com/sunng87/handlebars-rust/compare/2.0.3...3.0.0) - 2020-01-24
+
+* [Changed] Added lifetime specifier to `Handlebars` structure allowing helper definition to have non-static borrowed data #282
+* [Changed] Removed hashbrown dependency #279
+* [Changed] Features has been reorganized. `dir_source` were turned off by default. #289
+* [Changed] Refactored `RenderContext` API to improve performance up to 5x over `2.0`
+* [Added] Add new `BlockContext` API for helper developer to store block scope state #307
+* [Fixed] `RenderError` should be `Send` and `Sync` #304
+
+## [2.0.4](https://github.com/sunng87/handlebars-rust/compare/2.0.3...2.0.4) - 2020-01-06
+
+* [Fixed] `RenderError` should be `Send` and `Sync` #304
+
+## [2.0.3](https://github.com/sunng87/handlebars-rust/compare/2.0.2...2.0.3) - 2020-01-04
+
+* [Fixed] deprecated warnings on rust 1.42 nightly, due to changes in
+  `Error` trait
+
+## [2.0.2](https://github.com/sunng87/handlebars-rust/compare/2.0.1...2.0.2) - 2019-09-06
+
+* [Changed] Extended `eq` and `ne` helper for all json types #287
+* [Changed] Removed `regex` and `lazy_static` crate to optimize dependency tree
+
+## [2.0.1](https://github.com/sunng87/handlebars-rust/compare/2.0.0...2.0.1) - 2019-07-12
+* [Changed] Fixed issue with block context #275
+* [Changed] Added support for array index in block context #276
+* [Changed] Deprecated RenderContext `concat_path`
+* [Changed] Update hashbrown to 0.5.0
+
+## [2.0.0](https://github.com/sunng87/handlebars-rust/compare/2.0.0-beta3...2.0.0) - 2019-07-02
+* [Changed] Fixed more dyn trait warnings
+* [Changed] #80 Fixed support for zero-param helper
+* [Changed] Changed minimum Rust version to 1.32 as required by
+  getrandom crate
+
+## [2.0.0-beta.3](https://github.com/sunng87/handlebars-rust/compare/2.0.0-beta1...2.0.0-beta.3) - 2019-06-24
+
+* [Changed] Block parameter revamp, fixed cases for #260 and #264
+* [Changed] #265 Fixed block parameter order in `each` helper
+* [Changed] #266 Accept any JSON value in boolean helpers
+* [Changed] `RenderContext` API update, `evaluate_absolute` removed,
+  use `@root` instead
+
+## [2.0.0-beta.1](https://github.com/sunng87/handlebars-rust/compare/1.1.0...2.0.0-beta.1) - 2019-03-16
 
 * [Changed] Everything changed in yanked 1.2.0
 * [Changed] With Pest updated to 2.1, our minimal rust version is set
diff --git a/third_party/rust_crates/vendor/handlebars/Cargo.lock b/third_party/rust_crates/vendor/handlebars/Cargo.lock
new file mode 100644
index 0000000..8c1de53
--- /dev/null
+++ b/third_party/rust_crates/vendor/handlebars/Cargo.lock
@@ -0,0 +1,1415 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "addr2line"
+version = "0.14.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a55f82cfe485775d02112886f4169bde0c5894d75e79ead7eafe7e40a25e45f7"
+dependencies = [
+ "gimli",
+]
+
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
+name = "ahash"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "796540673305a66d127804eef19ad696f1f204b8c1025aaca4958c17eab32877"
+dependencies = [
+ "getrandom",
+ "once_cell",
+ "version_check",
+]
+
+[[package]]
+name = "aho-corasick"
+version = "0.7.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.39"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81cddc5f91628367664cc7c69714ff08deee8a3efc54623011c772544d7b2767"
+
+[[package]]
+name = "arrayvec"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9"
+dependencies = [
+ "nodrop",
+]
+
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
+
+[[package]]
+name = "backtrace"
+version = "0.3.56"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d117600f438b1707d4e4ae15d3595657288f8235a0eb593e80ecc98ab34e1bc"
+dependencies = [
+ "addr2line",
+ "cfg-if 1.0.0",
+ "libc",
+ "miniz_oxide",
+ "object",
+ "rustc-demangle",
+]
+
+[[package]]
+name = "bitflags"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
+
+[[package]]
+name = "block-buffer"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
+dependencies = [
+ "block-padding",
+ "byte-tools",
+ "byteorder",
+ "generic-array",
+]
+
+[[package]]
+name = "block-padding"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
+dependencies = [
+ "byte-tools",
+]
+
+[[package]]
+name = "bstr"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a40b47ad93e1a5404e6c18dec46b628214fee441c70f4ab5d6942142cc268a3d"
+dependencies = [
+ "lazy_static",
+ "memchr",
+ "regex-automata",
+ "serde",
+]
+
+[[package]]
+name = "bumpalo"
+version = "3.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe"
+
+[[package]]
+name = "byte-tools"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
+
+[[package]]
+name = "bytemuck"
+version = "1.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bed57e2090563b83ba8f83366628ce535a7584c9afa4c9fc0612a03925c6df58"
+
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
+name = "bytes"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
+
+[[package]]
+name = "cast"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0"
+dependencies = [
+ "rustc_version",
+]
+
+[[package]]
+name = "cc"
+version = "1.0.67"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
+
+[[package]]
+name = "cfg-if"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "clap"
+version = "2.33.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
+dependencies = [
+ "bitflags",
+ "textwrap",
+ "unicode-width",
+]
+
+[[package]]
+name = "cpp_demangle"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44919ecaf6f99e8e737bc239408931c9a01e9a6c74814fee8242dd2506b65390"
+dependencies = [
+ "cfg-if 1.0.0",
+ "glob",
+]
+
+[[package]]
+name = "criterion"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab327ed7354547cc2ef43cbe20ef68b988e70b4b593cbd66a2a61733123a3d23"
+dependencies = [
+ "atty",
+ "cast",
+ "clap",
+ "criterion-plot",
+ "csv",
+ "itertools 0.10.0",
+ "lazy_static",
+ "num-traits",
+ "oorandom",
+ "plotters",
+ "rayon",
+ "regex",
+ "serde",
+ "serde_cbor",
+ "serde_derive",
+ "serde_json",
+ "tinytemplate",
+ "walkdir",
+]
+
+[[package]]
+name = "criterion-plot"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e022feadec601fba1649cfa83586381a4ad31c6bf3a9ab7d408118b05dd9889d"
+dependencies = [
+ "cast",
+ "itertools 0.9.0",
+]
+
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775"
+dependencies = [
+ "cfg-if 1.0.0",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9"
+dependencies = [
+ "cfg-if 1.0.0",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2584f639eb95fea8c798496315b297cf81b9b58b6d30ab066a75455333cf4b12"
+dependencies = [
+ "cfg-if 1.0.0",
+ "crossbeam-utils",
+ "lazy_static",
+ "memoffset",
+ "scopeguard",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49"
+dependencies = [
+ "autocfg",
+ "cfg-if 1.0.0",
+ "lazy_static",
+]
+
+[[package]]
+name = "csv"
+version = "1.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1"
+dependencies = [
+ "bstr",
+ "csv-core",
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "csv-core"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "debugid"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f91cf5a8c2f2097e2a32627123508635d47ce10563d999ec1a95addf08b502ba"
+dependencies = [
+ "uuid",
+]
+
+[[package]]
+name = "digest"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "either"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
+
+[[package]]
+name = "env_logger"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
+dependencies = [
+ "atty",
+ "humantime",
+ "log",
+ "regex",
+ "termcolor",
+]
+
+[[package]]
+name = "fake-simd"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
+
+[[package]]
+name = "fixedbitset"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
+
+[[package]]
+name = "generic-array"
+version = "0.12.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
+dependencies = [
+ "typenum",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
+dependencies = [
+ "cfg-if 1.0.0",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "gimli"
+version = "0.23.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce"
+
+[[package]]
+name = "glob"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
+
+[[package]]
+name = "half"
+version = "1.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3"
+
+[[package]]
+name = "handlebars"
+version = "3.5.4"
+dependencies = [
+ "criterion",
+ "env_logger",
+ "log",
+ "maplit",
+ "pest",
+ "pest_derive",
+ "pprof",
+ "quick-error 2.0.0",
+ "rhai",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "tempfile",
+ "walkdir",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
+
+[[package]]
+name = "heck"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "humantime"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
+dependencies = [
+ "quick-error 1.2.3",
+]
+
+[[package]]
+name = "indexmap"
+version = "1.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3"
+dependencies = [
+ "autocfg",
+ "hashbrown",
+]
+
+[[package]]
+name = "inferno"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67bcf81cd7094c6827cec657c53f0d22dec1afed5eeccb16118f5763a7bbd869"
+dependencies = [
+ "ahash",
+ "atty",
+ "indexmap",
+ "itoa",
+ "lazy_static",
+ "log",
+ "num-format",
+ "quick-xml",
+ "rgb",
+ "str_stack",
+]
+
+[[package]]
+name = "instant"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
+dependencies = [
+ "cfg-if 1.0.0",
+ "js-sys",
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "itertools"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itertools"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itertools"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37d572918e350e82412fe766d24b15e6682fb2ed2bbe018280caa810397cb319"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itoa"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
+
+[[package]]
+name = "js-sys"
+version = "0.3.49"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc15e39392125075f60c95ba416f5381ff6c3a948ff02ab12464715adf56c821"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.91"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7"
+
+[[package]]
+name = "lock_api"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312"
+dependencies = [
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
+dependencies = [
+ "cfg-if 1.0.0",
+]
+
+[[package]]
+name = "maplit"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
+
+[[package]]
+name = "memchr"
+version = "2.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
+
+[[package]]
+name = "memmap"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "memoffset"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "miniz_oxide"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
+dependencies = [
+ "adler",
+ "autocfg",
+]
+
+[[package]]
+name = "multimap"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
+
+[[package]]
+name = "nix"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363"
+dependencies = [
+ "bitflags",
+ "cc",
+ "cfg-if 0.1.10",
+ "libc",
+ "void",
+]
+
+[[package]]
+name = "nodrop"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
+
+[[package]]
+name = "num-format"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bafe4179722c2894288ee77a9f044f02811c86af699344c498b0840c698a2465"
+dependencies = [
+ "arrayvec",
+ "itoa",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "object"
+version = "0.23.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4"
+
+[[package]]
+name = "once_cell"
+version = "1.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
+
+[[package]]
+name = "oorandom"
+version = "11.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
+
+[[package]]
+name = "opaque-debug"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
+
+[[package]]
+name = "parking_lot"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb"
+dependencies = [
+ "instant",
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018"
+dependencies = [
+ "cfg-if 1.0.0",
+ "instant",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "winapi",
+]
+
+[[package]]
+name = "pest"
+version = "2.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
+dependencies = [
+ "ucd-trie",
+]
+
+[[package]]
+name = "pest_derive"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0"
+dependencies = [
+ "pest",
+ "pest_generator",
+]
+
+[[package]]
+name = "pest_generator"
+version = "2.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55"
+dependencies = [
+ "pest",
+ "pest_meta",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "pest_meta"
+version = "2.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d"
+dependencies = [
+ "maplit",
+ "pest",
+ "sha-1",
+]
+
+[[package]]
+name = "petgraph"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7"
+dependencies = [
+ "fixedbitset",
+ "indexmap",
+]
+
+[[package]]
+name = "plotters"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45ca0ae5f169d0917a7c7f5a9c1a3d3d9598f18f529dd2b8373ed988efea307a"
+dependencies = [
+ "num-traits",
+ "plotters-backend",
+ "plotters-svg",
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "plotters-backend"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b07fffcddc1cb3a1de753caa4e4df03b79922ba43cf882acc1bdd7e8df9f4590"
+
+[[package]]
+name = "plotters-svg"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b38a02e23bd9604b842a812063aec4ef702b57989c37b655254bb61c471ad211"
+dependencies = [
+ "plotters-backend",
+]
+
+[[package]]
+name = "pprof"
+version = "0.3.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "937e4766a8d473f9dd3eb318c654dec77d6715a87ab50081d6e5cfceea73c105"
+dependencies = [
+ "backtrace",
+ "inferno",
+ "lazy_static",
+ "libc",
+ "log",
+ "nix",
+ "parking_lot",
+ "prost",
+ "prost-build",
+ "prost-derive",
+ "symbolic-demangle",
+ "tempfile",
+ "thiserror",
+]
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
+dependencies = [
+ "unicode-xid",
+]
+
+[[package]]
+name = "prost"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce49aefe0a6144a45de32927c77bd2859a5f7677b55f220ae5b744e87389c212"
+dependencies = [
+ "bytes",
+ "prost-derive",
+]
+
+[[package]]
+name = "prost-build"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02b10678c913ecbd69350e8535c3aef91a8676c0773fc1d7b95cdd196d7f2f26"
+dependencies = [
+ "bytes",
+ "heck",
+ "itertools 0.8.2",
+ "log",
+ "multimap",
+ "petgraph",
+ "prost",
+ "prost-types",
+ "tempfile",
+ "which",
+]
+
+[[package]]
+name = "prost-derive"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "537aa19b95acde10a12fec4301466386f757403de4cd4e5b4fa78fb5ecb18f72"
+dependencies = [
+ "anyhow",
+ "itertools 0.8.2",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "prost-types"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1834f67c0697c001304b75be76f67add9c89742eda3a085ad8ee0bb38c3417aa"
+dependencies = [
+ "bytes",
+ "prost",
+]
+
+[[package]]
+name = "quick-error"
+version = "1.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
+
+[[package]]
+name = "quick-error"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ac73b1112776fc109b2e61909bc46c7e1bf0d7f690ffb1676553acce16d5cda"
+
+[[package]]
+name = "quick-xml"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26aab6b48e2590e4a64d1ed808749ba06257882b461d01ca71baeb747074a6dd"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+ "rand_hc",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "rayon"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674"
+dependencies = [
+ "autocfg",
+ "crossbeam-deque",
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-utils",
+ "lazy_static",
+ "num_cpus",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "regex"
+version = "1.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4"
+dependencies = [
+ "byteorder",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
+
+[[package]]
+name = "remove_dir_all"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "rgb"
+version = "0.8.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "287f3c3f8236abb92d8b7e36797f19159df4b58f0a658cc3fb6dd3004b1f3bd3"
+dependencies = [
+ "bytemuck",
+]
+
+[[package]]
+name = "rhai"
+version = "0.18.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce6b581cc1ca2445d3eb409358dc703f296ac1cc22b0b064c02a15be82d515ad"
+dependencies = [
+ "instant",
+ "num-traits",
+ "serde",
+ "smallvec",
+]
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232"
+
+[[package]]
+name = "rustc_version"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
+dependencies = [
+ "semver",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
+
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "semver"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
+dependencies = [
+ "semver-parser",
+]
+
+[[package]]
+name = "semver-parser"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
+
+[[package]]
+name = "serde"
+version = "1.0.125"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_cbor"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622"
+dependencies = [
+ "half",
+ "serde",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.125"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.64"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "sha-1"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
+dependencies = [
+ "block-buffer",
+ "digest",
+ "fake-simd",
+ "opaque-debug",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+
+[[package]]
+name = "str_stack"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb"
+
+[[package]]
+name = "symbolic-common"
+version = "8.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7bf72c81c56cf2b1cba4c43f0ccf74da2354b503efa9fdf38119e955af38a17c"
+dependencies = [
+ "debugid",
+ "memmap",
+ "stable_deref_trait",
+ "uuid",
+]
+
+[[package]]
+name = "symbolic-demangle"
+version = "8.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "698d0cacb616eab775ce0acf244fe6dbce800beb185dae3657cd391b919fe22c"
+dependencies = [
+ "cpp_demangle",
+ "rustc-demangle",
+ "symbolic-common",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.64"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fd9d1e9976102a03c542daa2eff1b43f9d72306342f3f8b3ed5fb8908195d6f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
+]
+
+[[package]]
+name = "tempfile"
+version = "3.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
+dependencies = [
+ "cfg-if 1.0.0",
+ "libc",
+ "rand",
+ "redox_syscall",
+ "remove_dir_all",
+ "winapi",
+]
+
+[[package]]
+name = "termcolor"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "textwrap"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+dependencies = [
+ "unicode-width",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tinytemplate"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
+dependencies = [
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "typenum"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06"
+
+[[package]]
+name = "ucd-trie"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
+
+[[package]]
+name = "uuid"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
+
+[[package]]
+name = "version_check"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
+
+[[package]]
+name = "void"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
+
+[[package]]
+name = "walkdir"
+version = "2.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
+dependencies = [
+ "same-file",
+ "winapi",
+ "winapi-util",
+]
+
+[[package]]
+name = "wasi"
+version = "0.10.2+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.72"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fe8f61dba8e5d645a4d8132dc7a0a66861ed5e1045d2c0ed940fab33bac0fbe"
+dependencies = [
+ "cfg-if 1.0.0",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.72"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "046ceba58ff062da072c7cb4ba5b22a37f00a302483f7e2a6cdc18fedbdc1fd3"
+dependencies = [
+ "bumpalo",
+ "lazy_static",
+ "log",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.72"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ef9aa01d36cda046f797c57959ff5f3c615c9cc63997a8d545831ec7976819b"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.72"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96eb45c1b2ee33545a813a92dbb53856418bf7eb54ab34f7f7ff1448a5b3735d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.72"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7148f4696fb4960a346eaa60bbfb42a1ac4ebba21f750f75fc1375b098d5ffa"
+
+[[package]]
+name = "web-sys"
+version = "0.3.49"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59fe19d70f5dacc03f6e46777213facae5ac3801575d56ca6cbd4c93dcd12310"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "which"
+version = "3.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/third_party/rust_crates/vendor/handlebars/Cargo.toml b/third_party/rust_crates/vendor/handlebars/Cargo.toml
index 16fb524..2beacf1 100644
--- a/third_party/rust_crates/vendor/handlebars/Cargo.toml
+++ b/third_party/rust_crates/vendor/handlebars/Cargo.toml
@@ -13,7 +13,7 @@
 [package]
 edition = "2018"
 name = "handlebars"
-version = "2.0.0-beta.2"
+version = "3.5.4"
 authors = ["Ning Sun <sunng@pm.me>"]
 description = "Handlebars templating implemented in Rust."
 homepage = "https://github.com/sunng87/handlebars-rust"
@@ -23,20 +23,22 @@
 categories = ["template-engine"]
 license = "MIT"
 repository = "https://github.com/sunng87/handlebars-rust"
+[package.metadata.docs.rs]
+all-features = true
 
 [lib]
 name = "handlebars"
 path = "src/lib.rs"
-[dependencies.hashbrown]
-version = "0.2.0"
-features = ["serde"]
 
-[dependencies.lazy_static]
-version = "1.0.0"
+[[bin]]
+name = "handlebars-cli"
+path = "src/cli.rs"
 
+[[bench]]
+name = "bench"
+harness = false
 [dependencies.log]
 version = "0.4.0"
-optional = true
 
 [dependencies.pest]
 version = "2.1.0"
@@ -45,26 +47,35 @@
 version = "2.1.0"
 
 [dependencies.quick-error]
-version = "1.0.0"
+version = "2.0"
 
-[dependencies.regex]
-version = "1.0.3"
+[dependencies.rhai]
+version = "0.18.1"
+features = ["sync", "serde"]
+optional = true
 
 [dependencies.serde]
 version = "1.0.0"
 
 [dependencies.serde_json]
-version = "1.0.0"
+version = "1.0.39"
 
 [dependencies.walkdir]
 version = "2.2.3"
 optional = true
+[dev-dependencies.criterion]
+version = "0.3"
+
 [dev-dependencies.env_logger]
-version = "0.5.13"
+version = "0.7.1"
 
 [dev-dependencies.maplit]
 version = "1.0.0"
 
+[dev-dependencies.pprof]
+version = "0.3.13"
+features = ["flamegraph", "protobuf"]
+
 [dev-dependencies.serde_derive]
 version = "1.0.75"
 
@@ -72,10 +83,9 @@
 version = "3.0.0"
 
 [features]
-default = ["dir_source", "logging"]
+default = []
 dir_source = ["walkdir"]
-logging = ["log"]
-no_dir_source = ["logging"]
-no_logging = ["dir_source"]
+no_logging = []
+script_helper = ["rhai"]
 [badges.maintenance]
 status = "actively-developed"
diff --git a/third_party/rust_crates/vendor/handlebars/README.md b/third_party/rust_crates/vendor/handlebars/README.md
index 9aee1d5..a65c7a1e 100644
--- a/third_party/rust_crates/vendor/handlebars/README.md
+++ b/third_party/rust_crates/vendor/handlebars/README.md
@@ -1,14 +1,20 @@
 handlebars-rust
 ===============
 
-Rust templating with [Handlebars templating language](https://handlebarsjs.com).
+[Handlebars templating language](https://handlebarsjs.com) implemented
+in Rust and for Rust.
+
+Handlebars-rust is the template engine that renders the official Rust website
+[rust-lang.org](https://www.rust-lang.org), [its
+book](https://doc.rust-lang.org/book/).
 
 [![Build Status](https://travis-ci.org/sunng87/handlebars-rust.svg?branch=master)](https://travis-ci.org/sunng87/handlebars-rust)
-[![](http://meritbadge.herokuapp.com/handlebars)](https://crates.io/crates/handlebars)
+[![](https://meritbadge.herokuapp.com/handlebars)](https://crates.io/crates/handlebars)
 [![](https://img.shields.io/crates/d/handlebars.svg)](https://crates.io/crates/handlebars)
 [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)
 [![Docs](https://docs.rs/handlebars/badge.svg)](https://docs.rs/crate/handlebars/)
 [![Donate](https://img.shields.io/badge/donate-liberapay-yellow.svg)](https://liberapay.com/Sunng/donate)
+[![Donate](https://img.shields.io/badge/donate-buymeacoffee-yellow.svg)](https://www.buymeacoffee.com/Sunng)
 
 ## Getting Started
 
@@ -21,7 +27,7 @@
 
 use handlebars::Handlebars;
 
-fn main() -> Result<(), Box<Error>> {
+fn main() -> Result<(), Box<dyn Error>> {
     let mut reg = Handlebars::new();
     // render without register
     println!(
@@ -32,6 +38,7 @@
     // register template using given name
     reg.register_template_string("tpl_1", "Good afternoon, {{name}}")?;
     println!("{}", reg.render("tpl_1", &json!({"name": "foo"}))?);
+    Ok(())
 }
 ```
 
@@ -41,7 +48,7 @@
 syntax](https://handlebarsjs.com), it is recommended to walk through
 their introduction first.
 
-Check `render` example in the source tree. The example shows you how
+Check the `render` example in the source tree. The example shows you how
 to:
 
 * Create a `Handlebars` registry and register the template from files;
@@ -50,11 +57,11 @@
 * Define and prepare some data;
 * Render it;
 
-Run `cargo run --example render` to see results.
+Run `cargo run --example render` to see results
 (or `RUST_LOG=handlebars=info cargo run --example render` for logging
 output).
 
-Checkout `examples/` for more concrete demos of current API.
+Checkout `examples/` for more concrete demos of the current API.
 
 
 ## Minimum Rust Version Policy
@@ -67,6 +74,8 @@
 
 | Handlebars version range | Minimum Rust version |
 | --- | --- |
+| ~3.0.0 | 1.32 |
+| ~2.0.0 | 1.32 |
 | ~1.1.0 | 1.30 |
 | ~1.0.0 | 1.23 |
 
@@ -76,24 +85,27 @@
 
 ## Changelog
 
-Change log is available in the source tree named as `CHANGELOG.md`.
+Changelog is available in the source tree named as `CHANGELOG.md`.
 
 ## Contributor Guide
 
 Any contribution to this library is welcomed. To get started into
 development, I have several [Help
 Wanted](https://github.com/sunng87/handlebars-rust/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22)
-issue, with difficult level labeled. When running into any problem,
+issues, with the difficulty level labeled. When running into any problem,
 feel free to contact me on github.
 
 I'm always looking for maintainers to work together on this library,
-also let me know (via email or anywhere in the issue tracker) if you
+let me know (via email or anywhere in the issue tracker) if you
 want to join.
 
-## Donation
+## Donations
 
-I'm now accepting donation on [liberapay](https://liberapay.com/Sunng/donate),
-if you find my work helpful and want to keep it going.
+I'm now accepting donations on [liberapay](https://liberapay.com/Sunng/donate)
+and [buymeacoffee](https://www.buymeacoffee.com/Sunng) if you find my
+work helpful and want to keep it going.
+
+[![buymeacoffee](https://www.buymeacoffee.com/assets/img/guidelines/download-assets-3.svg)](https://www.buymeacoffee.com/Sunng)
 
 ## Why (this) Handlebars?
 
@@ -106,12 +118,12 @@
 
 This library doesn't attempt to use some macro magic to allow you to
 write your template within your rust code. I admit that it's fun to do
-that but it doesn't fit real-world use case.
+that but it doesn't fit real-world use cases.
 
-#### Limited but essential control structure built-in
+#### Limited but essential control structures built-in
 
-Only essential control directive `if` and `each` were built-in. This
-prevents you to put too much application logic into your template.
+Only essential control directives `if` and `each` are built-in. This
+prevents you from putting too much application logic into your template.
 
 #### Extensible helper system
 
@@ -134,93 +146,55 @@
 {{hex 16}}
 ```
 
+With `script_helper` feature flag enabled, you can also create helpers
+using [rhai](https://github.com/jonathandturner/rhai) script, just like JavaScript
+for handlebars-js. This feature was in early stage. Its API was limited at the
+moment, and can change in future.
+
 #### Template inheritance
 
 Every time I look into a templating system, I will investigate its
 support for [template
 inheritance](https://docs.djangoproject.com/en/1.9/ref/templates/language/#template-inheritance).
 
-Template include is not sufficient for template reuse. In most case
+Template include is not sufficient for template reuse. In most cases
 you will need a skeleton of page as parent (header, footer, etc.), and
-embed you page into this parent.
+embed your page into this parent.
 
-You can find a real example for template inheritance in
-`examples/partials.rs`, and templates used by this file.
+You can find a real example of template inheritance in
+`examples/partials.rs` and templates used by this file.
 
 #### WebAssembly compatible
 
-Handlebars 1.0 can be used in WebAssembly projects with directory
-source feature disabled. Adding handlebars to your project like this:
+Handlebars 3.0 can be used in WebAssembly projects.
 
-```
-handlebars = { version = "1", features = ["no_dir_source"], default-features = false }
-```
+## Related Projects
 
-#### Strict mode
-
-Handlebars, the language designed to work with JavaScript, has no
-strict restriction on accessing non-existed fields or index. It
-generates empty string for such case. However, in Rust we want a
-little bit strict sometime.
-
-By enabling `strict_mode` on handlebars:
-
-```rust
-handlebars.set_strict_mode(true);
-```
-
-You will get a `RenderError` when accessing field that not exists.
-
-### Limitations
-
-* This implementation is **not fully compatible** with the original
-  javascript version. Specifically, mustache list iteration and null
-  check doesn't work. But you can use `#each` and `#if` for same
-  behavior.
-* You will need to make your data `Serializable` on serde. We don't
-  actually serialize data into JSON string or similar. However, we use
-  JSON data type system in template render process.
-
-### Handlebars-js features supported in Handlebars-rust
-
-* Expression / Block Helpers
-* Built-in helpers
-  * each
-  * if
-  * with
-  * lookup
-  * log
-* Custom helper
-* Parameter and hashes for helper, block params
-* Partials, include, template inheritance
-* Omitting whitespace with `~`
-* Subexpression `{{(foo bar)}}`
-* Json expression `a.b.[0]` and `a.b.[c]`
-* RawHelper syntax `{{{{raw-helper}}}}...{{{{/raw-helper}}}}`
-* Decorator, implemented in Rust way
-
-### JavaScript implementation features we don't have
-
-* Mustache block (use `if`/`each` instead)
-* Chained else
-
-Feel free to report an issue if you find something broken. We aren't
-going to implement all features of handlebars-js, but we should have a
-workaround for cases we don't support.
-
-## Handlebars for Web Frameworks
+### Web frameworks
 
 * Iron: [handlebars-iron](https://github.com/sunng87/handlebars-iron)
-* Rocket: [rocket/contrib](https://api.rocket.rs/rocket_contrib/struct.Template.html)
+* Rocket: [rocket/contrib](https://api.rocket.rs/v0.4/rocket_contrib/templates/index.html)
 * Warp: [handlebars
   example](https://github.com/seanmonstar/warp/blob/master/examples/handlebars_template.rs)
 * Tower-web: [Built-in](https://github.com/carllerche/tower-web)
+* Actix: [handlebars
+  example](https://github.com/actix/examples/blob/master/template_handlebars/src/main.rs)
+* Tide: [tide-handlebars](https://github.com/No9/tide-handlebars)
 
-## Using handlebars-rust?
+### Adopters
 
-Add your project to our
-[adopters](https://github.com/sunng87/handlebars-rust/wiki/adopters).
+The
+[adopters](https://github.com/sunng87/handlebars-rust/wiki/Adopters)
+page lists projects that uses handlebars for part of their
+functionalities.
+
+### Extensions
+
+The
+[extensions](https://github.com/sunng87/handlebars-rust/wiki/Extensions)
+page has libraries that provide additional helpers, decorators and
+outputs to handlebars-rust, and you can use in your own projects.
 
 ## License
 
-This library (handlebars-rust) is open sourced under MIT License.
+This library (handlebars-rust) is open sourced under the MIT License.
diff --git a/third_party/rust_crates/vendor/handlebars/benches/bench.rs b/third_party/rust_crates/vendor/handlebars/benches/bench.rs
index 86e1108..b24e8c6 100644
--- a/third_party/rust_crates/vendor/handlebars/benches/bench.rs
+++ b/third_party/rust_crates/vendor/handlebars/benches/bench.rs
@@ -1,16 +1,72 @@
-#![feature(test)]
-extern crate handlebars;
+#[macro_use]
+extern crate criterion;
 #[macro_use]
 extern crate serde_derive;
-extern crate serde_json;
-
-extern crate test;
 
 use std::collections::BTreeMap;
+use std::fs::{create_dir_all, File};
+use std::io::Write;
+use std::path::Path;
 
-use handlebars::{to_json, Handlebars, Template};
+use criterion::profiler::Profiler;
+use criterion::Criterion;
+use handlebars::{to_json, Context, Handlebars, Template};
+use pprof::protos::Message;
+use pprof::ProfilerGuard;
 use serde_json::value::Value as Json;
 
+#[derive(Default)]
+struct CpuProfiler<'a> {
+    guard: Option<ProfilerGuard<'a>>,
+}
+
+impl<'a> Profiler for CpuProfiler<'a> {
+    fn start_profiling(&mut self, _benchmark_id: &str, benchmark_dir: &Path) {
+        create_dir_all(&benchmark_dir).unwrap();
+
+        let guard = ProfilerGuard::new(100).unwrap();
+        self.guard = Some(guard);
+    }
+
+    fn stop_profiling(&mut self, benchmark_id: &str, benchmark_dir: &Path) {
+        if let Ok(ref report) = self.guard.as_ref().unwrap().report().build() {
+            let fg_file_name = benchmark_dir.join(format!("{}.svg", benchmark_id));
+            let fg_file = File::create(fg_file_name).unwrap();
+            report.flamegraph(fg_file).unwrap();
+
+            let pb_file_name = benchmark_dir.join(format!("{}.pb", benchmark_id));
+            let mut pb_file = File::create(pb_file_name).unwrap();
+            let profile = report.pprof().unwrap();
+
+            let mut content = Vec::new();
+            profile.encode(&mut content).unwrap();
+            pb_file.write_all(&content).unwrap();
+        };
+
+        self.guard = None;
+    }
+}
+
+fn profiled() -> Criterion {
+    Criterion::default().with_profiler(CpuProfiler::default())
+}
+
+#[derive(Serialize)]
+struct DataWrapper {
+    v: String,
+}
+
+#[derive(Serialize)]
+struct RowWrapper {
+    real: Vec<DataWrapper>,
+    dummy: Vec<DataWrapper>,
+}
+
+#[derive(Serialize)]
+struct NestedRowWrapper {
+    parent: Vec<Vec<DataWrapper>>,
+}
+
 static SOURCE: &'static str = "<html>
   <head>
     <title>{{year}}</title>
@@ -53,36 +109,26 @@
     data
 }
 
-#[bench]
-fn parse_template(b: &mut test::Bencher) {
-    b.iter(|| Template::compile(SOURCE).ok().unwrap());
+fn parse_template(c: &mut Criterion) {
+    c.bench_function("parse_template", move |b| {
+        b.iter(|| Template::compile(SOURCE).ok().unwrap())
+    });
 }
 
-#[bench]
-fn render_template(b: &mut test::Bencher) {
+fn render_template(c: &mut Criterion) {
     let mut handlebars = Handlebars::new();
     handlebars
         .register_template_string("table", SOURCE)
         .ok()
         .expect("Invalid template format");
 
-    let data = make_data();
-    b.iter(|| handlebars.render("table", &data).ok().unwrap())
+    let ctx = Context::wraps(make_data()).unwrap();
+    c.bench_function("render_template", move |b| {
+        b.iter(|| handlebars.render_with_context("table", &ctx).ok().unwrap())
+    });
 }
 
-#[derive(Serialize)]
-struct DataWrapper {
-    v: String,
-}
-
-#[derive(Serialize)]
-struct RowWrapper {
-    real: Vec<DataWrapper>,
-    dummy: Vec<DataWrapper>,
-}
-
-#[bench]
-fn large_loop_helper(b: &mut test::Bencher) {
+fn large_loop_helper(c: &mut Criterion) {
     let mut handlebars = Handlebars::new();
     handlebars
         .register_template_string("test", "BEFORE\n{{#each real}}{{this.v}}{{/each}}AFTER")
@@ -90,17 +136,79 @@
         .expect("Invalid template format");
 
     let real: Vec<DataWrapper> = (1..1000)
-        .into_iter()
         .map(|i| DataWrapper {
             v: format!("n={}", i),
         })
         .collect();
     let dummy: Vec<DataWrapper> = (1..1000)
-        .into_iter()
         .map(|i| DataWrapper {
             v: format!("n={}", i),
         })
         .collect();
     let rows = RowWrapper { real, dummy };
-    b.iter(|| handlebars.render("test", &rows).ok().unwrap());
+
+    let ctx = Context::wraps(&rows).unwrap();
+    c.bench_function("large_loop_helper", move |b| {
+        b.iter(|| handlebars.render_with_context("test", &ctx).ok().unwrap())
+    });
 }
+
+fn large_loop_helper_with_context_creation(c: &mut Criterion) {
+    let mut handlebars = Handlebars::new();
+    handlebars
+        .register_template_string("test", "BEFORE\n{{#each real}}{{this.v}}{{/each}}AFTER")
+        .ok()
+        .expect("Invalid template format");
+
+    let real: Vec<DataWrapper> = (1..1000)
+        .map(|i| DataWrapper {
+            v: format!("n={}", i),
+        })
+        .collect();
+    let dummy: Vec<DataWrapper> = (1..1000)
+        .map(|i| DataWrapper {
+            v: format!("n={}", i),
+        })
+        .collect();
+    let rows = RowWrapper { real, dummy };
+
+    c.bench_function("large_loop_helper_with_context_creation", move |b| {
+        b.iter(|| handlebars.render("test", &rows).ok().unwrap())
+    });
+}
+
+fn large_nested_loop(c: &mut Criterion) {
+    let mut handlebars = Handlebars::new();
+    handlebars
+        .register_template_string(
+            "test",
+            "BEFORE\n{{#each parent as |child|}}{{#each child}}{{this.v}}{{/each}}{{/each}}AFTER",
+        )
+        .ok()
+        .expect("Invalid template format");
+
+    let parent: Vec<Vec<DataWrapper>> = (1..100)
+        .map(|_| {
+            (1..10)
+                .map(|v| DataWrapper {
+                    v: format!("v={}", v),
+                })
+                .collect()
+        })
+        .collect();
+
+    let rows = NestedRowWrapper { parent };
+
+    let ctx = Context::wraps(&rows).unwrap();
+    c.bench_function("large_nested_loop", move |b| {
+        b.iter(|| handlebars.render_with_context("test", &ctx).ok().unwrap())
+    });
+}
+
+criterion_group!(
+    name = benches;
+    config = profiled();
+    targets = parse_template, render_template, large_loop_helper, large_loop_helper_with_context_creation,
+              large_nested_loop
+);
+criterion_main!(benches);
diff --git a/third_party/rust_crates/vendor/handlebars/build-wasm.sh b/third_party/rust_crates/vendor/handlebars/build-wasm.sh
new file mode 100755
index 0000000..d1c3985
--- /dev/null
+++ b/third_party/rust_crates/vendor/handlebars/build-wasm.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+cargo build --target wasm32-wasi
+cp target/wasm32-wasi/debug/handlebars-cli.wasm wasm/
diff --git a/third_party/rust_crates/vendor/handlebars/examples/decorator.rs b/third_party/rust_crates/vendor/handlebars/examples/decorator.rs
index c62d452..81aa6fe 100644
--- a/third_party/rust_crates/vendor/handlebars/examples/decorator.rs
+++ b/third_party/rust_crates/vendor/handlebars/examples/decorator.rs
@@ -17,7 +17,7 @@
     _: &Handlebars,
     _: &Context,
     _: &mut RenderContext,
-    out: &mut Output,
+    out: &mut dyn Output,
 ) -> Result<(), RenderError> {
     // get parameter from helper or throw an error
     let param = h
@@ -28,6 +28,7 @@
     Ok(())
 }
 
+// a decorator registers helpers
 fn format_decorator(
     d: &Decorator,
     _: &Handlebars,
@@ -45,7 +46,7 @@
                   _: &Handlebars,
                   _: &Context,
                   _: &mut RenderContext,
-                  out: &mut Output| {
+                  out: &mut dyn Output| {
                 // get parameter from helper or throw an error
                 let param = h
                     .param(0)
@@ -59,13 +60,39 @@
     Ok(())
 }
 
+// a decorator mutates current context data
+fn set_decorator(
+    d: &Decorator,
+    _: &Handlebars,
+    ctx: &Context,
+    rc: &mut RenderContext,
+) -> Result<(), RenderError> {
+    // get the input of decorator
+    let data_to_set = d.hash();
+    // retrieve the json value in current context
+    let ctx_data = ctx.data();
+
+    if let Json::Object(m) = ctx_data {
+        let mut new_ctx_data = m.clone();
+
+        for (k, v) in data_to_set {
+            new_ctx_data.insert(k.to_string(), v.value().clone());
+        }
+
+        rc.set_context(Context::wraps(new_ctx_data)?);
+        Ok(())
+    } else {
+        Err(RenderError::new("Cannot extend non-object data"))
+    }
+}
+
 // another custom helper
 fn rank_helper(
     h: &Helper,
     _: &Handlebars,
     _: &Context,
     _: &mut RenderContext,
-    out: &mut Output,
+    out: &mut dyn Output,
 ) -> Result<(), RenderError> {
     let rank = h
         .param(0)
@@ -146,7 +173,7 @@
     data
 }
 
-fn main() -> Result<(), Box<Error>> {
+fn main() -> Result<(), Box<dyn Error>> {
     env_logger::init();
     // create the handlebars registry
     let mut handlebars = Handlebars::new();
@@ -159,6 +186,7 @@
     handlebars.register_helper("format", Box::new(format_helper));
     handlebars.register_helper("ranking_label", Box::new(rank_helper));
     handlebars.register_decorator("format_suffix", Box::new(format_decorator));
+    handlebars.register_decorator("set", Box::new(set_decorator));
 
     // make data and render it
     let data = make_data();
diff --git a/third_party/rust_crates/vendor/handlebars/examples/decorator/template.hbs b/third_party/rust_crates/vendor/handlebars/examples/decorator/template.hbs
index ce78afc..c21a403 100644
--- a/third_party/rust_crates/vendor/handlebars/examples/decorator/template.hbs
+++ b/third_party/rust_crates/vendor/handlebars/examples/decorator/template.hbs
@@ -1,7 +1,8 @@
 {{*format_suffix "分"}}
+
 <html>
   <head>
-    <title>中超联赛 {{year}}</title>
+    <title>CSL {{year}}</title>
   </head>
   <body>
     <h1>CSL {{year}}</h1>
@@ -14,6 +15,7 @@
     {{/each~}}
     </ul>
 
-    <p>Rendered by Handlebars from {{engine}} data.</p>
+    {{*set version="v3.0"}}
+    <p>Rendered by Handlebars {{version}} from {{engine}} data.</p>
   </body>
 </html>
diff --git a/third_party/rust_crates/vendor/handlebars/examples/error.rs b/third_party/rust_crates/vendor/handlebars/examples/error.rs
index 7c353a4..dcfcd0b 100644
--- a/third_party/rust_crates/vendor/handlebars/examples/error.rs
+++ b/third_party/rust_crates/vendor/handlebars/examples/error.rs
@@ -6,7 +6,7 @@
 
 use handlebars::Handlebars;
 
-fn main() -> Result<(), Box<Error>> {
+fn main() -> Result<(), Box<dyn Error>> {
     env_logger::init();
     let mut handlebars = Handlebars::new();
 
diff --git a/third_party/rust_crates/vendor/handlebars/examples/partials.rs b/third_party/rust_crates/vendor/handlebars/examples/partials.rs
index fa55880..80b20c2 100644
--- a/third_party/rust_crates/vendor/handlebars/examples/partials.rs
+++ b/third_party/rust_crates/vendor/handlebars/examples/partials.rs
@@ -6,7 +6,7 @@
 use handlebars::Handlebars;
 use std::error::Error;
 
-fn main() -> Result<(), Box<Error>> {
+fn main() -> Result<(), Box<dyn Error>> {
     env_logger::init();
     let mut handlebars = Handlebars::new();
 
diff --git a/third_party/rust_crates/vendor/handlebars/examples/quick.rs b/third_party/rust_crates/vendor/handlebars/examples/quick.rs
index 9ffe3e5..ff1c94c 100644
--- a/third_party/rust_crates/vendor/handlebars/examples/quick.rs
+++ b/third_party/rust_crates/vendor/handlebars/examples/quick.rs
@@ -1,12 +1,9 @@
-extern crate handlebars;
-#[macro_use]
-extern crate serde_json;
-
-use handlebars::Handlebars;
 use std::error::Error;
 
-// wait RFC1937 in
-fn main() -> Result<(), Box<Error>> {
+use handlebars::Handlebars;
+use serde_json::json;
+
+fn main() -> Result<(), Box<dyn Error>> {
     let mut reg = Handlebars::new();
     // render without register
     println!(
diff --git a/third_party/rust_crates/vendor/handlebars/examples/render.rs b/third_party/rust_crates/vendor/handlebars/examples/render.rs
index 39caf2c..112ec50 100644
--- a/third_party/rust_crates/vendor/handlebars/examples/render.rs
+++ b/third_party/rust_crates/vendor/handlebars/examples/render.rs
@@ -18,7 +18,7 @@
     _: &Handlebars,
     _: &Context,
     _: &mut RenderContext,
-    out: &mut Output,
+    out: &mut dyn Output,
 ) -> Result<(), RenderError> {
     // get parameter from helper or throw an error
     let param = h
@@ -35,7 +35,7 @@
     _: &Handlebars,
     _: &Context,
     _: &mut RenderContext,
-    out: &mut Output,
+    out: &mut dyn Output,
 ) -> Result<(), RenderError> {
     let rank = h
         .param(0)
@@ -116,7 +116,7 @@
     data
 }
 
-fn main() -> Result<(), Box<Error>> {
+fn main() -> Result<(), Box<dyn Error>> {
     env_logger::init();
     // create the handlebars registry
     let mut handlebars = Handlebars::new();
diff --git a/third_party/rust_crates/vendor/handlebars/examples/render_file.rs b/third_party/rust_crates/vendor/handlebars/examples/render_file.rs
index 4b885c2..c0a39c1 100644
--- a/third_party/rust_crates/vendor/handlebars/examples/render_file.rs
+++ b/third_party/rust_crates/vendor/handlebars/examples/render_file.rs
@@ -22,7 +22,7 @@
     _: &Handlebars,
     _: &Context,
     _: &mut RenderContext,
-    out: &mut Output,
+    out: &mut dyn Output,
 ) -> Result<(), RenderError> {
     let param = h
         .param(0)
@@ -38,7 +38,7 @@
     _: &Handlebars,
     _: &Context,
     _: &mut RenderContext,
-    out: &mut Output,
+    out: &mut dyn Output,
 ) -> Result<(), RenderError> {
     let rank = h
         .param(0)
@@ -119,7 +119,7 @@
     data
 }
 
-fn main() -> Result<(), Box<Error>> {
+fn main() -> Result<(), Box<dyn Error>> {
     env_logger::init();
     let mut handlebars = Handlebars::new();
 
diff --git a/third_party/rust_crates/vendor/handlebars/examples/script.rs b/third_party/rust_crates/vendor/handlebars/examples/script.rs
new file mode 100644
index 0000000..bedd426
--- /dev/null
+++ b/third_party/rust_crates/vendor/handlebars/examples/script.rs
@@ -0,0 +1,39 @@
+#![allow(unused_imports)]
+
+use handlebars::Handlebars;
+use std::error::Error;
+#[macro_use]
+extern crate serde_json;
+
+#[cfg(feature = "script_helper")]
+fn main() -> Result<(), Box<dyn Error>> {
+    let mut handlebars = Handlebars::new();
+
+    handlebars.register_template_file("tpl", "./examples/script/template.hbs")?;
+    handlebars.register_script_helper_file("score", "./examples/script/goals.rhai")?;
+
+    let data = json! {[
+        [{
+            "name": "Dortmund",
+            "goals": ["Haaland", "Guerreiro", "Hazard", "Guerreiro"]
+        }, {
+            "name": "Schalke",
+            "goals": []
+        }],
+        [{
+            "name": "RB Leipzig",
+            "goals": ["Poulsen"]
+        }, {
+            "name": "SC Feriburg",
+            "goals": ["Gulde"]
+        }]
+    ]};
+    println!("{}", handlebars.render("tpl", &data)?);
+    Ok(())
+}
+
+#[cfg(not(feature = "script_helper"))]
+fn main() -> Result<(), Box<dyn Error>> {
+    println!("Please enable feature flag script_helper for this example");
+    Ok(())
+}
diff --git a/third_party/rust_crates/vendor/handlebars/examples/script/goals.rhai b/third_party/rust_crates/vendor/handlebars/examples/script/goals.rhai
new file mode 100644
index 0000000..e53373b0
--- /dev/null
+++ b/third_party/rust_crates/vendor/handlebars/examples/script/goals.rhai
@@ -0,0 +1,3 @@
+let goals = params[0];
+
+len(goals)
diff --git a/third_party/rust_crates/vendor/handlebars/examples/script/template.hbs b/third_party/rust_crates/vendor/handlebars/examples/script/template.hbs
new file mode 100644
index 0000000..cfcb0d2
--- /dev/null
+++ b/third_party/rust_crates/vendor/handlebars/examples/script/template.hbs
@@ -0,0 +1,10 @@
+Bundesliga Match Day
+{{#each this as |match| ~}}
+  {{#each match as |team|}}
+    {{team.name}} - {{score team.goals}}
+    {{#each team.goals as |scorer|}}
+      > {{scorer}}
+    {{/each}}
+  {{~ /each}}
+  ---
+{{/each}}
diff --git a/third_party/rust_crates/vendor/handlebars/profile.sh b/third_party/rust_crates/vendor/handlebars/profile.sh
new file mode 100755
index 0000000..5862c87e
--- /dev/null
+++ b/third_party/rust_crates/vendor/handlebars/profile.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+RUSTCFLAGS=-g cargo bench --bench bench -- --profile-time 15
diff --git a/third_party/rust_crates/vendor/handlebars/release.toml b/third_party/rust_crates/vendor/handlebars/release.toml
index cd5a438..e0f365a 100644
--- a/third_party/rust_crates/vendor/handlebars/release.toml
+++ b/third_party/rust_crates/vendor/handlebars/release.toml
@@ -1,8 +1,6 @@
 sign-commit = true
-upload-doc = true
 pre-release-replacements = [
-  {file="CHANGELOG.md", search="Unreleased", replace="{{version}}"},
-  {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}"},
+  {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", prerelease=false},
+  {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", prerelease=false},
   {file="src/lib.rs", search="https://docs.rs/handlebars/[a-z0-9\\.-]+", replace="https://docs.rs/handlebars/{{version}}"},
 ]
-
diff --git a/third_party/rust_crates/vendor/handlebars/src/block.rs b/third_party/rust_crates/vendor/handlebars/src/block.rs
new file mode 100644
index 0000000..6bbc2b0
--- /dev/null
+++ b/third_party/rust_crates/vendor/handlebars/src/block.rs
@@ -0,0 +1,126 @@
+use std::collections::BTreeMap;
+
+use serde_json::value::Value as Json;
+
+use crate::error::RenderError;
+
+#[derive(Clone, Debug)]
+pub enum BlockParamHolder {
+    // a reference to certain context value
+    Path(Vec<String>),
+    // an actual value holder
+    Value(Json),
+}
+
+impl BlockParamHolder {
+    pub fn value(v: Json) -> BlockParamHolder {
+        BlockParamHolder::Value(v)
+    }
+
+    pub fn path(r: Vec<String>) -> BlockParamHolder {
+        BlockParamHolder::Path(r)
+    }
+}
+
+/// A map holds block parameters. The parameter can be either a value or a reference
+#[derive(Clone, Debug, Default)]
+pub struct BlockParams<'reg> {
+    data: BTreeMap<&'reg str, BlockParamHolder>,
+}
+
+impl<'reg> BlockParams<'reg> {
+    /// Create a empty block parameter map.
+    pub fn new() -> BlockParams<'reg> {
+        BlockParams::default()
+    }
+
+    /// Add a path reference as the parameter. The `path` is a vector of path
+    /// segments the relative to current block's base path.
+    pub fn add_path(&mut self, k: &'reg str, path: Vec<String>) -> Result<(), RenderError> {
+        self.data.insert(k, BlockParamHolder::path(path));
+        Ok(())
+    }
+
+    /// Add a value as parameter.
+    pub fn add_value(&mut self, k: &'reg str, v: Json) -> Result<(), RenderError> {
+        self.data.insert(k, BlockParamHolder::value(v));
+        Ok(())
+    }
+
+    /// Get a block parameter by its name.
+    pub fn get(&self, k: &str) -> Option<&BlockParamHolder> {
+        self.data.get(k)
+    }
+}
+
+/// A data structure holds contextual data for current block scope.
+#[derive(Debug, Clone, Default)]
+pub struct BlockContext<'reg> {
+    /// the base_path of current block scope
+    base_path: Vec<String>,
+    /// the base_value of current block scope, when the block is using a
+    /// constant or derived value as block base
+    /// FIXME: we use owned json temporarily to avoid lifetime issue
+    base_value: Option<Json>,
+    /// current block context variables
+    block_params: BlockParams<'reg>,
+    /// local variables in current context
+    local_variables: BTreeMap<String, Json>,
+}
+
+impl<'reg> BlockContext<'reg> {
+    /// create a new `BlockContext` with default data
+    pub fn new() -> BlockContext<'reg> {
+        BlockContext::default()
+    }
+
+    /// set a local variable into current scope
+    pub fn set_local_var(&mut self, name: String, value: Json) {
+        self.local_variables.insert(name, value);
+    }
+
+    /// get a local variable from current scope
+    pub fn get_local_var(&self, name: &str) -> Option<&Json> {
+        self.local_variables.get(&format!("@{}", name))
+    }
+
+    /// borrow a reference to current scope's base path
+    /// all paths inside this block will be relative to this path
+    pub fn base_path(&self) -> &Vec<String> {
+        &self.base_path
+    }
+
+    /// borrow a mutable reference to the base path
+    pub fn base_path_mut(&mut self) -> &mut Vec<String> {
+        &mut self.base_path
+    }
+
+    /// borrow the base value
+    pub fn base_value(&self) -> Option<&Json> {
+        self.base_value.as_ref()
+    }
+
+    /// set the base value
+    pub fn set_base_value(&mut self, value: Json) {
+        self.base_value = Some(value);
+    }
+
+    /// Get a block parameter from this block.
+    /// Block parameters needed to be supported by the block helper.
+    /// The typical syntax for block parameter is:
+    ///
+    /// ```skip
+    /// {{#myblock param1 as |block_param1|}}
+    ///    ...
+    /// {{/myblock}}
+    /// ```
+    ///
+    pub fn get_block_param(&self, block_param_name: &str) -> Option<&BlockParamHolder> {
+        self.block_params.get(block_param_name)
+    }
+
+    /// Set a block parameter into this block.
+    pub fn set_block_params(&mut self, block_params: BlockParams<'reg>) {
+        self.block_params = block_params;
+    }
+}
diff --git a/third_party/rust_crates/vendor/handlebars/examples/render-cli.rs b/third_party/rust_crates/vendor/handlebars/src/cli.rs
similarity index 77%
rename from third_party/rust_crates/vendor/handlebars/examples/render-cli.rs
rename to third_party/rust_crates/vendor/handlebars/src/cli.rs
index ead4be2..af83b7f 100644
--- a/third_party/rust_crates/vendor/handlebars/examples/render-cli.rs
+++ b/third_party/rust_crates/vendor/handlebars/src/cli.rs
@@ -1,10 +1,5 @@
-extern crate env_logger;
-extern crate handlebars;
-extern crate serde_json;
-
 use std::env;
 use std::fs;
-use std::io::{self, Write};
 use std::process;
 use std::str::FromStr;
 
@@ -13,17 +8,12 @@
 use handlebars::Handlebars;
 
 fn usage() -> ! {
-    writeln!(
-        &mut io::stderr(),
-        "{}",
-        r#"Usage: ./render-cli template.hbs '{"json": "data"}'"#
-    )
-    .ok();
+    eprintln!("Usage: handlebars-cli template.hbs '{{\"json\": \"data\"}}'");
     process::exit(1);
 }
 
 fn parse_json(text: &str) -> Json {
-    let text = if text.starts_with("@") {
+    let text = if text.starts_with('@') {
         fs::read_to_string(&text[1..]).unwrap()
     } else {
         text.to_owned()
@@ -35,8 +25,6 @@
 }
 
 fn main() {
-    env_logger::init();
-
     let mut args = env::args();
     args.next(); // skip own filename
     let (filename, json) = match (args.next(), args.next()) {
diff --git a/third_party/rust_crates/vendor/handlebars/src/context.rs b/third_party/rust_crates/vendor/handlebars/src/context.rs
index 7da428e..34c2585 100644
--- a/third_party/rust_crates/vendor/handlebars/src/context.rs
+++ b/third_party/rust_crates/vendor/handlebars/src/context.rs
@@ -1,13 +1,15 @@
-use std::collections::VecDeque;
+use std::collections::{HashMap, VecDeque};
 
-use hashbrown::HashMap;
-use pest::iterators::Pair;
-use pest::Parser;
 use serde::Serialize;
 use serde_json::value::{to_value, Map, Value as Json};
 
+use crate::block::{BlockContext, BlockParamHolder};
 use crate::error::RenderError;
-use crate::grammar::{HandlebarsParser, Rule};
+use crate::grammar::Rule;
+use crate::json::path::*;
+use crate::json::value::ScopedJson;
+use crate::util::extend;
+
 pub type Object = HashMap<String, Json>;
 
 /// The context wrap data you render on your templates.
@@ -17,89 +19,133 @@
     data: Json,
 }
 
-#[inline]
-fn parse_json_visitor_inner<'a>(
-    path_stack: &mut VecDeque<&'a str>,
-    path: &'a str,
-) -> Result<(), RenderError> {
-    let parsed_path = HandlebarsParser::parse(Rule::path, path)
-        .map(|p| p.flatten())
-        .map_err(|_| RenderError::new("Invalid JSON path"))?;
+#[derive(Debug)]
+enum ResolvedPath<'a> {
+    // FIXME: change to borrowed when possible
+    // full path
+    AbsolutePath(Vec<String>),
+    // relative path and path root
+    RelativePath(Vec<String>),
+    // relative path against block param value
+    BlockParamValue(Vec<String>, &'a Json),
+    // relative path against derived value,
+    LocalValue(Vec<String>, &'a Json),
+}
 
-    let mut seg_stack: VecDeque<Pair<Rule>> = VecDeque::new();
-    for seg in parsed_path {
-        if seg.as_str() == "@root" {
-            seg_stack.clear();
-            path_stack.clear();
-            continue;
-        }
+fn parse_json_visitor<'a, 'reg>(
+    relative_path: &[PathSeg],
+    block_contexts: &'a VecDeque<BlockContext<'reg>>,
+    always_for_absolute_path: bool,
+) -> Result<ResolvedPath<'a>, RenderError> {
+    let mut path_context_depth: i64 = 0;
+    let mut with_block_param = None;
+    let mut from_root = false;
 
-        match seg.as_rule() {
-            Rule::path_up => {
-                path_stack.pop_back();
-                if let Some(p) = seg_stack.pop_back() {
-                    // also pop array index like [1]
-                    if p.as_rule() == Rule::path_raw_id {
-                        seg_stack.pop_back();
-                    }
+    // peek relative_path for block param, @root and  "../../"
+    for path_seg in relative_path {
+        match path_seg {
+            PathSeg::Named(the_path) => {
+                if let Some((holder, base_path)) = get_in_block_params(&block_contexts, the_path) {
+                    with_block_param = Some((holder, base_path));
                 }
+                break;
             }
-            Rule::path_id | Rule::path_raw_id => {
-                seg_stack.push_back(seg);
-            }
-            _ => {}
+            PathSeg::Ruled(the_rule) => match the_rule {
+                Rule::path_root => {
+                    from_root = true;
+                    break;
+                }
+                Rule::path_up => path_context_depth += 1,
+                _ => break,
+            },
         }
     }
 
-    for i in seg_stack {
-        let span = i.as_span();
-        path_stack.push_back(&path[span.start()..span.end()]);
+    let mut path_stack = Vec::with_capacity(relative_path.len() + 5);
+    match with_block_param {
+        Some((BlockParamHolder::Value(ref value), _)) => {
+            merge_json_path(&mut path_stack, &relative_path[1..]);
+            Ok(ResolvedPath::BlockParamValue(path_stack, value))
+        }
+        Some((BlockParamHolder::Path(ref paths), base_path)) => {
+            extend(&mut path_stack, base_path);
+            if !paths.is_empty() {
+                extend(&mut path_stack, paths);
+            }
+            merge_json_path(&mut path_stack, &relative_path[1..]);
+
+            Ok(ResolvedPath::AbsolutePath(path_stack))
+        }
+        None => {
+            if path_context_depth > 0 {
+                let blk = block_contexts
+                    .get(path_context_depth as usize)
+                    .or_else(|| block_contexts.front());
+
+                if let Some(base_value) = blk.and_then(|blk| blk.base_value()) {
+                    merge_json_path(&mut path_stack, relative_path);
+                    Ok(ResolvedPath::LocalValue(path_stack, base_value))
+                } else {
+                    if let Some(base_path) = blk.map(|blk| blk.base_path()) {
+                        extend(&mut path_stack, base_path);
+                    }
+                    merge_json_path(&mut path_stack, relative_path);
+                    Ok(ResolvedPath::AbsolutePath(path_stack))
+                }
+            } else if from_root {
+                merge_json_path(&mut path_stack, relative_path);
+                Ok(ResolvedPath::AbsolutePath(path_stack))
+            } else if always_for_absolute_path {
+                if let Some(base_value) = block_contexts.front().and_then(|blk| blk.base_value()) {
+                    merge_json_path(&mut path_stack, relative_path);
+                    Ok(ResolvedPath::LocalValue(path_stack, base_value))
+                } else {
+                    if let Some(base_path) = block_contexts.front().map(|blk| blk.base_path()) {
+                        extend(&mut path_stack, base_path);
+                    }
+                    merge_json_path(&mut path_stack, relative_path);
+                    Ok(ResolvedPath::AbsolutePath(path_stack))
+                }
+            } else {
+                merge_json_path(&mut path_stack, relative_path);
+                Ok(ResolvedPath::RelativePath(path_stack))
+            }
+        }
     }
-    Ok(())
 }
 
-fn parse_json_visitor<'a>(
-    path_stack: &mut VecDeque<&'a str>,
-    base_path: &'a str,
-    path_context: &'a VecDeque<String>,
-    relative_path: &'a str,
-) -> Result<(), RenderError> {
-    let parser = HandlebarsParser::parse(Rule::path, relative_path)
-        .map(|p| p.flatten())
-        .map_err(|_| RenderError::new(format!("Invalid JSON path: {}", relative_path)))?;
-
-    let mut path_context_depth: i64 = -1;
-
-    for sg in parser {
-        if sg.as_rule() == Rule::path_up {
-            path_context_depth += 1;
-        } else {
-            break;
-        }
-    }
-
-    if path_context_depth >= 0 {
-        if let Some(context_base_path) = path_context.get(path_context_depth as usize) {
-            parse_json_visitor_inner(path_stack, context_base_path)?;
-        } else {
-            parse_json_visitor_inner(path_stack, base_path)?;
-        }
-    } else {
-        parse_json_visitor_inner(path_stack, base_path)?;
-    }
-
-    parse_json_visitor_inner(path_stack, relative_path)?;
-    Ok(())
+fn get_data<'a>(d: Option<&'a Json>, p: &str) -> Result<Option<&'a Json>, RenderError> {
+    let result = match d {
+        Some(&Json::Array(ref l)) => p.parse::<usize>().map(|idx_u| l.get(idx_u))?,
+        Some(&Json::Object(ref m)) => m.get(p),
+        Some(_) => None,
+        None => None,
+    };
+    Ok(result)
 }
 
-pub fn merge_json(base: &Json, addition: &Object) -> Json {
-    let mut base_map = match *base {
+fn get_in_block_params<'a, 'reg>(
+    block_contexts: &'a VecDeque<BlockContext<'reg>>,
+    p: &str,
+) -> Option<(&'a BlockParamHolder, &'a Vec<String>)> {
+    for bc in block_contexts {
+        let v = bc.get_block_param(p);
+        if v.is_some() {
+            return v.map(|v| (v, bc.base_path()));
+        }
+    }
+
+    None
+}
+
+pub(crate) fn merge_json(base: &Json, addition: &HashMap<&&str, &Json>) -> Json {
+    let mut base_map = match base {
         Json::Object(ref m) => m.clone(),
         _ => Map::new(),
     };
 
     for (k, v) in addition.iter() {
-        base_map.insert(k.clone(), v.clone());
+        base_map.insert((*(*k)).to_string(), (*v).clone());
     }
 
     Json::Object(base_map)
@@ -118,43 +164,60 @@
             .map(|d| Context { data: d })
     }
 
-    /// Navigate the context with base path and relative path
-    /// Typically you will set base path to `RenderContext.get_path()`
-    /// and set relative path to helper argument or so.
-    ///
-    /// If you want to navigate from top level, set the base path to `"."`
-    pub fn navigate(
-        &self,
-        base_path: &str,
-        path_context: &VecDeque<String>,
-        relative_path: &str,
-    ) -> Result<Option<&Json>, RenderError> {
-        let mut path_stack: VecDeque<&str> = VecDeque::new();
-        parse_json_visitor(&mut path_stack, base_path, path_context, relative_path)?;
+    /// Navigate the context with relative path and block scopes
+    pub(crate) fn navigate<'reg, 'rc>(
+        &'rc self,
+        relative_path: &[PathSeg],
+        block_contexts: &VecDeque<BlockContext<'reg>>,
+    ) -> Result<ScopedJson<'reg, 'rc>, RenderError> {
+        // always use absolute at the moment until we get base_value lifetime issue fixed
+        let resolved_visitor = parse_json_visitor(&relative_path, block_contexts, true)?;
 
-        let paths: Vec<&str> = path_stack.iter().cloned().collect();
-        let mut data: Option<&Json> = Some(&self.data);
-        for p in &paths {
-            if *p == "this" {
-                continue;
+        // debug logging
+        debug!("Accessing context value: {:?}", resolved_visitor);
+
+        match resolved_visitor {
+            ResolvedPath::AbsolutePath(paths) => {
+                let mut ptr = Some(self.data());
+                for p in paths.iter() {
+                    ptr = get_data(ptr, p)?;
+                }
+
+                Ok(ptr
+                    .map(|v| ScopedJson::Context(v, paths))
+                    .unwrap_or_else(|| ScopedJson::Missing))
             }
-            data = match data {
-                Some(&Json::Array(ref l)) => p
-                    .parse::<usize>()
-                    .map_err(RenderError::with)
-                    .map(|idx_u| l.get(idx_u))?,
-                Some(&Json::Object(ref m)) => m.get(*p),
-                Some(_) => None,
-                None => break,
+            ResolvedPath::RelativePath(_paths) => {
+                // relative path is disabled for now
+                unreachable!()
+                // let mut ptr = block_contexts.front().and_then(|blk| blk.base_value());
+                // for p in paths.iter() {
+                //     ptr = get_data(ptr, p)?;
+                // }
+
+                // Ok(ptr
+                //     .map(|v| ScopedJson::Context(v, paths))
+                //     .unwrap_or_else(|| ScopedJson::Missing))
+            }
+            ResolvedPath::BlockParamValue(paths, value)
+            | ResolvedPath::LocalValue(paths, value) => {
+                let mut ptr = Some(value);
+                for p in paths.iter() {
+                    ptr = get_data(ptr, p)?;
+                }
+                Ok(ptr
+                    .map(|v| ScopedJson::Derived(v.clone()))
+                    .unwrap_or_else(|| ScopedJson::Missing))
             }
         }
-        Ok(data)
     }
 
+    /// Return the Json data wrapped in context
     pub fn data(&self) -> &Json {
         &self.data
     }
 
+    /// Return the mutable reference to Json data wrapped in context
     pub fn data_mut(&mut self) -> &mut Json {
         &mut self.data
     }
@@ -162,11 +225,21 @@
 
 #[cfg(test)]
 mod test {
+    use crate::block::{BlockContext, BlockParams};
     use crate::context::{self, Context};
-    use crate::value::{self, JsonRender};
-    use hashbrown::HashMap;
+    use crate::error::RenderError;
+    use crate::json::path::Path;
+    use crate::json::value::{self, ScopedJson};
     use serde_json::value::Map;
-    use std::collections::VecDeque;
+    use std::collections::{HashMap, VecDeque};
+
+    fn navigate_from_root<'reg, 'rc>(
+        ctx: &'rc Context,
+        path: &str,
+    ) -> Result<ScopedJson<'reg, 'rc>, RenderError> {
+        let relative_path = Path::parse(path).unwrap();
+        ctx.navigate(relative_path.segs().unwrap(), &VecDeque::new())
+    }
 
     #[derive(Serialize)]
     struct Address {
@@ -187,10 +260,7 @@
         let v = "hello";
         let ctx = Context::wraps(&v.to_string()).unwrap();
         assert_eq!(
-            ctx.navigate(".", &VecDeque::new(), "this")
-                .unwrap()
-                .unwrap()
-                .render(),
+            navigate_from_root(&ctx, "this").unwrap().render(),
             v.to_string()
         );
     }
@@ -206,55 +276,33 @@
             name: "Ning Sun".to_string(),
             age: 27,
             addr,
-            titles: vec!["programmer".to_string(), "cartographier".to_string()],
+            titles: vec!["programmer".to_string(), "cartographer".to_string()],
         };
 
         let ctx = Context::wraps(&person).unwrap();
         assert_eq!(
-            ctx.navigate(".", &VecDeque::new(), "./name/../addr/country")
-                .unwrap()
-                .unwrap()
-                .render(),
+            navigate_from_root(&ctx, "./addr/country").unwrap().render(),
             "China".to_string()
         );
         assert_eq!(
-            ctx.navigate(".", &VecDeque::new(), "addr.[country]")
-                .unwrap()
-                .unwrap()
-                .render(),
+            navigate_from_root(&ctx, "addr.[country]").unwrap().render(),
             "China".to_string()
         );
 
         let v = true;
         let ctx2 = Context::wraps(&v).unwrap();
         assert_eq!(
-            ctx2.navigate(".", &VecDeque::new(), "this")
-                .unwrap()
-                .unwrap()
-                .render(),
+            navigate_from_root(&ctx2, "this").unwrap().render(),
             "true".to_string()
         );
 
         assert_eq!(
-            ctx.navigate(".", &VecDeque::new(), "titles.[0]")
-                .unwrap()
-                .unwrap()
-                .render(),
+            navigate_from_root(&ctx, "titles.[0]").unwrap().render(),
             "programmer".to_string()
         );
 
         assert_eq!(
-            ctx.navigate(".", &VecDeque::new(), "titles.[0]/../../age")
-                .unwrap()
-                .unwrap()
-                .render(),
-            "27".to_string()
-        );
-        assert_eq!(
-            ctx.navigate(".", &VecDeque::new(), "this.titles.[0]/../../age")
-                .unwrap()
-                .unwrap()
-                .render(),
+            navigate_from_root(&ctx, "age").unwrap().render(),
             "27".to_string()
         );
     }
@@ -271,17 +319,11 @@
         let ctx2 = Context::wraps(&map_without_this).unwrap();
 
         assert_eq!(
-            ctx1.navigate(".", &VecDeque::new(), "this")
-                .unwrap()
-                .unwrap()
-                .render(),
+            navigate_from_root(&ctx1, "this").unwrap().render(),
             "[object]".to_owned()
         );
         assert_eq!(
-            ctx2.navigate(".", &VecDeque::new(), "age")
-                .unwrap()
-                .unwrap()
-                .render(),
+            navigate_from_root(&ctx2, "age").unwrap().render(),
             "4".to_owned()
         );
     }
@@ -291,41 +333,26 @@
         let map = json!({ "age": 4 });
         let s = "hello".to_owned();
         let mut hash = HashMap::new();
-        hash.insert("tag".to_owned(), value::to_json("h1"));
+        let v = value::to_json("h1");
+        hash.insert(&"tag", &v);
 
         let ctx_a1 = Context::wraps(&context::merge_json(&map, &hash)).unwrap();
         assert_eq!(
-            ctx_a1
-                .navigate(".", &VecDeque::new(), "age")
-                .unwrap()
-                .unwrap()
-                .render(),
+            navigate_from_root(&ctx_a1, "age").unwrap().render(),
             "4".to_owned()
         );
         assert_eq!(
-            ctx_a1
-                .navigate(".", &VecDeque::new(), "tag")
-                .unwrap()
-                .unwrap()
-                .render(),
+            navigate_from_root(&ctx_a1, "tag").unwrap().render(),
             "h1".to_owned()
         );
 
         let ctx_a2 = Context::wraps(&context::merge_json(&value::to_json(s), &hash)).unwrap();
         assert_eq!(
-            ctx_a2
-                .navigate(".", &VecDeque::new(), "this")
-                .unwrap()
-                .unwrap()
-                .render(),
+            navigate_from_root(&ctx_a2, "this").unwrap().render(),
             "[object]".to_owned()
         );
         assert_eq!(
-            ctx_a2
-                .navigate(".", &VecDeque::new(), "tag")
-                .unwrap()
-                .unwrap()
-                .render(),
+            navigate_from_root(&ctx_a2, "tag").unwrap().render(),
             "h1".to_owned()
         );
     }
@@ -337,10 +364,7 @@
         };
         let ctx = Context::wraps(&m).unwrap();
         assert_eq!(
-            ctx.navigate(".", &VecDeque::new(), "this_name")
-                .unwrap()
-                .unwrap()
-                .render(),
+            navigate_from_root(&ctx, "this_name").unwrap().render(),
             "the_value".to_string()
         );
     }
@@ -378,12 +402,52 @@
             "b": 2
         });
         let ctx = Context::wraps(&m).unwrap();
+        let mut block = BlockContext::new();
+        *block.base_path_mut() = ["a".to_owned(), "b".to_owned()].to_vec();
+
+        let mut blocks = VecDeque::new();
+        blocks.push_front(block);
+
         assert_eq!(
-            ctx.navigate("a/b", &VecDeque::new(), "@root/b")
-                .unwrap()
+            ctx.navigate(&Path::parse("@root/b").unwrap().segs().unwrap(), &blocks)
                 .unwrap()
                 .render(),
             "2".to_string()
         );
     }
+
+    #[test]
+    fn test_block_params() {
+        let m = json!([{
+            "a": [1, 2]
+        }, {
+            "b": [2, 3]
+        }]);
+
+        let ctx = Context::wraps(&m).unwrap();
+        let mut block_params = BlockParams::new();
+        block_params
+            .add_path("z", ["0".to_owned(), "a".to_owned()].to_vec())
+            .unwrap();
+        block_params.add_value("t", json!("good")).unwrap();
+
+        let mut block = BlockContext::new();
+        block.set_block_params(block_params);
+
+        let mut blocks = VecDeque::new();
+        blocks.push_front(block);
+
+        assert_eq!(
+            ctx.navigate(&Path::parse("z.[1]").unwrap().segs().unwrap(), &blocks)
+                .unwrap()
+                .render(),
+            "2".to_string()
+        );
+        assert_eq!(
+            ctx.navigate(&Path::parse("t").unwrap().segs().unwrap(), &blocks)
+                .unwrap()
+                .render(),
+            "good".to_string()
+        );
+    }
 }
diff --git a/third_party/rust_crates/vendor/handlebars/src/directives/inline.rs b/third_party/rust_crates/vendor/handlebars/src/decorators/inline.rs
similarity index 70%
rename from third_party/rust_crates/vendor/handlebars/src/directives/inline.rs
rename to third_party/rust_crates/vendor/handlebars/src/decorators/inline.rs
index 58c081f..cbad5d8 100644
--- a/third_party/rust_crates/vendor/handlebars/src/directives/inline.rs
+++ b/third_party/rust_crates/vendor/handlebars/src/decorators/inline.rs
@@ -1,15 +1,15 @@
 use crate::context::Context;
-use crate::directives::{DirectiveDef, DirectiveResult};
+use crate::decorators::{DecoratorDef, DecoratorResult};
 use crate::error::RenderError;
 use crate::registry::Registry;
-use crate::render::{Directive, RenderContext};
+use crate::render::{Decorator, RenderContext};
 
 #[derive(Clone, Copy)]
-pub struct InlineDirective;
+pub struct InlineDecorator;
 
-fn get_name<'reg: 'rc, 'rc>(d: &'rc Directive<'reg, 'rc>) -> Result<&'rc str, RenderError> {
+fn get_name<'reg: 'rc, 'rc>(d: &'rc Decorator<'reg, 'rc>) -> Result<&'rc str, RenderError> {
     d.param(0)
-        .ok_or_else(|| RenderError::new("Param required for directive \"inline\""))
+        .ok_or_else(|| RenderError::new("Param required for decorator \"inline\""))
         .and_then(|v| {
             v.value()
                 .as_str()
@@ -17,14 +17,14 @@
         })
 }
 
-impl DirectiveDef for InlineDirective {
+impl DecoratorDef for InlineDecorator {
     fn call<'reg: 'rc, 'rc>(
         &self,
-        d: &Directive<'reg, 'rc>,
-        _: &'reg Registry,
+        d: &Decorator<'reg, 'rc>,
+        _: &'reg Registry<'reg>,
         _: &'rc Context,
-        rc: &mut RenderContext<'reg>,
-    ) -> DirectiveResult {
+        rc: &mut RenderContext<'reg, 'rc>,
+    ) -> DecoratorResult {
         let name = get_name(d)?;
 
         let template = d
@@ -36,7 +36,7 @@
     }
 }
 
-pub static INLINE_DIRECTIVE: InlineDirective = InlineDirective;
+pub static INLINE_DECORATOR: InlineDecorator = InlineDecorator;
 
 #[cfg(test)]
 mod test {
diff --git a/third_party/rust_crates/vendor/handlebars/src/directives/mod.rs b/third_party/rust_crates/vendor/handlebars/src/decorators/mod.rs
similarity index 77%
rename from third_party/rust_crates/vendor/handlebars/src/directives/mod.rs
rename to third_party/rust_crates/vendor/handlebars/src/decorators/mod.rs
index d5316b5..b8bad90 100644
--- a/third_party/rust_crates/vendor/handlebars/src/directives/mod.rs
+++ b/third_party/rust_crates/vendor/handlebars/src/decorators/mod.rs
@@ -1,22 +1,22 @@
 use crate::context::Context;
 use crate::error::RenderError;
 use crate::registry::Registry;
-use crate::render::{Directive, RenderContext};
+use crate::render::{Decorator, RenderContext};
 
-pub use self::inline::INLINE_DIRECTIVE;
+pub use self::inline::INLINE_DECORATOR;
 
-pub type DirectiveResult = Result<(), RenderError>;
+pub type DecoratorResult = Result<(), RenderError>;
 
 /// Decorator Definition
 ///
-/// Implement this trait to define your own decorators or directives. Currently
-/// decorator shares same definition with helper.
+/// Implement this trait to define your own decorators. Currently decorator
+/// shares same definition with helper.
 ///
 /// In handlebars, it is recommended to use decorator to change context data and update helper
 /// definition.
 /// ## Updating context data
 ///
-/// In decorator, you can change some context data your are about to render.
+/// In decorator, you can change some context data you are about to render.
 ///
 /// ```
 /// use handlebars::*;
@@ -46,7 +46,7 @@
 ///
 /// fn override_helper(_: &Decorator, _: &Handlebars, _: &Context, rc: &mut RenderContext)
 ///         -> Result<(), RenderError> {
-///     let new_helper = |h: &Helper, _: &Handlebars, _: &Context, rc: &mut RenderContext, out: &mut Output|
+///     let new_helper = |h: &Helper, _: &Handlebars, _: &Context, rc: &mut RenderContext, out: &mut dyn Output|
 ///             -> Result<(), RenderError> {
 ///         // your helper logic
 ///         Ok(())
@@ -56,35 +56,33 @@
 /// }
 /// ```
 ///
-pub trait DirectiveDef: Send + Sync {
+pub trait DecoratorDef {
     fn call<'reg: 'rc, 'rc>(
         &'reg self,
-        d: &Directive<'reg, 'rc>,
-        r: &'reg Registry,
+        d: &Decorator<'reg, 'rc>,
+        r: &'reg Registry<'reg>,
         ctx: &'rc Context,
-        rc: &mut RenderContext<'reg>,
-    ) -> DirectiveResult;
+        rc: &mut RenderContext<'reg, 'rc>,
+    ) -> DecoratorResult;
 }
 
-/// implement DirectiveDef for bare function so we can use function as directive
+/// Implement DecoratorDef for bare function so we can use function as decorator
 impl<
-        F: Send
-            + Sync
-            + for<'reg, 'rc> Fn(
-                &Directive<'reg, 'rc>,
-                &'reg Registry,
-                &'rc Context,
-                &mut RenderContext,
-            ) -> DirectiveResult,
-    > DirectiveDef for F
+        F: for<'reg, 'rc> Fn(
+            &Decorator<'reg, 'rc>,
+            &'reg Registry<'reg>,
+            &'rc Context,
+            &mut RenderContext<'reg, 'rc>,
+        ) -> DecoratorResult,
+    > DecoratorDef for F
 {
     fn call<'reg: 'rc, 'rc>(
         &'reg self,
-        d: &Directive<'reg, 'rc>,
-        reg: &'reg Registry,
+        d: &Decorator<'reg, 'rc>,
+        reg: &'reg Registry<'reg>,
         ctx: &'rc Context,
-        rc: &mut RenderContext,
-    ) -> DirectiveResult {
+        rc: &mut RenderContext<'reg, 'rc>,
+    ) -> DecoratorResult {
         (*self)(d, reg, ctx, rc)
     }
 }
@@ -95,10 +93,10 @@
 mod test {
     use crate::context::Context;
     use crate::error::RenderError;
+    use crate::json::value::{as_string, to_json};
     use crate::output::Output;
     use crate::registry::Registry;
-    use crate::render::{Directive, Helper, RenderContext};
-    use crate::value::{as_string, to_json};
+    use crate::render::{Decorator, Helper, RenderContext};
 
     #[test]
     fn test_register_decorator() {
@@ -116,10 +114,10 @@
         handlebars.register_decorator(
             "foo",
             Box::new(
-                |_: &Directive,
-                 _: &Registry,
+                |_: &Decorator<'_, '_>,
+                 _: &Registry<'_>,
                  _: &Context,
-                 _: &mut RenderContext|
+                 _: &mut RenderContext<'_, '_>|
                  -> Result<(), RenderError> { Ok(()) },
             ),
         );
@@ -141,10 +139,10 @@
         handlebars.register_decorator(
             "foo",
             Box::new(
-                |_: &Directive,
-                 _: &Registry,
+                |_: &Decorator<'_, '_>,
+                 _: &Registry<'_>,
                  ctx: &Context,
-                 rc: &mut RenderContext|
+                 rc: &mut RenderContext<'_, '_>|
                  -> Result<(), RenderError> {
                     // modify json object
                     let mut new_ctx = ctx.clone();
@@ -169,10 +167,10 @@
         handlebars.register_decorator(
             "bar",
             Box::new(
-                |d: &Directive,
-                 _: &Registry,
+                |d: &Decorator<'_, '_>,
+                 _: &Registry<'_>,
                  _: &Context,
-                 rc: &mut RenderContext|
+                 rc: &mut RenderContext<'_, '_>|
                  -> Result<(), RenderError> {
                     // modify value
                     let v = d
@@ -226,11 +224,11 @@
         handlebars.register_helper(
             "distance",
             Box::new(
-                |h: &Helper,
-                 _: &Registry,
+                |h: &Helper<'_, '_>,
+                 _: &Registry<'_>,
                  _: &Context,
-                 _: &mut RenderContext,
-                 out: &mut Output|
+                 _: &mut RenderContext<'_, '_>,
+                 out: &mut dyn Output|
                  -> Result<(), RenderError> {
                     let s = format!(
                         "{}m",
@@ -247,10 +245,10 @@
         handlebars.register_decorator(
             "foo",
             Box::new(
-                |d: &Directive,
-                 _: &Registry,
+                |d: &Decorator<'_, '_>,
+                 _: &Registry<'_>,
                  _: &Context,
-                 rc: &mut RenderContext|
+                 rc: &mut RenderContext<'_, '_>|
                  -> Result<(), RenderError> {
                     let new_unit = d
                         .param(0)
@@ -258,11 +256,11 @@
                         .and_then(|v| as_string(v.value()))
                         .unwrap_or("")
                         .to_owned();
-                    let new_helper = move |h: &Helper,
-                                           _: &Registry,
+                    let new_helper = move |h: &Helper<'_, '_>,
+                                           _: &Registry<'_>,
                                            _: &Context,
-                                           _: &mut RenderContext,
-                                           out: &mut Output|
+                                           _: &mut RenderContext<'_, '_>,
+                                           out: &mut dyn Output|
                           -> Result<(), RenderError> {
                         let s = format!(
                             "{}{}",
@@ -284,10 +282,10 @@
         handlebars.register_decorator(
             "bar",
             Box::new(
-                |_: &Directive,
-                 _: &Registry,
+                |_: &Decorator<'_, '_>,
+                 _: &Registry<'_>,
                  _: &Context,
-                 rc: &mut RenderContext|
+                 rc: &mut RenderContext<'_, '_>|
                  -> Result<(), RenderError> {
                     rc.unregister_local_helper("distance");
                     Ok(())
diff --git a/third_party/rust_crates/vendor/handlebars/src/error.rs b/third_party/rust_crates/vendor/handlebars/src/error.rs
index 9890f26..6b905b3 100644
--- a/third_party/rust_crates/vendor/handlebars/src/error.rs
+++ b/third_party/rust_crates/vendor/handlebars/src/error.rs
@@ -1,13 +1,15 @@
 use std::error::Error;
 use std::fmt;
 use std::io::Error as IOError;
+use std::num::ParseIntError;
 use std::string::FromUtf8Error;
 
 use serde_json::error::Error as SerdeError;
-#[cfg(not(feature = "no_dir_source"))]
+#[cfg(feature = "dir_source")]
 use walkdir::Error as WalkdirError;
 
-use crate::template::Parameter;
+#[cfg(feature = "script_helper")]
+use rhai::{EvalAltResult, ParseError};
 
 /// Error when rendering data on template.
 #[derive(Debug)]
@@ -16,11 +18,11 @@
     pub template_name: Option<String>,
     pub line_no: Option<usize>,
     pub column_no: Option<usize>,
-    cause: Option<Box<Error + Send + Sync>>,
+    cause: Option<Box<dyn Error + Send + Sync + 'static>>,
 }
 
 impl fmt::Display for RenderError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
         match (self.line_no, self.column_no) {
             (Some(line), Some(col)) => write!(
                 f,
@@ -38,30 +40,39 @@
 }
 
 impl Error for RenderError {
-    fn description(&self) -> &str {
-        &self.desc[..]
-    }
-
-    fn cause(&self) -> Option<&Error> {
-        self.cause.as_ref().map(|e| &**e as &Error)
+    fn source(&self) -> Option<&(dyn Error + 'static)> {
+        self.cause.as_ref().map(|e| &**e as &(dyn Error + 'static))
     }
 }
 
 impl From<IOError> for RenderError {
     fn from(e: IOError) -> RenderError {
-        RenderError::with(e)
+        RenderError::from_error("Error on output generation.", e)
     }
 }
 
 impl From<SerdeError> for RenderError {
     fn from(e: SerdeError) -> RenderError {
-        RenderError::with(e)
+        RenderError::from_error("Error when accessing JSON data.", e)
     }
 }
 
 impl From<FromUtf8Error> for RenderError {
     fn from(e: FromUtf8Error) -> RenderError {
-        RenderError::with(e)
+        RenderError::from_error("Error on bytes generation.", e)
+    }
+}
+
+impl From<ParseIntError> for RenderError {
+    fn from(e: ParseIntError) -> RenderError {
+        RenderError::from_error("Error on accessing array/vector with string index.", e)
+    }
+}
+
+#[cfg(feature = "script_helper")]
+impl From<Box<EvalAltResult>> for RenderError {
+    fn from(e: Box<EvalAltResult>) -> RenderError {
+        RenderError::from_error("Error on converting data to Rhai dynamic.", e)
     }
 }
 
@@ -84,11 +95,22 @@
         RenderError::new(&msg)
     }
 
+    #[deprecated]
     pub fn with<E>(cause: E) -> RenderError
     where
         E: Error + Send + Sync + 'static,
     {
-        let mut e = RenderError::new(cause.description());
+        let mut e = RenderError::new(cause.to_string());
+        e.cause = Some(Box::new(cause));
+
+        e
+    }
+
+    pub fn from_error<E>(error_kind: &str, cause: E) -> RenderError
+    where
+        E: Error + Send + Sync + 'static,
+    {
+        let mut e = RenderError::new(format!("{}: {}", error_kind, cause.to_string()));
         e.cause = Some(Box::new(cause));
 
         e
@@ -102,24 +124,19 @@
         MismatchingClosedHelper(open: String, closed: String) {
             display("helper {:?} was opened, but {:?} is closing",
                 open, closed)
-            description("wrong name of closing helper")
         }
-        MismatchingClosedDirective(open: Parameter, closed: Parameter) {
-            display("directive {:?} was opened, but {:?} is closing",
+        MismatchingClosedDecorator(open: String, closed: String) {
+            display("decorator {:?} was opened, but {:?} is closing",
                 open, closed)
-            description("wrong name of closing directive")
         }
         InvalidSyntax {
             display("invalid handlebars syntax.")
-            description("invalid handlebars syntax")
         }
         InvalidParam (param: String) {
             display("invalid parameter {:?}", param)
-            description("invalid parameter")
         }
         NestedSubexpression {
             display("nested subexpression is not supported")
-            description("nested subexpression is not supported")
         }
     }
 }
@@ -158,11 +175,7 @@
     }
 }
 
-impl Error for TemplateError {
-    fn description(&self) -> &str {
-        self.reason.description()
-    }
-}
+impl Error for TemplateError {}
 
 fn template_segment(template_str: &str, line: usize, col: usize) -> String {
     let range = 3;
@@ -191,7 +204,7 @@
 }
 
 impl fmt::Display for TemplateError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
         match (self.line_no, self.column_no, &self.segment) {
             (Some(line), Some(col), &Some(ref seg)) => writeln!(
                 f,
@@ -211,23 +224,22 @@
 }
 
 quick_error! {
+    /// A combined error type for `TemplateError` and `IOError`
     #[derive(Debug)]
     pub enum TemplateFileError {
         TemplateError(err: TemplateError) {
             from()
-            cause(err)
-            description(err.description())
+            source(err)
             display("{}", err)
         }
         IOError(err: IOError, name: String) {
-            cause(err)
-            description(err.description())
+            source(err)
             display("Template \"{}\": {}", name, err)
         }
     }
 }
 
-#[cfg(not(feature = "no_dir_source"))]
+#[cfg(feature = "dir_source")]
 impl From<WalkdirError> for TemplateFileError {
     fn from(error: WalkdirError) -> TemplateFileError {
         let path_string: String = error
@@ -239,23 +251,21 @@
 }
 
 quick_error! {
+    /// A combined error type for `TemplateError`, `IOError` and `RenderError`
     #[derive(Debug)]
     pub enum TemplateRenderError {
         TemplateError(err: TemplateError) {
             from()
-            cause(err)
-            description(err.description())
+            source(err)
             display("{}", err)
         }
         RenderError(err: RenderError) {
             from()
-            cause(err)
-            description(err.description())
+            source(err)
             display("{}", err)
         }
         IOError(err: IOError, name: String) {
-            cause(err)
-            description(err.description())
+            source(err)
             display("Template \"{}\": {}", name, err)
         }
     }
@@ -270,3 +280,18 @@
         }
     }
 }
+
+#[cfg(feature = "script_helper")]
+quick_error! {
+    #[derive(Debug)]
+    pub enum ScriptError {
+        IOError(err: IOError) {
+            from()
+            source(err)
+        }
+        ParseError(err: ParseError) {
+            from()
+            source(err)
+        }
+    }
+}
diff --git a/third_party/rust_crates/vendor/handlebars/src/grammar.pest b/third_party/rust_crates/vendor/handlebars/src/grammar.pest
index a27c5dd..7350ef0 100644
--- a/third_party/rust_crates/vendor/handlebars/src/grammar.pest
+++ b/third_party/rust_crates/vendor/handlebars/src/grammar.pest
@@ -1,5 +1,5 @@
 WHITESPACE = _{ " "|"\t"|"\n"|"\r" }
-keywords = @{ "as" | "else" }
+keywords = { "as" | "else" }
 
 escape = @{ ("\\" ~ "{{" ~ "{{"?) | ("\\" ~ "\\"+ ~ &"{{") }
 raw_text = ${ ( escape | (!"{{" ~ ANY) )+ }
@@ -12,43 +12,51 @@
             null_literal |
             boolean_literal }
 
-null_literal = { "null" }
-boolean_literal = { "true"|"false" }
-number_literal = @{ "-"? ~ ASCII_DIGIT+ ~ "."? ~ ASCII_DIGIT*
-~ ("E" ~ "-"? ~ ASCII_DIGIT+)? }
-string_literal = @{ ("\"" ~ (!"\"" ~ ("\\\"" | ANY))* ~ "\"") | ("'" ~ (!"'" ~ ("\\'" | ANY))* ~ "'") }
+null_literal = @{ "null" ~ !symbol_char }
+boolean_literal = @{ ("true"|"false") ~ !symbol_char }
+number_literal = @{ "-"? ~ ASCII_DIGIT+ ~ "."? ~ ASCII_DIGIT* ~ ("E" ~ "-"? ~ ASCII_DIGIT+)? }
+json_char = {
+    !("\"" | "\\") ~ ANY
+    | "\\" ~ ("\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t")
+    | "\\" ~ ("u" ~ ASCII_HEX_DIGIT{4})
+}
+string_inner = @{ json_char* }
+string_literal = ${ "\"" ~ string_inner ~ "\"" }
 array_literal = { "[" ~ literal? ~ ("," ~ literal)* ~ "]" }
 object_literal = { "{" ~ (string_literal ~ ":" ~ literal)?
                    ~ ("," ~ string_literal ~ ":" ~ literal)* ~ "}" }
 
-symbol_char = _{'a'..'z'|'A'..'Z'|ASCII_DIGIT|"@"|"-"|"_"|'\u{80}'..'\u{7ff}'|'\u{800}'..'\u{ffff}'|'\u{10000}'..'\u{10ffff}'}
+symbol_char = _{ASCII_ALPHANUMERIC|"-"|"_"|"$"|'\u{80}'..'\u{7ff}'|'\u{800}'..'\u{ffff}'|'\u{10000}'..'\u{10ffff}'}
+partial_symbol_char = _{ASCII_ALPHANUMERIC|"-"|"_"|'\u{80}'..'\u{7ff}'|'\u{800}'..'\u{ffff}'|'\u{10000}'..'\u{10ffff}'|"/"|"."}
 path_char = _{ "/" }
 
 identifier = @{ symbol_char+ }
-reference = @{ "@"? ~ path_inline }
+partial_identifier = @{ partial_symbol_char+ | ("[" ~ ANY+ ~ "]") | ("'" ~ (!"'" ~ ("\\'" | ANY))+ ~ "'") }
+reference = ${ path_inline }
+
 name = _{ subexpression | reference }
 
 param = { !(keywords ~ !symbol_char) ~ (literal | reference | subexpression) }
 hash = { identifier ~ "=" ~ param }
 block_param = { "as" ~ "|" ~ identifier ~ identifier? ~ "|"}
 exp_line = _{ identifier ~ (hash|param)* ~ block_param?}
-partial_exp_line = _{ name ~ (hash|param)* }
+partial_exp_line = _{ ((partial_identifier|name) ~ (hash|param)*) }
 
-subexpression = { "(" ~ name ~ (hash|param)* ~ ")" }
+subexpression = { "(" ~ ((identifier ~ (hash|param)+) | reference)  ~ ")" }
 
 pre_whitespace_omitter = { "~" }
 pro_whitespace_omitter = { "~" }
 
-expression = { !invert_tag ~ "{{" ~ pre_whitespace_omitter? ~ name ~
-pro_whitespace_omitter? ~ "}}" }
+expression = { !invert_tag ~ "{{" ~ pre_whitespace_omitter? ~
+              ((identifier ~ (hash|param)+) | name )
+              ~ pro_whitespace_omitter? ~ "}}" }
+html_expression_triple_bracket = _{ "{{{" ~ pre_whitespace_omitter? ~ name ~
+                                    pro_whitespace_omitter? ~ "}}}" }
+amp_expression = _{ "{{" ~ pre_whitespace_omitter? ~ "&" ~ name ~
+                       pro_whitespace_omitter? ~ "}}" }
+html_expression = { html_expression_triple_bracket | amp_expression }
 
-html_expression = { "{{{" ~ pre_whitespace_omitter? ~ name ~
-pro_whitespace_omitter? ~ "}}}" }
-
-helper_expression = { !invert_tag ~ "{{" ~ pre_whitespace_omitter? ~ exp_line ~
-pro_whitespace_omitter? ~ "}}" }
-
-directive_expression = { "{{" ~ pre_whitespace_omitter? ~ "*" ~ exp_line ~
+decorator_expression = { "{{" ~ pre_whitespace_omitter? ~ "*" ~ exp_line ~
 pro_whitespace_omitter? ~ "}}" }
 partial_expression = { "{{" ~ pre_whitespace_omitter? ~ ">" ~ partial_exp_line
                      ~ pro_whitespace_omitter? ~ "}}" }
@@ -57,27 +65,27 @@
              ~ pro_whitespace_omitter? ~ "}}"}
 helper_block_start = { "{{" ~ pre_whitespace_omitter? ~ "#" ~ exp_line ~
                      pro_whitespace_omitter? ~ "}}" }
-helper_block_end = { "{{" ~ pre_whitespace_omitter? ~ "/" ~ name ~
+helper_block_end = { "{{" ~ pre_whitespace_omitter? ~ "/" ~ identifier ~
                    pro_whitespace_omitter? ~ "}}" }
 helper_block = _{ helper_block_start ~ template ~
                   (invert_tag ~ template)? ~ helper_block_end }
 
-directive_block_start = { "{{" ~ pre_whitespace_omitter? ~ "#" ~ "*"
+decorator_block_start = { "{{" ~ pre_whitespace_omitter? ~ "#" ~ "*"
                         ~ exp_line ~ pro_whitespace_omitter? ~ "}}" }
-directive_block_end = { "{{" ~ pre_whitespace_omitter? ~ "/" ~ name ~
+decorator_block_end = { "{{" ~ pre_whitespace_omitter? ~ "/" ~ identifier ~
                         pro_whitespace_omitter? ~ "}}" }
-directive_block = _{ directive_block_start ~ template ~
-                     directive_block_end }
+decorator_block = _{ decorator_block_start ~ template ~
+                     decorator_block_end }
 
 partial_block_start = { "{{" ~ pre_whitespace_omitter? ~ "#" ~ ">"
                         ~ partial_exp_line ~ pro_whitespace_omitter? ~ "}}" }
-partial_block_end = { "{{" ~ pre_whitespace_omitter? ~ "/" ~ name ~
+partial_block_end = { "{{" ~ pre_whitespace_omitter? ~ "/" ~ partial_identifier ~
                       pro_whitespace_omitter? ~ "}}" }
 partial_block = _{ partial_block_start ~ template ~ partial_block_end }
 
 raw_block_start = { "{{{{" ~ pre_whitespace_omitter? ~ exp_line ~
                     pro_whitespace_omitter? ~ "}}}}" }
-raw_block_end = { "{{{{" ~ pre_whitespace_omitter? ~ "/" ~ name ~
+raw_block_end = { "{{{{" ~ pre_whitespace_omitter? ~ "/" ~ identifier ~
                   pro_whitespace_omitter? ~ "}}}}" }
 raw_block = _{ raw_block_start ~ raw_block_text ~ raw_block_end }
 
@@ -88,13 +96,12 @@
             raw_text |
             expression |
             html_expression |
-            helper_expression |
             helper_block |
             raw_block |
             hbs_comment |
             hbs_comment_compact |
-            directive_expression |
-            directive_block |
+            decorator_expression |
+            decorator_block |
             partial_expression |
             partial_block )* }
 
@@ -104,14 +111,15 @@
 // json path visitor
 // Disallowed chars: Whitespace ! " # % & ' ( ) * + , . / ; < = > @ [ \ ] ^ ` { | } ~
 
-path_id = { symbol_char+ }
+path_id = @{ symbol_char+ }
 
 path_raw_id = { (!"]" ~ ANY)* }
 path_sep = _{ "/" | "." }
 path_up = { ".." }
 path_key = _{ "[" ~  path_raw_id ~ "]" }
-path_item = _{ path_up|path_id|path_current|path_key }
-path_current = { "this" | "." }
-
-path_inline = _{ path_item ~ (path_sep ~  path_item)* }
+path_root = { "@root" }
+path_current = _{ "this" ~ path_sep | "./" }
+path_item = _{ path_id|path_key }
+path_local = { "@" }
+path_inline = ${ path_current? ~ (path_root ~ path_sep)? ~ path_local? ~ (path_up ~ path_sep)*  ~ path_item ~ (path_sep ~  path_item)* }
 path = _{ path_inline ~ EOI }
diff --git a/third_party/rust_crates/vendor/handlebars/src/grammar.rs b/third_party/rust_crates/vendor/handlebars/src/grammar.rs
index 57c37b2..60ddc48 100644
--- a/third_party/rust_crates/vendor/handlebars/src/grammar.rs
+++ b/third_party/rust_crates/vendor/handlebars/src/grammar.rs
@@ -5,333 +5,340 @@
 pub struct HandlebarsParser;
 
 #[cfg(test)]
-use pest::Parser;
+mod test {
+    use super::{HandlebarsParser, Rule};
+    use pest::Parser;
 
-#[cfg(test)]
-macro_rules! assert_rule {
-    ($rule:expr, $in:expr) => {
-        assert_eq!(
-            HandlebarsParser::parse($rule, $in)
-                .unwrap()
-                .last()
-                .unwrap()
-                .as_span()
-                .end(),
-            $in.len()
-        );
-    };
-}
-
-#[cfg(test)]
-macro_rules! assert_not_rule {
-    ($rule:expr, $in:expr) => {
-        assert!(
-            HandlebarsParser::parse($rule, $in).is_err()
-                || HandlebarsParser::parse($rule, $in)
+    macro_rules! assert_rule {
+        ($rule:expr, $in:expr) => {
+            assert_eq!(
+                HandlebarsParser::parse($rule, $in)
                     .unwrap()
                     .last()
                     .unwrap()
                     .as_span()
-                    .end()
-                    != $in.len()
-        );
-    };
-}
-
-#[cfg(test)]
-macro_rules! assert_rule_match {
-    ($rule:expr, $in:expr) => {
-        assert!(HandlebarsParser::parse($rule, $in).is_ok());
-    };
-}
-
-#[test]
-fn test_raw_text() {
-    let s = vec![
-        "<h1> helloworld </h1>    ",
-        r"hello\{{world}}",
-        r"hello\{{#if world}}nice\{{/if}}",
-        r"hello \{{{{raw}}}}hello\{{{{/raw}}}}",
-    ];
-    for i in s.iter() {
-        assert_rule!(Rule::raw_text, i);
+                    .end(),
+                $in.len()
+            );
+        };
     }
 
-    let s_not_escape = vec![r"\\{{hello}}"];
-    for i in s_not_escape.iter() {
-        assert_not_rule!(Rule::raw_text, i);
+    macro_rules! assert_not_rule {
+        ($rule:expr, $in:expr) => {
+            assert!(
+                HandlebarsParser::parse($rule, $in).is_err()
+                    || HandlebarsParser::parse($rule, $in)
+                        .unwrap()
+                        .last()
+                        .unwrap()
+                        .as_span()
+                        .end()
+                        != $in.len()
+            );
+        };
     }
-}
 
-#[test]
-fn test_raw_block_text() {
-    let s = "<h1> {{hello}} </h1>";
-    assert_rule!(Rule::raw_block_text, s);
-}
-
-#[test]
-fn test_reference() {
-    let s = vec![
-        "a",
-        "abc",
-        "../a",
-        "a.b",
-        "@abc",
-        "a.[abc]",
-        "aBc.[abc]",
-        "abc.[0].[nice]",
-        "some-name",
-        "this.[0].ok",
-    ];
-    for i in s.iter() {
-        assert_rule!(Rule::reference, i);
+    macro_rules! assert_rule_match {
+        ($rule:expr, $in:expr) => {
+            assert!(HandlebarsParser::parse($rule, $in).is_ok());
+        };
     }
-}
 
-#[test]
-fn test_name() {
-    let s = vec!["if", "(abc)"];
-    for i in s.iter() {
-        assert_rule!(Rule::name, i);
+    #[test]
+    fn test_raw_text() {
+        let s = vec![
+            "<h1> helloworld </h1>    ",
+            r"hello\{{world}}",
+            r"hello\{{#if world}}nice\{{/if}}",
+            r"hello \{{{{raw}}}}hello\{{{{/raw}}}}",
+        ];
+        for i in s.iter() {
+            assert_rule!(Rule::raw_text, i);
+        }
+
+        let s_not_escape = vec![r"\\{{hello}}"];
+        for i in s_not_escape.iter() {
+            assert_not_rule!(Rule::raw_text, i);
+        }
     }
-}
 
-#[test]
-fn test_param() {
-    let s = vec!["hello", "\"json literal\""];
-    for i in s.iter() {
-        assert_rule!(Rule::param, i);
+    #[test]
+    fn test_raw_block_text() {
+        let s = "<h1> {{hello}} </h1>";
+        assert_rule!(Rule::raw_block_text, s);
     }
-}
 
-#[test]
-fn test_hash() {
-    let s = vec![
-        "hello=world",
-        "hello=\"world\"",
-        "hello=(world)",
-        "hello=(world 0)",
-    ];
-    for i in s.iter() {
-        assert_rule!(Rule::hash, i);
+    #[test]
+    fn test_reference() {
+        let s = vec![
+            "a",
+            "abc",
+            "../a",
+            "a.b",
+            "@abc",
+            "a.[abc]",
+            "aBc.[abc]",
+            "abc.[0].[nice]",
+            "some-name",
+            "this.[0].ok",
+            "this.[$id]",
+            "[$id]",
+            "$id",
+            "this.[null]",
+        ];
+        for i in s.iter() {
+            assert_rule!(Rule::reference, i);
+        }
     }
-}
 
-#[test]
-fn test_json_literal() {
-    let s = vec![
-        "\"json string\"",
-        "\"quot: \\\"\"",
-        "'json string'",
-        "'quot: \\''",
-        "[]",
-        "[\"hello\"]",
-        "[1,2,3,4,true]",
-        "{\"hello\": \"world\"}",
-        "{}",
-        "{\"a\":1, \"b\":2 }",
-    ];
-    for i in s.iter() {
-        assert_rule!(Rule::literal, i);
+    #[test]
+    fn test_name() {
+        let s = vec!["if", "(abc)"];
+        for i in s.iter() {
+            assert_rule!(Rule::name, i);
+        }
     }
-}
 
-#[test]
-fn test_comment() {
-    let s = vec!["{{!-- <hello {{ a-b c-d}} {{d-c}} ok --}}",
+    #[test]
+    fn test_param() {
+        let s = vec!["hello", "\"json literal\"", "nullable", "truestory"];
+        for i in s.iter() {
+            assert_rule!(Rule::param, i);
+        }
+    }
+
+    #[test]
+    fn test_hash() {
+        let s = vec![
+            "hello=world",
+            "hello=\"world\"",
+            "hello=(world)",
+            "hello=(world 0)",
+        ];
+        for i in s.iter() {
+            assert_rule!(Rule::hash, i);
+        }
+    }
+
+    #[test]
+    fn test_json_literal() {
+        let s = vec![
+            "\"json string\"",
+            "\"quot: \\\"\"",
+            "[]",
+            "[\"hello\"]",
+            "[1,2,3,4,true]",
+            "{\"hello\": \"world\"}",
+            "{}",
+            "{\"a\":1, \"b\":2 }",
+            "\"nullable\"",
+        ];
+        for i in s.iter() {
+            assert_rule!(Rule::literal, i);
+        }
+    }
+
+    #[test]
+    fn test_comment() {
+        let s = vec!["{{!-- <hello {{ a-b c-d}} {{d-c}} ok --}}",
                  "{{!--
                     <li><a href=\"{{up-dir nest-count}}{{base-url}}index.html\">{{this.title}}</a></li>
                 --}}"];
-    for i in s.iter() {
-        assert_rule!(Rule::hbs_comment, i);
+        for i in s.iter() {
+            assert_rule!(Rule::hbs_comment, i);
+        }
+        let s2 = vec!["{{! hello }}", "{{! test me }}"];
+        for i in s2.iter() {
+            assert_rule!(Rule::hbs_comment_compact, i);
+        }
     }
-    let s2 = vec!["{{! hello }}", "{{! test me }}"];
-    for i in s2.iter() {
-        assert_rule!(Rule::hbs_comment_compact, i);
-    }
-}
 
-#[test]
-fn test_subexpression() {
-    let s = vec!["(sub)", "(sub 0)", "(sub a=1)"];
-    for i in s.iter() {
-        assert_rule!(Rule::subexpression, i);
+    #[test]
+    fn test_subexpression() {
+        let s = vec!["(sub)", "(sub 0)", "(sub a=1)"];
+        for i in s.iter() {
+            assert_rule!(Rule::subexpression, i);
+        }
     }
-}
 
-#[test]
-fn test_expression() {
-    let s = vec!["{{exp}}", "{{(exp)}}", "{{this.name}}", "{{this.[0].name}}"];
-    for i in s.iter() {
-        assert_rule!(Rule::expression, i);
+    #[test]
+    fn test_expression() {
+        let s = vec![
+            "{{exp}}",
+            "{{(exp)}}",
+            "{{../exp}}",
+            "{{exp 1}}",
+            "{{exp \"literal\"}}",
+            "{{exp \"literal with space\"}}",
+            r#"{{exp "literal with escape \\\\"}}"#,
+            "{{exp ref}}",
+            "{{exp (sub)}}",
+            "{{exp (sub 123)}}",
+            "{{exp []}}",
+            "{{exp {}}}",
+            "{{exp key=1}}",
+            "{{exp key=ref}}",
+            "{{exp key=(sub)}}",
+            "{{exp key=(sub 0)}}",
+            "{{exp key=(sub 0 key=1)}}",
+        ];
+        for i in s.iter() {
+            assert_rule!(Rule::expression, i);
+        }
     }
-}
 
-#[test]
-fn test_helper_expression() {
-    let s = vec![
-        "{{exp 1}}",
-        "{{exp \"literal\"}}",
-        "{{exp ref}}",
-        "{{exp (sub)}}",
-        "{{exp (sub 123)}}",
-        "{{exp []}}",
-        "{{exp {}}}",
-        "{{exp key=1}}",
-        "{{exp key=ref}}",
-        "{{exp key=(sub)}}",
-        "{{exp key=(sub 0)}}",
-    ];
-    for i in s.iter() {
-        assert_rule!(Rule::helper_expression, i);
+    #[test]
+    fn test_identifier_with_dash() {
+        let s = vec!["{{exp-foo}}"];
+        for i in s.iter() {
+            assert_rule!(Rule::expression, i);
+        }
     }
-}
 
-#[test]
-fn test_identifier_with_dash() {
-    let s = vec!["{{exp-foo}}"];
-    for i in s.iter() {
-        assert_rule!(Rule::expression, i);
+    #[test]
+    fn test_html_expression() {
+        let s = vec!["{{{html}}}", "{{{(html)}}}", "{{{(html)}}}", "{{&html}}"];
+        for i in s.iter() {
+            assert_rule!(Rule::html_expression, i);
+        }
     }
-}
 
-#[test]
-fn test_html_expression() {
-    let s = vec!["{{{html}}}", "{{{(html)}}}", "{{{(html)}}}"];
-    for i in s.iter() {
-        assert_rule!(Rule::html_expression, i);
+    #[test]
+    fn test_helper_start() {
+        let s = vec![
+            "{{#if hello}}",
+            "{{#if (hello)}}",
+            "{{#if hello=world}}",
+            "{{#if hello hello=world}}",
+            "{{#if []}}",
+            "{{#if {}}}",
+            "{{#if}}",
+            "{{~#if hello~}}",
+            "{{#each people as |person|}}",
+            "{{#each-obj obj as |val key|}}",
+            "{{#each assets}}",
+        ];
+        for i in s.iter() {
+            assert_rule!(Rule::helper_block_start, i);
+        }
     }
-}
 
-#[test]
-fn test_helper_start() {
-    let s = vec![
-        "{{#if hello}}",
-        "{{#if (hello)}}",
-        "{{#if hello=world}}",
-        "{{#if hello hello=world}}",
-        "{{#if []}}",
-        "{{#if {}}}",
-        "{{#if}}",
-        "{{~#if hello~}}",
-        "{{#each people as |person|}}",
-        "{{#each-obj obj as |key val|}}",
-        "{{#each assets}}",
-    ];
-    for i in s.iter() {
-        assert_rule!(Rule::helper_block_start, i);
+    #[test]
+    fn test_helper_end() {
+        let s = vec!["{{/if}}", "{{~/if}}", "{{~/if ~}}", "{{/if   ~}}"];
+        for i in s.iter() {
+            assert_rule!(Rule::helper_block_end, i);
+        }
     }
-}
 
-#[test]
-fn test_helper_end() {
-    let s = vec!["{{/if}}", "{{~/if}}", "{{~/if ~}}", "{{/if   ~}}"];
-    for i in s.iter() {
-        assert_rule!(Rule::helper_block_end, i);
+    #[test]
+    fn test_helper_block() {
+        let s = vec![
+            "{{#if hello}}hello{{/if}}",
+            "{{#if true}}hello{{/if}}",
+            "{{#if nice ok=1}}hello{{/if}}",
+            "{{#if}}hello{{else}}world{{/if}}",
+            "{{#if}}hello{{^}}world{{/if}}",
+            "{{#if}}{{#if}}hello{{/if}}{{/if}}",
+            "{{#if}}hello{{~else}}world{{/if}}",
+            "{{#if}}hello{{else~}}world{{/if}}",
+            "{{#if}}hello{{~^~}}world{{/if}}",
+            "{{#if}}{{/if}}",
+        ];
+        for i in s.iter() {
+            assert_rule!(Rule::helper_block, i);
+        }
     }
-}
 
-#[test]
-fn test_helper_block() {
-    let s = vec![
-        "{{#if hello}}hello{{/if}}",
-        "{{#if true}}hello{{/if}}",
-        "{{#if nice ok=1}}hello{{/if}}",
-        "{{#if}}hello{{else}}world{{/if}}",
-        "{{#if}}hello{{^}}world{{/if}}",
-        "{{#if}}{{#if}}hello{{/if}}{{/if}}",
-        "{{#if}}hello{{~else}}world{{/if}}",
-        "{{#if}}hello{{else~}}world{{/if}}",
-        "{{#if}}hello{{~^~}}world{{/if}}",
-        "{{#if}}{{/if}}",
-    ];
-    for i in s.iter() {
-        assert_rule!(Rule::helper_block, i);
+    #[test]
+    fn test_raw_block() {
+        let s = vec![
+            "{{{{if hello}}}}good {{hello}}{{{{/if}}}}",
+            "{{{{if hello}}}}{{#if nice}}{{/if}}{{{{/if}}}}",
+        ];
+        for i in s.iter() {
+            assert_rule!(Rule::raw_block, i);
+        }
     }
-}
 
-#[test]
-fn test_raw_block() {
-    let s = vec![
-        "{{{{if hello}}}}good {{hello}}{{{{/if}}}}",
-        "{{{{if hello}}}}{{#if nice}}{{/if}}{{{{/if}}}}",
-    ];
-    for i in s.iter() {
-        assert_rule!(Rule::raw_block, i);
+    #[test]
+    fn test_block_param() {
+        let s = vec!["as |person|", "as |val key|"];
+        for i in s.iter() {
+            assert_rule!(Rule::block_param, i);
+        }
     }
-}
 
-#[test]
-fn test_block_param() {
-    let s = vec!["as |person|", "as |key val|"];
-    for i in s.iter() {
-        assert_rule!(Rule::block_param, i);
+    #[test]
+    fn test_path() {
+        let s = vec![
+            "a",
+            "a.b.c.d",
+            "a.[0].[1].[2]",
+            "a.[abc]",
+            "a/v/c.d.s",
+            "a.[0]/b/c/d",
+            "a.[bb c]/b/c/d",
+            "a.[0].[#hello]",
+            "../a/b.[0].[1]",
+            "this.[0]/[1]/this/a",
+            "./this_name",
+            "./goo/[/bar]",
+            "a.[你好]",
+            "a.[10].[#comment]",
+            "a.[]", // empty key
+            "./[/foo]",
+            "[foo]",
+            "@root/a/b",
+            "nullable",
+        ];
+        for i in s.iter() {
+            assert_rule_match!(Rule::path, i);
+        }
     }
-}
 
-#[test]
-fn test_path() {
-    let s = vec![
-        "a",
-        "a.b.c.d",
-        "a.[0].[1].[2]",
-        "a.[abc]",
-        "a/v/c.d.s",
-        "a.[0]/b/c/../d",
-        "a.[bb c]/b/c/../d",
-        "a.[0].[#hello]",
-        "../a/b.[0].[1]",
-        "./this.[0]/[1]/this/../a",
-        "./this_name",
-        "./goo/[/bar]",
-        "a.[你好]",
-        "a.[10].[#comment]",
-        "a.[]", // empty key
-        "././[/foo]",
-        "[foo]",
-    ];
-    for i in s.iter() {
-        assert_rule_match!(Rule::path, i);
+    #[test]
+    fn test_decorator_expression() {
+        let s = vec!["{{* ssh}}", "{{~* ssh}}"];
+        for i in s.iter() {
+            assert_rule!(Rule::decorator_expression, i);
+        }
     }
-}
 
-#[test]
-fn test_directive_expression() {
-    let s = vec!["{{* ssh}}", "{{~* ssh}}"];
-    for i in s.iter() {
-        assert_rule!(Rule::directive_expression, i);
+    #[test]
+    fn test_decorator_block() {
+        let s = vec![
+            "{{#* inline}}something{{/inline}}",
+            "{{~#* inline}}hello{{/inline}}",
+            "{{#* inline \"partialname\"}}something{{/inline}}",
+        ];
+        for i in s.iter() {
+            assert_rule!(Rule::decorator_block, i);
+        }
     }
-}
 
-#[test]
-fn test_directive_block() {
-    let s = vec![
-        "{{#* inline}}something{{/inline}}",
-        "{{~#* inline}}hello{{/inline}}",
-        "{{#* inline \"partialname\"}}something{{/inline}}",
-    ];
-    for i in s.iter() {
-        assert_rule!(Rule::directive_block, i);
+    #[test]
+    fn test_partial_expression() {
+        let s = vec![
+            "{{> hello}}",
+            "{{> (hello)}}",
+            "{{~> hello a}}",
+            "{{> hello a=1}}",
+            "{{> (hello) a=1}}",
+            "{{> hello.world}}",
+            "{{> [a83?f4+.3]}}",
+            "{{> 'anif?.bar'}}",
+        ];
+        for i in s.iter() {
+            assert_rule!(Rule::partial_expression, i);
+        }
     }
-}
 
-#[test]
-fn test_partial_expression() {
-    let s = vec![
-        "{{> hello}}",
-        "{{> (hello)}}",
-        "{{~> hello a}}",
-        "{{> hello a=1}}",
-    ];
-    for i in s.iter() {
-        assert_rule!(Rule::partial_expression, i);
-    }
-}
-
-#[test]
-fn test_partial_block() {
-    let s = vec!["{{#> hello}}nice{{/hello}}"];
-    for i in s.iter() {
-        assert_rule!(Rule::partial_block, i);
+    #[test]
+    fn test_partial_block() {
+        let s = vec!["{{#> hello}}nice{{/hello}}"];
+        for i in s.iter() {
+            assert_rule!(Rule::partial_block, i);
+        }
     }
 }
diff --git a/third_party/rust_crates/vendor/handlebars/src/helpers/block_util.rs b/third_party/rust_crates/vendor/handlebars/src/helpers/block_util.rs
new file mode 100644
index 0000000..b1ac70d
--- /dev/null
+++ b/third_party/rust_crates/vendor/handlebars/src/helpers/block_util.rs
@@ -0,0 +1,18 @@
+use crate::block::BlockContext;
+use crate::error::RenderError;
+use crate::json::value::PathAndJson;
+
+pub(crate) fn create_block<'reg: 'rc, 'rc>(
+    param: &'rc PathAndJson<'reg, 'rc>,
+) -> Result<BlockContext<'reg>, RenderError> {
+    let mut block = BlockContext::new();
+
+    if let Some(new_path) = param.context_path() {
+        *block.base_path_mut() = new_path.clone();
+    } else {
+        // use clone for now
+        block.set_base_value(param.value().clone());
+    }
+
+    Ok(block)
+}
diff --git a/third_party/rust_crates/vendor/handlebars/src/helpers/helper_boolean.rs b/third_party/rust_crates/vendor/handlebars/src/helpers/helper_boolean.rs
index 53f30ef..c58f9fb 100644
--- a/third_party/rust_crates/vendor/handlebars/src/helpers/helper_boolean.rs
+++ b/third_party/rust_crates/vendor/handlebars/src/helpers/helper_boolean.rs
@@ -1,14 +1,16 @@
 //! Helpers for boolean operations
 
-handlebars_helper!(eq: |x: i64, y: i64| x == y);
-handlebars_helper!(ne: |x: i64, y: i64| x != y);
+use crate::json::value::JsonTruthy;
+
+handlebars_helper!(eq: |x: Json, y: Json| x == y);
+handlebars_helper!(ne: |x: Json, y: Json| x != y);
 handlebars_helper!(gt: |x: i64, y: i64| x > y);
 handlebars_helper!(gte: |x: i64, y: i64| x >= y);
 handlebars_helper!(lt: |x: i64, y: i64| x < y);
 handlebars_helper!(lte: |x: i64, y: i64| x <= y);
-handlebars_helper!(and: |x: bool, y: bool| x && y);
-handlebars_helper!(or: |x: bool, y: bool| x || y);
-handlebars_helper!(not: |x: bool| !x);
+handlebars_helper!(and: |x: Json, y: Json| x.is_truthy(false) && y.is_truthy(false));
+handlebars_helper!(or: |x: Json, y: Json| x.is_truthy(false) || y.is_truthy(false));
+handlebars_helper!(not: |x: Json| !x.is_truthy(false));
 
 #[cfg(test)]
 mod test_conditions {
@@ -32,10 +34,28 @@
         test_condition("(gt 5 3)", true);
         test_condition("(gt 3 5)", false);
         test_condition("(or (gt 3 5) (gt 5 3))", true);
+        test_condition("(not [])", true);
+        test_condition("(and null 4)", false);
+    }
+
+    #[test]
+    fn test_eq() {
         test_condition("(eq 5 5)", true);
         test_condition("(eq 5 6)", false);
+        test_condition(r#"(eq "foo" "foo")"#, true);
+        test_condition(r#"(eq "foo" "Foo")"#, false);
+        test_condition(r#"(eq [5] [5])"#, true);
+        test_condition(r#"(eq [5] [4])"#, false);
+        test_condition(r#"(eq 5 "5")"#, false);
+        test_condition(r#"(eq 5 [5])"#, false);
+    }
+
+    #[test]
+    fn test_ne() {
         test_condition("(ne 5 6)", true);
         test_condition("(ne 5 5)", false);
+        test_condition(r#"(ne "foo" "foo")"#, false);
+        test_condition(r#"(ne "foo" "Foo")"#, true);
     }
 
     #[test]
@@ -55,5 +75,4 @@
             .unwrap();
         assert_eq!(&result, "ipsum");
     }
-
 }
diff --git a/third_party/rust_crates/vendor/handlebars/src/helpers/helper_each.rs b/third_party/rust_crates/vendor/handlebars/src/helpers/helper_each.rs
index 09feeba..48d7b15 100644
--- a/third_party/rust_crates/vendor/handlebars/src/helpers/helper_each.rs
+++ b/third_party/rust_crates/vendor/handlebars/src/helpers/helper_each.rs
@@ -1,13 +1,64 @@
-use hashbrown::HashMap;
 use serde_json::value::Value as Json;
 
+use super::block_util::create_block;
+use crate::block::{BlockContext, BlockParams};
 use crate::context::Context;
 use crate::error::RenderError;
 use crate::helpers::{HelperDef, HelperResult};
+use crate::json::value::to_json;
 use crate::output::Output;
 use crate::registry::Registry;
 use crate::render::{Helper, RenderContext, Renderable};
-use crate::value::{to_json, JsonTruthy};
+use crate::util::copy_on_push_vec;
+
+fn update_block_context<'reg>(
+    block: &mut BlockContext<'reg>,
+    base_path: Option<&Vec<String>>,
+    relative_path: String,
+    is_first: bool,
+    value: &Json,
+) {
+    if let Some(ref p) = base_path {
+        if is_first {
+            *block.base_path_mut() = copy_on_push_vec(p, relative_path);
+        } else if let Some(ptr) = block.base_path_mut().last_mut() {
+            *ptr = relative_path;
+        }
+    } else {
+        block.set_base_value(value.clone());
+    }
+}
+
+fn set_block_param<'reg: 'rc, 'rc>(
+    block: &mut BlockContext<'reg>,
+    h: &Helper<'reg, 'rc>,
+    base_path: Option<&Vec<String>>,
+    k: &Json,
+    v: &Json,
+) -> Result<(), RenderError> {
+    if let Some(bp_val) = h.block_param() {
+        let mut params = BlockParams::new();
+        if base_path.is_some() {
+            params.add_path(bp_val, Vec::with_capacity(0))?;
+        } else {
+            params.add_value(bp_val, v.clone())?;
+        }
+
+        block.set_block_params(params);
+    } else if let Some((bp_val, bp_key)) = h.block_param_pair() {
+        let mut params = BlockParams::new();
+        if base_path.is_some() {
+            params.add_path(bp_val, Vec::with_capacity(0))?;
+        } else {
+            params.add_value(bp_val, v.clone())?;
+        }
+        params.add_value(bp_key, k.clone())?;
+
+        block.set_block_params(params);
+    }
+
+    Ok(())
+}
 
 #[derive(Clone, Copy)]
 pub struct EachHelper;
@@ -16,10 +67,10 @@
     fn call<'reg: 'rc, 'rc>(
         &self,
         h: &Helper<'reg, 'rc>,
-        r: &'reg Registry,
-        ctx: &Context,
-        rc: &mut RenderContext<'reg>,
-        out: &mut Output,
+        r: &'reg Registry<'reg>,
+        ctx: &'rc Context,
+        rc: &mut RenderContext<'reg, 'rc>,
+        out: &mut dyn Output,
     ) -> HelperResult {
         let value = h
             .param(0)
@@ -28,107 +79,70 @@
         let template = h.template();
 
         match template {
-            Some(t) => {
-                rc.promote_local_vars();
-                let local_path_root = value
-                    .path_root()
-                    .map(|p| format!("{}/{}", rc.get_path(), p));
+            Some(t) => match *value.value() {
+                Json::Array(ref list) if !list.is_empty() => {
+                    let block_context = create_block(&value)?;
+                    rc.push_block(block_context);
 
-                debug!("each value {:?}", value.value());
-                let rendered = match (value.value().is_truthy(false), value.value()) {
-                    (true, &Json::Array(ref list)) => {
-                        let len = list.len();
-                        for (i, _) in list.iter().enumerate().take(len) {
-                            let mut local_rc = rc.derive();
-                            if let Some(ref p) = local_path_root {
-                                local_rc.push_local_path_root(p.clone());
-                            }
+                    let len = list.len();
 
-                            local_rc.set_local_var("@first".to_string(), to_json(i == 0usize));
-                            local_rc.set_local_var("@last".to_string(), to_json(i == len - 1));
-                            local_rc.set_local_var("@index".to_string(), to_json(i));
+                    let array_path = value.context_path();
 
-                            if let Some(inner_path) = value.path() {
-                                let new_path =
-                                    format!("{}/{}/[{}]", local_rc.get_path(), inner_path, i);
-                                debug!("each path {:?}", new_path);
-                                local_rc.set_path(new_path);
-                            }
+                    for (i, v) in list.iter().enumerate().take(len) {
+                        if let Some(ref mut block) = rc.block_mut() {
+                            let is_first = i == 0usize;
+                            let is_last = i == len - 1;
 
-                            if let Some(block_param) = h.block_param() {
-                                let mut map = HashMap::new();
-                                map.insert(block_param.to_string(), to_json(&list[i]));
-                                local_rc.push_block_context(&map)?;
-                            }
+                            let index = to_json(i);
+                            block.set_local_var("@first".to_string(), to_json(is_first));
+                            block.set_local_var("@last".to_string(), to_json(is_last));
+                            block.set_local_var("@index".to_string(), index.clone());
 
-                            t.render(r, ctx, &mut local_rc, out)?;
-
-                            if h.block_param().is_some() {
-                                local_rc.pop_block_context();
-                            }
-
-                            if local_path_root.is_some() {
-                                local_rc.pop_local_path_root();
-                            }
-                        }
-                        Ok(())
-                    }
-                    (true, &Json::Object(ref obj)) => {
-                        let mut first: bool = true;
-                        for (k, v) in obj.iter() {
-                            let mut local_rc = rc.derive();
-
-                            if let Some(ref p) = local_path_root {
-                                local_rc.push_local_path_root(p.clone());
-                            }
-                            local_rc.set_local_var("@first".to_string(), to_json(first));
-                            if first {
-                                first = false;
-                            }
-
-                            local_rc.set_local_var("@key".to_string(), to_json(k));
-
-                            if let Some(inner_path) = value.path() {
-                                let new_path =
-                                    format!("{}/{}/[{}]", local_rc.get_path(), inner_path, k);
-                                local_rc.set_path(new_path);
-                            }
-
-                            if let Some((bp_key, bp_val)) = h.block_param_pair() {
-                                let mut map = HashMap::new();
-                                map.insert(bp_key.to_string(), to_json(k));
-                                map.insert(bp_val.to_string(), to_json(v));
-                                local_rc.push_block_context(&map)?;
-                            }
-
-                            t.render(r, ctx, &mut local_rc, out)?;
-
-                            if h.block_param().is_some() {
-                                local_rc.pop_block_context();
-                            }
-
-                            if local_path_root.is_some() {
-                                local_rc.pop_local_path_root();
-                            }
+                            update_block_context(block, array_path, i.to_string(), is_first, &v);
+                            set_block_param(block, h, array_path, &index, &v)?;
                         }
 
-                        Ok(())
+                        t.render(r, ctx, rc, out)?;
                     }
-                    (false, _) => {
-                        if let Some(else_template) = h.inverse() {
-                            else_template.render(r, ctx, rc, out)?;
-                        }
-                        Ok(())
-                    }
-                    _ => Err(RenderError::new(format!(
-                        "Param type is not iterable: {:?}",
-                        value.value()
-                    ))),
-                };
 
-                rc.demote_local_vars();
-                rendered
-            }
+                    rc.pop_block();
+                    Ok(())
+                }
+                Json::Object(ref obj) if !obj.is_empty() => {
+                    let block_context = create_block(&value)?;
+                    rc.push_block(block_context);
+
+                    let mut is_first = true;
+                    let obj_path = value.context_path();
+
+                    for (k, v) in obj.iter() {
+                        if let Some(ref mut block) = rc.block_mut() {
+                            let key = to_json(k);
+
+                            block.set_local_var("@first".to_string(), to_json(is_first));
+                            block.set_local_var("@key".to_string(), key.clone());
+
+                            update_block_context(block, obj_path, k.to_string(), is_first, &v);
+                            set_block_param(block, h, obj_path, &key, &v)?;
+                        }
+
+                        t.render(r, ctx, rc, out)?;
+
+                        if is_first {
+                            is_first = false;
+                        }
+                    }
+
+                    rc.pop_block();
+                    Ok(())
+                }
+                _ => {
+                    if let Some(else_template) = h.inverse() {
+                        else_template.render(r, ctx, rc, out)?;
+                    }
+                    Ok(())
+                }
+            },
             None => Ok(()),
         }
     }
@@ -138,9 +152,8 @@
 
 #[cfg(test)]
 mod test {
+    use crate::json::value::to_json;
     use crate::registry::Registry;
-    use crate::value::to_json;
-
     use serde_json::value::Value as Json;
     use std::collections::BTreeMap;
     use std::str::FromStr;
@@ -247,19 +260,13 @@
         let r0 = handlebars
             .render(
                 "t0",
-                &({
-                    let mut rv = BTreeMap::new();
-                    rv.insert("foo".to_owned(), {
-                        let mut rv = BTreeMap::new();
-                        rv.insert("value".to_owned(), "bar".to_owned());
-                        rv
-                    });
-                    rv.insert("".to_owned(), {
-                        let mut rv = BTreeMap::new();
-                        rv.insert("value".to_owned(), "baz".to_owned());
-                        rv
-                    });
-                    rv
+                &json!({
+                    "foo": {
+                        "value": "bar"
+                    },
+                    "": {
+                        "value": "baz"
+                    }
                 }),
             )
             .unwrap();
@@ -305,7 +312,7 @@
     #[test]
     fn test_each_object_block_param() {
         let mut handlebars = Registry::new();
-        let template = "{{#each this as |k v|}}\
+        let template = "{{#each this as |v k|}}\
                         {{#with k as |inner_k|}}{{inner_k}}{{/with}}:{{v}}|\
                         {{/each}}";
         assert!(handlebars.register_template_string("t0", template).is_ok());
@@ -319,6 +326,22 @@
     }
 
     #[test]
+    fn test_each_object_block_param2() {
+        let mut handlebars = Registry::new();
+        let template = "{{#each this as |v k|}}\
+                        {{#with v as |inner_v|}}{{k}}:{{inner_v}}{{/with}}|\
+                        {{/each}}";
+
+        assert!(handlebars.register_template_string("t0", template).is_ok());
+
+        let m = btreemap! {
+            "ftp".to_string() => 21,
+            "http".to_string() => 80
+        };
+        let r0 = handlebars.render("t0", &m);
+        assert_eq!(r0.ok().unwrap(), "ftp:21|http:80|".to_string());
+    }
+
     fn test_nested_each_with_path_ups() {
         let mut handlebars = Registry::new();
         assert!(handlebars
@@ -374,4 +397,131 @@
         assert!(r0.contains("😂: 4"));
         assert!(r0.contains("me.dot.key: 5"));
     }
+
+    #[test]
+    fn test_base_path_after_each() {
+        let mut handlebars = Registry::new();
+        assert!(handlebars
+            .register_template_string("t0", "{{#each a}}{{this}}{{/each}} {{b}}")
+            .is_ok());
+        let data = json!({
+            "a": [1, 2, 3, 4],
+            "b": "good",
+        });
+
+        let r0 = handlebars.render("t0", &data).ok().unwrap();
+
+        assert_eq!("1234 good", r0);
+    }
+
+    #[test]
+    fn test_else_context() {
+        let reg = Registry::new();
+        let template = "{{#each list}}A{{else}}{{foo}}{{/each}}";
+        let input = json!({"list": [], "foo": "bar"});
+        let rendered = reg.render_template(template, &input).unwrap();
+        assert_eq!("bar", rendered);
+    }
+
+    #[test]
+    fn test_block_context_leak() {
+        let reg = Registry::new();
+        let template = "{{#each list}}{{#each inner}}{{this}}{{/each}}{{foo}}{{/each}}";
+        let input = json!({"list": [{"inner": [], "foo": 1}, {"inner": [], "foo": 2}]});
+        let rendered = reg.render_template(template, &input).unwrap();
+        assert_eq!("12", rendered);
+    }
+
+    #[test]
+    fn test_derived_array_as_block_params() {
+        handlebars_helper!(range: |x: u64| (0..x).collect::<Vec<u64>>());
+        let mut reg = Registry::new();
+        reg.register_helper("range", Box::new(range));
+        let template = "{{#each (range 3) as |i|}}{{i}}{{/each}}";
+        let input = json!(0);
+        let rendered = reg.render_template(template, &input).unwrap();
+        assert_eq!("012", rendered);
+    }
+
+    #[test]
+    fn test_derived_object_as_block_params() {
+        handlebars_helper!(point: |x: u64, y: u64| json!({"x":x, "y":y}));
+        let mut reg = Registry::new();
+        reg.register_helper("point", Box::new(point));
+        let template = "{{#each (point 0 1) as |i|}}{{i}}{{/each}}";
+        let input = json!(0);
+        let rendered = reg.render_template(template, &input).unwrap();
+        assert_eq!("01", rendered);
+    }
+
+    #[test]
+    fn test_derived_array_without_block_param() {
+        handlebars_helper!(range: |x: u64| (0..x).collect::<Vec<u64>>());
+        let mut reg = Registry::new();
+        reg.register_helper("range", Box::new(range));
+        let template = "{{#each (range 3)}}{{this}}{{/each}}";
+        let input = json!(0);
+        let rendered = reg.render_template(template, &input).unwrap();
+        assert_eq!("012", rendered);
+    }
+
+    #[test]
+    fn test_derived_object_without_block_params() {
+        handlebars_helper!(point: |x: u64, y: u64| json!({"x":x, "y":y}));
+        let mut reg = Registry::new();
+        reg.register_helper("point", Box::new(point));
+        let template = "{{#each (point 0 1)}}{{this}}{{/each}}";
+        let input = json!(0);
+        let rendered = reg.render_template(template, &input).unwrap();
+        assert_eq!("01", rendered);
+    }
+
+    #[test]
+    fn test_non_iterable() {
+        let reg = Registry::new();
+        let template = "{{#each this}}each block{{else}}else block{{/each}}";
+        let input = json!("strings aren't iterable");
+        let rendered = reg.render_template(template, &input).unwrap();
+        assert_eq!("else block", rendered);
+    }
+
+    #[test]
+    fn test_recursion() {
+        let mut reg = Registry::new();
+        assert!(reg
+            .register_template_string(
+                "walk",
+                "(\
+                    {{#each this}}\
+                        {{#if @key}}{{@key}}{{else}}{{@index}}{{/if}}: \
+                        {{this}} \
+                        {{> walk this}}, \
+                    {{/each}}\
+                )",
+            )
+            .is_ok());
+
+        let input = json!({
+            "array": [42, {"wow": "cool"}, [[]]],
+            "object": { "a": { "b": "c", "d": ["e"] } },
+            "string": "hi"
+        });
+        let expected_output = "(\
+            array: [42, [object], [[], ], ] (\
+                0: 42 (), \
+                1: [object] (wow: cool (), ), \
+                2: [[], ] (0: [] (), ), \
+            ), \
+            object: [object] (\
+                a: [object] (\
+                    b: c (), \
+                    d: [e, ] (0: e (), ), \
+                ), \
+            ), \
+            string: hi (), \
+        )";
+
+        let rendered = reg.render("walk", &input).unwrap();
+        assert_eq!(expected_output, rendered);
+    }
 }
diff --git a/third_party/rust_crates/vendor/handlebars/src/helpers/helper_if.rs b/third_party/rust_crates/vendor/handlebars/src/helpers/helper_if.rs
index 10f6656..3f8f040 100644
--- a/third_party/rust_crates/vendor/handlebars/src/helpers/helper_if.rs
+++ b/third_party/rust_crates/vendor/handlebars/src/helpers/helper_if.rs
@@ -1,10 +1,10 @@
 use crate::context::Context;
 use crate::error::RenderError;
 use crate::helpers::{HelperDef, HelperResult};
+use crate::json::value::JsonTruthy;
 use crate::output::Output;
 use crate::registry::Registry;
 use crate::render::{Helper, RenderContext, Renderable};
-use crate::value::JsonTruthy;
 
 #[derive(Clone, Copy)]
 pub struct IfHelper {
@@ -15,10 +15,10 @@
     fn call<'reg: 'rc, 'rc>(
         &self,
         h: &Helper<'reg, 'rc>,
-        r: &'reg Registry,
-        ctx: &Context,
-        rc: &mut RenderContext<'reg>,
-        out: &mut Output,
+        r: &'reg Registry<'reg>,
+        ctx: &'rc Context,
+        rc: &mut RenderContext<'reg, 'rc>,
+        out: &mut dyn Output,
     ) -> HelperResult {
         let param = h
             .param(0)
@@ -90,10 +90,10 @@
             .is_ok());
 
         let r0 = handlebars.render("t0", &data);
-        assert_eq!(r0.ok().unwrap(), "hello 99".to_string());
+        assert_eq!(r0.unwrap(), "hello 99".to_string());
 
         let r1 = handlebars.render("t1", &data);
-        assert_eq!(r1.ok().unwrap(), "hello 99".to_string());
+        assert_eq!(r1.unwrap(), "hello 99".to_string());
     }
 
     #[test]
diff --git a/third_party/rust_crates/vendor/handlebars/src/helpers/helper_log.rs b/third_party/rust_crates/vendor/handlebars/src/helpers/helper_log.rs
index e173a82..5821efa 100644
--- a/third_party/rust_crates/vendor/handlebars/src/helpers/helper_log.rs
+++ b/third_party/rust_crates/vendor/handlebars/src/helpers/helper_log.rs
@@ -2,12 +2,12 @@
 #[cfg(not(feature = "no_logging"))]
 use crate::error::RenderError;
 use crate::helpers::{HelperDef, HelperResult};
+#[cfg(not(feature = "no_logging"))]
+use crate::json::value::JsonRender;
 use crate::output::Output;
 use crate::registry::Registry;
 use crate::render::{Helper, RenderContext};
 #[cfg(not(feature = "no_logging"))]
-use crate::value::JsonRender;
-#[cfg(not(feature = "no_logging"))]
 use log::Level;
 #[cfg(not(feature = "no_logging"))]
 use std::str::FromStr;
@@ -19,27 +19,32 @@
 impl HelperDef for LogHelper {
     fn call<'reg: 'rc, 'rc>(
         &self,
-        h: &Helper,
-        _: &Registry,
-        _: &Context,
-        _: &mut RenderContext,
-        _: &mut Output,
+        h: &Helper<'reg, 'rc>,
+        _: &'reg Registry<'reg>,
+        _: &'rc Context,
+        _: &mut RenderContext<'reg, 'rc>,
+        _: &mut dyn Output,
     ) -> HelperResult {
-        let param = h
-            .param(0)
-            .ok_or_else(|| RenderError::new("Param not found for helper \"log\""))?;
+        let param_to_log = h
+            .params()
+            .iter()
+            .map(|p| {
+                if let Some(ref relative_path) = p.relative_path() {
+                    format!("{}: {}", relative_path, p.value().render())
+                } else {
+                    p.value().render()
+                }
+            })
+            .collect::<Vec<String>>()
+            .join(", ");
+
         let level = h
             .hash_get("level")
             .and_then(|v| v.value().as_str())
             .unwrap_or("info");
 
         if let Ok(log_level) = Level::from_str(level) {
-            log!(
-                log_level,
-                "{}: {}",
-                param.path().unwrap_or(&"".to_owned()),
-                param.value().render()
-            )
+            log!(log_level, "{}", param_to_log)
         } else {
             return Err(RenderError::new(&format!(
                 "Unsupported logging level {}",
@@ -54,11 +59,11 @@
 impl HelperDef for LogHelper {
     fn call<'reg: 'rc, 'rc>(
         &self,
-        _: &Helper,
-        _: &Registry,
+        _: &Helper<'reg, 'rc>,
+        _: &Registry<'reg>,
         _: &Context,
-        _: &mut RenderContext,
-        _: &mut Output,
+        _: &mut RenderContext<'reg, 'rc>,
+        _: &mut dyn Output,
     ) -> HelperResult {
         Ok(())
     }
diff --git a/third_party/rust_crates/vendor/handlebars/src/helpers/helper_lookup.rs b/third_party/rust_crates/vendor/handlebars/src/helpers/helper_lookup.rs
index ed10d25..87f9c5a 100644
--- a/third_party/rust_crates/vendor/handlebars/src/helpers/helper_lookup.rs
+++ b/third_party/rust_crates/vendor/handlebars/src/helpers/helper_lookup.rs
@@ -2,24 +2,22 @@
 
 use crate::context::Context;
 use crate::error::RenderError;
-use crate::helpers::{HelperDef, HelperResult};
-use crate::output::Output;
+use crate::helpers::HelperDef;
+use crate::json::value::ScopedJson;
 use crate::registry::Registry;
 use crate::render::{Helper, RenderContext};
-use crate::value::JsonRender;
 
 #[derive(Clone, Copy)]
 pub struct LookupHelper;
 
 impl HelperDef for LookupHelper {
-    fn call<'reg: 'rc, 'rc>(
+    fn call_inner<'reg: 'rc, 'rc>(
         &self,
-        h: &Helper,
-        _: &Registry,
-        _: &Context,
-        _: &mut RenderContext,
-        out: &mut Output,
-    ) -> HelperResult {
+        h: &Helper<'reg, 'rc>,
+        _: &'reg Registry<'reg>,
+        _: &'rc Context,
+        _: &mut RenderContext<'reg, 'rc>,
+    ) -> Result<Option<ScopedJson<'reg, 'rc>>, RenderError> {
         let collection_value = h
             .param(0)
             .ok_or_else(|| RenderError::new("Param not found for helper \"lookup\""))?;
@@ -27,24 +25,20 @@
             .param(1)
             .ok_or_else(|| RenderError::new("Insufficient params for helper \"lookup\""))?;
 
-        let null = Json::Null;
         let value = match *collection_value.value() {
             Json::Array(ref v) => index
                 .value()
                 .as_u64()
-                .and_then(|u| Some(u as usize))
-                .and_then(|u| v.get(u))
-                .unwrap_or(&null),
+                .and_then(|u| v.get(u as usize))
+                .map(|i| ScopedJson::Derived(i.clone())),
             Json::Object(ref m) => index
                 .value()
                 .as_str()
                 .and_then(|k| m.get(k))
-                .unwrap_or(&null),
-            _ => &null,
+                .map(|i| ScopedJson::Derived(i.clone())),
+            _ => None,
         };
-        let r = value.render();
-        out.write(r.as_ref())?;
-        Ok(())
+        Ok(value)
     }
 }
 
@@ -60,10 +54,10 @@
     fn test_lookup() {
         let mut handlebars = Registry::new();
         assert!(handlebars
-            .register_template_string("t0", "{{#each v1}}{{lookup ../../v2 @index}}{{/each}}")
+            .register_template_string("t0", "{{#each v1}}{{lookup ../v2 @index}}{{/each}}")
             .is_ok());
         assert!(handlebars
-            .register_template_string("t1", "{{#each v1}}{{lookup ../../v2 1}}{{/each}}")
+            .register_template_string("t1", "{{#each v1}}{{lookup ../v2 1}}{{/each}}")
             .is_ok());
         assert!(handlebars
             .register_template_string("t2", "{{lookup kk \"a\"}}")
diff --git a/third_party/rust_crates/vendor/handlebars/src/helpers/helper_raw.rs b/third_party/rust_crates/vendor/handlebars/src/helpers/helper_raw.rs
index f0997aa..55aef6b 100644
--- a/third_party/rust_crates/vendor/handlebars/src/helpers/helper_raw.rs
+++ b/third_party/rust_crates/vendor/handlebars/src/helpers/helper_raw.rs
@@ -11,10 +11,10 @@
     fn call<'reg: 'rc, 'rc>(
         &self,
         h: &Helper<'reg, 'rc>,
-        r: &'reg Registry,
-        ctx: &Context,
-        rc: &mut RenderContext<'reg>,
-        out: &mut Output,
+        r: &'reg Registry<'reg>,
+        ctx: &'rc Context,
+        rc: &mut RenderContext<'reg, 'rc>,
+        out: &mut dyn Output,
     ) -> HelperResult {
         let tpl = h.template();
         if let Some(t) = tpl {
diff --git a/third_party/rust_crates/vendor/handlebars/src/helpers/helper_with.rs b/third_party/rust_crates/vendor/handlebars/src/helpers/helper_with.rs
index c24a500..4b68b78 100644
--- a/third_party/rust_crates/vendor/handlebars/src/helpers/helper_with.rs
+++ b/third_party/rust_crates/vendor/handlebars/src/helpers/helper_with.rs
@@ -1,12 +1,12 @@
-use hashbrown::HashMap;
-
+use super::block_util::create_block;
+use crate::block::BlockParams;
 use crate::context::Context;
 use crate::error::RenderError;
 use crate::helpers::{HelperDef, HelperResult};
+use crate::json::value::JsonTruthy;
 use crate::output::Output;
 use crate::registry::Registry;
 use crate::render::{Helper, RenderContext, Renderable};
-use crate::value::{to_json, JsonTruthy};
 
 #[derive(Clone, Copy)]
 pub struct WithHelper;
@@ -14,58 +14,44 @@
 impl HelperDef for WithHelper {
     fn call<'reg: 'rc, 'rc>(
         &self,
-        h: &Helper,
-        r: &Registry,
-        ctx: &Context,
-        rc: &mut RenderContext,
-        out: &mut Output,
+        h: &Helper<'reg, 'rc>,
+        r: &'reg Registry<'reg>,
+        ctx: &'rc Context,
+        rc: &mut RenderContext<'reg, 'rc>,
+        out: &mut dyn Output,
     ) -> HelperResult {
         let param = h
             .param(0)
             .ok_or_else(|| RenderError::new("Param not found for helper \"with\""))?;
 
-        rc.promote_local_vars();
+        let not_empty = param.value().is_truthy(false);
+        let template = if not_empty { h.template() } else { h.inverse() };
 
-        let result = {
-            let mut local_rc = rc.derive();
+        if not_empty {
+            let mut block = create_block(&param)?;
 
-            let not_empty = param.value().is_truthy(false);
-            let template = if not_empty { h.template() } else { h.inverse() };
-
-            if let Some(path_root) = param.path_root() {
-                let local_path_root = format!("{}/{}", local_rc.get_path(), path_root);
-                local_rc.push_local_path_root(local_path_root);
-            }
-            if not_empty {
-                if let Some(inner_path) = param.path() {
-                    let new_path = format!("{}/{}", local_rc.get_path(), inner_path);
-                    local_rc.set_path(new_path);
+            if let Some(block_param) = h.block_param() {
+                let mut params = BlockParams::new();
+                if param.context_path().is_some() {
+                    params.add_path(block_param, Vec::with_capacity(0))?;
+                } else {
+                    params.add_value(block_param, param.value().clone())?;
                 }
 
-                if let Some(block_param) = h.block_param() {
-                    let mut map = HashMap::new();
-                    map.insert(block_param.to_string(), to_json(param.value()));
-                    local_rc.push_block_context(&map)?;
-                }
+                block.set_block_params(params);
             }
 
-            let result = match template {
-                Some(t) => t.render(r, ctx, &mut local_rc, out),
-                None => Ok(()),
-            };
+            rc.push_block(block);
+        }
 
-            if h.block_param().is_some() {
-                local_rc.pop_block_context();
-            }
-
-            if param.path_root().is_some() {
-                local_rc.pop_local_path_root();
-            }
-
-            result
+        let result = match template {
+            Some(t) => t.render(r, ctx, rc, out),
+            None => Ok(()),
         };
 
-        rc.demote_local_vars();
+        if not_empty {
+            rc.pop_block();
+        }
         result
     }
 }
@@ -74,8 +60,8 @@
 
 #[cfg(test)]
 mod test {
+    use crate::json::value::to_json;
     use crate::registry::Registry;
-    use crate::value::to_json;
 
     #[derive(Serialize)]
     struct Address {
@@ -235,4 +221,29 @@
         let r0 = handlebars.render("t0", &data);
         assert_eq!(r0.ok().unwrap(), "1".to_string());
     }
+
+    #[test]
+    fn test_else_context() {
+        let reg = Registry::new();
+        let template = "{{#with list}}A{{else}}{{foo}}{{/with}}";
+        let input = json!({"list": [], "foo": "bar"});
+        let rendered = reg.render_template(template, &input).unwrap();
+        assert_eq!("bar", rendered);
+    }
+
+    #[test]
+    fn test_derived_value() {
+        let hb = Registry::new();
+        let data = json!({"a": {"b": {"c": "d"}}});
+        let template = "{{#with (lookup a.b \"c\")}}{{this}}{{/with}}";
+        assert_eq!("d", hb.render_template(template, &data).unwrap());
+    }
+
+    #[test]
+    fn test_nested_derived_value() {
+        let hb = Registry::new();
+        let data = json!({"a": {"b": {"c": "d"}}});
+        let template = "{{#with (lookup a \"b\")}}{{#with this}}{{c}}{{/with}}{{/with}}";
+        assert_eq!("d", hb.render_template(template, &data).unwrap());
+    }
 }
diff --git a/third_party/rust_crates/vendor/handlebars/src/helpers/mod.rs b/third_party/rust_crates/vendor/handlebars/src/helpers/mod.rs
index 4ad921b..8d1c2d7 100644
--- a/third_party/rust_crates/vendor/handlebars/src/helpers/mod.rs
+++ b/third_party/rust_crates/vendor/handlebars/src/helpers/mod.rs
@@ -1,9 +1,9 @@
 use crate::context::Context;
 use crate::error::RenderError;
+use crate::json::value::ScopedJson;
 use crate::output::Output;
 use crate::registry::Registry;
-use crate::render::{Helper, RenderContext};
-use crate::value::ScopedJson;
+use crate::render::{do_escape, Helper, RenderContext};
 
 pub use self::helper_each::EACH_HELPER;
 pub use self::helper_if::{IF_HELPER, UNLESS_HELPER};
@@ -12,26 +12,27 @@
 pub use self::helper_raw::RAW_HELPER;
 pub use self::helper_with::WITH_HELPER;
 
+/// A type alias for `Result<(), RenderError>`
 pub type HelperResult = Result<(), RenderError>;
 
 /// Helper Definition
 ///
-/// Implement `HelperDef` to create custom helper. You can retrieve useful information from these arguments.
+/// Implement `HelperDef` to create custom helpers. You can retrieve useful information from these arguments.
 ///
 /// * `&Helper`: current helper template information, contains name, params, hashes and nested template
 /// * `&Registry`: the global registry, you can find templates by name from registry
 /// * `&Context`: the whole data to render, in most case you can use data from `Helper`
 /// * `&mut RenderContext`: you can access data or modify variables (starts with @)/partials in render context, for example, @index of #each. See its document for detail.
-/// * `&mut Output`: where you write output to
+/// * `&mut dyn Output`: where you write output to
 ///
-/// By default, you can use bare function as helper definition because we have supported unboxed_closure. If you have stateful or configurable helper, you can create a struct to implement `HelperDef`.
+/// By default, you can use a bare function as a helper definition because we have supported unboxed_closure. If you have stateful or configurable helper, you can create a struct to implement `HelperDef`.
 ///
 /// ## Define an inline helper
 ///
 /// ```
 /// use handlebars::*;
 ///
-/// fn upper(h: &Helper, _: &Handlebars, _: &Context, rc: &mut RenderContext, out: &mut Output)
+/// fn upper(h: &Helper<'_, '_>, _: &Handlebars<'_>, _: &Context, rc: &mut RenderContext<'_, '_>, out: &mut Output)
 ///     -> HelperResult {
 ///    // get parameter from helper or throw an error
 ///    let param = h.param(0).and_then(|v| v.value().as_str()).unwrap_or("");
@@ -42,17 +43,17 @@
 ///
 /// ## Define block helper
 ///
-/// Block helper is like `#if` or `#each` which has a inner template and an optional *inverse* template (the template in else branch). You can access the inner template by `helper.template()` and `helper.inverse()`. In most case you will just call `render` on it.
+/// Block helper is like `#if` or `#each` which has a inner template and an optional *inverse* template (the template in else branch). You can access the inner template by `helper.template()` and `helper.inverse()`. In most cases you will just call `render` on it.
 ///
 /// ```
 /// use handlebars::*;
 ///
 /// fn dummy_block<'reg, 'rc>(
 ///     h: &Helper<'reg, 'rc>,
-///     r: &'reg Handlebars,
-///     ctx: &Context,
-///     rc: &mut RenderContext<'reg>,
-///     out: &mut Output,
+///     r: &'reg Handlebars<'reg>,
+///     ctx: &'rc Context,
+///     rc: &mut RenderContext<'reg, 'rc>,
+///     out: &mut dyn Output,
 /// ) -> HelperResult {
 ///     h.template()
 ///         .map(|t| t.render(r, ctx, rc, out))
@@ -62,7 +63,7 @@
 ///
 /// ## Define helper function using macro
 ///
-/// In most case you just need some simple function to call from template. We have  `handlebars_helper!` macro to simplify the job.
+/// In most cases you just need some simple function to call from templates. We have a `handlebars_helper!` macro to simplify the job.
 ///
 /// ```
 /// use handlebars::*;
@@ -74,13 +75,13 @@
 /// ```
 ///
 
-pub trait HelperDef: Send + Sync {
+pub trait HelperDef {
     fn call_inner<'reg: 'rc, 'rc>(
         &self,
         _: &Helper<'reg, 'rc>,
-        _: &'reg Registry,
+        _: &'reg Registry<'reg>,
         _: &'rc Context,
-        _: &mut RenderContext<'reg>,
+        _: &mut RenderContext<'reg, 'rc>,
     ) -> Result<Option<ScopedJson<'reg, 'rc>>, RenderError> {
         Ok(None)
     }
@@ -88,16 +89,18 @@
     fn call<'reg: 'rc, 'rc>(
         &self,
         h: &Helper<'reg, 'rc>,
-        r: &'reg Registry,
+        r: &'reg Registry<'reg>,
         ctx: &'rc Context,
-        rc: &mut RenderContext<'reg>,
-        out: &mut Output,
+        rc: &mut RenderContext<'reg, 'rc>,
+        out: &mut dyn Output,
     ) -> HelperResult {
         if let Some(result) = self.call_inner(h, r, ctx, rc)? {
             if r.strict_mode() && result.is_missing() {
                 return Err(RenderError::strict_error(None));
             } else {
-                out.write(result.render().as_ref())?;
+                // auto escape according to settings
+                let output = do_escape(r, rc, result.render());
+                out.write(output.as_ref())?;
             }
         }
 
@@ -107,29 +110,28 @@
 
 /// implement HelperDef for bare function so we can use function as helper
 impl<
-        F: Send
-            + Sync
-            + for<'reg, 'rc> Fn(
-                &Helper<'reg, 'rc>,
-                &'reg Registry,
-                &'rc Context,
-                &mut RenderContext<'reg>,
-                &mut Output,
-            ) -> HelperResult,
+        F: for<'reg, 'rc> Fn(
+            &Helper<'reg, 'rc>,
+            &'reg Registry<'reg>,
+            &'rc Context,
+            &mut RenderContext<'reg, 'rc>,
+            &mut dyn Output,
+        ) -> HelperResult,
     > HelperDef for F
 {
     fn call<'reg: 'rc, 'rc>(
         &self,
         h: &Helper<'reg, 'rc>,
-        r: &'reg Registry,
+        r: &'reg Registry<'reg>,
         ctx: &'rc Context,
-        rc: &mut RenderContext<'reg>,
-        out: &mut Output,
+        rc: &mut RenderContext<'reg, 'rc>,
+        out: &mut dyn Output,
     ) -> HelperResult {
         (*self)(h, r, ctx, rc, out)
     }
 }
 
+mod block_util;
 pub(crate) mod helper_boolean;
 mod helper_each;
 mod helper_if;
@@ -137,6 +139,8 @@
 mod helper_lookup;
 mod helper_raw;
 mod helper_with;
+#[cfg(feature = "script_helper")]
+pub(crate) mod scripting;
 
 // pub type HelperDef = for <'a, 'b, 'c> Fn<(&'a Context, &'b Helper, &'b Registry, &'c mut RenderContext), Result<String, RenderError>>;
 //
@@ -144,7 +148,6 @@
 // h.template().unwrap().render(ctx, r, rc).unwrap()
 // }
 //
-
 #[cfg(test)]
 mod test {
     use std::collections::BTreeMap;
@@ -152,10 +155,10 @@
     use crate::context::Context;
     use crate::error::RenderError;
     use crate::helpers::HelperDef;
+    use crate::json::value::JsonRender;
     use crate::output::Output;
     use crate::registry::Registry;
     use crate::render::{Helper, RenderContext, Renderable};
-    use crate::value::JsonRender;
 
     #[derive(Clone, Copy)]
     struct MetaHelper;
@@ -164,10 +167,10 @@
         fn call<'reg: 'rc, 'rc>(
             &self,
             h: &Helper<'reg, 'rc>,
-            r: &'reg Registry,
-            ctx: &Context,
-            rc: &mut RenderContext<'reg>,
-            out: &mut Output,
+            r: &'reg Registry<'reg>,
+            ctx: &'rc Context,
+            rc: &mut RenderContext<'reg, 'rc>,
+            out: &mut dyn Output,
         ) -> Result<(), RenderError> {
             let v = h.param(0).unwrap();
 
@@ -215,11 +218,11 @@
         handlebars.register_helper(
             "helperMissing",
             Box::new(
-                |h: &Helper,
-                 _: &Registry,
+                |h: &Helper<'_, '_>,
+                 _: &Registry<'_>,
                  _: &Context,
-                 _: &mut RenderContext,
-                 out: &mut Output|
+                 _: &mut RenderContext<'_, '_>,
+                 out: &mut dyn Output|
                  -> Result<(), RenderError> {
                     let output = format!("{}{}", h.name(), h.param(0).unwrap().value());
                     out.write(output.as_ref())?;
@@ -230,11 +233,11 @@
         handlebars.register_helper(
             "foo",
             Box::new(
-                |h: &Helper,
-                 _: &Registry,
+                |h: &Helper<'_, '_>,
+                 _: &Registry<'_>,
                  _: &Context,
-                 _: &mut RenderContext,
-                 out: &mut Output|
+                 _: &mut RenderContext<'_, '_>,
+                 out: &mut dyn Output|
                  -> Result<(), RenderError> {
                     let output = format!("{}", h.hash_get("value").unwrap().value().render());
                     out.write(output.as_ref())?;
diff --git a/third_party/rust_crates/vendor/handlebars/src/helpers/scripting.rs b/third_party/rust_crates/vendor/handlebars/src/helpers/scripting.rs
new file mode 100644
index 0000000..d111ab4
--- /dev/null
+++ b/third_party/rust_crates/vendor/handlebars/src/helpers/scripting.rs
@@ -0,0 +1,113 @@
+use std::collections::{BTreeMap, HashMap};
+
+use crate::context::Context;
+use crate::error::RenderError;
+use crate::helpers::HelperDef;
+use crate::json::value::{PathAndJson, ScopedJson};
+use crate::registry::Registry;
+use crate::render::{Helper, RenderContext};
+
+use rhai::de::from_dynamic;
+use rhai::ser::to_dynamic;
+use rhai::{Dynamic, Engine, Scope, AST};
+
+use serde_json::value::Value as Json;
+
+pub struct ScriptHelper {
+    pub(crate) script: AST,
+}
+
+#[inline]
+fn call_script_helper<'reg: 'rc, 'rc>(
+    params: &Vec<PathAndJson<'reg, 'rc>>,
+    hash: &BTreeMap<&'reg str, PathAndJson<'reg, 'rc>>,
+    engine: &Engine,
+    script: &AST,
+) -> Result<Option<ScopedJson<'reg, 'rc>>, RenderError> {
+    let params: Dynamic = to_dynamic(params.iter().map(|p| p.value()).collect::<Vec<&Json>>())?;
+
+    let hash: Dynamic = to_dynamic(
+        hash.iter()
+            .map(|(k, v)| ((*k).to_owned(), v.value()))
+            .collect::<HashMap<String, &Json>>(),
+    )?;
+
+    let mut scope = Scope::new();
+    scope.push_dynamic("params", params);
+    scope.push_dynamic("hash", hash);
+
+    let result = engine
+        .eval_ast_with_scope::<Dynamic>(&mut scope, script)
+        .map_err(RenderError::from)?;
+
+    let result_json: Json = from_dynamic(&result)?;
+
+    Ok(Some(ScopedJson::Derived(result_json)))
+}
+
+impl HelperDef for ScriptHelper {
+    fn call_inner<'reg: 'rc, 'rc>(
+        &self,
+        h: &Helper<'reg, 'rc>,
+        reg: &'reg Registry<'reg>,
+        _ctx: &'rc Context,
+        _rc: &mut RenderContext<'reg, 'rc>,
+    ) -> Result<Option<ScopedJson<'reg, 'rc>>, RenderError> {
+        call_script_helper(h.params(), h.hash(), &reg.engine, &self.script)
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    use crate::json::value::{PathAndJson, ScopedJson};
+    use rhai::Engine;
+
+    #[test]
+    fn test_dynamic_convert() {
+        let j0 = json! {
+            [{"name": "tomcat"}, {"name": "jetty"}]
+        };
+
+        let d0 = to_dynamic(&j0).unwrap();
+        assert_eq!("array", d0.type_name());
+
+        let j1 = json!({
+            "name": "tomcat",
+            "value": 4000,
+        });
+
+        let d1 = to_dynamic(&j1).unwrap();
+        assert_eq!("map", d1.type_name());
+    }
+
+    #[test]
+    fn test_to_json() {
+        let d0 = Dynamic::from("tomcat".to_owned());
+
+        assert_eq!(
+            Json::String("tomcat".to_owned()),
+            from_dynamic::<Json>(&d0).unwrap()
+        );
+    }
+
+    #[test]
+    fn test_script_helper_value_access() {
+        let engine = Engine::new();
+
+        let script = "let plen = len(params); let p0 = params[0]; let hlen = len(hash); let hme = hash[\"me\"]; plen + \",\" + p0 + \",\" + hlen + \",\" + hme";
+        let ast = engine.compile(&script).unwrap();
+
+        let params = vec![PathAndJson::new(None, ScopedJson::Derived(json!(true)))];
+        let hash = btreemap! {
+            "me" => PathAndJson::new(None, ScopedJson::Derived(json!("no"))),
+            "you" => PathAndJson::new(None, ScopedJson::Derived(json!("yes"))),
+        };
+
+        let result = call_script_helper(&params, &hash, &engine, &ast)
+            .unwrap()
+            .unwrap()
+            .render();
+        assert_eq!("1,true,2,no", &result);
+    }
+}
diff --git a/third_party/rust_crates/vendor/handlebars/src/json/mod.rs b/third_party/rust_crates/vendor/handlebars/src/json/mod.rs
new file mode 100644
index 0000000..85f783d0
--- /dev/null
+++ b/third_party/rust_crates/vendor/handlebars/src/json/mod.rs
@@ -0,0 +1,2 @@
+pub(crate) mod path;
+pub(crate) mod value;
diff --git a/third_party/rust_crates/vendor/handlebars/src/json/path.rs b/third_party/rust_crates/vendor/handlebars/src/json/path.rs
new file mode 100644
index 0000000..a6ba472
--- /dev/null
+++ b/third_party/rust_crates/vendor/handlebars/src/json/path.rs
@@ -0,0 +1,138 @@
+use std::iter::Peekable;
+
+use pest::iterators::Pair;
+use pest::Parser;
+
+use crate::error::RenderError;
+use crate::grammar::{HandlebarsParser, Rule};
+
+#[derive(PartialEq, Clone, Debug)]
+pub enum PathSeg {
+    Named(String),
+    Ruled(Rule),
+}
+
+/// Represents the Json path in templates.
+///
+/// It can be either a local variable like `@first`, `../@index`,
+/// or a normal relative path like `a/b/c`.
+#[derive(PartialEq, Clone, Debug)]
+pub enum Path {
+    Relative((Vec<PathSeg>, String)),
+    Local((usize, String, String)),
+}
+
+impl Path {
+    pub(crate) fn new(raw: &str, segs: Vec<PathSeg>) -> Path {
+        if let Some((level, name)) = get_local_path_and_level(&segs) {
+            Path::Local((level, name, raw.to_owned()))
+        } else {
+            Path::Relative((segs, raw.to_owned()))
+        }
+    }
+
+    pub fn parse(raw: &str) -> Result<Path, RenderError> {
+        HandlebarsParser::parse(Rule::path, raw)
+            .map(|p| {
+                let parsed = p.flatten();
+                let segs = parse_json_path_from_iter(&mut parsed.peekable(), raw.len());
+                Ok(Path::new(raw, segs))
+            })
+            .map_err(|_| RenderError::new("Invalid JSON path"))?
+    }
+
+    pub(crate) fn raw(&self) -> &str {
+        match self {
+            Path::Relative((_, ref raw)) => raw,
+            Path::Local((_, _, ref raw)) => raw,
+        }
+    }
+
+    pub(crate) fn current() -> Path {
+        Path::Relative((Vec::with_capacity(0), "".to_owned()))
+    }
+
+    // for test only
+    pub(crate) fn with_named_paths(name_segs: &[&str]) -> Path {
+        let segs = name_segs
+            .iter()
+            .map(|n| PathSeg::Named((*n).to_string()))
+            .collect();
+        Path::Relative((segs, name_segs.join("/")))
+    }
+
+    // for test only
+    pub(crate) fn segs(&self) -> Option<&[PathSeg]> {
+        match self {
+            Path::Relative((segs, _)) => Some(segs),
+            _ => None,
+        }
+    }
+}
+
+fn get_local_path_and_level(paths: &[PathSeg]) -> Option<(usize, String)> {
+    paths.get(0).and_then(|seg| {
+        if seg == &PathSeg::Ruled(Rule::path_local) {
+            let mut level = 0;
+            while paths[level + 1] == PathSeg::Ruled(Rule::path_up) {
+                level += 1;
+            }
+            if let Some(PathSeg::Named(name)) = paths.get(level + 1) {
+                Some((level, name.clone()))
+            } else {
+                None
+            }
+        } else {
+            None
+        }
+    })
+}
+
+pub(crate) fn parse_json_path_from_iter<'a, I>(it: &mut Peekable<I>, limit: usize) -> Vec<PathSeg>
+where
+    I: Iterator<Item = Pair<'a, Rule>>,
+{
+    let mut path_stack = Vec::with_capacity(5);
+    while let Some(n) = it.peek() {
+        let span = n.as_span();
+        if span.end() > limit {
+            break;
+        }
+
+        match n.as_rule() {
+            Rule::path_root => {
+                path_stack.push(PathSeg::Ruled(Rule::path_root));
+            }
+            Rule::path_local => {
+                path_stack.push(PathSeg::Ruled(Rule::path_local));
+            }
+            Rule::path_up => {
+                path_stack.push(PathSeg::Ruled(Rule::path_up));
+            }
+            Rule::path_id | Rule::path_raw_id => {
+                let name = n.as_str();
+                if name != "this" {
+                    path_stack.push(PathSeg::Named(name.to_string()));
+                }
+            }
+            _ => {}
+        }
+
+        it.next();
+    }
+
+    path_stack
+}
+
+pub(crate) fn merge_json_path<'a>(path_stack: &mut Vec<String>, relative_path: &'a [PathSeg]) {
+    for seg in relative_path {
+        match seg {
+            PathSeg::Named(ref s) => {
+                path_stack.push(s.to_owned());
+            }
+            PathSeg::Ruled(Rule::path_root) => {}
+            PathSeg::Ruled(Rule::path_up) => {}
+            _ => {}
+        }
+    }
+}
diff --git a/third_party/rust_crates/vendor/handlebars/src/value.rs b/third_party/rust_crates/vendor/handlebars/src/json/value.rs
similarity index 79%
rename from third_party/rust_crates/vendor/handlebars/src/value.rs
rename to third_party/rust_crates/vendor/handlebars/src/json/value.rs
index 57db246..c5a4384 100644
--- a/third_party/rust_crates/vendor/handlebars/src/value.rs
+++ b/third_party/rust_crates/vendor/handlebars/src/json/value.rs
@@ -13,17 +13,18 @@
 pub enum ScopedJson<'reg: 'rc, 'rc> {
     Constant(&'reg Json),
     Derived(Json),
-    Context(&'rc Json),
+    // represents a json reference to context value, its full path
+    Context(&'rc Json, Vec<String>),
     Missing,
 }
 
 impl<'reg: 'rc, 'rc> ScopedJson<'reg, 'rc> {
     /// get the JSON reference
     pub fn as_json(&self) -> &Json {
-        match *self {
+        match self {
             ScopedJson::Constant(j) => j,
             ScopedJson::Derived(ref j) => j,
-            ScopedJson::Context(j) => j,
+            ScopedJson::Context(j, _) => j,
             _ => &DEFAULT_VALUE,
         }
     }
@@ -33,11 +34,23 @@
     }
 
     pub fn is_missing(&self) -> bool {
-        match *self {
+        match self {
             ScopedJson::Missing => true,
             _ => false,
         }
     }
+
+    pub fn into_derived(self) -> ScopedJson<'reg, 'rc> {
+        let v = self.as_json();
+        ScopedJson::Derived(v.clone())
+    }
+
+    pub fn context_path(&self) -> Option<&Vec<String>> {
+        match self {
+            ScopedJson::Context(_, ref p) => Some(p),
+            _ => None,
+        }
+    }
 }
 
 impl<'reg: 'rc, 'rc> From<Json> for ScopedJson<'reg, 'rc> {
@@ -49,27 +62,31 @@
 /// Json wrapper that holds the Json value and reference path information
 ///
 #[derive(Debug)]
-pub struct PathAndJson<'reg: 'rc, 'rc> {
-    path: Option<String>,
+pub struct PathAndJson<'reg, 'rc> {
+    relative_path: Option<String>,
     value: ScopedJson<'reg, 'rc>,
 }
 
 impl<'reg: 'rc, 'rc> PathAndJson<'reg, 'rc> {
-    pub fn new(path: Option<String>, value: ScopedJson<'reg, 'rc>) -> PathAndJson<'reg, 'rc> {
-        PathAndJson { path, value }
+    pub fn new(
+        relative_path: Option<String>,
+        value: ScopedJson<'reg, 'rc>,
+    ) -> PathAndJson<'reg, 'rc> {
+        PathAndJson {
+            relative_path,
+            value,
+        }
     }
 
     /// Returns relative path when the value is referenced
     /// If the value is from a literal, the path is `None`
-    pub fn path(&self) -> Option<&String> {
-        self.path.as_ref()
+    pub fn relative_path(&self) -> Option<&String> {
+        self.relative_path.as_ref()
     }
 
-    /// Return root level of this path if any
-    pub fn path_root(&self) -> Option<&str> {
-        self.path
-            .as_ref()
-            .and_then(|p| p.split(|c| c == '.' || c == '/').nth(0))
+    /// Returns full path to this value if any
+    pub fn context_path(&self) -> Option<&Vec<String>> {
+        self.value.context_path()
     }
 
     /// Returns the value
@@ -81,6 +98,10 @@
     pub fn is_value_missing(&self) -> bool {
         self.value.is_missing()
     }
+
+    pub fn render(&self) -> String {
+        self.value.render()
+    }
 }
 
 /// Render Json data with default format
@@ -114,6 +135,7 @@
     }
 }
 
+/// Convert any serializable data into Serde Json type
 pub fn to_json<T>(src: T) -> Json
 where
     T: Serialize,
diff --git a/third_party/rust_crates/vendor/handlebars/src/lib.rs b/third_party/rust_crates/vendor/handlebars/src/lib.rs
index bf8bc00..a88f538 100644
--- a/third_party/rust_crates/vendor/handlebars/src/lib.rs
+++ b/third_party/rust_crates/vendor/handlebars/src/lib.rs
@@ -1,4 +1,4 @@
-#![doc(html_root_url = "https://docs.rs/handlebars/2.0.0-beta.2")]
+#![doc(html_root_url = "https://docs.rs/handlebars/3.5.4")]
 //! # Handlebars
 //!
 //! [Handlebars](http://handlebarsjs.com/) is a modern and extensible templating solution originally created in the JavaScript world. It's used by many popular frameworks like [Ember.js](http://emberjs.com) and Chaplin. It's also ported to some other platforms such as [Java](https://github.com/jknack/handlebars.java).
@@ -35,50 +35,51 @@
 //! I recommend you to walk through handlebars.js' [intro page](http://handlebarsjs.com)
 //! if you are not quite familiar with the template language itself.
 //!
-//! ## Rational: Why (this) Handlebars?
+//! ## Features
 //!
 //! Handlebars is a real-world templating system that you can use to build
 //! your application without pain.
 //!
-//! ### Features
-//!
-//! #### Isolation of Rust and HTML
+//! ### Isolation of Rust and HTML
 //!
 //! This library doesn't attempt to use some macro magic to allow you to
-//! write your template within your rust code. I admit that it's fun (and feel cool) to do
-//! that but it doesn't fit real-world use case in my opinion.
+//! write your template within your rust code. I admit that it's fun to do
+//! that but it doesn't fit real-world use cases.
 //!
-//! #### Limited but essential control structure built-in
+//! ### Limited but essential control structures built-in
 //!
-//! Only essential control directive `if` and `each` were built-in. This
-//! prevents you to put too much application logic into your template.
+//! Only essential control directives `if` and `each` are built-in. This
+//! prevents you from putting too much application logic into your template.
 //!
-//! #### Extensible helper system
+//! ### Extensible helper system
 //!
 //! You can write your own helper with Rust! It can be a block helper or
-//! inline helper. Put you logic into the helper and don't repeat
+//! inline helper. Put your logic into the helper and don't repeat
 //! yourself.
 //!
-//! #### Template inheritance
+//! The built-in helpers like `if` and `each` were written with these
+//! helper APIs and the APIs are fully available to developers.
+//!
+//! ### Template inheritance
 //!
 //! Every time I look into a templating system, I will investigate its
 //! support for [template inheritance][t].
 //!
 //! [t]: https://docs.djangoproject.com/en/1.9/ref/templates/language/#template-inheritance
 //!
-//! Template include is not enough. In most case you will need a skeleton
-//! of page as parent (header, footer, etc.), and embed you page into this
-//! parent.
+//! Template include is not sufficient for template reuse. In most cases
+//! you will need a skeleton of page as parent (header, footer, etc.), and
+//! embed your page into this parent.
 //!
-//! You can find a real example for template inheritance in
-//! `examples/partials.rs`, and templates used by this file.
+//! You can find a real example of template inheritance in
+//! `examples/partials.rs` and templates used by this file.
 //!
-//! #### Strict mode
+//! ### Strict mode
 //!
 //! Handlebars, the language designed to work with JavaScript, has no
-//! strict restriction on accessing non-existed fields or index. It
-//! generates empty string for such case. However, in Rust we want a
-//! little bit strict sometime.
+//! strict restriction on accessing nonexistent fields or indexes. It
+//! generates empty strings for such cases. However, in Rust we want to be
+//! a little stricter sometimes.
 //!
 //! By enabling `strict_mode` on handlebars:
 //!
@@ -88,37 +89,37 @@
 //! handlebars.set_strict_mode(true);
 //! ```
 //!
-//! You will get a `RenderError` when accessing fields that not exists.
+//! You will get a `RenderError` when accessing fields that do not exist.
 //!
-//! ### Limitations
+//! ## Limitations
 //!
-//! #### Compatibility with JavaScript version
+//! ### Compatibility with original JavaScript version
 //!
-//! This implementation is **not fully compatible** with the original javascript version.
+//! This implementation is **not fully compatible** with the original JavaScript version.
 //!
-//! First of all, mustache block is not supported. I suggest you to use `#if` and `#each` for
-//! same functionality.
+//! First of all, mustache blocks are not supported. I suggest you to use `#if` and `#each` for
+//! the same functionality.
 //!
 //! There are some other minor features missing:
 //!
 //! * Chained else [#12](https://github.com/sunng87/handlebars-rust/issues/12)
 //!
-//! Feel free to fire an issue on [github](https://github.com/sunng87/handlebars-rust/issues) if
+//! Feel free to file an issue on [github](https://github.com/sunng87/handlebars-rust/issues) if
 //! you find missing features.
 //!
-//! #### Static typed
+//! ### Types
 //!
 //! As a static typed language, it's a little verbose to use handlebars.
 //! Handlebars templating language is designed against JSON data type. In rust,
-//! we will convert user's structs, vectors or maps to JSON type in order to use
-//! in template. You have to make sure your data implements the `Serialize` trait
-//! from the [Serde](https://serde.rs) project.
+//! we will convert user's structs, vectors or maps into Serde-Json's `Value` type
+//! in order to use in templates. You have to make sure your data implements the
+//! `Serialize` trait from the [Serde](https://serde.rs) project.
 //!
 //! ## Usage
 //!
 //! ### Template Creation and Registration
 //!
-//! Templates are created from String and registered to `Handlebars` with a name.
+//! Templates are created from `String`s and registered to `Handlebars` with a name.
 //!
 //! ```
 //! # extern crate handlebars;
@@ -163,7 +164,7 @@
 //!
 //! That means, if you want to render something, you have to ensure the data type implements the `serde::Serialize` trait. Most rust internal types already have that trait. Use `#derive[Serialize]` for your types to generate default implementation.
 //!
-//! You can use default `render` function to render a template into `String`. From 0.9, there's `renderw` to render text into anything of `std::io::Write`.
+//! You can use default `render` function to render a template into `String`. From 0.9, there's `render_to_write` to render text into anything of `std::io::Write`.
 //!
 //! ```
 //! # use std::error::Error;
@@ -211,7 +212,7 @@
 //! #  age: i16,
 //! # }
 //!
-//! # fn main() -> Result<(), Box<Error>> {
+//! # fn main() -> Result<(), Box<dyn Error>> {
 //!   let source = "Hello, {{name}}";
 //!
 //!   let mut handlebars = Handlebars::new();
@@ -244,7 +245,7 @@
 //! struct SimpleHelper;
 //!
 //! impl HelperDef for SimpleHelper {
-//!   fn call<'reg: 'rc, 'rc>(&self, h: &Helper, _: &Handlebars, _: &Context, rc: &mut RenderContext, out: &mut Output) -> HelperResult {
+//!   fn call<'reg: 'rc, 'rc>(&self, h: &Helper, _: &Handlebars, _: &Context, rc: &mut RenderContext, out: &mut dyn Output) -> HelperResult {
 //!     let param = h.param(0).unwrap();
 //!
 //!     out.write("1st helper: ")?;
@@ -254,7 +255,7 @@
 //! }
 //!
 //! // implement via bare function
-//! fn another_simple_helper (h: &Helper, _: &Handlebars, _: &Context, rc: &mut RenderContext, out: &mut Output) -> HelperResult {
+//! fn another_simple_helper (h: &Helper, _: &Handlebars, _: &Context, rc: &mut RenderContext, out: &mut dyn Output) -> HelperResult {
 //!     let param = h.param(0).unwrap();
 //!
 //!     out.write("2nd helper: ")?;
@@ -263,13 +264,13 @@
 //! }
 //!
 //!
-//! # fn main() -> Result<(), Box<Error>> {
+//! # fn main() -> Result<(), Box<dyn Error>> {
 //!   let mut handlebars = Handlebars::new();
 //!   handlebars.register_helper("simple-helper", Box::new(SimpleHelper));
 //!   handlebars.register_helper("another-simple-helper", Box::new(another_simple_helper));
 //!   // via closure
 //!   handlebars.register_helper("closure-helper",
-//!       Box::new(|h: &Helper, r: &Handlebars, _: &Context, rc: &mut RenderContext, out: &mut Output| -> HelperResult {
+//!       Box::new(|h: &Helper, r: &Handlebars, _: &Context, rc: &mut RenderContext, out: &mut dyn Output| -> HelperResult {
 //!           let param = h.param(0).ok_or(RenderError::new("param not found"))?;
 //!
 //!           out.write("3rd helper: ")?;
@@ -284,18 +285,45 @@
 //! # }
 //!
 //! ```
+//!
 //! Data available to helper can be found in [Helper](struct.Helper.html). And there are more
 //! examples in [HelperDef](trait.HelperDef.html) page.
 //!
 //! You can learn more about helpers by looking into source code of built-in helpers.
 //!
+//!
+//! ### Script Helper
+//!
+//! Like our JavaScript counterparts, handlebars allows user to define simple helpers with
+//! a scripting language, [rhai](https://docs.rs/crate/rhai/). This can be enabled by
+//! turning on `script_helper` feature flag.
+//!
+//! A sample script:
+//!
+//! ```handlebars
+//! {{percent 0.34 label="%"}}
+//! ```
+//!
+//! ```rhai
+//! // percent.rhai
+//! // get first parameter from `params` array
+//! let value = params[0];
+//! // get key  value pair `label` from `hash` map
+//! let label = hash["label"];
+//!
+//! // compute the final string presentation
+//! (value * 100).to_string() + label
+//! ```
+//!
+//! A runnable [example](https://github.com/sunng87/handlebars-rust/blob/master/examples/script.rs) can be find in the repo.
+//!
 //! #### Built-in Helpers
 //!
 //! * `{{{{raw}}}} ... {{{{/raw}}}}` escape handlebars expression within the block
 //! * `{{#if ...}} ... {{else}} ... {{/if}}` if-else block
 //! * `{{#unless ...}} ... {{else}} .. {{/unless}}` if-not-else block
-//! * `{{#each ...}} ... {{/each}}` iterates over an array or object. Handlebar-rust doesn't support mustache iteration syntax so use this instead.
-//! * `{{#with ...}} ... {{/with}}` change current context. Similar to {{#each}}, used for replace corresponding mustache syntax.
+//! * `{{#each ...}} ... {{/each}}` iterates over an array or object. Handlebars-rust doesn't support mustache iteration syntax so use this instead.
+//! * `{{#with ...}} ... {{/with}}` change current context. Similar to `{{#each}}`, used for replace corresponding mustache syntax.
 //! * `{{lookup ... ...}}` get value from array by `@index` or `@key`
 //! * `{{> ...}}` include template with name
 //! * `{{log ...}}` log value with rust logger, default level: INFO. Currently you cannot change the level.
@@ -318,11 +346,9 @@
 //!
 
 #![allow(dead_code)]
+#![warn(rust_2018_idioms)]
 #![recursion_limit = "200"]
 
-#[macro_use]
-extern crate lazy_static;
-
 #[cfg(not(feature = "no_logging"))]
 #[macro_use]
 extern crate log;
@@ -330,7 +356,6 @@
 #[cfg(test)]
 #[macro_use]
 extern crate maplit;
-extern crate pest;
 #[macro_use]
 extern crate pest_derive;
 #[macro_use]
@@ -338,44 +363,39 @@
 #[cfg(test)]
 #[macro_use]
 extern crate serde_derive;
-#[cfg(test)]
-extern crate tempfile;
 
-extern crate regex;
-extern crate serde;
 #[allow(unused_imports)]
 #[macro_use]
 extern crate serde_json;
-#[cfg(not(feature = "no_dir_source"))]
-extern crate walkdir;
 
-extern crate hashbrown;
-
+pub use self::block::{BlockContext, BlockParams};
 pub use self::context::Context;
-pub use self::directives::DirectiveDef as DecoratorDef;
+pub use self::decorators::DecoratorDef;
 pub use self::error::{RenderError, TemplateError, TemplateFileError, TemplateRenderError};
 pub use self::helpers::{HelperDef, HelperResult};
+pub use self::json::path::Path;
+pub use self::json::value::{to_json, JsonRender, PathAndJson, ScopedJson};
 pub use self::output::Output;
 pub use self::registry::{html_escape, no_escape, EscapeFn, Registry as Handlebars};
-pub use self::render::{Directive as Decorator, Evaluable, Helper, RenderContext, Renderable};
-pub use self::support::str::StringWriter;
+pub use self::render::{Decorator, Evaluable, Helper, RenderContext, Renderable};
 pub use self::template::Template;
-pub use self::value::{to_json, JsonRender, PathAndJson, ScopedJson};
 
 #[doc(hidden)]
 pub use self::serde_json::Value as JsonValue;
 
 #[macro_use]
 mod macros;
+mod block;
 mod context;
-mod directives;
+mod decorators;
 mod error;
 mod grammar;
 mod helpers;
+mod json;
 mod output;
 mod partial;
 mod registry;
 mod render;
 mod support;
 pub mod template;
-mod value;
+mod util;
diff --git a/third_party/rust_crates/vendor/handlebars/src/macros.rs b/third_party/rust_crates/vendor/handlebars/src/macros.rs
index dc0239b..29babb4 100644
--- a/third_party/rust_crates/vendor/handlebars/src/macros.rs
+++ b/third_party/rust_crates/vendor/handlebars/src/macros.rs
@@ -1,6 +1,15 @@
 /// Macro that allows you to quickly define a handlebars helper by passing a
 /// name and a closure.
 ///
+/// There are several types of arguments available to closure:
+///
+/// * Parameters are mapped to closure arguments one by one. Any declared
+/// parameters are required
+/// * Hash are mapped as named arguments and declared in a bracket block.
+/// All named arguments are optional so default value is required.
+/// * An optional `*args` provides a vector of all helper parameters.
+/// * An optional `**kwargs` provides a map of all helper hash.
+///
 /// # Examples
 ///
 /// ```rust
@@ -8,21 +17,32 @@
 /// #[macro_use] extern crate serde_json;
 ///
 /// handlebars_helper!(is_above_10: |x: u64| x > 10);
+/// handlebars_helper!(is_above: |x: u64, { compare: u64 = 10 }| x > compare);
 ///
 /// # fn main() {
 /// #
 /// let mut handlebars = handlebars::Handlebars::new();
 /// handlebars.register_helper("is-above-10", Box::new(is_above_10));
+/// handlebars.register_helper("is-above", Box::new(is_above));
 ///
 /// let result = handlebars
 ///     .render_template("{{#if (is-above-10 12)}}great!{{else}}okay{{/if}}", &json!({}))
 ///     .unwrap();
 ///  assert_eq!(&result, "great!");
+/// let result2 = handlebars
+///     .render_template("{{#if (is-above 12 compare=10)}}great!{{else}}okay{{/if}}", &json!({}))
+///     .unwrap();
+///  assert_eq!(&result2, "great!");
 /// # }
 /// ```
+
 #[macro_export]
 macro_rules! handlebars_helper {
-    ($struct_name:ident: |$($name:ident: $tpe:tt),*| $body:expr ) => {
+    ($struct_name:ident: |$($name:ident: $tpe:tt),*
+     $($(,)?{$($hash_name:ident: $hash_tpe:tt=$dft_val:literal),*})?
+     $($(,)?*$args:ident)?
+     $($(,)?**$kwargs:ident)?|
+     $body:expr ) => {
         #[allow(non_camel_case_types)]
         pub struct $struct_name;
 
@@ -31,9 +51,9 @@
             fn call_inner<'reg: 'rc, 'rc>(
                 &self,
                 h: &$crate::Helper<'reg, 'rc>,
-                _: &'reg $crate::Handlebars,
+                _: &'reg $crate::Handlebars<'reg>,
                 _: &'rc $crate::Context,
-                _: &mut $crate::RenderContext<'reg>,
+                _: &mut $crate::RenderContext<'reg, 'rc>,
             ) -> Result<Option<$crate::ScopedJson<'reg, 'rc>>, $crate::RenderError> {
                 let mut param_idx = 0;
 
@@ -42,20 +62,40 @@
                         .map(|x| x.value())
                         .ok_or_else(|| $crate::RenderError::new(&format!(
                             "`{}` helper: Couldn't read parameter {}",
-                            stringify!($fn_name), stringify!($name),
+                            stringify!($struct_name), stringify!($name),
                         )))
                         .and_then(|x|
                                   handlebars_helper!(@as_json_value x, $tpe)
                                   .ok_or_else(|| $crate::RenderError::new(&format!(
                                       "`{}` helper: Couldn't convert parameter {} to type `{}`. \
                                        It's {:?} as JSON. Got these params: {:?}",
-                                      stringify!($fn_name), stringify!($name), stringify!($tpe),
+                                      stringify!($struct_name), stringify!($name), stringify!($tpe),
                                       x, h.params(),
                                   )))
                         )?;
                     param_idx += 1;
                 )*
 
+                    $(
+                        $(
+                            let $hash_name = h.hash_get(stringify!($hash_name))
+                                .map(|x| x.value())
+                                .map(|x|
+                                     handlebars_helper!(@as_json_value x, $hash_tpe)
+                                     .ok_or_else(|| $crate::RenderError::new(&format!(
+                                         "`{}` helper: Couldn't convert hash {} to type `{}`. \
+                                          It's {:?} as JSON. Got these hash: {:?}",
+                                         stringify!($struct_name), stringify!($hash_name), stringify!($hash_tpe),
+                                         x, h.hash(),
+                                     )))
+                                )
+                                .unwrap_or_else(|| Ok($dft_val))?;
+                        )*
+                    )?
+
+                    $(let $args = h.params().iter().map(|x| x.value()).collect::<Vec<&serde_json::Value>>();)?
+                    $(let $kwargs = h.hash().iter().map(|(k, v)| (k.to_owned(), v.value())).collect::<std::collections::BTreeMap<&str, &serde_json::Value>>();)?
+
                 let result = $body;
                 Ok(Some($crate::ScopedJson::Derived($crate::JsonValue::from(result))))
             }
@@ -70,6 +110,7 @@
     (@as_json_value $x:ident, f64) => { $x.as_f64() };
     (@as_json_value $x:ident, bool) => { $x.as_bool() };
     (@as_json_value $x:ident, null) => { $x.as_null() };
+    (@as_json_value $x:ident, Json) => { Some($x) };
 }
 
 /// This macro is defined if the `logging` feature is set.
@@ -95,7 +136,7 @@
 /// This macro is defined if the `logging` feature is not set.
 ///
 /// It ignores all logging calls inside the library.
-#[cfg(not(feature = "logging"))]
+#[cfg(feature = "no_logging")]
 #[macro_export]
 macro_rules! info {
     (target: $target:expr, $($arg:tt)*) => {};
diff --git a/third_party/rust_crates/vendor/handlebars/src/output.rs b/third_party/rust_crates/vendor/handlebars/src/output.rs
index 74173d4..f1c5865 100644
--- a/third_party/rust_crates/vendor/handlebars/src/output.rs
+++ b/third_party/rust_crates/vendor/handlebars/src/output.rs
@@ -1,6 +1,9 @@
 use std::io::{Error as IOError, Write};
 use std::string::FromUtf8Error;
 
+/// The Output API.
+///
+/// Handlebars uses this trait to define rendered output.
 pub trait Output {
     fn write(&mut self, seg: &str) -> Result<(), IOError>;
 }
diff --git a/third_party/rust_crates/vendor/handlebars/src/partial.rs b/third_party/rust_crates/vendor/handlebars/src/partial.rs
index bfe8717..fe68322 100644
--- a/third_party/rust_crates/vendor/handlebars/src/partial.rs
+++ b/third_party/rust_crates/vendor/handlebars/src/partial.rs
@@ -1,61 +1,62 @@
-use std::iter::FromIterator;
+use std::collections::HashMap;
 
-use hashbrown::HashMap;
+use serde_json::value::Value as Json;
 
 use crate::context::{merge_json, Context};
 use crate::error::RenderError;
+use crate::json::path::Path;
 use crate::output::Output;
 use crate::registry::Registry;
-use crate::render::{Directive, Evaluable, RenderContext, Renderable};
+use crate::render::{Decorator, Evaluable, RenderContext, Renderable};
 use crate::template::Template;
-use crate::value::DEFAULT_VALUE;
 
 fn render_partial<'reg: 'rc, 'rc>(
     t: &'reg Template,
-    d: &Directive<'reg, 'rc>,
-    r: &'reg Registry,
+    d: &Decorator<'reg, 'rc>,
+    r: &'reg Registry<'reg>,
     ctx: &'rc Context,
-    local_rc: &mut RenderContext<'reg>,
-    out: &mut Output,
+    local_rc: &mut RenderContext<'reg, 'rc>,
+    out: &mut dyn Output,
 ) -> Result<(), RenderError> {
     // partial context path
-    if let Some(ref p) = d.param(0) {
-        if let Some(ref param_path) = p.path() {
-            let old_path = local_rc.get_path().clone();
-            local_rc.promote_local_vars();
-            let new_path = format!("{}/{}", old_path, param_path);
-            local_rc.set_path(new_path);
+    if let Some(ref param_ctx) = d.param(0) {
+        if let (Some(p), Some(block)) = (param_ctx.context_path(), local_rc.block_mut()) {
+            *block.base_path_mut() = p.clone();
         }
-    };
+    }
 
     // @partial-block
     if let Some(t) = d.template() {
         local_rc.set_partial("@partial-block".to_owned(), t);
     }
 
-    if d.hash().is_empty() {
+    let result = if d.hash().is_empty() {
         t.render(r, ctx, local_rc, out)
     } else {
-        let hash_ctx =
-            HashMap::from_iter(d.hash().iter().map(|(k, v)| (k.clone(), v.value().clone())));
-        let partial_context = merge_json(
-            local_rc
-                .evaluate(ctx, ".")?
-                .unwrap_or_else(|| &DEFAULT_VALUE),
-            &hash_ctx,
-        );
+        let hash_ctx = d
+            .hash()
+            .iter()
+            .map(|(k, v)| (k, v.value()))
+            .collect::<HashMap<&&str, &Json>>();
+        let current_path = Path::current();
+        let partial_context =
+            merge_json(local_rc.evaluate2(ctx, &current_path)?.as_json(), &hash_ctx);
         let ctx = Context::wraps(&partial_context)?;
         let mut partial_rc = local_rc.new_for_block();
         t.render(r, &ctx, &mut partial_rc, out)
-    }
+    };
+
+    local_rc.remove_partial("@partial-block");
+
+    result
 }
 
 pub fn expand_partial<'reg: 'rc, 'rc>(
-    d: &Directive<'reg, 'rc>,
-    r: &'reg Registry,
+    d: &Decorator<'reg, 'rc>,
+    r: &'reg Registry<'reg>,
     ctx: &'rc Context,
-    rc: &mut RenderContext<'reg>,
-    out: &mut Output,
+    rc: &mut RenderContext<'reg, 'rc>,
+    out: &mut dyn Output,
 ) -> Result<(), RenderError> {
     // try eval inline partials first
     if let Some(t) = d.template() {
@@ -71,12 +72,12 @@
 
     match partial {
         Some(t) => {
-            let mut local_rc = rc.derive();
+            let mut local_rc = rc.clone();
             render_partial(&t, d, r, ctx, &mut local_rc, out)?;
         }
         None => {
             if let Some(t) = r.get_template(tname).or_else(|| d.template()) {
-                let mut local_rc = rc.derive();
+                let mut local_rc = rc.clone();
                 render_partial(t, d, r, ctx, &mut local_rc, out)?;
             }
         }
@@ -87,7 +88,11 @@
 
 #[cfg(test)]
 mod test {
+    use crate::context::Context;
+    use crate::error::RenderError;
+    use crate::output::Output;
     use crate::registry::Registry;
+    use crate::render::{Helper, RenderContext};
 
     #[test]
     fn test() {
@@ -209,6 +214,47 @@
     }
 
     #[test]
+    fn test_partial_context_hash() {
+        let mut hbs = Registry::new();
+        hbs.register_template_string("one", "This is a test. {{> two name=\"fred\" }}")
+            .unwrap();
+        hbs.register_template_string("two", "Lets test {{name}}")
+            .unwrap();
+        assert_eq!(
+            "This is a test. Lets test fred",
+            hbs.render("one", &0).unwrap()
+        );
+    }
+
+    #[test]
+    fn test_partial_subexpression_context_hash() {
+        let mut hbs = Registry::new();
+        hbs.register_template_string("one", "This is a test. {{> (x @root) name=\"fred\" }}")
+            .unwrap();
+        hbs.register_template_string("two", "Lets test {{name}}")
+            .unwrap();
+
+        hbs.register_helper(
+            "x",
+            Box::new(
+                |_: &Helper<'_, '_>,
+                 _: &Registry<'_>,
+                 _: &Context,
+                 _: &mut RenderContext<'_, '_>,
+                 out: &mut dyn Output|
+                 -> Result<(), RenderError> {
+                    out.write("two")?;
+                    Ok(())
+                },
+            ),
+        );
+        assert_eq!(
+            "This is a test. Lets test fred",
+            hbs.render("one", &0).unwrap()
+        );
+    }
+
+    #[test]
     fn test_nested_partial_scope() {
         let t = "{{#*inline \"pp\"}}{{a}} {{b}}{{/inline}}{{#each c}}{{> pp a=2}}{{/each}}";
         let data = json!({"c": [{"b": true}, {"b": false}]});
@@ -218,4 +264,21 @@
         let r0 = handlebars.render("t", &data);
         assert_eq!(r0.ok().unwrap(), "2 true2 false");
     }
+
+    #[test]
+    fn test_up_to_partial_level() {
+        let outer = r#"{{>inner name="fruit:" vegetables=fruits}}"#;
+        let inner = "{{#each vegetables}}{{../name}} {{this}},{{/each}}";
+
+        let data = json!({ "fruits": ["carrot", "tomato"] });
+
+        let mut handlebars = Registry::new();
+        handlebars.register_template_string("outer", outer).unwrap();
+        handlebars.register_template_string("inner", inner).unwrap();
+
+        assert_eq!(
+            handlebars.render("outer", &data).unwrap(),
+            "fruit: carrot,fruit: tomato,"
+        );
+    }
 }
diff --git a/third_party/rust_crates/vendor/handlebars/src/registry.rs b/third_party/rust_crates/vendor/handlebars/src/registry.rs
index 68a4980..67530de 100644
--- a/third_party/rust_crates/vendor/handlebars/src/registry.rs
+++ b/third_party/rust_crates/vendor/handlebars/src/registry.rs
@@ -1,54 +1,48 @@
+use std::collections::HashMap;
 use std::fmt::{self, Debug, Formatter};
 use std::fs::File;
 use std::io::prelude::*;
+use std::io::BufReader;
 use std::path::Path;
 
-use hashbrown::HashMap;
 use serde::Serialize;
 
-use regex::{Captures, Regex};
-
 use crate::context::Context;
-use crate::directives::{self, DirectiveDef};
+use crate::decorators::{self, DecoratorDef};
+#[cfg(feature = "script_helper")]
+use crate::error::ScriptError;
 use crate::error::{RenderError, TemplateError, TemplateFileError, TemplateRenderError};
 use crate::helpers::{self, HelperDef};
 use crate::output::{Output, StringOutput, WriteOutput};
 use crate::render::{RenderContext, Renderable};
-use crate::support::str::StringWriter;
+use crate::support::str::{self, StringWriter};
 use crate::template::Template;
 
-#[cfg(not(feature = "no_dir_source"))]
+#[cfg(feature = "dir_source")]
+use std::path;
+#[cfg(feature = "dir_source")]
 use walkdir::{DirEntry, WalkDir};
 
-lazy_static! {
-    static ref DEFAULT_REPLACE: Regex = Regex::new(">|<|\"|&").unwrap();
-}
+#[cfg(feature = "script_helper")]
+use rhai::Engine;
 
-/// This type represents an *escape fn*, that is a function who's purpose it is
+#[cfg(feature = "script_helper")]
+use crate::helpers::scripting::ScriptHelper;
+
+/// This type represents an *escape fn*, that is a function whose purpose it is
 /// to escape potentially problematic characters in a string.
 ///
 /// An *escape fn* is represented as a `Box` to avoid unnecessary type
 /// parameters (and because traits cannot be aliased using `type`).
-pub type EscapeFn = Box<Fn(&str) -> String + Send + Sync>;
+pub type EscapeFn = Box<dyn Fn(&str) -> String + Send + Sync>;
 
 /// The default *escape fn* replaces the characters `&"<>`
 /// with the equivalent html / xml entities.
 pub fn html_escape(data: &str) -> String {
-    DEFAULT_REPLACE
-        .replace_all(data, |cap: &Captures| {
-            match cap.get(0).map(|m| m.as_str()) {
-                Some("<") => "&lt;",
-                Some(">") => "&gt;",
-                Some("\"") => "&quot;",
-                Some("&") => "&amp;",
-                _ => unreachable!(),
-            }
-            .to_owned()
-        })
-        .into_owned()
+    str::escape_html(data)
 }
 
-/// `EscapeFn` that do not change any thing. Useful when using in a non-html
+/// `EscapeFn` that does not change anything. Useful when using in a non-html
 /// environment.
 pub fn no_escape(data: &str) -> String {
     data.to_owned()
@@ -57,33 +51,35 @@
 /// The single entry point of your Handlebars templates
 ///
 /// It maintains compiled templates and registered helpers.
-pub struct Registry {
+pub struct Registry<'reg> {
     templates: HashMap<String, Template>,
-    helpers: HashMap<String, Box<HelperDef + 'static>>,
-    directives: HashMap<String, Box<DirectiveDef + 'static>>,
+    helpers: HashMap<String, Box<dyn HelperDef + Send + Sync + 'reg>>,
+    decorators: HashMap<String, Box<dyn DecoratorDef + Send + Sync + 'reg>>,
     escape_fn: EscapeFn,
     source_map: bool,
     strict_mode: bool,
+    #[cfg(feature = "script_helper")]
+    pub(crate) engine: Engine,
 }
 
-impl Debug for Registry {
-    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
+impl<'reg> Debug for Registry<'reg> {
+    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
         f.debug_struct("Handlebars")
             .field("templates", &self.templates)
             .field("helpers", &self.helpers.keys())
-            .field("directives", &self.directives.keys())
+            .field("decorators", &self.decorators.keys())
             .field("source_map", &self.source_map)
             .finish()
     }
 }
 
-impl Default for Registry {
+impl<'reg> Default for Registry<'reg> {
     fn default() -> Self {
         Self::new()
     }
 }
 
-#[cfg(not(feature = "no_dir_source"))]
+#[cfg(feature = "dir_source")]
 fn filter_file(entry: &DirEntry, suffix: &str) -> bool {
     let path = entry.path();
 
@@ -98,21 +94,28 @@
             .unwrap_or(true)
 }
 
-impl Registry {
-    pub fn new() -> Registry {
+#[cfg(feature = "script_helper")]
+fn rhai_engine() -> Engine {
+    Engine::new()
+}
+
+impl<'reg> Registry<'reg> {
+    pub fn new() -> Registry<'reg> {
         let r = Registry {
             templates: HashMap::new(),
             helpers: HashMap::new(),
-            directives: HashMap::new(),
+            decorators: HashMap::new(),
             escape_fn: Box::new(html_escape),
             source_map: true,
             strict_mode: false,
+            #[cfg(feature = "script_helper")]
+            engine: rhai_engine(),
         };
 
         r.setup_builtins()
     }
 
-    fn setup_builtins(mut self) -> Registry {
+    fn setup_builtins(mut self) -> Registry<'reg> {
         self.register_helper("if", Box::new(helpers::IF_HELPER));
         self.register_helper("unless", Box::new(helpers::UNLESS_HELPER));
         self.register_helper("each", Box::new(helpers::EACH_HELPER));
@@ -131,7 +134,7 @@
         self.register_helper("or", Box::new(helpers::helper_boolean::or));
         self.register_helper("not", Box::new(helpers::helper_boolean::not));
 
-        self.register_decorator("inline", Box::new(directives::INLINE_DIRECTIVE));
+        self.register_decorator("inline", Box::new(decorators::INLINE_DECORATOR));
         self
     }
 
@@ -167,9 +170,18 @@
         self.strict_mode
     }
 
+    /// Register a `Template`
+    ///
+    /// This is infallible since the template has already been parsed and
+    /// insert cannot fail. If there is an existing template with this name it
+    /// will be overwritten.
+    pub fn register_template(&mut self, name: &str, tpl: Template) {
+        self.templates.insert(name.to_string(), tpl);
+    }
+
     /// Register a template string
     ///
-    /// Returns `TemplateError` if there is syntax error on parsing template.
+    /// Returns `TemplateError` if there is syntax error on parsing the template.
     pub fn register_template_string<S>(
         &mut self,
         name: &str,
@@ -178,15 +190,15 @@
     where
         S: AsRef<str>,
     {
-        Template::compile_with_name(tpl_str, name.to_owned(), self.source_map)
-            .and_then(|t| Ok(self.templates.insert(name.to_string(), t)))?;
+        let template = Template::compile_with_name(tpl_str, name.to_owned(), self.source_map)?;
+        self.register_template(name, template);
         Ok(())
     }
 
     /// Register a partial string
     ///
     /// A named partial will be added to the registry. It will overwrite template with
-    /// same name. Currently registered partial is just identical to template.
+    /// same name. Currently a registered partial is just identical to a template.
     pub fn register_partial<S>(&mut self, name: &str, partial_str: S) -> Result<(), TemplateError>
     where
         S: AsRef<str>,
@@ -203,9 +215,10 @@
     where
         P: AsRef<Path>,
     {
-        let mut file =
-            File::open(tpl_path).map_err(|e| TemplateFileError::IOError(e, name.to_owned()))?;
-        self.register_template_source(name, &mut file)
+        let mut reader = BufReader::new(
+            File::open(tpl_path).map_err(|e| TemplateFileError::IOError(e, name.to_owned()))?,
+        );
+        self.register_template_source(name, &mut reader)
     }
 
     /// Register templates from a directory
@@ -216,8 +229,11 @@
     /// Hidden files and tempfile (starts with `#`) will be ignored. All registered
     /// will use their relative name as template name. For example, when `dir_path` is
     /// `templates/` and `tpl_extension` is `.hbs`, the file
-    /// `templates/some/path/file.hbs` will be registerd as `some/path/file`.
-    #[cfg(not(feature = "no_dir_source"))]
+    /// `templates/some/path/file.hbs` will be registered as `some/path/file`.
+    ///
+    /// This method is not available by default.
+    /// You will need to enable the `dir_source` feature to use it.
+    #[cfg(feature = "dir_source")]
     pub fn register_templates_directory<P>(
         &mut self,
         tpl_extension: &'static str,
@@ -228,7 +244,11 @@
     {
         let dir_path = dir_path.as_ref();
 
-        let prefix_len = if dir_path.to_string_lossy().ends_with('/') {
+        let prefix_len = if dir_path
+            .to_string_lossy()
+            .ends_with(|c| c == '\\' || c == '/')
+        // `/` will work on windows too so we still need to check
+        {
             dir_path.to_string_lossy().len()
         } else {
             dir_path.to_string_lossy().len() + 1
@@ -247,7 +267,8 @@
             let tpl_file_path = entry.path().to_string_lossy();
 
             let tpl_name = &tpl_file_path[prefix_len..tpl_file_path.len() - tpl_extension.len()];
-            let tpl_canonical_name = tpl_name.replace("\\", "/");
+            // replace platform path separator with our internal one
+            let tpl_canonical_name = tpl_name.replace(path::MAIN_SEPARATOR, "/");
             self.register_template_file(&tpl_canonical_name, &tpl_path)?;
         }
 
@@ -255,11 +276,14 @@
     }
 
     /// Register a template from `std::io::Read` source
-    pub fn register_template_source(
+    pub fn register_template_source<R>(
         &mut self,
         name: &str,
-        tpl_source: &mut Read,
-    ) -> Result<(), TemplateFileError> {
+        tpl_source: &mut R,
+    ) -> Result<(), TemplateFileError>
+    where
+        R: Read,
+    {
         let mut buf = String::new();
         tpl_source
             .read_to_string(&mut buf)
@@ -268,27 +292,80 @@
         Ok(())
     }
 
-    /// remove a template from the registry
+    /// Remove a template from the registry
     pub fn unregister_template(&mut self, name: &str) {
         self.templates.remove(name);
     }
 
-    /// register a helper
+    /// Register a helper
     pub fn register_helper(
         &mut self,
         name: &str,
-        def: Box<HelperDef + 'static>,
-    ) -> Option<Box<HelperDef + 'static>> {
+        def: Box<dyn HelperDef + Send + Sync + 'reg>,
+    ) -> Option<Box<dyn HelperDef + Send + Sync + 'reg>> {
         self.helpers.insert(name.to_string(), def)
     }
 
-    /// register a decorator
+    /// Register a [rhai](https://docs.rs/rhai/) script as handlebars helper
+    ///
+    /// Currently only simple helpers are supported. You can do computation or
+    /// string formatting with rhai script.
+    ///
+    /// Helper parameters and hash are available in rhai script as array `params`
+    /// and map `hash`. Example script:
+    ///
+    /// ```handlebars
+    /// {{percent 0.34 label="%"}}
+    /// ```
+    ///
+    /// ```rhai
+    /// // percent.rhai
+    /// let value = params[0];
+    /// let label = hash["label"];
+    ///
+    /// (value * 100).to_string() + label
+    /// ```
+    ///
+    ///
+    #[cfg(feature = "script_helper")]
+    pub fn register_script_helper(
+        &mut self,
+        name: &str,
+        script: String,
+    ) -> Result<Option<Box<dyn HelperDef + Send + Sync + 'reg>>, ScriptError> {
+        let compiled = self.engine.compile(&script)?;
+        let script_helper = ScriptHelper { script: compiled };
+        Ok(self
+            .helpers
+            .insert(name.to_string(), Box::new(script_helper)))
+    }
+
+    /// Register a [rhai](https://docs.rs/rhai/) script from file
+    #[cfg(feature = "script_helper")]
+    pub fn register_script_helper_file<P>(
+        &mut self,
+        name: &str,
+        script_path: P,
+    ) -> Result<Option<Box<dyn HelperDef + Send + Sync + 'reg>>, ScriptError>
+    where
+        P: AsRef<Path>,
+    {
+        let mut script = String::new();
+        {
+            let mut file = File::open(script_path)?;
+            file.read_to_string(&mut script)?;
+        }
+
+        self.register_script_helper(name, script)
+    }
+
+    /// Register a decorator
     pub fn register_decorator(
         &mut self,
         name: &str,
-        def: Box<DirectiveDef + 'static>,
-    ) -> Option<Box<DirectiveDef + 'static>> {
-        self.directives.insert(name.to_string(), def)
+        def: Box<dyn DecoratorDef + Send + Sync + 'reg>,
+    ) -> Option<Box<dyn DecoratorDef + Send + Sync + 'reg>> {
+        self.decorators.insert(name.to_string(), def)
     }
 
     /// Register a new *escape fn* to be used from now on by this registry.
@@ -305,7 +382,7 @@
     }
 
     /// Get a reference to the current *escape fn*.
-    pub fn get_escape_fn(&self) -> &Fn(&str) -> String {
+    pub fn get_escape_fn(&self) -> &dyn Fn(&str) -> String {
         &*self.escape_fn
     }
 
@@ -320,13 +397,18 @@
     }
 
     /// Return a registered helper
-    pub fn get_helper(&self, name: &str) -> Option<&(HelperDef + 'static)> {
+    pub fn get_helper(&self, name: &str) -> Option<&(dyn HelperDef + Send + Sync + 'reg)> {
         self.helpers.get(name).map(|v| v.as_ref())
     }
 
-    /// Return a registered directive, aka decorator
-    pub fn get_decorator(&self, name: &str) -> Option<&(DirectiveDef + 'static)> {
-        self.directives.get(name).map(|v| v.as_ref())
+    #[inline]
+    pub(crate) fn has_helper(&self, name: &str) -> bool {
+        self.helpers.contains_key(name)
+    }
+
+    /// Return a registered decorator
+    pub fn get_decorator(&self, name: &str) -> Option<&(dyn DecoratorDef + Send + Sync + 'reg)> {
+        self.decorators.get(name).map(|v| v.as_ref())
     }
 
     /// Return all templates registered
@@ -339,37 +421,43 @@
         self.templates.clear();
     }
 
-    fn render_to_output<T>(
+    fn render_to_output<O>(
         &self,
         name: &str,
-        data: &T,
-        output: &mut Output,
+        ctx: &Context,
+        output: &mut O,
     ) -> Result<(), RenderError>
     where
-        T: Serialize,
+        O: Output,
     {
         self.get_template(name)
             .ok_or_else(|| RenderError::new(format!("Template not found: {}", name)))
             .and_then(|t| {
-                let ctx = Context::wraps(data)?;
                 let mut render_context = RenderContext::new(t.name.as_ref());
                 t.render(self, &ctx, &mut render_context, output)
             })
-            .map(|_| ())
     }
 
     /// Render a registered template with some data into a string
     ///
-    /// * `name` is the template name you registred previously
-    /// * `ctx` is the data that implements `serde::Serialize`
+    /// * `name` is the template name you registered previously
+    /// * `data` is the data that implements `serde::Serialize`
     ///
-    /// Returns rendered string or an struct with error information
+    /// Returns rendered string or a struct with error information
     pub fn render<T>(&self, name: &str, data: &T) -> Result<String, RenderError>
     where
         T: Serialize,
     {
         let mut output = StringOutput::new();
-        self.render_to_output(name, data, &mut output)?;
+        let ctx = Context::wraps(&data)?;
+        self.render_to_output(name, &ctx, &mut output)?;
+        output.into_string().map_err(RenderError::from)
+    }
+
+    /// Render a registered template with reused context
+    pub fn render_with_context(&self, name: &str, ctx: &Context) -> Result<String, RenderError> {
+        let mut output = StringOutput::new();
+        self.render_to_output(name, ctx, &mut output)?;
         output.into_string().map_err(RenderError::from)
     }
 
@@ -380,10 +468,11 @@
         W: Write,
     {
         let mut output = WriteOutput::new(writer);
-        self.render_to_output(name, data, &mut output)
+        let ctx = Context::wraps(data)?;
+        self.render_to_output(name, &ctx, &mut output)
     }
 
-    /// render a template string using current registry without register it
+    /// Render a template string using current registry without registering it
     pub fn render_template<T>(
         &self,
         template_string: &str,
@@ -397,7 +486,25 @@
         Ok(writer.into_string())
     }
 
-    /// render a template string using current registry without register it
+    /// Render a template string using reused context data
+    pub fn render_template_with_context(
+        &self,
+        template_string: &str,
+        ctx: &Context,
+    ) -> Result<String, TemplateRenderError> {
+        let tpl = Template::compile2(template_string, self.source_map)?;
+
+        let mut out = StringOutput::new();
+        {
+            let mut render_context = RenderContext::new(None);
+            tpl.render(self, &ctx, &mut render_context, &mut out)?;
+        }
+
+        out.into_string()
+            .map_err(|e| TemplateRenderError::from(RenderError::from(e)))
+    }
+
+    /// Render a template string using current registry without registering it
     pub fn render_template_to_write<T, W>(
         &self,
         template_string: &str,
@@ -413,20 +520,20 @@
         let mut render_context = RenderContext::new(None);
         let mut out = WriteOutput::new(writer);
         tpl.render(self, &ctx, &mut render_context, &mut out)
-            .map(|_| ())
             .map_err(TemplateRenderError::from)
     }
 
-    /// render a template source using current registry without register it
-    pub fn render_template_source_to_write<T, W>(
+    /// Render a template source using current registry without registering it
+    pub fn render_template_source_to_write<T, R, W>(
         &self,
-        template_source: &mut Read,
+        template_source: &mut R,
         data: &T,
         writer: W,
     ) -> Result<(), TemplateRenderError>
     where
         T: Serialize,
         W: Write,
+        R: Read,
     {
         let mut tpl_str = String::new();
         template_source
@@ -445,11 +552,12 @@
     use crate::registry::Registry;
     use crate::render::{Helper, RenderContext, Renderable};
     use crate::support::str::StringWriter;
-    #[cfg(not(feature = "no_dir_source"))]
+    use crate::template::Template;
+    #[cfg(feature = "dir_source")]
     use std::fs::{DirBuilder, File};
-    #[cfg(not(feature = "no_dir_source"))]
+    #[cfg(feature = "dir_source")]
     use std::io::Write;
-    #[cfg(not(feature = "no_dir_source"))]
+    #[cfg(feature = "dir_source")]
     use tempfile::tempdir;
 
     #[derive(Clone, Copy)]
@@ -459,10 +567,10 @@
         fn call<'reg: 'rc, 'rc>(
             &self,
             h: &Helper<'reg, 'rc>,
-            r: &'reg Registry,
-            ctx: &Context,
-            rc: &mut RenderContext<'reg>,
-            out: &mut Output,
+            r: &'reg Registry<'reg>,
+            ctx: &'rc Context,
+            rc: &mut RenderContext<'reg, 'rc>,
+            out: &mut dyn Output,
         ) -> Result<(), RenderError> {
             h.template().unwrap().render(r, ctx, rc, out)
         }
@@ -475,7 +583,9 @@
         let mut r = Registry::new();
 
         assert!(r.register_template_string("index", "<h1></h1>").is_ok());
-        assert!(r.register_template_string("index2", "<h2></h2>").is_ok());
+
+        let tpl = Template::compile("<h2></h2>").unwrap();
+        r.register_template("index2", tpl);
 
         assert_eq!(r.templates.len(), 2);
 
@@ -498,7 +608,7 @@
     }
 
     #[test]
-    #[cfg(not(feature = "no_dir_source"))]
+    #[cfg(feature = "dir_source")]
     fn test_register_templates_directory() {
         let mut r = Registry::new();
         {
@@ -600,6 +710,29 @@
 
             dir.close().unwrap();
         }
+
+        {
+            let dir = tempdir().unwrap();
+
+            let file1_path = dir.path().join("t10.hbs");
+            let mut file1: File = File::create(&file1_path).unwrap();
+            writeln!(file1, "<h1>Bonjour {{world}}!</h1>").unwrap();
+
+            let mut dir_path = dir
+                .path()
+                .to_string_lossy()
+                .replace(std::path::MAIN_SEPARATOR, "/");
+            if !dir_path.ends_with("/") {
+                dir_path.push('/');
+            }
+            r.register_templates_directory(".hbs", dir_path).unwrap();
+
+            assert_eq!(r.templates.len(), 8);
+            assert_eq!(r.templates.contains_key("t10"), true);
+
+            drop(file1);
+            dir.close().unwrap();
+        }
     }
 
     #[test]
@@ -697,15 +830,15 @@
         );
     }
 
-    use crate::value::ScopedJson;
+    use crate::json::value::ScopedJson;
     struct GenMissingHelper;
     impl HelperDef for GenMissingHelper {
         fn call_inner<'reg: 'rc, 'rc>(
             &self,
             _: &Helper<'reg, 'rc>,
-            _: &'reg Registry,
+            _: &'reg Registry<'reg>,
             _: &'rc Context,
-            _: &mut RenderContext<'reg>,
+            _: &mut RenderContext<'reg, 'rc>,
         ) -> Result<Option<ScopedJson<'reg, 'rc>>, RenderError> {
             Ok(Some(ScopedJson::Missing))
         }
@@ -719,11 +852,11 @@
         r.register_helper(
             "check_missing",
             Box::new(
-                |h: &Helper,
-                 _: &Registry,
+                |h: &Helper<'_, '_>,
+                 _: &Registry<'_>,
                  _: &Context,
-                 _: &mut RenderContext,
-                 _: &mut Output|
+                 _: &mut RenderContext<'_, '_>,
+                 _: &mut dyn Output|
                  -> Result<(), RenderError> {
                     let value = h.param(0).unwrap();
                     assert!(value.is_value_missing());
@@ -753,4 +886,104 @@
             )
             .is_err());
     }
+
+    #[test]
+    fn test_html_expression() {
+        let reg = Registry::new();
+        assert_eq!(
+            reg.render_template("{{{ a }}}", &json!({"a": "<b>bold</b>"}))
+                .unwrap(),
+            "<b>bold</b>"
+        );
+        assert_eq!(
+            reg.render_template("{{ &a }}", &json!({"a": "<b>bold</b>"}))
+                .unwrap(),
+            "<b>bold</b>"
+        );
+    }
+
+    #[test]
+    fn test_render_context() {
+        let mut reg = Registry::new();
+
+        let data = json!([0, 1, 2, 3]);
+
+        assert_eq!(
+            "0123",
+            reg.render_template_with_context(
+                "{{#each this}}{{this}}{{/each}}",
+                &Context::wraps(&data).unwrap()
+            )
+            .unwrap()
+        );
+
+        reg.register_template_string("t0", "{{#each this}}{{this}}{{/each}}")
+            .unwrap();
+        assert_eq!(
+            "0123",
+            reg.render_with_context("t0", &Context::wraps(&data).unwrap())
+                .unwrap()
+        );
+    }
+
+    #[test]
+    fn test_keys_starts_with_null() {
+        env_logger::init();
+        let reg = Registry::new();
+        let data = json!({
+            "optional": true,
+            "is_null": true,
+            "nullable": true,
+            "null": true,
+            "falsevalue": true,
+        });
+        assert_eq!(
+            "optional: true --> true",
+            reg.render_template(
+                "optional: {{optional}} --> {{#if optional }}true{{else}}false{{/if}}",
+                &data
+            )
+            .unwrap()
+        );
+        assert_eq!(
+            "is_null: true --> true",
+            reg.render_template(
+                "is_null: {{is_null}} --> {{#if is_null }}true{{else}}false{{/if}}",
+                &data
+            )
+            .unwrap()
+        );
+        assert_eq!(
+            "nullable: true --> true",
+            reg.render_template(
+                "nullable: {{nullable}} --> {{#if nullable }}true{{else}}false{{/if}}",
+                &data
+            )
+            .unwrap()
+        );
+        assert_eq!(
+            "falsevalue: true --> true",
+            reg.render_template(
+                "falsevalue: {{falsevalue}} --> {{#if falsevalue }}true{{else}}false{{/if}}",
+                &data
+            )
+            .unwrap()
+        );
+        assert_eq!(
+            "null: true --> false",
+            reg.render_template(
+                "null: {{null}} --> {{#if null }}true{{else}}false{{/if}}",
+                &data
+            )
+            .unwrap()
+        );
+        assert_eq!(
+            "null: true --> true",
+            reg.render_template(
+                "null: {{null}} --> {{#if this.[null]}}true{{else}}false{{/if}}",
+                &data
+            )
+            .unwrap()
+        );
+    }
 }
diff --git a/third_party/rust_crates/vendor/handlebars/src/render.rs b/third_party/rust_crates/vendor/handlebars/src/render.rs
index 25488d7..b49310f 100644
--- a/third_party/rust_crates/vendor/handlebars/src/render.rs
+++ b/third_party/rust_crates/vendor/handlebars/src/render.rs
@@ -1,44 +1,46 @@
-use std::borrow::Borrow;
-use std::collections::VecDeque;
+use std::borrow::{Borrow, Cow};
+use std::collections::{BTreeMap, VecDeque};
 use std::fmt;
 use std::ops::Deref;
 use std::rc::Rc;
 
-use hashbrown::HashMap;
-use serde::Serialize;
 use serde_json::value::Value as Json;
 
+use crate::block::BlockContext;
 use crate::context::Context;
 use crate::error::RenderError;
 use crate::helpers::HelperDef;
+use crate::json::path::Path;
+use crate::json::value::{JsonRender, PathAndJson, ScopedJson};
 use crate::output::{Output, StringOutput};
 use crate::partial;
 use crate::registry::Registry;
 use crate::template::TemplateElement::*;
 use crate::template::{
-    BlockParam, DirectiveTemplate, HelperTemplate, Parameter, Template, TemplateElement,
+    BlockParam, DecoratorTemplate, HelperTemplate, Parameter, Template, TemplateElement,
     TemplateMapping,
 };
-use crate::value::{JsonRender, PathAndJson, ScopedJson};
+
+const HELPER_MISSING: &str = "helperMissing";
+const BLOCK_HELPER_MISSING: &str = "blockHelperMissing";
 
 /// The context of a render call
 ///
-/// this context stores information of a render and a writer where generated
+/// This context stores information of a render and a writer where generated
 /// content is written to.
 ///
 #[derive(Clone, Debug)]
-pub struct RenderContext<'reg> {
-    inner: Rc<RenderContextInner<'reg>>,
-    block: Rc<BlockRenderContext>,
+pub struct RenderContext<'reg, 'rc> {
+    inner: Rc<RenderContextInner<'reg, 'rc>>,
+    blocks: VecDeque<BlockContext<'reg>>,
     // copy-on-write context
     modified_context: Option<Rc<Context>>,
 }
 
 #[derive(Clone)]
-pub struct RenderContextInner<'reg> {
-    partials: HashMap<String, &'reg Template>,
-    local_helpers: HashMap<String, Rc<Box<HelperDef + 'static>>>,
-    local_variables: HashMap<String, Json>,
+pub struct RenderContextInner<'reg: 'rc, 'rc> {
+    partials: BTreeMap<String, &'reg Template>,
+    local_helpers: BTreeMap<String, Rc<dyn HelperDef + 'rc>>,
     /// current template name
     current_template: Option<&'reg String>,
     /// root template name
@@ -46,138 +48,137 @@
     disable_escape: bool,
 }
 
-#[derive(Debug, Clone)]
-pub struct BlockRenderContext {
-    path: String,
-    local_path_root: VecDeque<String>,
-    block_context: VecDeque<Context>,
-}
-
-impl Default for BlockRenderContext {
-    fn default() -> BlockRenderContext {
-        BlockRenderContext {
-            path: ".".to_owned(),
-            local_path_root: VecDeque::new(),
-            block_context: VecDeque::new(),
-        }
-    }
-}
-
-impl<'reg> RenderContext<'reg> {
+impl<'reg: 'rc, 'rc> RenderContext<'reg, 'rc> {
     /// Create a render context from a `Write`
-    pub fn new(root_template: Option<&'reg String>) -> RenderContext<'reg> {
+    pub fn new(root_template: Option<&'reg String>) -> RenderContext<'reg, 'rc> {
         let inner = Rc::new(RenderContextInner {
-            partials: HashMap::new(),
-            local_variables: HashMap::new(),
-            local_helpers: HashMap::new(),
+            partials: BTreeMap::new(),
+            local_helpers: BTreeMap::new(),
             current_template: None,
             root_template,
             disable_escape: false,
         });
 
-        let block = Rc::new(BlockRenderContext::default());
+        let mut blocks = VecDeque::with_capacity(5);
+        blocks.push_front(BlockContext::new());
+
         let modified_context = None;
         RenderContext {
             inner,
-            block,
+            blocks,
             modified_context,
         }
     }
 
-    pub fn derive(&self) -> RenderContext<'reg> {
-        self.clone()
-    }
-
-    pub fn new_for_block(&self) -> RenderContext<'reg> {
+    // TODO: better name
+    pub(crate) fn new_for_block(&self) -> RenderContext<'reg, 'rc> {
         let inner = self.inner.clone();
-        let block = Rc::new(BlockRenderContext::default());
+
+        let mut blocks = VecDeque::with_capacity(2);
+        blocks.push_front(BlockContext::new());
+
         let modified_context = self.modified_context.clone();
 
         RenderContext {
             inner,
-            block,
+            blocks,
             modified_context,
         }
     }
 
-    fn inner(&self) -> &RenderContextInner<'reg> {
+    /// Push a block context into render context stack. This is typically
+    /// called when you entering a block scope.
+    pub fn push_block(&mut self, block: BlockContext<'reg>) {
+        self.blocks.push_front(block);
+    }
+
+    /// Pop and drop current block context.
+    /// This is typically called when leaving a block scope.
+    pub fn pop_block(&mut self) {
+        self.blocks.pop_front();
+    }
+
+    /// Borrow a reference to current block context
+    pub fn block(&self) -> Option<&BlockContext<'reg>> {
+        self.blocks.front()
+    }
+
+    /// Borrow a mutable reference to current block context in order to
+    /// modify some data.
+    pub fn block_mut(&mut self) -> Option<&mut BlockContext<'reg>> {
+        self.blocks.front_mut()
+    }
+
+    fn inner(&self) -> &RenderContextInner<'reg, 'rc> {
         self.inner.borrow()
     }
 
-    fn inner_mut(&mut self) -> &mut RenderContextInner<'reg> {
+    fn inner_mut(&mut self) -> &mut RenderContextInner<'reg, 'rc> {
         Rc::make_mut(&mut self.inner)
     }
 
-    fn block(&self) -> &BlockRenderContext {
-        self.block.borrow()
-    }
-
-    fn block_mut(&mut self) -> &mut BlockRenderContext {
-        Rc::make_mut(&mut self.block)
-    }
-
+    /// Get the modified context data if any
     pub fn context(&self) -> Option<Rc<Context>> {
         self.modified_context.clone()
     }
 
+    /// Set new context data into the render process.
+    /// This is typically called in decorators where user can modify
+    /// the data they were rendering.
     pub fn set_context(&mut self, ctx: Context) {
         self.modified_context = Some(Rc::new(ctx))
     }
 
-    pub fn evaluate<'ctx>(
+    /// Evaluate a Json path in current scope.
+    ///
+    /// Typically you don't need to evaluate it by yourself.
+    /// The Helper and Decorator API will provide your evaluated value of
+    /// their parameters and hash data.
+    pub fn evaluate(
         &self,
-        context: &'ctx Context,
-        path: &str,
-    ) -> Result<Option<&'ctx Json>, RenderError> {
-        context.navigate(self.get_path(), self.get_local_path_root(), path)
+        context: &'rc Context,
+        relative_path: &str,
+    ) -> Result<ScopedJson<'reg, 'rc>, RenderError> {
+        let path = Path::parse(relative_path)?;
+        self.evaluate2(context, &path)
     }
 
-    pub fn evaluate_absolute<'ctx>(
+    pub(crate) fn evaluate2(
         &self,
-        context: &'ctx Context,
-        path: &str,
-    ) -> Result<Option<&'ctx Json>, RenderError> {
-        context.navigate(".", &VecDeque::new(), path)
+        context: &'rc Context,
+        path: &Path,
+    ) -> Result<ScopedJson<'reg, 'rc>, RenderError> {
+        match path {
+            Path::Local((level, name, _)) => Ok(self
+                .get_local_var(*level, name)
+                .map(|v| ScopedJson::Derived(v.clone()))
+                .unwrap_or_else(|| ScopedJson::Missing)),
+            Path::Relative((segs, _)) => context.navigate(segs, &self.blocks),
+        }
     }
 
+    /// Get registered partial in this render context
     pub fn get_partial(&self, name: &str) -> Option<&&Template> {
         self.inner().partials.get(name)
     }
 
-    pub fn set_partial(&mut self, name: String, result: &'reg Template) {
-        self.inner_mut().partials.insert(name, result);
+    /// Register a partial for this context
+    pub fn set_partial(&mut self, name: String, partial: &'reg Template) {
+        self.inner_mut().partials.insert(name, partial);
     }
 
-    pub fn set_local_var(&mut self, name: String, value: Json) {
-        self.inner_mut().local_variables.insert(name, value);
+    /// Remove a registered partial
+    pub fn remove_partial(&mut self, name: &str) {
+        self.inner_mut().partials.remove(name);
     }
 
-    pub fn clear_local_vars(&mut self) {
-        self.inner_mut().local_variables.clear();
+    fn get_local_var(&self, level: usize, name: &str) -> Option<&Json> {
+        self.blocks
+            .get(level)
+            .and_then(|blk| blk.get_local_var(&name))
     }
 
-    pub fn promote_local_vars(&mut self) {
-        let mut new_map: HashMap<String, Json> = HashMap::new();
-        for (key, v) in &self.inner().local_variables {
-            new_map.insert(format!("@../{}", &key[1..]), v.clone());
-        }
-        self.inner_mut().local_variables = new_map;
-    }
-
-    pub fn demote_local_vars(&mut self) {
-        let mut new_map: HashMap<String, Json> = HashMap::new();
-        for (key, v) in &self.inner().local_variables {
-            if key.starts_with("@../") {
-                new_map.insert(format!("@{}", &key[4..]), v.clone());
-            }
-        }
-        self.inner_mut().local_variables = new_map;
-    }
-
-    pub fn get_local_var(&self, name: &str) -> Option<&Json> {
-        self.inner().local_variables.get(name)
-    }
-
+    /// Test if given template name is current template.
     pub fn is_current_template(&self, p: &str) -> bool {
         self.inner()
             .current_template
@@ -185,103 +186,68 @@
             .unwrap_or(false)
     }
 
+    /// Register a helper in this render context.
+    /// This is a feature provided by Decorator where you can create
+    /// temporary helpers.
     pub fn register_local_helper(
         &mut self,
         name: &str,
-        def: Box<HelperDef + 'static>,
-    ) -> Option<Rc<Box<HelperDef + 'static>>> {
+        def: Box<dyn HelperDef + 'rc>,
+    ) -> Option<Rc<dyn HelperDef + 'rc>> {
         self.inner_mut()
             .local_helpers
-            .insert(name.to_string(), Rc::new(def))
+            .insert(name.to_string(), def.into())
     }
 
+    /// Remove a helper from render context
     pub fn unregister_local_helper(&mut self, name: &str) {
         self.inner_mut().local_helpers.remove(name);
     }
 
-    pub fn get_local_helper(&self, name: &str) -> Option<Rc<Box<HelperDef + 'static>>> {
+    /// Attempt to get a helper from current render context.
+    pub fn get_local_helper(&self, name: &str) -> Option<Rc<dyn HelperDef + 'rc>> {
         self.inner().local_helpers.get(name).cloned()
     }
 
+    #[inline]
+    fn has_local_helper(&self, name: &str) -> bool {
+        self.inner.local_helpers.contains_key(name)
+    }
+
+    /// Returns the current template name.
+    /// Note that the name can be vary from root template when you are rendering
+    /// from partials.
     pub fn get_current_template_name(&self) -> Option<&'reg String> {
         self.inner().current_template
     }
 
+    /// Set the current template name.
     pub fn set_current_template_name(&mut self, name: Option<&'reg String>) {
         self.inner_mut().current_template = name;
     }
 
+    /// Get root template name if any.
+    /// This is the template name that you call `render` from `Handlebars`.
     pub fn get_root_template_name(&self) -> Option<&'reg String> {
         self.inner().root_template
     }
 
-    pub fn set_root_template_name(&mut self, name: Option<&'reg String>) {
-        self.inner_mut().root_template = name;
-    }
-
+    /// Get the escape toggle
     pub fn is_disable_escape(&self) -> bool {
         self.inner().disable_escape
     }
 
+    /// Set the escape toggle.
+    /// When toggle is on, escape_fn will be called when rendering.
     pub fn set_disable_escape(&mut self, disable: bool) {
         self.inner_mut().disable_escape = disable
     }
-
-    pub fn get_path(&self) -> &String {
-        &self.block().path
-    }
-
-    pub fn set_path(&mut self, path: String) {
-        self.block_mut().path = path;
-    }
-
-    pub fn get_local_path_root(&self) -> &VecDeque<String> {
-        &self.block().local_path_root
-    }
-
-    pub fn push_local_path_root(&mut self, path: String) {
-        self.block_mut().local_path_root.push_front(path)
-    }
-
-    pub fn pop_local_path_root(&mut self) {
-        self.block_mut().local_path_root.pop_front();
-    }
-
-    pub fn push_block_context<T>(&mut self, ctx: &T) -> Result<(), RenderError>
-    where
-        T: Serialize,
-    {
-        self.block_mut()
-            .block_context
-            .push_front(Context::wraps(ctx)?);
-        Ok(())
-    }
-
-    pub fn pop_block_context(&mut self) {
-        self.block_mut().block_context.pop_front();
-    }
-
-    pub fn evaluate_in_block_context(
-        &self,
-        local_path: &str,
-    ) -> Result<Option<&Json>, RenderError> {
-        let block = self.block();
-        for bc in &block.block_context {
-            let v = bc.navigate(".", &block.local_path_root, local_path)?;
-            if v.is_some() {
-                return Ok(v);
-            }
-        }
-
-        Ok(None)
-    }
 }
 
-impl<'reg> fmt::Debug for RenderContextInner<'reg> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+impl<'reg, 'rc> fmt::Debug for RenderContextInner<'reg, 'rc> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
         f.debug_struct("RenderContextInner")
             .field("partials", &self.partials)
-            .field("local_variables", &self.local_variables)
             .field("root_template", &self.root_template)
             .field("current_template", &self.current_template)
             .field("disable_eacape", &self.disable_escape)
@@ -289,12 +255,12 @@
     }
 }
 
-// Render-time Helper data when using in a helper definition
+/// Render-time Helper data when using in a helper definition
 #[derive(Debug)]
-pub struct Helper<'reg: 'rc, 'rc> {
-    name: &'reg String,
+pub struct Helper<'reg, 'rc> {
+    name: Cow<'reg, str>,
     params: Vec<PathAndJson<'reg, 'rc>>,
-    hash: HashMap<String, PathAndJson<'reg, 'rc>>,
+    hash: BTreeMap<&'reg str, PathAndJson<'reg, 'rc>>,
     template: Option<&'reg Template>,
     inverse: Option<&'reg Template>,
     block_param: Option<&'reg BlockParam>,
@@ -304,24 +270,25 @@
 impl<'reg: 'rc, 'rc> Helper<'reg, 'rc> {
     fn try_from_template(
         ht: &'reg HelperTemplate,
-        registry: &'reg Registry,
+        registry: &'reg Registry<'reg>,
         context: &'rc Context,
-        render_context: &mut RenderContext<'reg>,
+        render_context: &mut RenderContext<'reg, 'rc>,
     ) -> Result<Helper<'reg, 'rc>, RenderError> {
+        let name = ht.name.expand_as_name(registry, context, render_context)?;
         let mut pv = Vec::with_capacity(ht.params.len());
         for p in &ht.params {
             let r = p.expand(registry, context, render_context)?;
             pv.push(r);
         }
 
-        let mut hm = HashMap::new();
+        let mut hm = BTreeMap::new();
         for (k, p) in &ht.hash {
             let r = p.expand(registry, context, render_context)?;
-            hm.insert(k.clone(), r);
+            hm.insert(k.as_ref(), r);
         }
 
         Ok(Helper {
-            name: &ht.name,
+            name,
             params: pv,
             hash: hm,
             template: ht.template.as_ref(),
@@ -332,8 +299,8 @@
     }
 
     /// Returns helper name
-    pub fn name(&self) -> &'reg str {
-        self.name
+    pub fn name(&self) -> &str {
+        &self.name
     }
 
     /// Returns all helper params, resolved within the context
@@ -364,7 +331,7 @@
     }
 
     /// Returns hash, resolved within the context
-    pub fn hash(&self) -> &HashMap<String, PathAndJson<'reg, 'rc>> {
+    pub fn hash(&self) -> &BTreeMap<&'reg str, PathAndJson<'reg, 'rc>> {
         &self.hash
     }
 
@@ -408,8 +375,13 @@
         self.block
     }
 
+    /// Returns if the helper has either a block param or block param pair
+    pub fn has_block_param(&self) -> bool {
+        self.block_param.is_some()
+    }
+
     /// Returns block param if any
-    pub fn block_param(&self) -> Option<&str> {
+    pub fn block_param(&self) -> Option<&'reg str> {
         if let Some(&BlockParam::Single(Parameter::Name(ref s))) = self.block_param {
             Some(s)
         } else {
@@ -418,7 +390,7 @@
     }
 
     /// Return block param pair (for example |key, val|) if any
-    pub fn block_param_pair(&self) -> Option<(&str, &str)> {
+    pub fn block_param_pair(&self) -> Option<(&'reg str, &'reg str)> {
         if let Some(&BlockParam::Pair((Parameter::Name(ref s1), Parameter::Name(ref s2)))) =
             self.block_param
         {
@@ -429,22 +401,22 @@
     }
 }
 
-// Render-time Directive data when using in a directive definition
+/// Render-time Decorator data when using in a decorator definition
 #[derive(Debug)]
-pub struct Directive<'reg: 'rc, 'rc> {
-    name: String,
+pub struct Decorator<'reg, 'rc> {
+    name: Cow<'reg, str>,
     params: Vec<PathAndJson<'reg, 'rc>>,
-    hash: HashMap<String, PathAndJson<'reg, 'rc>>,
+    hash: BTreeMap<&'reg str, PathAndJson<'reg, 'rc>>,
     template: Option<&'reg Template>,
 }
 
-impl<'reg: 'rc, 'rc> Directive<'reg, 'rc> {
+impl<'reg: 'rc, 'rc> Decorator<'reg, 'rc> {
     fn try_from_template(
-        dt: &'reg DirectiveTemplate,
-        registry: &'reg Registry,
+        dt: &'reg DecoratorTemplate,
+        registry: &'reg Registry<'reg>,
         context: &'rc Context,
-        render_context: &mut RenderContext<'reg>,
-    ) -> Result<Directive<'reg, 'rc>, RenderError> {
+        render_context: &mut RenderContext<'reg, 'rc>,
+    ) -> Result<Decorator<'reg, 'rc>, RenderError> {
         let name = dt.name.expand_as_name(registry, context, render_context)?;
 
         let mut pv = Vec::with_capacity(dt.params.len());
@@ -453,13 +425,13 @@
             pv.push(r);
         }
 
-        let mut hm = HashMap::new();
+        let mut hm = BTreeMap::new();
         for (k, p) in &dt.hash {
             let r = p.expand(registry, context, render_context)?;
-            hm.insert(k.clone(), r);
+            hm.insert(k.as_ref(), r);
         }
 
-        Ok(Directive {
+        Ok(Decorator {
             name,
             params: pv,
             hash: hm,
@@ -468,8 +440,8 @@
     }
 
     /// Returns helper name
-    pub fn name(&self) -> &String {
-        &self.name
+    pub fn name(&self) -> &str {
+        self.name.as_ref()
     }
 
     /// Returns all helper params, resolved within the context
@@ -483,7 +455,7 @@
     }
 
     /// Returns hash, resolved within the context
-    pub fn hash(&self) -> &HashMap<String, PathAndJson<'reg, 'rc>> {
+    pub fn hash(&self) -> &BTreeMap<&'reg str, PathAndJson<'reg, 'rc>> {
         &self.hash
     }
 
@@ -503,18 +475,18 @@
     /// render into RenderContext's `writer`
     fn render<'reg: 'rc, 'rc>(
         &'reg self,
-        registry: &'reg Registry,
+        registry: &'reg Registry<'reg>,
         context: &'rc Context,
-        rc: &'rc mut RenderContext<'reg>,
-        out: &mut Output,
+        rc: &mut RenderContext<'reg, 'rc>,
+        out: &mut dyn Output,
     ) -> Result<(), RenderError>;
 
     /// render into string
     fn renders<'reg: 'rc, 'rc>(
         &'reg self,
-        registry: &'reg Registry,
+        registry: &'reg Registry<'reg>,
         ctx: &'rc Context,
-        rc: &'rc mut RenderContext<'reg>,
+        rc: &mut RenderContext<'reg, 'rc>,
     ) -> Result<String, RenderError> {
         let mut so = StringOutput::new();
         self.render(registry, ctx, rc, &mut so)?;
@@ -522,22 +494,22 @@
     }
 }
 
-/// Evaluate directive or decorator
+/// Evaluate decorator
 pub trait Evaluable {
     fn eval<'reg: 'rc, 'rc>(
         &'reg self,
-        registry: &'reg Registry,
+        registry: &'reg Registry<'reg>,
         context: &'rc Context,
-        rc: &'rc mut RenderContext<'reg>,
+        rc: &mut RenderContext<'reg, 'rc>,
     ) -> Result<(), RenderError>;
 }
 
 fn call_helper_for_value<'reg: 'rc, 'rc>(
-    hd: &HelperDef,
+    hd: &dyn HelperDef,
     ht: &Helper<'reg, 'rc>,
-    r: &'reg Registry,
+    r: &'reg Registry<'reg>,
     ctx: &'rc Context,
-    rc: &mut RenderContext<'reg>,
+    rc: &mut RenderContext<'reg, 'rc>,
 ) -> Result<PathAndJson<'reg, 'rc>, RenderError> {
     if let Some(result) = hd.call_inner(ht, r, ctx, rc)? {
         Ok(PathAndJson::new(None, result))
@@ -564,87 +536,71 @@
 impl Parameter {
     pub fn expand_as_name<'reg: 'rc, 'rc>(
         &'reg self,
-        registry: &'reg Registry,
+        registry: &'reg Registry<'reg>,
         ctx: &'rc Context,
-        rc: &mut RenderContext<'reg>,
-    ) -> Result<String, RenderError> {
-        match *self {
-            Parameter::Name(ref name) => Ok(name.to_owned()),
-            Parameter::Subexpression(_) => {
-                self.expand(registry, ctx, rc).map(|v| v.value().render())
-            }
-            Parameter::Literal(ref j) => Ok(j.render()),
+        rc: &mut RenderContext<'reg, 'rc>,
+    ) -> Result<Cow<'reg, str>, RenderError> {
+        match self {
+            Parameter::Name(ref name) => Ok(Cow::Borrowed(name)),
+            Parameter::Path(ref p) => Ok(Cow::Borrowed(p.raw())),
+            Parameter::Subexpression(_) => self
+                .expand(registry, ctx, rc)
+                .map(|v| v.value().render())
+                .map(Cow::Owned),
+            Parameter::Literal(ref j) => Ok(Cow::Owned(j.render())),
         }
     }
 
     pub fn expand<'reg: 'rc, 'rc>(
         &'reg self,
-        registry: &'reg Registry,
+        registry: &'reg Registry<'reg>,
         ctx: &'rc Context,
-        rc: &mut RenderContext<'reg>,
+        rc: &mut RenderContext<'reg, 'rc>,
     ) -> Result<PathAndJson<'reg, 'rc>, RenderError> {
-        match *self {
+        match self {
             Parameter::Name(ref name) => {
-                if let Some(value) = rc.get_local_var(name) {
-                    // local var, @first, @last for example
-                    // here we count it as derived value, and simply clone it
-                    // to bypass lifetime issue
+                // FIXME: raise error when expanding with name?
+                Ok(PathAndJson::new(Some(name.to_owned()), ScopedJson::Missing))
+            }
+            Parameter::Path(ref path) => {
+                if let Some(rc_context) = rc.context() {
+                    let result = rc.evaluate2(rc_context.borrow(), path)?;
                     Ok(PathAndJson::new(
-                        Some(name.to_owned()),
-                        ScopedJson::Derived(value.clone()),
-                    ))
-                } else if let Some(block_context_value) = rc.evaluate_in_block_context(name)? {
-                    // try to evaluate using block context if any
-
-                    // we do clone for block context because it's from
-                    // render_context
-                    Ok(PathAndJson::new(
-                        Some(name.to_owned()),
-                        ScopedJson::Derived(block_context_value.clone()),
-                    ))
-                } else if let Some(rc_context) = rc.context() {
-                    // the context is modified from a decorator
-                    // use the modified one
-                    let json = rc.evaluate(rc_context.borrow(), name)?;
-                    // the data is fetched from mutable reference render_context
-                    // so we have to clone it to bypass lifetime check
-                    Ok(PathAndJson::new(
-                        Some(name.to_owned()),
-                        json.map(|j| ScopedJson::Derived(j.clone()))
-                            .unwrap_or_else(|| ScopedJson::Missing),
+                        Some(path.raw().to_owned()),
+                        ScopedJson::Derived(result.as_json().clone()),
                     ))
                 } else {
-                    // failback to normal evaluation
-                    Ok(PathAndJson::new(
-                        Some(name.to_owned()),
-                        rc.evaluate(ctx, name)?
-                            .map(|json| ScopedJson::Context(json))
-                            .unwrap_or_else(|| ScopedJson::Missing),
-                    ))
+                    let result = rc.evaluate2(ctx, path)?;
+                    Ok(PathAndJson::new(Some(path.raw().to_owned()), result))
                 }
             }
             Parameter::Literal(ref j) => Ok(PathAndJson::new(None, ScopedJson::Constant(j))),
             Parameter::Subexpression(ref t) => match *t.as_element() {
-                Expression(ref expr) => expr.expand(registry, ctx, rc),
-                HelperExpression(ref ht) => {
-                    let h = Helper::try_from_template(ht, registry, ctx, rc)?;
-                    if let Some(ref d) = rc.get_local_helper(&ht.name) {
-                        let helper_def = d.deref().as_ref();
-                        call_helper_for_value(helper_def, &h, registry, ctx, rc)
+                Expression(ref ht) => {
+                    if ht.is_name_only() {
+                        ht.name.expand(registry, ctx, rc)
                     } else {
-                        registry
-                            .get_helper(&ht.name)
-                            .or_else(|| {
-                                registry.get_helper(if ht.block {
-                                    "blockHelperMissing"
-                                } else {
-                                    "helperMissing"
+                        let name = ht.name.expand_as_name(registry, ctx, rc)?;
+
+                        let h = Helper::try_from_template(ht, registry, ctx, rc)?;
+                        if let Some(ref d) = rc.get_local_helper(&name) {
+                            let helper_def = d.deref();
+                            call_helper_for_value(helper_def, &h, registry, ctx, rc)
+                        } else {
+                            registry
+                                .get_helper(&name)
+                                .or_else(|| {
+                                    registry.get_helper(if ht.block {
+                                        BLOCK_HELPER_MISSING
+                                    } else {
+                                        HELPER_MISSING
+                                    })
                                 })
-                            })
-                            .ok_or_else(|| {
-                                RenderError::new(format!("Helper not defined: {:?}", ht.name))
-                            })
-                            .and_then(move |d| call_helper_for_value(d, &h, registry, ctx, rc))
+                                .ok_or_else(|| {
+                                    RenderError::new(format!("Helper not defined: {:?}", ht.name))
+                                })
+                                .and_then(move |d| call_helper_for_value(d, &h, registry, ctx, rc))
+                        }
                     }
                 }
                 _ => unreachable!(),
@@ -656,15 +612,15 @@
 impl Renderable for Template {
     fn render<'reg: 'rc, 'rc>(
         &'reg self,
-        registry: &'reg Registry,
+        registry: &'reg Registry<'reg>,
         ctx: &'rc Context,
-        rc: &mut RenderContext<'reg>,
-        out: &mut Output,
+        rc: &mut RenderContext<'reg, 'rc>,
+        out: &mut dyn Output,
     ) -> Result<(), RenderError> {
         rc.set_current_template_name(self.name.as_ref());
         let iter = self.elements.iter();
-        let mut idx = 0;
-        for t in iter {
+
+        for (idx, t) in iter.enumerate() {
             t.render(registry, ctx, rc, out).map_err(|mut e| {
                 // add line/col number if the template has mapping data
                 if e.line_no.is_none() {
@@ -682,7 +638,6 @@
 
                 e
             })?;
-            idx += 1;
         }
         Ok(())
     }
@@ -691,13 +646,13 @@
 impl Evaluable for Template {
     fn eval<'reg: 'rc, 'rc>(
         &'reg self,
-        registry: &'reg Registry,
+        registry: &'reg Registry<'reg>,
         ctx: &'rc Context,
-        rc: &mut RenderContext<'reg>,
+        rc: &mut RenderContext<'reg, 'rc>,
     ) -> Result<(), RenderError> {
         let iter = self.elements.iter();
-        let mut idx = 0;
-        for t in iter {
+
+        for (idx, t) in iter.enumerate() {
             t.eval(registry, ctx, rc).map_err(|mut e| {
                 if e.line_no.is_none() {
                     if let Some(ref mapping) = self.mapping {
@@ -711,78 +666,122 @@
                 e.template_name = self.name.clone();
                 e
             })?;
-            idx += 1;
         }
         Ok(())
     }
 }
 
+fn helper_exists<'reg: 'rc, 'rc>(
+    name: &str,
+    reg: &Registry<'reg>,
+    rc: &RenderContext<'reg, 'rc>,
+) -> bool {
+    rc.has_local_helper(name) || reg.has_helper(name)
+}
+
+fn render_helper<'reg: 'rc, 'rc>(
+    ht: &'reg HelperTemplate,
+    registry: &'reg Registry<'reg>,
+    ctx: &'rc Context,
+    rc: &mut RenderContext<'reg, 'rc>,
+    out: &mut dyn Output,
+) -> Result<(), RenderError> {
+    let h = Helper::try_from_template(ht, registry, ctx, rc)?;
+    debug!(
+        "Rendering helper: {:?}, params: {:?}, hash: {:?}",
+        h.name(),
+        h.params(),
+        h.hash()
+    );
+    if let Some(ref d) = rc.get_local_helper(h.name()) {
+        d.call(&h, registry, ctx, rc, out)
+    } else {
+        registry
+            .get_helper(h.name())
+            .or_else(|| {
+                registry.get_helper(if ht.block {
+                    BLOCK_HELPER_MISSING
+                } else {
+                    HELPER_MISSING
+                })
+            })
+            .ok_or_else(|| RenderError::new(format!("Helper not defined: {:?}", ht.name)))
+            .and_then(move |d| d.call(&h, registry, ctx, rc, out))
+    }
+}
+
+pub(crate) fn do_escape(r: &Registry<'_>, rc: &RenderContext<'_, '_>, content: String) -> String {
+    if !rc.is_disable_escape() {
+        r.get_escape_fn()(&content)
+    } else {
+        content
+    }
+}
+
 impl Renderable for TemplateElement {
     fn render<'reg: 'rc, 'rc>(
         &'reg self,
-        registry: &'reg Registry,
+        registry: &'reg Registry<'reg>,
         ctx: &'rc Context,
-        rc: &mut RenderContext<'reg>,
-        out: &mut Output,
+        rc: &mut RenderContext<'reg, 'rc>,
+        out: &mut dyn Output,
     ) -> Result<(), RenderError> {
         match *self {
             RawString(ref v) => {
                 out.write(v.as_ref())?;
                 Ok(())
             }
-            Expression(ref v) => {
-                let context_json = v.expand(registry, ctx, rc)?;
-
-                // strict mode check
-                if registry.strict_mode() && context_json.is_value_missing() {
-                    return Err(RenderError::strict_error(context_json.path()));
-                }
-
-                let rendered = context_json.value().render();
-
-                let output = if !rc.is_disable_escape() {
-                    registry.get_escape_fn()(&rendered)
+            Expression(ref ht) => {
+                // test if the expression is to render some value
+                if ht.is_name_only() {
+                    let helper_name = ht.name.expand_as_name(registry, ctx, rc)?;
+                    if helper_exists(&helper_name, registry, rc) {
+                        render_helper(ht, registry, ctx, rc, out)
+                    } else {
+                        debug!("Rendering value: {:?}", ht.name);
+                        let context_json = ht.name.expand(registry, ctx, rc)?;
+                        if context_json.is_value_missing() {
+                            if registry.strict_mode() {
+                                Err(RenderError::strict_error(context_json.relative_path()))
+                            } else {
+                                // helper missing
+                                if let Some(hook) = registry.get_helper(HELPER_MISSING) {
+                                    let h = Helper::try_from_template(ht, registry, ctx, rc)?;
+                                    hook.call(&h, registry, ctx, rc, out)
+                                } else {
+                                    Ok(())
+                                }
+                            }
+                        } else {
+                            let rendered = context_json.value().render();
+                            let output = do_escape(registry, rc, rendered);
+                            out.write(output.as_ref())?;
+                            Ok(())
+                        }
+                    }
                 } else {
-                    rendered
-                };
-                out.write(output.as_ref())?;
-                Ok(())
+                    // this is a helper expression
+                    render_helper(ht, registry, ctx, rc, out)
+                }
             }
             HTMLExpression(ref v) => {
+                debug!("Rendering value: {:?}", v);
                 let context_json = v.expand(registry, ctx, rc)?;
 
                 // strict mode check
                 if registry.strict_mode() && context_json.is_value_missing() {
-                    return Err(RenderError::strict_error(context_json.path()));
+                    return Err(RenderError::strict_error(context_json.relative_path()));
                 }
 
                 let rendered = context_json.value().render();
                 out.write(rendered.as_ref())?;
                 Ok(())
             }
-            HelperExpression(ref ht) | HelperBlock(ref ht) => {
-                let h = Helper::try_from_template(ht, registry, ctx, rc)?;
-                if let Some(ref d) = rc.get_local_helper(&ht.name) {
-                    d.call(&h, registry, ctx, rc, out)
-                } else {
-                    registry
-                        .get_helper(&ht.name)
-                        .or_else(|| {
-                            registry.get_helper(if ht.block {
-                                "blockHelperMissing"
-                            } else {
-                                "helperMissing"
-                            })
-                        })
-                        .ok_or_else(|| {
-                            RenderError::new(format!("Helper not defined: {:?}", ht.name))
-                        })
-                        .and_then(move |d| d.call(&h, registry, ctx, rc, out))
-                }
-            }
-            DirectiveExpression(_) | DirectiveBlock(_) => self.eval(registry, ctx, rc),
+            HelperBlock(ref ht) => render_helper(ht, registry, ctx, rc, out),
+            DecoratorExpression(_) | DecoratorBlock(_) => self.eval(registry, ctx, rc),
             PartialExpression(ref dt) | PartialBlock(ref dt) => {
-                let di = Directive::try_from_template(dt, registry, ctx, rc)?;
+                let di = Decorator::try_from_template(dt, registry, ctx, rc)?;
+
                 partial::expand_partial(&di, registry, ctx, rc, out)
             }
             _ => Ok(()),
@@ -793,17 +792,17 @@
 impl Evaluable for TemplateElement {
     fn eval<'reg: 'rc, 'rc>(
         &'reg self,
-        registry: &'reg Registry,
+        registry: &'reg Registry<'reg>,
         ctx: &'rc Context,
-        rc: &mut RenderContext<'reg>,
+        rc: &mut RenderContext<'reg, 'rc>,
     ) -> Result<(), RenderError> {
         match *self {
-            DirectiveExpression(ref dt) | DirectiveBlock(ref dt) => {
-                let di = Directive::try_from_template(dt, registry, ctx, rc)?;
+            DecoratorExpression(ref dt) | DecoratorBlock(ref dt) => {
+                let di = Decorator::try_from_template(dt, registry, ctx, rc)?;
                 match registry.get_decorator(di.name()) {
                     Some(d) => d.call(&di, registry, ctx, rc),
                     None => Err(RenderError::new(format!(
-                        "Directive not defined: {:?}",
+                        "Decorator not defined: {:?}",
                         dt.name
                     ))),
                 }
@@ -833,10 +832,12 @@
 #[test]
 fn test_expression() {
     let r = Registry::new();
-    let element = Expression(Parameter::Name("hello".into()));
+    let element = Expression(Box::new(HelperTemplate::with_path(Path::with_named_paths(
+        &["hello"],
+    ))));
 
     let mut out = StringOutput::new();
-    let mut m: HashMap<String, String> = HashMap::new();
+    let mut m: BTreeMap<String, String> = BTreeMap::new();
     let value = "<p></p>".to_string();
     m.insert("hello".to_string(), value);
     let ctx = Context::wraps(&m).unwrap();
@@ -854,10 +855,10 @@
 #[test]
 fn test_html_expression() {
     let r = Registry::new();
-    let element = HTMLExpression(Parameter::Name("hello".into()));
+    let element = HTMLExpression(Parameter::Path(Path::with_named_paths(&["hello"])));
 
     let mut out = StringOutput::new();
-    let mut m: HashMap<String, String> = HashMap::new();
+    let mut m: BTreeMap<String, String> = BTreeMap::new();
     let value = "world";
     m.insert("hello".to_string(), value.to_string());
     let ctx = Context::wraps(&m).unwrap();
@@ -873,14 +874,16 @@
 fn test_template() {
     let r = Registry::new();
     let mut out = StringOutput::new();
-    let mut m: HashMap<String, String> = HashMap::new();
+    let mut m: BTreeMap<String, String> = BTreeMap::new();
     let value = "world".to_string();
     m.insert("hello".to_string(), value);
     let ctx = Context::wraps(&m).unwrap();
 
     let elements: Vec<TemplateElement> = vec![
         RawString("<h1>".to_string()),
-        Expression(Parameter::Name("hello".into())),
+        Expression(Box::new(HelperTemplate::with_path(Path::with_named_paths(
+            &["hello"],
+        )))),
         RawString("</h1>".to_string()),
         Comment("".to_string()),
     ];
@@ -901,24 +904,23 @@
 
 #[test]
 fn test_render_context_promotion_and_demotion() {
-    use crate::value::to_json;
+    use crate::json::value::to_json;
     let mut render_context = RenderContext::new(None);
+    let mut block = BlockContext::new();
 
-    render_context.set_local_var("@index".to_string(), to_json(0));
+    block.set_local_var("@index".to_string(), to_json(0));
+    render_context.push_block(block);
 
-    render_context.promote_local_vars();
-
+    render_context.push_block(BlockContext::new());
     assert_eq!(
-        render_context
-            .get_local_var(&"@../index".to_string())
-            .unwrap(),
+        render_context.get_local_var(1, "index").unwrap(),
         &to_json(0)
     );
 
-    render_context.demote_local_vars();
+    render_context.pop_block();
 
     assert_eq!(
-        render_context.get_local_var(&"@index".to_string()).unwrap(),
+        render_context.get_local_var(0, "index").unwrap(),
         &to_json(0)
     );
 }
@@ -930,7 +932,7 @@
     let r = Registry::new();
     let mut sw = StringWriter::new();
 
-    let mut m: HashMap<String, String> = HashMap::new();
+    let mut m: BTreeMap<String, String> = BTreeMap::new();
     m.insert("hello".to_string(), "world".to_string());
     m.insert("world".to_string(), "nice".to_string());
     m.insert("const".to_string(), "truthy".to_string());
@@ -954,11 +956,11 @@
     r.register_helper(
         "format",
         Box::new(
-            |h: &Helper,
-             _: &Registry,
+            |h: &Helper<'_, '_>,
+             _: &Registry<'_>,
              _: &Context,
-             _: &mut RenderContext,
-             out: &mut Output|
+             _: &mut RenderContext<'_, '_>,
+             out: &mut dyn Output|
              -> Result<(), RenderError> {
                 out.write(format!("{}", h.param(0).unwrap().value().render()).as_ref())
                     .map(|_| ())
@@ -968,7 +970,7 @@
     );
 
     let mut sw = StringWriter::new();
-    let mut m: HashMap<String, String> = HashMap::new();
+    let mut m: BTreeMap<String, String> = BTreeMap::new();
     m.insert("a".to_string(), "123".to_string());
 
     {
@@ -983,7 +985,7 @@
 #[test]
 fn test_render_error_line_no() {
     let mut r = Registry::new();
-    let m: HashMap<String, String> = HashMap::new();
+    let m: BTreeMap<String, String> = BTreeMap::new();
 
     let name = "invalid_template";
     assert!(r
@@ -1023,10 +1025,10 @@
     let mut r = Registry::new();
 
     assert!(r
-        .register_template_string("t", "{{#each .}}{{@key}}: {{this}}\n{{/each}}")
+        .register_template_string("t", "{{#each this}}{{@key}}: {{this}}\n{{/each}}")
         .is_ok());
 
-    let r = r.render("t", &json!({"/foo": "bar"})).expect("should work");
+    let r = r.render("t", &json!({"/foo": "bar"})).unwrap();
 
     assert_eq!(r, "/foo: bar\n");
 }
@@ -1041,3 +1043,67 @@
         "Hello 0 "
     );
 }
+
+#[test]
+fn test_zero_args_heler() {
+    let mut r = Registry::new();
+
+    r.register_helper(
+        "name",
+        Box::new(
+            |_: &Helper<'_, '_>,
+             _: &Registry<'_>,
+             _: &Context,
+             _: &mut RenderContext<'_, '_>,
+             out: &mut dyn Output|
+             -> Result<(), RenderError> { out.write("N/A").map_err(Into::into) },
+        ),
+    );
+
+    r.register_template_string("t0", "Output name: {{name}}")
+        .unwrap();
+    r.register_template_string("t1", "Output name: {{first_name}}")
+        .unwrap();
+    r.register_template_string("t2", "Output name: {{./name}}")
+        .unwrap();
+
+    // when "name" is available in context, use context first
+    assert_eq!(
+        r.render("t0", &json!({"name": "Alex"})).unwrap(),
+        "Output name: N/A"
+    );
+
+    // when "name" is unavailable, call helper with same name
+    assert_eq!(
+        r.render("t2", &json!({"name": "Alex"})).unwrap(),
+        "Output name: Alex"
+    );
+
+    // output nothing when neither context nor helper available
+    assert_eq!(
+        r.render("t1", &json!({"name": "Alex"})).unwrap(),
+        "Output name: "
+    );
+
+    // generate error in strict mode for above case
+    r.set_strict_mode(true);
+    assert!(r.render("t1", &json!({"name": "Alex"})).is_err());
+
+    // output nothing when helperMissing was defined
+    r.set_strict_mode(false);
+    r.register_helper(
+        "helperMissing",
+        Box::new(
+            |_: &Helper<'_, '_>,
+             _: &Registry<'_>,
+             _: &Context,
+             _: &mut RenderContext<'_, '_>,
+             out: &mut dyn Output|
+             -> Result<(), RenderError> { out.write("Default").map_err(Into::into) },
+        ),
+    );
+    assert_eq!(
+        r.render("t1", &json!({"name": "Alex"})).unwrap(),
+        "Output name: Default"
+    );
+}
diff --git a/third_party/rust_crates/vendor/handlebars/src/support.rs b/third_party/rust_crates/vendor/handlebars/src/support.rs
index bd61e1b..bd5564d 100644
--- a/third_party/rust_crates/vendor/handlebars/src/support.rs
+++ b/third_party/rust_crates/vendor/handlebars/src/support.rs
@@ -39,6 +39,24 @@
         }
     }
 
+    /// See https://github.com/handlebars-lang/handlebars.js/blob/37411901da42200ced8e1a7fc2f67bf83526b497/lib/handlebars/utils.js#L1
+    pub fn escape_html(s: &str) -> String {
+        let mut output = String::new();
+        for c in s.chars() {
+            match c {
+                '<' => output.push_str("&lt;"),
+                '>' => output.push_str("&gt;"),
+                '"' => output.push_str("&quot;"),
+                '&' => output.push_str("&amp;"),
+                '\'' => output.push_str("&#x27;"),
+                '`' => output.push_str("&#x60;"),
+                '=' => output.push_str("&#x3D;"),
+                _ => output.push(c),
+            }
+        }
+        output
+    }
+
     #[cfg(test)]
     mod test {
         use crate::support::str::StringWriter;
diff --git a/third_party/rust_crates/vendor/handlebars/src/template.rs b/third_party/rust_crates/vendor/handlebars/src/template.rs
index d14e536..79db431 100644
--- a/third_party/rust_crates/vendor/handlebars/src/template.rs
+++ b/third_party/rust_crates/vendor/handlebars/src/template.rs
@@ -1,17 +1,16 @@
-use std::collections::VecDeque;
+use std::collections::{HashMap, VecDeque};
 use std::convert::From;
 use std::iter::Peekable;
+use std::str::FromStr;
 
-use crate::grammar::{HandlebarsParser, Rule};
 use pest::error::LineColLocation;
 use pest::iterators::Pair;
 use pest::{Parser, Position};
-
-use hashbrown::HashMap;
 use serde_json::value::Value as Json;
-use std::str::FromStr;
 
 use crate::error::{TemplateError, TemplateErrorReason};
+use crate::grammar::{HandlebarsParser, Rule};
+use crate::json::path::{parse_json_path_from_iter, Path};
 
 use self::TemplateElement::*;
 
@@ -34,32 +33,26 @@
 
 impl Subexpression {
     pub fn new(
-        name: String,
-        params: &[Parameter],
-        hash: &HashMap<String, Parameter>,
+        name: Parameter,
+        params: Vec<Parameter>,
+        hash: HashMap<String, Parameter>,
     ) -> Subexpression {
-        if params.is_empty() && hash.is_empty() {
-            Subexpression {
-                element: Box::new(Expression(Parameter::Name(name))),
-            }
-        } else {
-            Subexpression {
-                element: Box::new(HelperExpression(Box::new(HelperTemplate {
-                    name,
-                    params: params.to_owned(),
-                    hash: hash.clone(),
-                    template: None,
-                    inverse: None,
-                    block_param: None,
-                    block: false,
-                }))),
-            }
+        Subexpression {
+            element: Box::new(Expression(Box::new(HelperTemplate {
+                name,
+                params,
+                hash,
+                template: None,
+                inverse: None,
+                block_param: None,
+                block: false,
+            }))),
         }
     }
 
     pub fn is_helper(&self) -> bool {
         match *self.as_element() {
-            TemplateElement::HelperExpression(_) => true,
+            TemplateElement::Expression(ref ht) => !ht.is_name_only(),
             _ => false,
         }
     }
@@ -70,25 +63,22 @@
 
     pub fn name(&self) -> &str {
         match *self.as_element() {
-            HelperExpression(ref ht) => &ht.name,
-            Expression(ref p) => match *p {
-                Parameter::Name(ref s) => s,
-                _ => unreachable!(),
-            },
+            // FIXME: avoid unwrap here
+            Expression(ref ht) => ht.name.as_name().unwrap(),
             _ => unreachable!(),
         }
     }
 
     pub fn params(&self) -> Option<&Vec<Parameter>> {
         match *self.as_element() {
-            HelperExpression(ref ht) => Some(&ht.params),
+            Expression(ref ht) => Some(&ht.params),
             _ => None,
         }
     }
 
     pub fn hash(&self) -> Option<&HashMap<String, Parameter>> {
         match *self.as_element() {
-            HelperExpression(ref ht) => Some(&ht.hash),
+            Expression(ref ht) => Some(&ht.hash),
             _ => None,
         }
     }
@@ -112,14 +102,17 @@
 
 #[derive(PartialEq, Clone, Debug)]
 pub enum Parameter {
+    // for helper name only
     Name(String),
+    // for expression, helper param and hash
+    Path(Path),
     Literal(Json),
     Subexpression(Subexpression),
 }
 
 #[derive(PartialEq, Clone, Debug)]
 pub struct HelperTemplate {
-    pub name: String,
+    pub name: Parameter,
     pub params: Vec<Parameter>,
     pub hash: HashMap<String, Parameter>,
     pub block_param: Option<BlockParam>,
@@ -128,8 +121,27 @@
     pub block: bool,
 }
 
+impl HelperTemplate {
+    // test only
+    pub(crate) fn with_path(path: Path) -> HelperTemplate {
+        HelperTemplate {
+            name: Parameter::Path(path),
+            params: Vec::with_capacity(5),
+            hash: HashMap::new(),
+            block_param: None,
+            template: None,
+            inverse: None,
+            block: false,
+        }
+    }
+
+    pub(crate) fn is_name_only(&self) -> bool {
+        !self.block && self.params.is_empty() && self.hash.is_empty()
+    }
+}
+
 #[derive(PartialEq, Clone, Debug)]
-pub struct DirectiveTemplate {
+pub struct DecoratorTemplate {
     pub name: Parameter,
     pub params: Vec<Parameter>,
     pub hash: HashMap<String, Parameter>,
@@ -137,11 +149,11 @@
 }
 
 impl Parameter {
-    pub fn into_name(self) -> Option<String> {
-        if let Parameter::Name(n) = self {
-            Some(n)
-        } else {
-            None
+    pub fn as_name(&self) -> Option<&str> {
+        match self {
+            Parameter::Name(ref n) => Some(n),
+            Parameter::Path(ref p) => Some(p.raw()),
+            _ => None,
         }
     }
 
@@ -183,16 +195,11 @@
         I: Iterator<Item = Pair<'a, Rule>>,
     {
         let espec = Template::parse_expression(source, it.by_ref(), limit)?;
-        if let Parameter::Name(name) = espec.name {
-            Ok(Parameter::Subexpression(Subexpression::new(
-                name,
-                &espec.params,
-                &espec.hash,
-            )))
-        } else {
-            // line/col no
-            Err(TemplateError::of(TemplateErrorReason::NestedSubexpression))
-        }
+        Ok(Parameter::Subexpression(Subexpression::new(
+            espec.name,
+            espec.params,
+            espec.hash,
+        )))
     }
 
     fn parse_name<'a, I>(
@@ -207,9 +214,13 @@
         let rule = name_node.as_rule();
         let name_span = name_node.as_span();
         match rule {
-            Rule::identifier | Rule::reference | Rule::invert_tag_item => {
+            Rule::identifier | Rule::partial_identifier | Rule::invert_tag_item => {
                 Ok(Parameter::Name(name_span.as_str().to_owned()))
             }
+            Rule::reference => {
+                let paths = parse_json_path_from_iter(it, name_span.end());
+                Ok(Parameter::Path(Path::new(name_span.as_str(), paths)))
+            }
             Rule::subexpression => {
                 Template::parse_subexpression(source, it.by_ref(), name_span.end())
             }
@@ -232,7 +243,10 @@
         let param_rule = param.as_rule();
         let param_span = param.as_span();
         let result = match param_rule {
-            Rule::reference => Parameter::Name(param_span.as_str().to_owned()),
+            Rule::reference => {
+                let path_segs = parse_json_path_from_iter(it, param_span.end());
+                Parameter::Path(Path::new(param_span.as_str(), path_segs))
+            }
             Rule::literal => {
                 let s = param_span.as_str();
                 if let Ok(json) = Json::from_str(s) {
@@ -297,12 +311,9 @@
             }
         });
 
-        if p2.is_some() {
+        if let Some(p2) = p2 {
             it.next();
-            Ok(BlockParam::Pair((
-                Parameter::Name(p1),
-                Parameter::Name(p2.unwrap()),
-            )))
+            Ok(BlockParam::Pair((Parameter::Name(p1), Parameter::Name(p2))))
         } else {
             Ok(BlockParam::Single(Parameter::Name(p1)))
         }
@@ -423,10 +434,13 @@
         }
     }
 
-    pub fn compile2<S: AsRef<str>>(source: S, mapping: bool) -> Result<Template, TemplateError> {
+    pub fn compile2<'a, S: AsRef<str> + 'a>(
+        source: S,
+        mapping: bool,
+    ) -> Result<Template, TemplateError> {
         let source = source.as_ref();
         let mut helper_stack: VecDeque<HelperTemplate> = VecDeque::new();
-        let mut directive_stack: VecDeque<DirectiveTemplate> = VecDeque::new();
+        let mut decorator_stack: VecDeque<DecoratorTemplate> = VecDeque::new();
         let mut template_stack: VecDeque<Template> = VecDeque::new();
 
         let mut omit_pro_ws = false;
@@ -439,14 +453,14 @@
             TemplateError::of(TemplateErrorReason::InvalidSyntax).at(source, line_no, col_no)
         })?;
 
-        // println!("{:?}", parser_queue.clone());
+        // dbg!(parser_queue.clone());
 
         // remove escape from our pair queue
         let mut it = parser_queue
             .flatten()
             .filter(|p| p.as_rule() != Rule::escape)
             .peekable();
-        let mut end_pos: Option<Position> = None;
+        let mut end_pos: Option<Position<'_>> = None;
         loop {
             if let Some(pair) = it.next() {
                 let prev_end = end_pos.as_ref().map(|p| p.pos()).unwrap_or(0);
@@ -506,14 +520,14 @@
                     }
                     Rule::helper_block_start
                     | Rule::raw_block_start
-                    | Rule::directive_block_start
+                    | Rule::decorator_block_start
                     | Rule::partial_block_start => {
                         let exp = Template::parse_expression(source, it.by_ref(), span.end())?;
 
                         match rule {
                             Rule::helper_block_start | Rule::raw_block_start => {
                                 let helper_template = HelperTemplate {
-                                    name: exp.name.into_name().unwrap(),
+                                    name: exp.name,
                                     params: exp.params,
                                     hash: exp.hash,
                                     block_param: exp.block_param,
@@ -523,14 +537,14 @@
                                 };
                                 helper_stack.push_front(helper_template);
                             }
-                            Rule::directive_block_start | Rule::partial_block_start => {
-                                let directive = DirectiveTemplate {
+                            Rule::decorator_block_start | Rule::partial_block_start => {
+                                let decorator = DecoratorTemplate {
                                     name: exp.name,
                                     params: exp.params,
                                     hash: exp.hash,
                                     template: None,
                                 };
-                                directive_stack.push_front(directive);
+                                decorator_stack.push_front(decorator);
                             }
                             _ => unreachable!(),
                         }
@@ -570,12 +584,11 @@
                     }
                     Rule::expression
                     | Rule::html_expression
-                    | Rule::helper_expression
-                    | Rule::directive_expression
+                    | Rule::decorator_expression
                     | Rule::partial_expression
                     | Rule::helper_block_end
                     | Rule::raw_block_end
-                    | Rule::directive_block_end
+                    | Rule::decorator_block_end
                     | Rule::partial_block_end => {
                         let exp = Template::parse_expression(source, it.by_ref(), span.end())?;
                         if exp.omit_pre_ws {
@@ -585,19 +598,14 @@
                         omit_pro_ws = exp.omit_pro_ws;
 
                         match rule {
-                            Rule::expression => {
-                                let el = Expression(exp.name);
-                                let t = template_stack.front_mut().unwrap();
-                                t.push_element(el, line_no, col_no);
-                            }
                             Rule::html_expression => {
                                 let el = HTMLExpression(exp.name);
                                 let t = template_stack.front_mut().unwrap();
                                 t.push_element(el, line_no, col_no);
                             }
-                            Rule::helper_expression => {
+                            Rule::expression => {
                                 let helper_template = HelperTemplate {
-                                    name: exp.name.into_name().unwrap(),
+                                    name: exp.name,
                                     params: exp.params,
                                     hash: exp.hash,
                                     block_param: exp.block_param,
@@ -605,29 +613,29 @@
                                     template: None,
                                     inverse: None,
                                 };
-                                let el = HelperExpression(Box::new(helper_template));
+                                let el = Expression(Box::new(helper_template));
                                 let t = template_stack.front_mut().unwrap();
                                 t.push_element(el, line_no, col_no);
                             }
-                            Rule::directive_expression | Rule::partial_expression => {
-                                let directive = DirectiveTemplate {
+                            Rule::decorator_expression | Rule::partial_expression => {
+                                let decorator = DecoratorTemplate {
                                     name: exp.name,
                                     params: exp.params,
                                     hash: exp.hash,
                                     template: None,
                                 };
-                                let el = if rule == Rule::directive_expression {
-                                    DirectiveExpression(directive)
+                                let el = if rule == Rule::decorator_expression {
+                                    DecoratorExpression(Box::new(decorator))
                                 } else {
-                                    PartialExpression(directive)
+                                    PartialExpression(Box::new(decorator))
                                 };
                                 let t = template_stack.front_mut().unwrap();
                                 t.push_element(el, line_no, col_no);
                             }
                             Rule::helper_block_end | Rule::raw_block_end => {
                                 let mut h = helper_stack.pop_front().unwrap();
-                                let close_tag_name = exp.name.into_name().unwrap();
-                                if h.name == close_tag_name {
+                                let close_tag_name = exp.name.as_name();
+                                if h.name.as_name() == close_tag_name {
                                     let prev_t = template_stack.pop_front().unwrap();
                                     if h.template.is_some() {
                                         h.inverse = Some(prev_t);
@@ -639,30 +647,30 @@
                                 } else {
                                     return Err(TemplateError::of(
                                         TemplateErrorReason::MismatchingClosedHelper(
-                                            h.name,
-                                            close_tag_name,
+                                            h.name.as_name().unwrap().into(),
+                                            close_tag_name.unwrap().into(),
                                         ),
                                     )
                                     .at(source, line_no, col_no));
                                 }
                             }
-                            Rule::directive_block_end | Rule::partial_block_end => {
-                                let mut d = directive_stack.pop_front().unwrap();
-                                let close_tag_name = exp.name;
-                                if d.name == close_tag_name {
+                            Rule::decorator_block_end | Rule::partial_block_end => {
+                                let mut d = decorator_stack.pop_front().unwrap();
+                                let close_tag_name = exp.name.as_name();
+                                if d.name.as_name() == close_tag_name {
                                     let prev_t = template_stack.pop_front().unwrap();
                                     d.template = Some(prev_t);
                                     let t = template_stack.front_mut().unwrap();
-                                    if rule == Rule::directive_block_end {
-                                        t.elements.push(DirectiveBlock(d));
+                                    if rule == Rule::decorator_block_end {
+                                        t.elements.push(DecoratorBlock(Box::new(d)));
                                     } else {
-                                        t.elements.push(PartialBlock(d));
+                                        t.elements.push(PartialBlock(Box::new(d)));
                                     }
                                 } else {
                                     return Err(TemplateError::of(
-                                        TemplateErrorReason::MismatchingClosedDirective(
-                                            d.name,
-                                            close_tag_name,
+                                        TemplateErrorReason::MismatchingClosedDecorator(
+                                            d.name.as_name().unwrap().into(),
+                                            close_tag_name.unwrap().into(),
                                         ),
                                     )
                                     .at(source, line_no, col_no));
@@ -725,14 +733,13 @@
 #[derive(PartialEq, Clone, Debug)]
 pub enum TemplateElement {
     RawString(String),
-    Expression(Parameter),
     HTMLExpression(Parameter),
-    HelperExpression(Box<HelperTemplate>),
+    Expression(Box<HelperTemplate>),
     HelperBlock(Box<HelperTemplate>),
-    DirectiveExpression(DirectiveTemplate),
-    DirectiveBlock(DirectiveTemplate),
-    PartialExpression(DirectiveTemplate),
-    PartialBlock(DirectiveTemplate),
+    DecoratorExpression(Box<DecoratorTemplate>),
+    DecoratorBlock(Box<DecoratorTemplate>),
+    PartialExpression(Box<DecoratorTemplate>),
+    PartialBlock(Box<DecoratorTemplate>),
     Comment(String),
 }
 
@@ -778,17 +785,19 @@
     assert_eq!(*t.elements.get(0).unwrap(), RawString("<h1>".to_string()));
     assert_eq!(
         *t.elements.get(1).unwrap(),
-        Expression(Parameter::Name("title".to_string()))
+        Expression(Box::new(HelperTemplate::with_path(Path::with_named_paths(
+            &["title"]
+        ))))
     );
 
     assert_eq!(
         *t.elements.get(3).unwrap(),
-        HTMLExpression(Parameter::Name("content".to_string()))
+        HTMLExpression(Parameter::Path(Path::with_named_paths(&["content"])))
     );
 
     match *t.elements.get(5).unwrap() {
         HelperBlock(ref h) => {
-            assert_eq!(h.name, "if".to_string());
+            assert_eq!(h.name.as_name().unwrap(), "if".to_string());
             assert_eq!(h.params.len(), 1);
             assert_eq!(h.template.as_ref().unwrap().elements.len(), 1);
         }
@@ -798,10 +807,13 @@
     };
 
     match *t.elements.get(7).unwrap() {
-        HelperExpression(ref h) => {
-            assert_eq!(h.name, "foo".to_string());
+        Expression(ref h) => {
+            assert_eq!(h.name.as_name().unwrap(), "foo".to_string());
             assert_eq!(h.params.len(), 1);
-            assert_eq!(*(h.params.get(0).unwrap()), Parameter::Name("bar".into()));
+            assert_eq!(
+                *(h.params.get(0).unwrap()),
+                Parameter::Path(Path::with_named_paths(&["bar"]))
+            )
         }
         _ => {
             panic!("Helper expression here");
@@ -810,7 +822,7 @@
 
     match *t.elements.get(9).unwrap() {
         HelperBlock(ref h) => {
-            assert_eq!(h.name, "unless".to_string());
+            assert_eq!(h.name.as_name().unwrap(), "unless".to_string());
             assert_eq!(h.params.len(), 1);
             assert_eq!(h.inverse.as_ref().unwrap().elements.len(), 1);
         }
@@ -821,6 +833,12 @@
 }
 
 #[test]
+fn test_parse_block_partial_path_identifier() {
+    let source = "{{#> foo/bar}}{{/foo/bar}}";
+    assert!(Template::compile(source.to_string()).is_ok());
+}
+
+#[test]
 fn test_parse_error() {
     let source = "{{#ifequals name compare=\"hello\"}}\nhello\n\t{{else}}\ngood";
 
@@ -839,8 +857,8 @@
 
     assert_eq!(t.elements.len(), 4);
     match *t.elements.get(0).unwrap() {
-        HelperExpression(ref h) => {
-            assert_eq!(h.name, "foo".to_owned());
+        Expression(ref h) => {
+            assert_eq!(h.name.as_name().unwrap(), "foo".to_owned());
             assert_eq!(h.params.len(), 1);
             if let &Parameter::Subexpression(ref t) = h.params.get(0).unwrap() {
                 assert_eq!(t.name(), "bar".to_owned());
@@ -854,13 +872,13 @@
     };
 
     match *t.elements.get(1).unwrap() {
-        HelperExpression(ref h) => {
-            assert_eq!(h.name, "foo".to_string());
+        Expression(ref h) => {
+            assert_eq!(h.name.as_name().unwrap(), "foo".to_string());
             assert_eq!(h.params.len(), 1);
             if let &Parameter::Subexpression(ref t) = h.params.get(0).unwrap() {
                 assert_eq!(t.name(), "bar".to_owned());
-                if let Some(&Parameter::Name(ref n)) = t.params().unwrap().get(0) {
-                    assert_eq!(n, "baz");
+                if let Some(Parameter::Path(p)) = t.params().unwrap().get(0) {
+                    assert_eq!(p, &Path::with_named_paths(&["baz"]));
                 } else {
                     panic!("non-empty param expected ");
                 }
@@ -875,14 +893,14 @@
 
     match *t.elements.get(3).unwrap() {
         HelperBlock(ref h) => {
-            assert_eq!(h.name, "if".to_string());
+            assert_eq!(h.name.as_name().unwrap(), "if".to_string());
             assert_eq!(h.params.len(), 1);
             assert_eq!(h.hash.len(), 1);
 
             if let &Parameter::Subexpression(ref t) = h.params.get(0).unwrap() {
                 assert_eq!(t.name(), "baz".to_owned());
-                if let Some(&Parameter::Name(ref n)) = t.params().unwrap().get(0) {
-                    assert_eq!(n, "bar");
+                if let Some(Parameter::Path(p)) = t.params().unwrap().get(0) {
+                    assert_eq!(p, &Path::with_named_paths(&["bar"]));
                 } else {
                     panic!("non-empty param expected ");
                 }
@@ -910,7 +928,12 @@
     assert_eq!(t.elements.len(), 4);
 
     assert_eq!(t.elements[0], RawString("hello~".to_string()));
-    assert_eq!(t.elements[1], Expression(Parameter::Name("world".into())));
+    assert_eq!(
+        t.elements[1],
+        Expression(Box::new(HelperTemplate::with_path(Path::with_named_paths(
+            &["world"]
+        ))))
+    );
     assert_eq!(t.elements[2], RawString("!".to_string()));
 
     let t2 = Template::compile("{{#if true}}1  {{~ else ~}} 2 {{~/if}}".to_string())
@@ -960,7 +983,7 @@
             assert_eq!(t.elements[2], RawString("world".to_owned()));
             match t.elements[1] {
                 HelperBlock(ref h) => {
-                    assert_eq!(h.name, "raw".to_owned());
+                    assert_eq!(h.name.as_name().unwrap(), "raw".to_owned());
                     if let Some(ref ht) = h.template {
                         assert_eq!(ht.elements.len(), 1);
                         assert_eq!(
@@ -986,14 +1009,17 @@
 fn test_literal_parameter_parser() {
     match Template::compile("{{hello 1 name=\"value\" valid=false ref=someref}}") {
         Ok(t) => {
-            if let HelperExpression(ref ht) = t.elements[0] {
+            if let Expression(ref ht) = t.elements[0] {
                 assert_eq!(ht.params[0], Parameter::Literal(json!(1)));
                 assert_eq!(
                     ht.hash["name"],
                     Parameter::Literal(Json::String("value".to_owned()))
                 );
                 assert_eq!(ht.hash["valid"], Parameter::Literal(Json::Bool(false)));
-                assert_eq!(ht.hash["ref"], Parameter::Name("someref".to_owned()));
+                assert_eq!(
+                    ht.hash["ref"],
+                    Parameter::Path(Path::with_named_paths(&["someref"]))
+                );
             }
         }
         Err(e) => panic!("{}", e),
@@ -1043,14 +1069,14 @@
         Err(e) => panic!("{}", e),
     }
 
-    match Template::compile("{{#each people as |key val|}}{{person}}{{/each}}") {
+    match Template::compile("{{#each people as |val key|}}{{person}}{{/each}}") {
         Ok(t) => {
             if let HelperBlock(ref ht) = t.elements[0] {
                 if let Some(BlockParam::Pair((Parameter::Name(ref n1), Parameter::Name(ref n2)))) =
                     ht.block_param
                 {
-                    assert_eq!(n1, "key");
-                    assert_eq!(n2, "val");
+                    assert_eq!(n1, "val");
+                    assert_eq!(n2, "key");
                 } else {
                     panic!("helper block param expected.");
                 }
@@ -1063,12 +1089,12 @@
 }
 
 #[test]
-fn test_directive() {
+fn test_decorator() {
     match Template::compile("hello {{* ssh}} world") {
         Err(e) => panic!("{}", e),
         Ok(t) => {
-            if let DirectiveExpression(ref de) = t.elements[1] {
-                assert_eq!(de.name, Parameter::Name("ssh".to_owned()));
+            if let DecoratorExpression(ref de) = t.elements[1] {
+                assert_eq!(de.name.as_name(), Some("ssh"));
                 assert_eq!(de.template, None);
             }
         }
@@ -1078,7 +1104,7 @@
         Err(e) => panic!("{}", e),
         Ok(t) => {
             if let PartialExpression(ref de) = t.elements[1] {
-                assert_eq!(de.name, Parameter::Name("ssh".to_owned()));
+                assert_eq!(de.name.as_name(), Some("ssh"));
                 assert_eq!(de.template, None);
             }
         }
@@ -1087,7 +1113,7 @@
     match Template::compile("{{#*inline \"hello\"}}expand to hello{{/inline}}{{> hello}}") {
         Err(e) => panic!("{}", e),
         Ok(t) => {
-            if let DirectiveBlock(ref db) = t.elements[0] {
+            if let DecoratorBlock(ref db) = t.elements[0] {
                 assert_eq!(db.name, Parameter::Name("inline".to_owned()));
                 assert_eq!(
                     db.params[0],
diff --git a/third_party/rust_crates/vendor/handlebars/src/util.rs b/third_party/rust_crates/vendor/handlebars/src/util.rs
new file mode 100644
index 0000000..7bfca24
--- /dev/null
+++ b/third_party/rust_crates/vendor/handlebars/src/util.rs
@@ -0,0 +1,25 @@
+pub(crate) fn empty_or_none<T>(input: &[T]) -> Option<&[T]> {
+    if input.is_empty() {
+        None
+    } else {
+        Some(input)
+    }
+}
+
+#[inline]
+pub(crate) fn copy_on_push_vec<T>(input: &[T], el: T) -> Vec<T>
+where
+    T: Clone,
+{
+    let mut new_vec = Vec::with_capacity(input.len() + 1);
+    new_vec.extend_from_slice(input);
+    new_vec.push(el);
+    new_vec
+}
+
+#[inline]
+pub(crate) fn extend(base: &mut Vec<String>, slice: &[String]) {
+    for i in slice {
+        base.push(i.to_owned());
+    }
+}
diff --git a/third_party/rust_crates/vendor/handlebars/tests/block_context.rs b/third_party/rust_crates/vendor/handlebars/tests/block_context.rs
new file mode 100644
index 0000000..bbaa89a
--- /dev/null
+++ b/third_party/rust_crates/vendor/handlebars/tests/block_context.rs
@@ -0,0 +1,106 @@
+use handlebars::Handlebars;
+use serde_json::json;
+
+#[test]
+fn test_partial_with_blocks() {
+    let hbs = Handlebars::new();
+
+    let data = json!({
+        "a": [
+            {"b": 1},
+            {"b": 2},
+        ],
+    });
+
+    let template = "{{#*inline \"test\"}}{{b}};{{/inline}}{{#each a as |z|}}{{> test z}}{{/each}}";
+    assert_eq!(hbs.render_template(template, &data).unwrap(), "1;2;");
+}
+
+#[test]
+fn test_root_with_blocks() {
+    let hbs = Handlebars::new();
+
+    let data = json!({
+        "a": [
+            {"b": 1},
+            {"b": 2},
+        ],
+        "b": 3,
+    });
+
+    let template =
+        "{{#*inline \"test\"}}{{b}}:{{@root.b}};{{/inline}}{{#each a}}{{> test}}{{/each}}";
+    assert_eq!(hbs.render_template(template, &data).unwrap(), "1:3;2:3;");
+}
+
+#[test]
+fn test_singular_and_pair_block_params() {
+    let hbs = Handlebars::new();
+
+    let data = json!([
+        {"value": 11},
+        {"value": 22},
+    ]);
+
+    let template =
+        "{{#each this as |b index|}}{{b.value}}{{#each this as |value key|}}:{{key}},{{/each}}{{/each}}";
+    assert_eq!(
+        hbs.render_template(template, &data).unwrap(),
+        "11:value,22:value,"
+    );
+}
+
+#[test]
+fn test_nested_each() {
+    let hbs = Handlebars::new();
+
+    let data = json!({
+        "classes": [
+            {
+                "methods": [
+                    {"id": 1},
+                    {"id": 2}
+                ]
+            },
+            {
+                "methods": [
+                    {"id": 3},
+                    {"id": 4}
+                ]
+            },
+        ],
+    });
+
+    let template = "{{#each classes as |class|}}{{#each class.methods as |method|}}{{method.id}};{{/each}}{{/each}}";
+    assert_eq!(hbs.render_template(template, &data).unwrap(), "1;2;3;4;");
+}
+
+#[test]
+fn test_referencing_block_param_from_upper_scope() {
+    let hbs = Handlebars::new();
+
+    let data = json!({
+        "classes": [
+            {
+                "methods": [
+                    {"id": 1},
+                    {"id": 2}
+                ],
+                "private": false
+            },
+            {
+                "methods": [
+                    {"id": 3},
+                    {"id": 4}
+                ],
+                "private": true
+            },
+        ],
+    });
+
+    let template = "{{#each classes as |class|}}{{#each class.methods as |method|}}{{class.private}}|{{method.id}};{{/each}}{{/each}}";
+    assert_eq!(
+        hbs.render_template(template, &data).unwrap(),
+        "false|1;false|2;true|3;true|4;"
+    );
+}
diff --git a/third_party/rust_crates/vendor/handlebars/tests/data_helper.rs b/third_party/rust_crates/vendor/handlebars/tests/data_helper.rs
new file mode 100644
index 0000000..7734b0d
--- /dev/null
+++ b/third_party/rust_crates/vendor/handlebars/tests/data_helper.rs
@@ -0,0 +1,29 @@
+use handlebars::*;
+use serde_json::json;
+
+struct HelperWithBorrowedData<'a>(&'a String);
+
+impl<'a> HelperDef for HelperWithBorrowedData<'a> {
+    fn call<'_reg: '_rc, '_rc>(
+        &self,
+        _: &Helper<'_reg, '_rc>,
+        _: &'_reg Handlebars,
+        _: &Context,
+        _: &mut RenderContext,
+        out: &mut dyn Output,
+    ) -> Result<(), RenderError> {
+        out.write(self.0).map_err(RenderError::from)
+    }
+}
+
+#[test]
+fn test_helper_with_ref_data() {
+    let s = "hello helper".to_owned();
+    let the_helper = HelperWithBorrowedData(&s);
+
+    let mut r = Handlebars::new();
+    r.register_helper("hello", Box::new(the_helper));
+
+    let s = r.render_template("Output: {{hello}}", &json!({})).unwrap();
+    assert_eq!(s, "Output: hello helper".to_owned());
+}
diff --git a/third_party/rust_crates/vendor/handlebars/tests/helper_function_lifetime.rs b/third_party/rust_crates/vendor/handlebars/tests/helper_function_lifetime.rs
new file mode 100644
index 0000000..fd21f30
--- /dev/null
+++ b/third_party/rust_crates/vendor/handlebars/tests/helper_function_lifetime.rs
@@ -0,0 +1,36 @@
+use handlebars::*;
+
+fn ifcond<'reg, 'rc>(
+    h: &Helper<'reg, 'rc>,
+    handle: &'reg Handlebars,
+    ctx: &'rc Context,
+    render_ctx: &mut RenderContext<'reg, 'rc>,
+    out: &mut dyn Output,
+) -> Result<(), RenderError> {
+    let cond = h
+        .param(0)
+        .and_then(|ref v| v.value().as_bool())
+        .ok_or(RenderError::new("Ifcond takes a boolean !"))? as bool;
+    let temp = if cond { h.template() } else { h.inverse() };
+    match temp {
+        Some(t) => t.render(handle, ctx, render_ctx, out),
+        None => Ok(()),
+    }
+}
+
+#[test]
+fn test_helper() {
+    let mut handlebars = Handlebars::new();
+
+    // register some custom helpers
+    handlebars.register_helper("ifcond", Box::new(ifcond));
+
+    // make data and render it
+    let data = true;
+    assert_eq!(
+        "yes",
+        handlebars
+            .render_template("{{#ifcond this}}yes{{/ifcond}}", &data)
+            .unwrap()
+    );
+}
diff --git a/third_party/rust_crates/vendor/handlebars/tests/helper_macro.rs b/third_party/rust_crates/vendor/handlebars/tests/helper_macro.rs
index 9198db6..9a845bb 100644
--- a/third_party/rust_crates/vendor/handlebars/tests/helper_macro.rs
+++ b/third_party/rust_crates/vendor/handlebars/tests/helper_macro.rs
@@ -8,6 +8,12 @@
 handlebars_helper!(lower: |s: str| s.to_lowercase());
 handlebars_helper!(upper: |s: str| s.to_uppercase());
 handlebars_helper!(hex: |v: i64| format!("0x{:x}", v));
+handlebars_helper!(money: |v: i64, {cur: str="$"}| format!("{}{}.00", cur, v));
+handlebars_helper!(all_hash: |{cur: str="$"}| cur);
+handlebars_helper!(nargs: |*args| args.len());
+handlebars_helper!(has_a: |{a:i64 = 99}, **kwargs|
+                   format!("{}, {}", a, kwargs.get("a").is_some()));
+handlebars_helper!(tag: |t: str| format!("<{}>", t));
 
 #[test]
 fn test_macro_helper() {
@@ -16,6 +22,10 @@
     hbs.register_helper("lower", Box::new(lower));
     hbs.register_helper("upper", Box::new(upper));
     hbs.register_helper("hex", Box::new(hex));
+    hbs.register_helper("money", Box::new(money));
+    hbs.register_helper("nargs", Box::new(nargs));
+    hbs.register_helper("has_a", Box::new(has_a));
+    hbs.register_helper("tag", Box::new(tag));
 
     let data = json!("Teixeira");
 
@@ -28,4 +38,34 @@
         "TEIXEIRA"
     );
     assert_eq!(hbs.render_template("{{hex 16}}", &()).unwrap(), "0x10");
+
+    assert_eq!(
+        hbs.render_template("{{money 5000}}", &()).unwrap(),
+        "$5000.00"
+    );
+    assert_eq!(
+        hbs.render_template("{{money 5000 cur=\"£\"}}", &())
+            .unwrap(),
+        "£5000.00"
+    );
+    assert_eq!(
+        hbs.render_template("{{nargs 1 1 1 1 1}}", &()).unwrap(),
+        "5"
+    );
+    assert_eq!(hbs.render_template("{{nargs}}", &()).unwrap(), "0");
+
+    assert_eq!(
+        hbs.render_template("{{has_a a=1 b=2}}", &()).unwrap(),
+        "1, true"
+    );
+
+    assert_eq!(
+        hbs.render_template("{{has_a x=1 b=2}}", &()).unwrap(),
+        "99, false"
+    );
+
+    assert_eq!(
+        hbs.render_template("{{tag \"html\"}}", &()).unwrap(),
+        "&lt;html&gt;"
+    );
 }
diff --git a/third_party/rust_crates/vendor/handlebars/tests/helper_with_space.rs b/third_party/rust_crates/vendor/handlebars/tests/helper_with_space.rs
new file mode 100644
index 0000000..5a55ab12
--- /dev/null
+++ b/third_party/rust_crates/vendor/handlebars/tests/helper_with_space.rs
@@ -0,0 +1,36 @@
+use handlebars::*;
+use serde_json::json;
+
+fn dump<'reg, 'rc>(
+    h: &Helper<'reg, 'rc>,
+    _: &'reg Handlebars,
+    _: &Context,
+    _: &mut RenderContext,
+    out: &mut dyn Output,
+) -> Result<(), RenderError> {
+    assert_eq!(2, h.params().len());
+
+    let result = h
+        .params()
+        .iter()
+        .map(|p| p.value().render())
+        .collect::<Vec<String>>()
+        .join(", ");
+    out.write(&result)?;
+
+    Ok(())
+}
+
+#[test]
+fn test_helper_with_space_param() {
+    let mut r = Handlebars::new();
+    r.register_helper("echo", Box::new(dump));
+
+    let s = r
+        .render_template(
+            "Output: {{echo \"Mozilla Firefox\" \"Google Chrome\"}}",
+            &json!({}),
+        )
+        .unwrap();
+    assert_eq!(s, "Output: Mozilla Firefox, Google Chrome".to_owned());
+}
diff --git a/third_party/rust_crates/vendor/handlebars/tests/template_names.rs b/third_party/rust_crates/vendor/handlebars/tests/template_names.rs
new file mode 100644
index 0000000..eea9e03
--- /dev/null
+++ b/third_party/rust_crates/vendor/handlebars/tests/template_names.rs
@@ -0,0 +1,35 @@
+extern crate handlebars;
+#[macro_use]
+extern crate serde_json;
+
+use handlebars::Handlebars;
+
+#[test]
+fn test_walk_dir_template_name() {
+    let mut hbs = Handlebars::new();
+
+    let data = json!({
+        "a": [1, 2, 3, 4],
+        "b": "top"
+    });
+
+    hbs.register_template_string("foo/bar", "{{@root/b}}")
+        .unwrap();
+    assert_eq!(hbs.render_template("{{> foo/bar }}", &data).unwrap(), "top");
+}
+
+#[test]
+fn test_walk_dir_template_name_with_args() {
+    let mut hbs = Handlebars::new();
+
+    let data = json!({
+        "a": [1, 2, 3, 4],
+        "b": "top"
+    });
+
+    hbs.register_template_string("foo/bar", "{{this}}").unwrap();
+    assert_eq!(
+        hbs.render_template("{{> foo/bar b }}", &data).unwrap(),
+        "top"
+    );
+}
diff --git a/third_party/rust_crates/vendor/handlebars/wasm/LICENSE b/third_party/rust_crates/vendor/handlebars/wasm/LICENSE
new file mode 100644
index 0000000..384d0c9
--- /dev/null
+++ b/third_party/rust_crates/vendor/handlebars/wasm/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Ning Sun
+
+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_crates/vendor/handlebars/wasm/README.md b/third_party/rust_crates/vendor/handlebars/wasm/README.md
new file mode 100644
index 0000000..77670a5
--- /dev/null
+++ b/third_party/rust_crates/vendor/handlebars/wasm/README.md
@@ -0,0 +1,6 @@
+# handlebars wasm modules
+
+## cli
+
+A commandline tool to render handlebars with given json input.
+
diff --git a/third_party/rust_crates/vendor/handlebars/wasm/wapm.toml b/third_party/rust_crates/vendor/handlebars/wasm/wapm.toml
new file mode 100644
index 0000000..eca9c78
--- /dev/null
+++ b/third_party/rust_crates/vendor/handlebars/wasm/wapm.toml
@@ -0,0 +1,18 @@
+[package]
+name = "sunng/handlebars"
+version = "1.0.0"
+description = "wasm packages for handlebars"
+license = "MIT"
+repository = "https://github.com/sunng87/handlebars-rust"
+
+[[module]]
+name = "handlebars-cli"
+source = "handlebars-cli.wasm"
+abi = "wasi"
+
+# [module.interfaces]
+# wasi = "0.0.0-unstable"
+
+[[command]]
+name = "handlebars-cli"
+module = "handlebars-cli"
diff --git a/third_party/rust_crates/vendor/hashbrown/.cargo-checksum.json b/third_party/rust_crates/vendor/hashbrown/.cargo-checksum.json
deleted file mode 100644
index 79c5a4b..0000000
--- a/third_party/rust_crates/vendor/hashbrown/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"CHANGELOG.md":"b08feed24f19abb9f55a25e57b631d9c4f1c6805c6df8a70a54c4dd67c2fbe64","Cargo.toml":"b8a6e8785d0af8091d0d4da986c5d63b6c8d44da1e8fdb9a1ec93168391fe499","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"ff8f68cb076caf8cefe7a6430d4ac086ce6af2ca8ce2c4e5a2004d4552ef52a2","README.md":"ae62e6891a89eb5e286c8fb06088dff3910666fe42401fd631ff870f5576f6ff","benches/bench.rs":"b786c75f23e5dbaba1b13a0acd35a1c91b757c343a1cb2e2ac04e4df48681fd2","clippy.toml":"7535949f908c6d9aea4f9a9f3a7625552c93fc29e963d059d40f4def9d77ea7b","src/external_trait_impls/mod.rs":"d69528827794524cfd9acbeacc1ac4f6131e3c7574311e6d919f818f65fbff07","src/external_trait_impls/rayon/helpers.rs":"d4fbca4db924925548f8dab8eb94cf4a3955a53c5e1ff15f59c460546c394034","src/external_trait_impls/rayon/map.rs":"fb0c2c1cafee4d5b65ede372fe5bfce86181d87ac71dcc2e7fd5b882fb920ecc","src/external_trait_impls/rayon/mod.rs":"b48139960a89ee84ed3b5e10ee5abb0259b40f2bb0ef867d0dd65784252a47c0","src/external_trait_impls/rayon/raw.rs":"1bf4f9fddaec0c6270cfc3dc3f3096027aeccdf73c259af3c7bfd61d6c672b9f","src/external_trait_impls/rayon/set.rs":"40dbd669a60f13d5fe4697837cacbcc1109b36c84a964dd74a02d8754eb058a3","src/external_trait_impls/serde.rs":"c429ec8fb922706df2bb3b774284c7951d0e2101a18a8bfd4a44323b50a33709","src/fx.rs":"4756873e73ad698109de6d2d8fd0711a047ac994200827fc3e6cfa9b18bff32a","src/lib.rs":"6455a8d9271d9adecaf12748ae6d0421b3f928324028eae9c1af6f4f4f34381a","src/macros.rs":"c53829e64b434b3b89e88f3dd5ec974cd812b7fb8ed981074c666852667651d4","src/map.rs":"e546756ddc9b933baea36e32df76f8b65ba78d72169ec2fc1c50024b45431d8c","src/raw/bitmask.rs":"3c1f33b09b212d3828a89c11a86ab1bb18dedc20e45ff0032787ca49de2833c5","src/raw/generic.rs":"9df50cf88e80acde6a13aa9e083a8512090d25ab4daeac5eed43c3602560e844","src/raw/mod.rs":"b8692074202b128e6124f99fdbb21f89b95be35ecc4aa3e208d0e817f1a32c8f","src/raw/sse2.rs":"8a564c91c9af1e824d0400a562e23bf2b6e3398744c39e32d1c22afff75612a1","src/rustc_entry.rs":"96f78e34cc41bc4a3866445b144070cdb325be14d54c9935605e9f23b8a06f31","src/scopeguard.rs":"808655b3e98512fdcee5a4597e7763a6be99582ba8d77e5ba5ca130d85a97211","src/set.rs":"517ea92827194679f2087f03e55d0635735c91a630dac771e045018a4d47f660","tests/hasher.rs":"9a8fdf67e4415618e16729969c386eefe71408cded5d46cf7b67d969276a3452","tests/rayon.rs":"2286707a87b139f41902c82488c355b9fb402a3e734f392f3a73e87b9b932795","tests/serde.rs":"1260f576d3fb1c0979dd12718cb46e96a1989f95ca928014deccd279ec33b4a3","tests/set.rs":"fe75951f508db10055d2f4a9cde30d4418e941ff28c3b068fc5b0d57c71cab6c"},"package":"61e4900fa4e80b3d15c78a08ec8a08433246063fa7577e7b2c6426b3b21b1f79"}
\ No newline at end of file
diff --git a/third_party/rust_crates/vendor/hashbrown/CHANGELOG.md b/third_party/rust_crates/vendor/hashbrown/CHANGELOG.md
deleted file mode 100644
index b71cd2c..0000000
--- a/third_party/rust_crates/vendor/hashbrown/CHANGELOG.md
+++ /dev/null
@@ -1,107 +0,0 @@
-# Change Log
-
-All notable changes to this project will be documented in this file.
-
-The format is based on [Keep a Changelog](http://keepachangelog.com/)
-and this project adheres to [Semantic Versioning](http://semver.org/).
-
-## [Unreleased]
-
-## [v0.2.2] - 2019-04-16
-
-### Fixed
-- Inlined non-nightly lowest_set_bit_nonzero. (#64)
-- Fixed build on latest nightly. (#65)
-
-## [v0.2.1] - 2019-04-14
-
-### Changed
-- Use for_each in map Extend and FromIterator. (#58)
-- Improved worst-case performance of HashSet.is_subset. (#61)
-
-### Fixed
-- Removed incorrect debug_assert. (#60)
-
-## [v0.2.0] - 2019-03-31
-
-### Changed
-- The code has been updated to Rust 2018 edition. This means that the minimum
-  Rust version has been bumped to 1.31 (2018 edition).
-
-### Added
-- Added `insert_with_hasher` to the raw_entry API to allow `K: !(Hash + Eq)`. (#54)
-- Added support for using hashbrown as the hash table implementation in libstd. (#46)
-
-### Fixed
-- Fixed cargo build with minimal-versions. (#45)
-- Fixed `#[may_dangle]` attributes to match the libstd `HashMap`. (#46)
-- ZST keys and values are now handled properly. (#46)
-
-## [v0.1.8] - 2019-01-14
-
-### Added
-- Rayon parallel iterator support (#37)
-- `raw_entry` support (#31)
-- `#[may_dangle]` on nightly (#31)
-- `try_reserve` support (#31)
-
-### Fixed
-- Fixed variance on `IterMut`. (#31)
-
-## [v0.1.7] - 2018-12-05
-
-### Fixed
-- Fixed non-SSE version of convert_special_to_empty_and_full_to_deleted. (#32)
-- Fixed overflow in rehash_in_place. (#33)
-
-## [v0.1.6] - 2018-11-17
-
-### Fixed
-- Fixed compile error on nightly. (#29)
-
-## [v0.1.5] - 2018-11-08
-
-### Fixed
-- Fixed subtraction overflow in generic::Group::match_byte. (#28)
-
-## [v0.1.4] - 2018-11-04
-
-### Fixed
-- Fixed a bug in the `erase_no_drop` implementation. (#26)
-
-## [v0.1.3] - 2018-11-01
-
-### Added
-- Serde support. (#14)
-
-### Fixed
-- Make the compiler inline functions more aggressively. (#20)
-
-## [v0.1.2] - 2018-10-31
-
-### Fixed
-- `clear` segfaults when called on an empty table. (#13)
-
-## [v0.1.1] - 2018-10-30
-
-### Fixed
-- `erase_no_drop` optimization not triggering in the SSE2 implementation. (#3)
-- Missing `Send` and `Sync` for hash map and iterator types. (#7)
-- Bug when inserting into a table smaller than the group width. (#5)
-
-## v0.1.0 - 2018-10-29
-
-- Initial release
-
-[Unreleased]: https://github.com/Amanieu/hashbrown/compare/v0.2.2...HEAD
-[v0.2.2]: https://github.com/Amanieu/hashbrown/compare/v0.2.1...v0.2.2
-[v0.2.1]: https://github.com/Amanieu/hashbrown/compare/v0.2.0...v0.2.1
-[v0.2.0]: https://github.com/Amanieu/hashbrown/compare/v0.1.8...v0.2.0
-[v0.1.8]: https://github.com/Amanieu/hashbrown/compare/v0.1.7...v0.1.8
-[v0.1.7]: https://github.com/Amanieu/hashbrown/compare/v0.1.6...v0.1.7
-[v0.1.6]: https://github.com/Amanieu/hashbrown/compare/v0.1.5...v0.1.6
-[v0.1.5]: https://github.com/Amanieu/hashbrown/compare/v0.1.4...v0.1.5
-[v0.1.4]: https://github.com/Amanieu/hashbrown/compare/v0.1.3...v0.1.4
-[v0.1.3]: https://github.com/Amanieu/hashbrown/compare/v0.1.2...v0.1.3
-[v0.1.2]: https://github.com/Amanieu/hashbrown/compare/v0.1.1...v0.1.2
-[v0.1.1]: https://github.com/Amanieu/hashbrown/compare/v0.1.0...v0.1.1
diff --git a/third_party/rust_crates/vendor/hashbrown/Cargo.toml b/third_party/rust_crates/vendor/hashbrown/Cargo.toml
deleted file mode 100644
index 6dbcbb6..0000000
--- a/third_party/rust_crates/vendor/hashbrown/Cargo.toml
+++ /dev/null
@@ -1,65 +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 = "hashbrown"
-version = "0.2.2"
-authors = ["Amanieu d'Antras <amanieu@gmail.com>"]
-exclude = [".travis.yml", "bors.toml", "/ci/*"]
-description = "A Rust port of Google's SwissTable hash map"
-readme = "README.md"
-keywords = ["hash", "no_std", "hashmap", "swisstable"]
-categories = ["data-structures", "no-std"]
-license = "Apache-2.0/MIT"
-repository = "https://github.com/Amanieu/hashbrown"
-[dependencies.alloc]
-version = "1.0.0"
-optional = true
-package = "rustc-std-workspace-alloc"
-
-[dependencies.compiler_builtins]
-version = "0.1.2"
-optional = true
-
-[dependencies.core]
-version = "1.0.0"
-optional = true
-package = "rustc-std-workspace-core"
-
-[dependencies.rayon]
-version = "1.0"
-optional = true
-
-[dependencies.serde]
-version = "1.0.25"
-optional = true
-default-features = false
-[dev-dependencies.lazy_static]
-version = "~1.2"
-
-[dev-dependencies.rand]
-version = "0.5.1"
-
-[dev-dependencies.rayon]
-version = "1.0"
-
-[dev-dependencies.rustc-hash]
-version = "1.0"
-
-[dev-dependencies.serde_test]
-version = "1.0"
-
-[features]
-default = []
-nightly = []
-rustc-dep-of-std = ["nightly", "core", "compiler_builtins", "alloc"]
diff --git a/third_party/rust_crates/vendor/hashbrown/LICENSE-APACHE b/third_party/rust_crates/vendor/hashbrown/LICENSE-APACHE
deleted file mode 100644
index 16fe87b..0000000
--- a/third_party/rust_crates/vendor/hashbrown/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_crates/vendor/hashbrown/LICENSE-MIT b/third_party/rust_crates/vendor/hashbrown/LICENSE-MIT
deleted file mode 100644
index 5afc2a7..0000000
--- a/third_party/rust_crates/vendor/hashbrown/LICENSE-MIT
+++ /dev/null
@@ -1,25 +0,0 @@
-Copyright (c) 2016 Amanieu d'Antras
-
-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_crates/vendor/hashbrown/README.md b/third_party/rust_crates/vendor/hashbrown/README.md
deleted file mode 100644
index 4490654..0000000
--- a/third_party/rust_crates/vendor/hashbrown/README.md
+++ /dev/null
@@ -1,87 +0,0 @@
-hashbrown
-=========
-
-[![Build Status](https://travis-ci.com/Amanieu/hashbrown.svg?branch=master)](https://travis-ci.com/Amanieu/hashbrown) [![Crates.io](https://img.shields.io/crates/v/hashbrown.svg)](https://crates.io/crates/hashbrown)
-
-This crate is a Rust port of Google's high-performance [SwissTable] hash
-map, adapted to make it a drop-in replacement for Rust's standard `HashMap`
-and `HashSet` types.
-
-The original C++ version of SwissTable can be found [here], and this
-[CppCon talk] gives an overview of how the algorithm works.
-
-[SwissTable]: https://abseil.io/blog/20180927-swisstables
-[here]: https://github.com/abseil/abseil-cpp/blob/master/absl/container/internal/raw_hash_set.h
-[CppCon talk]: https://www.youtube.com/watch?v=ncHmEUmJZf4
-
-## [Documentation](https://docs.rs/hashbrown)
-
-## [Change log](CHANGELOG.md)
-
-## Features
-
-- Drop-in replacement for the standard library `HashMap` and `HashSet` types.
-- Uses `FxHash` as the default hasher, which is much faster than SipHash.
-- Around 2x faster than `FxHashMap` and 8x faster than the standard `HashMap`.
-- Lower memory usage: only 1 byte of overhead per entry instead of 8.
-- Compatible with `#[no_std]` (currently requires nightly for the `alloc` crate).
-- Empty hash maps do not allocate any memory.
-- SIMD lookups to scan multiple hash entries in parallel.
-
-## Performance
-
-Compared to `std::collections::HashMap`:
-
-```
- name               stdhash ns/iter  hashbrown ns/iter  diff ns/iter    diff %  speedup
- find_existing      23,831           2,935                   -20,896   -87.68%   x 8.12
- find_nonexisting   25,326           2,283                   -23,043   -90.99%  x 11.09
- get_remove_insert  124              25                          -99   -79.84%   x 4.96
- grow_by_insertion  197              177                         -20   -10.15%   x 1.11
- hashmap_as_queue   72               18                          -54   -75.00%   x 4.00
- new_drop           14               0                           -14  -100.00%    x inf
- new_insert_drop    78               55                          -23   -29.49%   x 1.42
-```
-
-Compared to `rustc_hash::FxHashMap` (standard `HashMap` using `FxHash` instead of `SipHash`):
-
-```
- name               fxhash ns/iter  hashbrown ns/iter  diff ns/iter    diff %  speedup
- find_existing      5,951           2,935                    -3,016   -50.68%   x 2.03
- find_nonexisting   4,637           2,283                    -2,354   -50.77%   x 2.03
- get_remove_insert  29              25                           -4   -13.79%   x 1.16
- grow_by_insertion  160             177                          17    10.62%   x 0.90
- hashmap_as_queue   22              18                           -4   -18.18%   x 1.22
- new_drop           9               0                            -9  -100.00%    x inf
- new_insert_drop    64              55                           -9   -14.06%   x 1.16
-```
-
-## Usage
-
-Add this to your `Cargo.toml`:
-
-```toml
-[dependencies]
-hashbrown = "0.2"
-```
-
-This crate has the following Cargo features:
-
-- `nightly`: Enables nightly-only features: `no_std` support and `#[may_dangle]`.
-- `serde`: Enables serde serialization support.
-- `rayon`: Enables rayon parallel iterator support.
-
-## License
-
-Licensed under either of:
-
- * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
-
-at your option.
-
-### Contribution
-
-Unless you explicitly state otherwise, any contribution intentionally submitted
-for inclusion in 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_crates/vendor/hashbrown/benches/bench.rs b/third_party/rust_crates/vendor/hashbrown/benches/bench.rs
deleted file mode 100644
index bcf0730..0000000
--- a/third_party/rust_crates/vendor/hashbrown/benches/bench.rs
+++ /dev/null
@@ -1,159 +0,0 @@
-#![feature(test)]
-
-extern crate test;
-
-use std::hash::Hash;
-use test::Bencher;
-
-use hashbrown::HashMap;
-//use rustc_hash::FxHashMap as HashMap;
-//use std::collections::HashMap;
-
-fn new_map<K: Eq + Hash, V>() -> HashMap<K, V> {
-    HashMap::default()
-}
-
-#[bench]
-fn new_drop(b: &mut Bencher) {
-    b.iter(|| {
-        let m: HashMap<i32, i32> = new_map();
-        assert_eq!(m.len(), 0);
-    })
-}
-
-#[bench]
-fn new_insert_drop(b: &mut Bencher) {
-    b.iter(|| {
-        let mut m = new_map();
-        m.insert(0, 0);
-        assert_eq!(m.len(), 1);
-    })
-}
-
-#[bench]
-fn grow_by_insertion(b: &mut Bencher) {
-    let mut m = new_map();
-
-    for i in 1..1001 {
-        m.insert(i, i);
-    }
-
-    let mut k = 1001;
-
-    b.iter(|| {
-        m.insert(k, k);
-        k += 1;
-    });
-}
-
-#[bench]
-fn grow_by_insertion_kb(b: &mut Bencher) {
-    let mut m = new_map();
-    let kb = 1024;
-    for i in 1..1001 {
-        m.insert(i * kb, i);
-    }
-
-    let mut k = 1001 * kb;
-
-    b.iter(|| {
-        m.insert(k, k);
-        k += kb;
-    });
-}
-
-#[bench]
-fn find_existing(b: &mut Bencher) {
-    let mut m = new_map();
-
-    for i in 1..1001 {
-        m.insert(i, i);
-    }
-
-    b.iter(|| {
-        for i in 1..1001 {
-            m.contains_key(&i);
-        }
-    });
-}
-
-#[bench]
-fn find_existing_high_bits(b: &mut Bencher) {
-    let mut m = new_map();
-
-    for i in 1..1001_u64 {
-        m.insert(i << 32, i);
-    }
-
-    b.iter(|| {
-        for i in 1..1001_u64 {
-            m.contains_key(&(i << 32));
-        }
-    });
-}
-
-#[bench]
-fn find_nonexisting(b: &mut Bencher) {
-    let mut m = new_map();
-
-    for i in 1..1001 {
-        m.insert(i, i);
-    }
-
-    b.iter(|| {
-        for i in 1001..2001 {
-            m.contains_key(&i);
-        }
-    });
-}
-
-#[bench]
-fn hashmap_as_queue(b: &mut Bencher) {
-    let mut m = new_map();
-
-    for i in 1..1001 {
-        m.insert(i, i);
-    }
-
-    let mut k = 1;
-
-    b.iter(|| {
-        m.remove(&k);
-        m.insert(k + 1000, k + 1000);
-        k += 1;
-    });
-}
-
-#[bench]
-fn get_remove_insert(b: &mut Bencher) {
-    let mut m = new_map();
-
-    for i in 1..1001 {
-        m.insert(i, i);
-    }
-
-    let mut k = 1;
-
-    b.iter(|| {
-        m.get(&(k + 400));
-        m.get(&(k + 2000));
-        m.remove(&k);
-        m.insert(k + 1000, k + 1000);
-        k += 1;
-    })
-}
-
-#[bench]
-fn insert_8_char_string(b: &mut Bencher) {
-    let mut strings: Vec<_> = Vec::new();
-    for i in 1..1001 {
-        strings.push(format!("{:x}", -i));
-    }
-
-    let mut m = new_map();
-    b.iter(|| {
-        for key in &strings {
-            m.insert(key, key);
-        }
-    })
-}
diff --git a/third_party/rust_crates/vendor/hashbrown/clippy.toml b/third_party/rust_crates/vendor/hashbrown/clippy.toml
deleted file mode 100644
index d98bf2c..0000000
--- a/third_party/rust_crates/vendor/hashbrown/clippy.toml
+++ /dev/null
@@ -1 +0,0 @@
-doc-valid-idents = [ "CppCon", "SwissTable", "SipHash", "HashDoS" ]
diff --git a/third_party/rust_crates/vendor/hashbrown/src/external_trait_impls/mod.rs b/third_party/rust_crates/vendor/hashbrown/src/external_trait_impls/mod.rs
deleted file mode 100644
index ef49783..0000000
--- a/third_party/rust_crates/vendor/hashbrown/src/external_trait_impls/mod.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-#[cfg(feature = "rayon")]
-pub(crate) mod rayon;
-#[cfg(feature = "serde")]
-mod serde;
diff --git a/third_party/rust_crates/vendor/hashbrown/src/external_trait_impls/rayon/helpers.rs b/third_party/rust_crates/vendor/hashbrown/src/external_trait_impls/rayon/helpers.rs
deleted file mode 100644
index 9382007..0000000
--- a/third_party/rust_crates/vendor/hashbrown/src/external_trait_impls/rayon/helpers.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-use alloc::collections::LinkedList;
-use alloc::vec::Vec;
-
-use rayon::iter::{IntoParallelIterator, ParallelIterator};
-
-/// Helper for collecting parallel iterators to an intermediary
-pub(super) fn collect<I: IntoParallelIterator>(iter: I) -> (LinkedList<Vec<I::Item>>, usize) {
-    let list = iter
-        .into_par_iter()
-        .fold(Vec::new, |mut vec, elem| {
-            vec.push(elem);
-            vec
-        })
-        .map(|vec| {
-            let mut list = LinkedList::new();
-            list.push_back(vec);
-            list
-        })
-        .reduce(LinkedList::new, |mut list1, mut list2| {
-            list1.append(&mut list2);
-            list1
-        });
-
-    let len = list.iter().map(Vec::len).sum();
-    (list, len)
-}
diff --git a/third_party/rust_crates/vendor/hashbrown/src/external_trait_impls/rayon/map.rs b/third_party/rust_crates/vendor/hashbrown/src/external_trait_impls/rayon/map.rs
deleted file mode 100644
index 6f869ae..0000000
--- a/third_party/rust_crates/vendor/hashbrown/src/external_trait_impls/rayon/map.rs
+++ /dev/null
@@ -1,676 +0,0 @@
-//! Rayon extensions for `HashMap`.
-
-use crate::hash_map::HashMap;
-use core::fmt;
-use core::hash::{BuildHasher, Hash};
-use rayon::iter::plumbing::UnindexedConsumer;
-use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelExtend, ParallelIterator};
-
-/// Parallel iterator over shared references to entries in a map.
-///
-/// This iterator is created by the [`par_iter`] method on [`HashMap`]
-/// (provided by the [`IntoParallelRefIterator`] trait).
-/// See its documentation for more.
-///
-/// [`par_iter`]: /hashbrown/struct.HashMap.html#method.par_iter
-/// [`HashMap`]: /hashbrown/struct.HashMap.html
-/// [`IntoParallelRefIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelRefIterator.html
-pub struct ParIter<'a, K, V, S> {
-    map: &'a HashMap<K, V, S>,
-}
-
-impl<'a, K: Sync, V: Sync, S: Sync> ParallelIterator for ParIter<'a, K, V, S> {
-    type Item = (&'a K, &'a V);
-
-    #[inline]
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        self.map
-            .table
-            .par_iter()
-            .map(|x| unsafe {
-                let r = x.as_ref();
-                (&r.0, &r.1)
-            })
-            .drive_unindexed(consumer)
-    }
-}
-
-impl<K, V, S> Clone for ParIter<'_, K, V, S> {
-    #[inline]
-    fn clone(&self) -> Self {
-        ParIter { map: self.map }
-    }
-}
-
-impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug, S: BuildHasher> fmt::Debug for ParIter<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.map.iter().fmt(f)
-    }
-}
-
-/// Parallel iterator over shared references to keys in a map.
-///
-/// This iterator is created by the [`par_keys`] method on [`HashMap`].
-/// See its documentation for more.
-///
-/// [`par_keys`]: /hashbrown/struct.HashMap.html#method.par_keys
-/// [`HashMap`]: /hashbrown/struct.HashMap.html
-pub struct ParKeys<'a, K, V, S> {
-    map: &'a HashMap<K, V, S>,
-}
-
-impl<'a, K: Sync, V: Sync, S: Sync> ParallelIterator for ParKeys<'a, K, V, S> {
-    type Item = &'a K;
-
-    #[inline]
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        self.map
-            .table
-            .par_iter()
-            .map(|x| unsafe { &x.as_ref().0 })
-            .drive_unindexed(consumer)
-    }
-}
-
-impl<K, V, S> Clone for ParKeys<'_, K, V, S> {
-    #[inline]
-    fn clone(&self) -> Self {
-        ParKeys { map: self.map }
-    }
-}
-
-impl<K: fmt::Debug + Eq + Hash, V, S: BuildHasher> fmt::Debug for ParKeys<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.map.keys().fmt(f)
-    }
-}
-
-/// Parallel iterator over shared references to values in a map.
-///
-/// This iterator is created by the [`par_values`] method on [`HashMap`].
-/// See its documentation for more.
-///
-/// [`par_values`]: /hashbrown/struct.HashMap.html#method.par_values
-/// [`HashMap`]: /hashbrown/struct.HashMap.html
-pub struct ParValues<'a, K, V, S> {
-    map: &'a HashMap<K, V, S>,
-}
-
-impl<'a, K: Sync, V: Sync, S: Sync> ParallelIterator for ParValues<'a, K, V, S> {
-    type Item = &'a V;
-
-    #[inline]
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        self.map
-            .table
-            .par_iter()
-            .map(|x| unsafe { &x.as_ref().1 })
-            .drive_unindexed(consumer)
-    }
-}
-
-impl<K, V, S> Clone for ParValues<'_, K, V, S> {
-    #[inline]
-    fn clone(&self) -> Self {
-        ParValues { map: self.map }
-    }
-}
-
-impl<K: Eq + Hash, V: fmt::Debug, S: BuildHasher> fmt::Debug for ParValues<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.map.values().fmt(f)
-    }
-}
-
-/// Parallel iterator over mutable references to entries in a map.
-///
-/// This iterator is created by the [`par_iter_mut`] method on [`HashMap`]
-/// (provided by the [`IntoParallelRefMutIterator`] trait).
-/// See its documentation for more.
-///
-/// [`par_iter_mut`]: /hashbrown/struct.HashMap.html#method.par_iter_mut
-/// [`HashMap`]: /hashbrown/struct.HashMap.html
-/// [`IntoParallelRefMutIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelRefMutIterator.html
-pub struct ParIterMut<'a, K, V, S> {
-    map: &'a mut HashMap<K, V, S>,
-}
-
-impl<'a, K: Send + Sync, V: Send, S: Send> ParallelIterator for ParIterMut<'a, K, V, S> {
-    type Item = (&'a K, &'a mut V);
-
-    #[inline]
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        self.map
-            .table
-            .par_iter()
-            .map(|x| unsafe {
-                let r = x.as_mut();
-                (&r.0, &mut r.1)
-            })
-            .drive_unindexed(consumer)
-    }
-}
-
-impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug, S: BuildHasher> fmt::Debug
-    for ParIterMut<'_, K, V, S>
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.map.iter().fmt(f)
-    }
-}
-
-/// Parallel iterator over mutable references to values in a map.
-///
-/// This iterator is created by the [`par_values_mut`] method on [`HashMap`].
-/// See its documentation for more.
-///
-/// [`par_values_mut`]: /hashbrown/struct.HashMap.html#method.par_values_mut
-/// [`HashMap`]: /hashbrown/struct.HashMap.html
-pub struct ParValuesMut<'a, K, V, S> {
-    map: &'a mut HashMap<K, V, S>,
-}
-
-impl<'a, K: Send, V: Send, S: Send> ParallelIterator for ParValuesMut<'a, K, V, S> {
-    type Item = &'a mut V;
-
-    #[inline]
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        self.map
-            .table
-            .par_iter()
-            .map(|x| unsafe { &mut x.as_mut().1 })
-            .drive_unindexed(consumer)
-    }
-}
-
-impl<K: Eq + Hash, V: fmt::Debug, S: BuildHasher> fmt::Debug for ParValuesMut<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.map.values().fmt(f)
-    }
-}
-
-/// Parallel iterator over entries of a consumed map.
-///
-/// This iterator is created by the [`into_par_iter`] method on [`HashMap`]
-/// (provided by the [`IntoParallelIterator`] trait).
-/// See its documentation for more.
-///
-/// [`into_par_iter`]: /hashbrown/struct.HashMap.html#method.into_par_iter
-/// [`HashMap`]: /hashbrown/struct.HashMap.html
-/// [`IntoParallelIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelIterator.html
-pub struct IntoParIter<K, V, S> {
-    map: HashMap<K, V, S>,
-}
-
-impl<K: Send, V: Send, S: Send> ParallelIterator for IntoParIter<K, V, S> {
-    type Item = (K, V);
-
-    #[inline]
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        self.map.table.into_par_iter().drive_unindexed(consumer)
-    }
-}
-
-impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug, S: BuildHasher> fmt::Debug for IntoParIter<K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.map.iter().fmt(f)
-    }
-}
-
-/// Parallel draining iterator over entries of a map.
-///
-/// This iterator is created by the [`par_drain`] method on [`HashMap`].
-/// See its documentation for more.
-///
-/// [`par_drain`]: /hashbrown/struct.HashMap.html#method.par_drain
-/// [`HashMap`]: /hashbrown/struct.HashMap.html
-pub struct ParDrain<'a, K, V, S> {
-    map: &'a mut HashMap<K, V, S>,
-}
-
-impl<K: Send, V: Send, S: Send> ParallelIterator for ParDrain<'_, K, V, S> {
-    type Item = (K, V);
-
-    #[inline]
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        self.map.table.par_drain().drive_unindexed(consumer)
-    }
-}
-
-impl<K: fmt::Debug + Eq + Hash, V: fmt::Debug, S: BuildHasher> fmt::Debug
-    for ParDrain<'_, K, V, S>
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.map.iter().fmt(f)
-    }
-}
-
-impl<K: Sync, V: Sync, S: Sync> HashMap<K, V, S> {
-    /// Visits (potentially in parallel) immutably borrowed keys in an arbitrary order.
-    #[inline]
-    pub fn par_keys(&self) -> ParKeys<'_, K, V, S> {
-        ParKeys { map: self }
-    }
-
-    /// Visits (potentially in parallel) immutably borrowed values in an arbitrary order.
-    #[inline]
-    pub fn par_values(&self) -> ParValues<'_, K, V, S> {
-        ParValues { map: self }
-    }
-}
-
-impl<K: Send, V: Send, S: Send> HashMap<K, V, S> {
-    /// Visits (potentially in parallel) mutably borrowed values in an arbitrary order.
-    #[inline]
-    pub fn par_values_mut(&mut self) -> ParValuesMut<'_, K, V, S> {
-        ParValuesMut { map: self }
-    }
-
-    /// Consumes (potentially in parallel) all values in an arbitrary order,
-    /// while preserving the map's allocated memory for reuse.
-    #[inline]
-    pub fn par_drain(&mut self) -> ParDrain<'_, K, V, S> {
-        ParDrain { map: self }
-    }
-}
-
-impl<K, V, S> HashMap<K, V, S>
-where
-    K: Eq + Hash + Sync,
-    V: PartialEq + Sync,
-    S: BuildHasher + Sync,
-{
-    /// Returns `true` if the map is equal to another,
-    /// i.e. both maps contain the same keys mapped to the same values.
-    ///
-    /// This method runs in a potentially parallel fashion.
-    pub fn par_eq(&self, other: &Self) -> bool {
-        self.len() == other.len()
-            && self
-                .into_par_iter()
-                .all(|(key, value)| other.get(key).map_or(false, |v| *value == *v))
-    }
-}
-
-impl<K: Send, V: Send, S: Send> IntoParallelIterator for HashMap<K, V, S> {
-    type Item = (K, V);
-    type Iter = IntoParIter<K, V, S>;
-
-    #[inline]
-    fn into_par_iter(self) -> Self::Iter {
-        IntoParIter { map: self }
-    }
-}
-
-impl<'a, K: Sync, V: Sync, S: Sync> IntoParallelIterator for &'a HashMap<K, V, S> {
-    type Item = (&'a K, &'a V);
-    type Iter = ParIter<'a, K, V, S>;
-
-    #[inline]
-    fn into_par_iter(self) -> Self::Iter {
-        ParIter { map: self }
-    }
-}
-
-impl<'a, K: Send + Sync, V: Send, S: Send> IntoParallelIterator for &'a mut HashMap<K, V, S> {
-    type Item = (&'a K, &'a mut V);
-    type Iter = ParIterMut<'a, K, V, S>;
-
-    #[inline]
-    fn into_par_iter(self) -> Self::Iter {
-        ParIterMut { map: self }
-    }
-}
-
-/// Collect (key, value) pairs from a parallel iterator into a
-/// hashmap. If multiple pairs correspond to the same key, then the
-/// ones produced earlier in the parallel iterator will be
-/// overwritten, just as with a sequential iterator.
-impl<K, V, S> FromParallelIterator<(K, V)> for HashMap<K, V, S>
-where
-    K: Eq + Hash + Send,
-    V: Send,
-    S: BuildHasher + Default,
-{
-    fn from_par_iter<P>(par_iter: P) -> Self
-    where
-        P: IntoParallelIterator<Item = (K, V)>,
-    {
-        let mut map = HashMap::default();
-        map.par_extend(par_iter);
-        map
-    }
-}
-
-/// Extend a hash map with items from a parallel iterator.
-impl<K, V, S> ParallelExtend<(K, V)> for HashMap<K, V, S>
-where
-    K: Eq + Hash + Send,
-    V: Send,
-    S: BuildHasher,
-{
-    fn par_extend<I>(&mut self, par_iter: I)
-    where
-        I: IntoParallelIterator<Item = (K, V)>,
-    {
-        extend(self, par_iter);
-    }
-}
-
-/// Extend a hash map with copied items from a parallel iterator.
-impl<'a, K, V, S> ParallelExtend<(&'a K, &'a V)> for HashMap<K, V, S>
-where
-    K: Copy + Eq + Hash + Sync,
-    V: Copy + Sync,
-    S: BuildHasher,
-{
-    fn par_extend<I>(&mut self, par_iter: I)
-    where
-        I: IntoParallelIterator<Item = (&'a K, &'a V)>,
-    {
-        extend(self, par_iter);
-    }
-}
-
-// This is equal to the normal `HashMap` -- no custom advantage.
-fn extend<K, V, S, I>(map: &mut HashMap<K, V, S>, par_iter: I)
-where
-    K: Eq + Hash,
-    S: BuildHasher,
-    I: IntoParallelIterator,
-    HashMap<K, V, S>: Extend<I::Item>,
-{
-    let (list, len) = super::helpers::collect(par_iter);
-
-    // Keys may be already present or show multiple times in the iterator.
-    // Reserve the entire length if the map is empty.
-    // Otherwise reserve half the length (rounded up), so the map
-    // will only resize twice in the worst case.
-    let reserve = if map.is_empty() { len } else { (len + 1) / 2 };
-    map.reserve(reserve);
-    for vec in list {
-        map.extend(vec);
-    }
-}
-
-#[cfg(test)]
-mod test_par_map {
-    use alloc::vec::Vec;
-    use core::hash::{Hash, Hasher};
-    use core::sync::atomic::{AtomicUsize, Ordering};
-
-    use rayon::prelude::*;
-
-    use crate::hash_map::HashMap;
-
-    struct Dropable<'a> {
-        k: usize,
-        counter: &'a AtomicUsize,
-    }
-
-    impl Dropable<'_> {
-        fn new(k: usize, counter: &AtomicUsize) -> Dropable<'_> {
-            counter.fetch_add(1, Ordering::Relaxed);
-
-            Dropable { k, counter }
-        }
-    }
-
-    impl Drop for Dropable<'_> {
-        fn drop(&mut self) {
-            self.counter.fetch_sub(1, Ordering::Relaxed);
-        }
-    }
-
-    impl Clone for Dropable<'_> {
-        fn clone(&self) -> Self {
-            Dropable::new(self.k, self.counter)
-        }
-    }
-
-    impl Hash for Dropable<'_> {
-        fn hash<H>(&self, state: &mut H)
-        where
-            H: Hasher,
-        {
-            self.k.hash(state)
-        }
-    }
-
-    impl PartialEq for Dropable<'_> {
-        fn eq(&self, other: &Self) -> bool {
-            self.k == other.k
-        }
-    }
-
-    impl Eq for Dropable<'_> {}
-
-    #[test]
-    fn test_into_iter_drops() {
-        let key = AtomicUsize::new(0);
-        let value = AtomicUsize::new(0);
-
-        let hm = {
-            let mut hm = HashMap::new();
-
-            assert_eq!(key.load(Ordering::Relaxed), 0);
-            assert_eq!(value.load(Ordering::Relaxed), 0);
-
-            for i in 0..100 {
-                let d1 = Dropable::new(i, &key);
-                let d2 = Dropable::new(i + 100, &value);
-                hm.insert(d1, d2);
-            }
-
-            assert_eq!(key.load(Ordering::Relaxed), 100);
-            assert_eq!(value.load(Ordering::Relaxed), 100);
-
-            hm
-        };
-
-        // By the way, ensure that cloning doesn't screw up the dropping.
-        drop(hm.clone());
-
-        assert_eq!(key.load(Ordering::Relaxed), 100);
-        assert_eq!(value.load(Ordering::Relaxed), 100);
-
-        // Ensure that dropping the iterator does not leak anything.
-        drop(hm.clone().into_par_iter());
-
-        {
-            assert_eq!(key.load(Ordering::Relaxed), 100);
-            assert_eq!(value.load(Ordering::Relaxed), 100);
-
-            // retain only half
-            let _v: Vec<_> = hm
-                .into_par_iter()
-                .filter(|&(ref key, _)| key.k < 50)
-                .collect();
-
-            assert_eq!(key.load(Ordering::Relaxed), 50);
-            assert_eq!(value.load(Ordering::Relaxed), 50);
-        };
-
-        assert_eq!(key.load(Ordering::Relaxed), 0);
-        assert_eq!(value.load(Ordering::Relaxed), 0);
-    }
-
-    #[test]
-    fn test_drain_drops() {
-        let key = AtomicUsize::new(0);
-        let value = AtomicUsize::new(0);
-
-        let mut hm = {
-            let mut hm = HashMap::new();
-
-            assert_eq!(key.load(Ordering::Relaxed), 0);
-            assert_eq!(value.load(Ordering::Relaxed), 0);
-
-            for i in 0..100 {
-                let d1 = Dropable::new(i, &key);
-                let d2 = Dropable::new(i + 100, &value);
-                hm.insert(d1, d2);
-            }
-
-            assert_eq!(key.load(Ordering::Relaxed), 100);
-            assert_eq!(value.load(Ordering::Relaxed), 100);
-
-            hm
-        };
-
-        // By the way, ensure that cloning doesn't screw up the dropping.
-        drop(hm.clone());
-
-        assert_eq!(key.load(Ordering::Relaxed), 100);
-        assert_eq!(value.load(Ordering::Relaxed), 100);
-
-        // Ensure that dropping the drain iterator does not leak anything.
-        drop(hm.clone().par_drain());
-
-        {
-            assert_eq!(key.load(Ordering::Relaxed), 100);
-            assert_eq!(value.load(Ordering::Relaxed), 100);
-
-            // retain only half
-            let _v: Vec<_> = hm.drain().filter(|&(ref key, _)| key.k < 50).collect();
-            assert!(hm.is_empty());
-
-            assert_eq!(key.load(Ordering::Relaxed), 50);
-            assert_eq!(value.load(Ordering::Relaxed), 50);
-        };
-
-        assert_eq!(key.load(Ordering::Relaxed), 0);
-        assert_eq!(value.load(Ordering::Relaxed), 0);
-    }
-
-    #[test]
-    fn test_empty_iter() {
-        let mut m: HashMap<isize, bool> = HashMap::new();
-        assert_eq!(m.par_drain().count(), 0);
-        assert_eq!(m.par_keys().count(), 0);
-        assert_eq!(m.par_values().count(), 0);
-        assert_eq!(m.par_values_mut().count(), 0);
-        assert_eq!(m.par_iter().count(), 0);
-        assert_eq!(m.par_iter_mut().count(), 0);
-        assert_eq!(m.len(), 0);
-        assert!(m.is_empty());
-        assert_eq!(m.into_par_iter().count(), 0);
-    }
-
-    #[test]
-    fn test_iterate() {
-        let mut m = HashMap::with_capacity(4);
-        for i in 0..32 {
-            assert!(m.insert(i, i * 2).is_none());
-        }
-        assert_eq!(m.len(), 32);
-
-        let observed = AtomicUsize::new(0);
-
-        m.par_iter().for_each(|(k, v)| {
-            assert_eq!(*v, *k * 2);
-            observed.fetch_or(1 << *k, Ordering::Relaxed);
-        });
-        assert_eq!(observed.into_inner(), 0xFFFF_FFFF);
-    }
-
-    #[test]
-    fn test_keys() {
-        let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
-        let map: HashMap<_, _> = vec.into_par_iter().collect();
-        let keys: Vec<_> = map.par_keys().cloned().collect();
-        assert_eq!(keys.len(), 3);
-        assert!(keys.contains(&1));
-        assert!(keys.contains(&2));
-        assert!(keys.contains(&3));
-    }
-
-    #[test]
-    fn test_values() {
-        let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
-        let map: HashMap<_, _> = vec.into_par_iter().collect();
-        let values: Vec<_> = map.par_values().cloned().collect();
-        assert_eq!(values.len(), 3);
-        assert!(values.contains(&'a'));
-        assert!(values.contains(&'b'));
-        assert!(values.contains(&'c'));
-    }
-
-    #[test]
-    fn test_values_mut() {
-        let vec = vec![(1, 1), (2, 2), (3, 3)];
-        let mut map: HashMap<_, _> = vec.into_par_iter().collect();
-        map.par_values_mut().for_each(|value| *value = (*value) * 2);
-        let values: Vec<_> = map.par_values().cloned().collect();
-        assert_eq!(values.len(), 3);
-        assert!(values.contains(&2));
-        assert!(values.contains(&4));
-        assert!(values.contains(&6));
-    }
-
-    #[test]
-    fn test_eq() {
-        let mut m1 = HashMap::new();
-        m1.insert(1, 2);
-        m1.insert(2, 3);
-        m1.insert(3, 4);
-
-        let mut m2 = HashMap::new();
-        m2.insert(1, 2);
-        m2.insert(2, 3);
-
-        assert!(!m1.par_eq(&m2));
-
-        m2.insert(3, 4);
-
-        assert!(m1.par_eq(&m2));
-    }
-
-    #[test]
-    fn test_from_iter() {
-        let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
-
-        let map: HashMap<_, _> = xs.par_iter().cloned().collect();
-
-        for &(k, v) in &xs {
-            assert_eq!(map.get(&k), Some(&v));
-        }
-    }
-
-    #[test]
-    fn test_extend_ref() {
-        let mut a = HashMap::new();
-        a.insert(1, "one");
-        let mut b = HashMap::new();
-        b.insert(2, "two");
-        b.insert(3, "three");
-
-        a.par_extend(&b);
-
-        assert_eq!(a.len(), 3);
-        assert_eq!(a[&1], "one");
-        assert_eq!(a[&2], "two");
-        assert_eq!(a[&3], "three");
-    }
-}
diff --git a/third_party/rust_crates/vendor/hashbrown/src/external_trait_impls/rayon/mod.rs b/third_party/rust_crates/vendor/hashbrown/src/external_trait_impls/rayon/mod.rs
deleted file mode 100644
index 6765299..0000000
--- a/third_party/rust_crates/vendor/hashbrown/src/external_trait_impls/rayon/mod.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-mod helpers;
-mod raw;
-
-pub(crate) mod map;
-pub(crate) mod set;
diff --git a/third_party/rust_crates/vendor/hashbrown/src/external_trait_impls/rayon/raw.rs b/third_party/rust_crates/vendor/hashbrown/src/external_trait_impls/rayon/raw.rs
deleted file mode 100644
index 6834705..0000000
--- a/third_party/rust_crates/vendor/hashbrown/src/external_trait_impls/rayon/raw.rs
+++ /dev/null
@@ -1,193 +0,0 @@
-use crate::raw::Bucket;
-use crate::raw::{RawIterRange, RawTable};
-use crate::scopeguard::guard;
-use alloc::alloc::dealloc;
-use core::marker::PhantomData;
-use core::mem;
-use core::ptr::NonNull;
-use rayon::iter::{
-    plumbing::{self, Folder, UnindexedConsumer, UnindexedProducer},
-    ParallelIterator,
-};
-
-/// Parallel iterator which returns a raw pointer to every full bucket in the table.
-pub struct RawParIter<T> {
-    iter: RawIterRange<T>,
-}
-
-impl<T> ParallelIterator for RawParIter<T> {
-    type Item = Bucket<T>;
-
-    #[inline]
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        let producer = ParIterProducer { iter: self.iter };
-        plumbing::bridge_unindexed(producer, consumer)
-    }
-}
-
-/// Producer which returns a `Bucket<T>` for every element.
-struct ParIterProducer<T> {
-    iter: RawIterRange<T>,
-}
-
-impl<T> UnindexedProducer for ParIterProducer<T> {
-    type Item = Bucket<T>;
-
-    #[inline]
-    fn split(self) -> (Self, Option<Self>) {
-        let (left, right) = self.iter.split();
-        let left = ParIterProducer { iter: left };
-        let right = right.map(|right| ParIterProducer { iter: right });
-        (left, right)
-    }
-
-    #[inline]
-    fn fold_with<F>(self, folder: F) -> F
-    where
-        F: Folder<Self::Item>,
-    {
-        folder.consume_iter(self.iter)
-    }
-}
-
-/// Parallel iterator which consumes a table and returns elements.
-pub struct RawIntoParIter<T> {
-    table: RawTable<T>,
-}
-
-impl<T: Send> ParallelIterator for RawIntoParIter<T> {
-    type Item = T;
-
-    #[inline]
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        let iter = unsafe { self.table.iter().iter };
-        let _guard = guard(self.table.into_alloc(), |alloc| {
-            if let Some((ptr, layout)) = *alloc {
-                unsafe {
-                    dealloc(ptr.as_ptr(), layout);
-                }
-            }
-        });
-        let producer = ParDrainProducer { iter };
-        plumbing::bridge_unindexed(producer, consumer)
-    }
-}
-
-/// Parallel iterator which consumes elements without freeing the table storage.
-pub struct RawParDrain<'a, T> {
-    // We don't use a &'a mut RawTable<T> because we want RawParDrain to be
-    // covariant over T.
-    table: NonNull<RawTable<T>>,
-    marker: PhantomData<&'a RawTable<T>>,
-}
-
-unsafe impl<T> Send for RawParDrain<'_, T> {}
-
-impl<T: Send> ParallelIterator for RawParDrain<'_, T> {
-    type Item = T;
-
-    #[inline]
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        let _guard = guard(self.table, |table| unsafe {
-            table.as_mut().clear_no_drop()
-        });
-        let iter = unsafe { self.table.as_ref().iter().iter };
-        mem::forget(self);
-        let producer = ParDrainProducer { iter };
-        plumbing::bridge_unindexed(producer, consumer)
-    }
-}
-
-impl<T> Drop for RawParDrain<'_, T> {
-    fn drop(&mut self) {
-        // If drive_unindexed is not called then simply clear the table.
-        unsafe { self.table.as_mut().clear() }
-    }
-}
-
-/// Producer which will consume all elements in the range, even if it is dropped
-/// halfway through.
-struct ParDrainProducer<T> {
-    iter: RawIterRange<T>,
-}
-
-impl<T: Send> UnindexedProducer for ParDrainProducer<T> {
-    type Item = T;
-
-    #[inline]
-    fn split(self) -> (Self, Option<Self>) {
-        let (left, right) = self.iter.clone().split();
-        mem::forget(self);
-        let left = ParDrainProducer { iter: left };
-        let right = right.map(|right| ParDrainProducer { iter: right });
-        (left, right)
-    }
-
-    #[inline]
-    fn fold_with<F>(mut self, mut folder: F) -> F
-    where
-        F: Folder<Self::Item>,
-    {
-        // Make sure to modify the iterator in-place so that any remaining
-        // elements are processed in our Drop impl.
-        while let Some(item) = self.iter.next() {
-            folder = folder.consume(unsafe { item.read() });
-            if folder.full() {
-                return folder;
-            }
-        }
-
-        // If we processed all elements then we don't need to run the drop.
-        mem::forget(self);
-        folder
-    }
-}
-
-impl<T> Drop for ParDrainProducer<T> {
-    #[inline]
-    fn drop(&mut self) {
-        // Drop all remaining elements
-        if mem::needs_drop::<T>() {
-            while let Some(item) = self.iter.next() {
-                unsafe {
-                    item.drop();
-                }
-            }
-        }
-    }
-}
-
-impl<T> RawTable<T> {
-    /// Returns a parallel iterator over the elements in a `RawTable`.
-    #[inline]
-    pub fn par_iter(&self) -> RawParIter<T> {
-        RawParIter {
-            iter: unsafe { self.iter().iter },
-        }
-    }
-
-    /// Returns a parallel iterator over the elements in a `RawTable`.
-    #[inline]
-    pub fn into_par_iter(self) -> RawIntoParIter<T> {
-        RawIntoParIter { table: self }
-    }
-
-    /// Returns a parallel iterator which consumes all elements of a `RawTable`
-    /// without freeing its memory allocation.
-    #[inline]
-    pub fn par_drain(&mut self) -> RawParDrain<'_, T> {
-        RawParDrain {
-            table: NonNull::from(self),
-            marker: PhantomData,
-        }
-    }
-}
diff --git a/third_party/rust_crates/vendor/hashbrown/src/external_trait_impls/rayon/set.rs b/third_party/rust_crates/vendor/hashbrown/src/external_trait_impls/rayon/set.rs
deleted file mode 100644
index 896be75..0000000
--- a/third_party/rust_crates/vendor/hashbrown/src/external_trait_impls/rayon/set.rs
+++ /dev/null
@@ -1,646 +0,0 @@
-//! Rayon extensions for `HashSet`.
-
-use crate::hash_set::HashSet;
-use core::hash::{BuildHasher, Hash};
-use rayon::iter::plumbing::UnindexedConsumer;
-use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelExtend, ParallelIterator};
-
-/// Parallel iterator over elements of a consumed set.
-///
-/// This iterator is created by the [`into_par_iter`] method on [`HashSet`]
-/// (provided by the [`IntoParallelIterator`] trait).
-/// See its documentation for more.
-///
-/// [`into_par_iter`]: /hashbrown/struct.HashSet.html#method.into_par_iter
-/// [`HashSet`]: /hashbrown/struct.HashSet.html
-/// [`IntoParallelIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelIterator.html
-pub struct IntoParIter<T, S> {
-    set: HashSet<T, S>,
-}
-
-impl<T: Send, S: Send> ParallelIterator for IntoParIter<T, S> {
-    type Item = T;
-
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        self.set
-            .map
-            .into_par_iter()
-            .map(|(k, _)| k)
-            .drive_unindexed(consumer)
-    }
-}
-
-/// Parallel draining iterator over entries of a set.
-///
-/// This iterator is created by the [`par_drain`] method on [`HashSet`].
-/// See its documentation for more.
-///
-/// [`par_drain`]: /hashbrown/struct.HashSet.html#method.par_drain
-/// [`HashSet`]: /hashbrown/struct.HashSet.html
-pub struct ParDrain<'a, T, S> {
-    set: &'a mut HashSet<T, S>,
-}
-
-impl<T: Send, S: Send> ParallelIterator for ParDrain<'_, T, S> {
-    type Item = T;
-
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        self.set
-            .map
-            .par_drain()
-            .map(|(k, _)| k)
-            .drive_unindexed(consumer)
-    }
-}
-
-/// Parallel iterator over shared references to elements in a set.
-///
-/// This iterator is created by the [`par_iter`] method on [`HashSet`]
-/// (provided by the [`IntoParallelRefIterator`] trait).
-/// See its documentation for more.
-///
-/// [`par_iter`]: /hashbrown/struct.HashSet.html#method.par_iter
-/// [`HashSet`]: /hashbrown/struct.HashSet.html
-/// [`IntoParallelRefIterator`]: https://docs.rs/rayon/1.0/rayon/iter/trait.IntoParallelRefIterator.html
-pub struct ParIter<'a, T, S> {
-    set: &'a HashSet<T, S>,
-}
-
-impl<'a, T: Sync, S: Sync> ParallelIterator for ParIter<'a, T, S> {
-    type Item = &'a T;
-
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        self.set.map.par_keys().drive_unindexed(consumer)
-    }
-}
-
-/// Parallel iterator over shared references to elements in the difference of
-/// sets.
-///
-/// This iterator is created by the [`par_difference`] method on [`HashSet`].
-/// See its documentation for more.
-///
-/// [`par_difference`]: /hashbrown/struct.HashSet.html#method.par_difference
-/// [`HashSet`]: /hashbrown/struct.HashSet.html
-pub struct ParDifference<'a, T, S> {
-    a: &'a HashSet<T, S>,
-    b: &'a HashSet<T, S>,
-}
-
-impl<'a, T, S> ParallelIterator for ParDifference<'a, T, S>
-where
-    T: Eq + Hash + Sync,
-    S: BuildHasher + Sync,
-{
-    type Item = &'a T;
-
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        self.a
-            .into_par_iter()
-            .filter(|&x| !self.b.contains(x))
-            .drive_unindexed(consumer)
-    }
-}
-
-/// Parallel iterator over shared references to elements in the symmetric
-/// difference of sets.
-///
-/// This iterator is created by the [`par_symmetric_difference`] method on
-/// [`HashSet`].
-/// See its documentation for more.
-///
-/// [`par_symmetric_difference`]: /hashbrown/struct.HashSet.html#method.par_symmetric_difference
-/// [`HashSet`]: /hashbrown/struct.HashSet.html
-pub struct ParSymmetricDifference<'a, T, S> {
-    a: &'a HashSet<T, S>,
-    b: &'a HashSet<T, S>,
-}
-
-impl<'a, T, S> ParallelIterator for ParSymmetricDifference<'a, T, S>
-where
-    T: Eq + Hash + Sync,
-    S: BuildHasher + Sync,
-{
-    type Item = &'a T;
-
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        self.a
-            .par_difference(self.b)
-            .chain(self.b.par_difference(self.a))
-            .drive_unindexed(consumer)
-    }
-}
-
-/// Parallel iterator over shared references to elements in the intersection of
-/// sets.
-///
-/// This iterator is created by the [`par_intersection`] method on [`HashSet`].
-/// See its documentation for more.
-///
-/// [`par_intersection`]: /hashbrown/struct.HashSet.html#method.par_intersection
-/// [`HashSet`]: /hashbrown/struct.HashSet.html
-pub struct ParIntersection<'a, T, S> {
-    a: &'a HashSet<T, S>,
-    b: &'a HashSet<T, S>,
-}
-
-impl<'a, T, S> ParallelIterator for ParIntersection<'a, T, S>
-where
-    T: Eq + Hash + Sync,
-    S: BuildHasher + Sync,
-{
-    type Item = &'a T;
-
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        self.a
-            .into_par_iter()
-            .filter(|&x| self.b.contains(x))
-            .drive_unindexed(consumer)
-    }
-}
-
-/// Parallel iterator over shared references to elements in the union of sets.
-///
-/// This iterator is created by the [`par_union`] method on [`HashSet`].
-/// See its documentation for more.
-///
-/// [`par_union`]: /hashbrown/struct.HashSet.html#method.par_union
-/// [`HashSet`]: /hashbrown/struct.HashSet.html
-pub struct ParUnion<'a, T, S> {
-    a: &'a HashSet<T, S>,
-    b: &'a HashSet<T, S>,
-}
-
-impl<'a, T, S> ParallelIterator for ParUnion<'a, T, S>
-where
-    T: Eq + Hash + Sync,
-    S: BuildHasher + Sync,
-{
-    type Item = &'a T;
-
-    fn drive_unindexed<C>(self, consumer: C) -> C::Result
-    where
-        C: UnindexedConsumer<Self::Item>,
-    {
-        self.a
-            .into_par_iter()
-            .chain(self.b.par_difference(self.a))
-            .drive_unindexed(consumer)
-    }
-}
-
-impl<T, S> HashSet<T, S>
-where
-    T: Eq + Hash + Sync,
-    S: BuildHasher + Sync,
-{
-    /// Visits (potentially in parallel) the values representing the difference,
-    /// i.e. the values that are in `self` but not in `other`.
-    #[inline]
-    pub fn par_difference<'a>(&'a self, other: &'a Self) -> ParDifference<'a, T, S> {
-        ParDifference { a: self, b: other }
-    }
-
-    /// Visits (potentially in parallel) the values representing the symmetric
-    /// difference, i.e. the values that are in `self` or in `other` but not in both.
-    #[inline]
-    pub fn par_symmetric_difference<'a>(
-        &'a self,
-        other: &'a Self,
-    ) -> ParSymmetricDifference<'a, T, S> {
-        ParSymmetricDifference { a: self, b: other }
-    }
-
-    /// Visits (potentially in parallel) the values representing the
-    /// intersection, i.e. the values that are both in `self` and `other`.
-    #[inline]
-    pub fn par_intersection<'a>(&'a self, other: &'a Self) -> ParIntersection<'a, T, S> {
-        ParIntersection { a: self, b: other }
-    }
-
-    /// Visits (potentially in parallel) the values representing the union,
-    /// i.e. all the values in `self` or `other`, without duplicates.
-    #[inline]
-    pub fn par_union<'a>(&'a self, other: &'a Self) -> ParUnion<'a, T, S> {
-        ParUnion { a: self, b: other }
-    }
-
-    /// Returns `true` if `self` has no elements in common with `other`.
-    /// This is equivalent to checking for an empty intersection.
-    ///
-    /// This method runs in a potentially parallel fashion.
-    pub fn par_is_disjoint(&self, other: &Self) -> bool {
-        self.into_par_iter().all(|x| !other.contains(x))
-    }
-
-    /// Returns `true` if the set is a subset of another,
-    /// i.e. `other` contains at least all the values in `self`.
-    ///
-    /// This method runs in a potentially parallel fashion.
-    pub fn par_is_subset(&self, other: &Self) -> bool {
-        if self.len() <= other.len() {
-            self.into_par_iter().all(|x| other.contains(x))
-        } else {
-            false
-        }
-    }
-
-    /// Returns `true` if the set is a superset of another,
-    /// i.e. `self` contains at least all the values in `other`.
-    ///
-    /// This method runs in a potentially parallel fashion.
-    pub fn par_is_superset(&self, other: &Self) -> bool {
-        other.par_is_subset(self)
-    }
-
-    /// Returns `true` if the set is equal to another,
-    /// i.e. both sets contain the same values.
-    ///
-    /// This method runs in a potentially parallel fashion.
-    pub fn par_eq(&self, other: &Self) -> bool {
-        self.len() == other.len() && self.par_is_subset(other)
-    }
-}
-
-impl<T, S> HashSet<T, S>
-where
-    T: Eq + Hash + Send,
-    S: BuildHasher + Send,
-{
-    /// Consumes (potentially in parallel) all values in an arbitrary order,
-    /// while preserving the set's allocated memory for reuse.
-    #[inline]
-    pub fn par_drain(&mut self) -> ParDrain<'_, T, S> {
-        ParDrain { set: self }
-    }
-}
-
-impl<T: Send, S: Send> IntoParallelIterator for HashSet<T, S> {
-    type Item = T;
-    type Iter = IntoParIter<T, S>;
-
-    #[inline]
-    fn into_par_iter(self) -> Self::Iter {
-        IntoParIter { set: self }
-    }
-}
-
-impl<'a, T: Sync, S: Sync> IntoParallelIterator for &'a HashSet<T, S> {
-    type Item = &'a T;
-    type Iter = ParIter<'a, T, S>;
-
-    #[inline]
-    fn into_par_iter(self) -> Self::Iter {
-        ParIter { set: self }
-    }
-}
-
-/// Collect values from a parallel iterator into a hashset.
-impl<T, S> FromParallelIterator<T> for HashSet<T, S>
-where
-    T: Eq + Hash + Send,
-    S: BuildHasher + Default,
-{
-    fn from_par_iter<P>(par_iter: P) -> Self
-    where
-        P: IntoParallelIterator<Item = T>,
-    {
-        let mut set = HashSet::default();
-        set.par_extend(par_iter);
-        set
-    }
-}
-
-/// Extend a hash set with items from a parallel iterator.
-impl<T, S> ParallelExtend<T> for HashSet<T, S>
-where
-    T: Eq + Hash + Send,
-    S: BuildHasher,
-{
-    fn par_extend<I>(&mut self, par_iter: I)
-    where
-        I: IntoParallelIterator<Item = T>,
-    {
-        extend(self, par_iter);
-    }
-}
-
-/// Extend a hash set with copied items from a parallel iterator.
-impl<'a, T, S> ParallelExtend<&'a T> for HashSet<T, S>
-where
-    T: 'a + Copy + Eq + Hash + Sync,
-    S: BuildHasher,
-{
-    fn par_extend<I>(&mut self, par_iter: I)
-    where
-        I: IntoParallelIterator<Item = &'a T>,
-    {
-        extend(self, par_iter);
-    }
-}
-
-// This is equal to the normal `HashSet` -- no custom advantage.
-fn extend<T, S, I>(set: &mut HashSet<T, S>, par_iter: I)
-where
-    T: Eq + Hash,
-    S: BuildHasher,
-    I: IntoParallelIterator,
-    HashSet<T, S>: Extend<I::Item>,
-{
-    let (list, len) = super::helpers::collect(par_iter);
-
-    // Values may be already present or show multiple times in the iterator.
-    // Reserve the entire length if the set is empty.
-    // Otherwise reserve half the length (rounded up), so the set
-    // will only resize twice in the worst case.
-    let reserve = if set.is_empty() { len } else { (len + 1) / 2 };
-    set.reserve(reserve);
-    for vec in list {
-        set.extend(vec);
-    }
-}
-
-#[cfg(test)]
-mod test_par_set {
-    use alloc::vec::Vec;
-    use core::sync::atomic::{AtomicUsize, Ordering};
-
-    use rayon::prelude::*;
-
-    use crate::hash_set::HashSet;
-
-    #[test]
-    fn test_disjoint() {
-        let mut xs = HashSet::new();
-        let mut ys = HashSet::new();
-        assert!(xs.par_is_disjoint(&ys));
-        assert!(ys.par_is_disjoint(&xs));
-        assert!(xs.insert(5));
-        assert!(ys.insert(11));
-        assert!(xs.par_is_disjoint(&ys));
-        assert!(ys.par_is_disjoint(&xs));
-        assert!(xs.insert(7));
-        assert!(xs.insert(19));
-        assert!(xs.insert(4));
-        assert!(ys.insert(2));
-        assert!(ys.insert(-11));
-        assert!(xs.par_is_disjoint(&ys));
-        assert!(ys.par_is_disjoint(&xs));
-        assert!(ys.insert(7));
-        assert!(!xs.par_is_disjoint(&ys));
-        assert!(!ys.par_is_disjoint(&xs));
-    }
-
-    #[test]
-    fn test_subset_and_superset() {
-        let mut a = HashSet::new();
-        assert!(a.insert(0));
-        assert!(a.insert(5));
-        assert!(a.insert(11));
-        assert!(a.insert(7));
-
-        let mut b = HashSet::new();
-        assert!(b.insert(0));
-        assert!(b.insert(7));
-        assert!(b.insert(19));
-        assert!(b.insert(250));
-        assert!(b.insert(11));
-        assert!(b.insert(200));
-
-        assert!(!a.par_is_subset(&b));
-        assert!(!a.par_is_superset(&b));
-        assert!(!b.par_is_subset(&a));
-        assert!(!b.par_is_superset(&a));
-
-        assert!(b.insert(5));
-
-        assert!(a.par_is_subset(&b));
-        assert!(!a.par_is_superset(&b));
-        assert!(!b.par_is_subset(&a));
-        assert!(b.par_is_superset(&a));
-    }
-
-    #[test]
-    fn test_iterate() {
-        let mut a = HashSet::new();
-        for i in 0..32 {
-            assert!(a.insert(i));
-        }
-        let observed = AtomicUsize::new(0);
-        a.par_iter().for_each(|k| {
-            observed.fetch_or(1 << *k, Ordering::Relaxed);
-        });
-        assert_eq!(observed.into_inner(), 0xFFFF_FFFF);
-    }
-
-    #[test]
-    fn test_intersection() {
-        let mut a = HashSet::new();
-        let mut b = HashSet::new();
-
-        assert!(a.insert(11));
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(77));
-        assert!(a.insert(103));
-        assert!(a.insert(5));
-        assert!(a.insert(-5));
-
-        assert!(b.insert(2));
-        assert!(b.insert(11));
-        assert!(b.insert(77));
-        assert!(b.insert(-9));
-        assert!(b.insert(-42));
-        assert!(b.insert(5));
-        assert!(b.insert(3));
-
-        let expected = [3, 5, 11, 77];
-        let i = a
-            .par_intersection(&b)
-            .map(|x| {
-                assert!(expected.contains(x));
-                1
-            })
-            .sum::<usize>();
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_difference() {
-        let mut a = HashSet::new();
-        let mut b = HashSet::new();
-
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(5));
-        assert!(a.insert(9));
-        assert!(a.insert(11));
-
-        assert!(b.insert(3));
-        assert!(b.insert(9));
-
-        let expected = [1, 5, 11];
-        let i = a
-            .par_difference(&b)
-            .map(|x| {
-                assert!(expected.contains(x));
-                1
-            })
-            .sum::<usize>();
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_symmetric_difference() {
-        let mut a = HashSet::new();
-        let mut b = HashSet::new();
-
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(5));
-        assert!(a.insert(9));
-        assert!(a.insert(11));
-
-        assert!(b.insert(-2));
-        assert!(b.insert(3));
-        assert!(b.insert(9));
-        assert!(b.insert(14));
-        assert!(b.insert(22));
-
-        let expected = [-2, 1, 5, 11, 14, 22];
-        let i = a
-            .par_symmetric_difference(&b)
-            .map(|x| {
-                assert!(expected.contains(x));
-                1
-            })
-            .sum::<usize>();
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_union() {
-        let mut a = HashSet::new();
-        let mut b = HashSet::new();
-
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(5));
-        assert!(a.insert(9));
-        assert!(a.insert(11));
-        assert!(a.insert(16));
-        assert!(a.insert(19));
-        assert!(a.insert(24));
-
-        assert!(b.insert(-2));
-        assert!(b.insert(1));
-        assert!(b.insert(5));
-        assert!(b.insert(9));
-        assert!(b.insert(13));
-        assert!(b.insert(19));
-
-        let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24];
-        let i = a
-            .par_union(&b)
-            .map(|x| {
-                assert!(expected.contains(x));
-                1
-            })
-            .sum::<usize>();
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_from_iter() {
-        let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9];
-
-        let set: HashSet<_> = xs.par_iter().cloned().collect();
-
-        for x in &xs {
-            assert!(set.contains(x));
-        }
-    }
-
-    #[test]
-    fn test_move_iter() {
-        let hs = {
-            let mut hs = HashSet::new();
-
-            hs.insert('a');
-            hs.insert('b');
-
-            hs
-        };
-
-        let v = hs.into_par_iter().collect::<Vec<char>>();
-        assert!(v == ['a', 'b'] || v == ['b', 'a']);
-    }
-
-    #[test]
-    fn test_eq() {
-        // These constants once happened to expose a bug in insert().
-        // I'm keeping them around to prevent a regression.
-        let mut s1 = HashSet::new();
-
-        s1.insert(1);
-        s1.insert(2);
-        s1.insert(3);
-
-        let mut s2 = HashSet::new();
-
-        s2.insert(1);
-        s2.insert(2);
-
-        assert!(!s1.par_eq(&s2));
-
-        s2.insert(3);
-
-        assert!(s1.par_eq(&s2));
-    }
-
-    #[test]
-    fn test_extend_ref() {
-        let mut a = HashSet::new();
-        a.insert(1);
-
-        a.par_extend(&[2, 3, 4][..]);
-
-        assert_eq!(a.len(), 4);
-        assert!(a.contains(&1));
-        assert!(a.contains(&2));
-        assert!(a.contains(&3));
-        assert!(a.contains(&4));
-
-        let mut b = HashSet::new();
-        b.insert(5);
-        b.insert(6);
-
-        a.par_extend(&b);
-
-        assert_eq!(a.len(), 6);
-        assert!(a.contains(&1));
-        assert!(a.contains(&2));
-        assert!(a.contains(&3));
-        assert!(a.contains(&4));
-        assert!(a.contains(&5));
-        assert!(a.contains(&6));
-    }
-}
diff --git a/third_party/rust_crates/vendor/hashbrown/src/external_trait_impls/serde.rs b/third_party/rust_crates/vendor/hashbrown/src/external_trait_impls/serde.rs
deleted file mode 100644
index 5adac8c..0000000
--- a/third_party/rust_crates/vendor/hashbrown/src/external_trait_impls/serde.rs
+++ /dev/null
@@ -1,200 +0,0 @@
-mod size_hint {
-    use core::cmp;
-
-    /// This presumably exists to prevent denial of service attacks.
-    ///
-    /// Original discussion: https://github.com/serde-rs/serde/issues/1114.
-    #[inline]
-    pub(super) fn cautious(hint: Option<usize>) -> usize {
-        cmp::min(hint.unwrap_or(0), 4096)
-    }
-}
-
-mod map {
-    use core::fmt;
-    use core::hash::{BuildHasher, Hash};
-    use core::marker::PhantomData;
-    use serde::de::{Deserialize, Deserializer, MapAccess, Visitor};
-    use serde::ser::{Serialize, Serializer};
-
-    use crate::hash_map::HashMap;
-
-    use super::size_hint;
-
-    impl<K, V, H> Serialize for HashMap<K, V, H>
-    where
-        K: Serialize + Eq + Hash,
-        V: Serialize,
-        H: BuildHasher,
-    {
-        #[inline]
-        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-        where
-            S: Serializer,
-        {
-            serializer.collect_map(self)
-        }
-    }
-
-    impl<'de, K, V, S> Deserialize<'de> for HashMap<K, V, S>
-    where
-        K: Deserialize<'de> + Eq + Hash,
-        V: Deserialize<'de>,
-        S: BuildHasher + Default,
-    {
-        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
-        where
-            D: Deserializer<'de>,
-        {
-            struct MapVisitor<K, V, S> {
-                marker: PhantomData<HashMap<K, V, S>>,
-            }
-
-            impl<'de, K, V, S> Visitor<'de> for MapVisitor<K, V, S>
-            where
-                K: Deserialize<'de> + Eq + Hash,
-                V: Deserialize<'de>,
-                S: BuildHasher + Default,
-            {
-                type Value = HashMap<K, V, S>;
-
-                fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-                    formatter.write_str("a map")
-                }
-
-                #[inline]
-                fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
-                where
-                    A: MapAccess<'de>,
-                {
-                    let mut values = HashMap::with_capacity_and_hasher(
-                        size_hint::cautious(map.size_hint()),
-                        S::default(),
-                    );
-
-                    while let Some((key, value)) = map.next_entry()? {
-                        values.insert(key, value);
-                    }
-
-                    Ok(values)
-                }
-            }
-
-            let visitor = MapVisitor {
-                marker: PhantomData,
-            };
-            deserializer.deserialize_map(visitor)
-        }
-    }
-}
-
-mod set {
-    use core::fmt;
-    use core::hash::{BuildHasher, Hash};
-    use core::marker::PhantomData;
-    use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor};
-    use serde::ser::{Serialize, Serializer};
-
-    use crate::hash_set::HashSet;
-
-    use super::size_hint;
-
-    impl<T, H> Serialize for HashSet<T, H>
-    where
-        T: Serialize + Eq + Hash,
-        H: BuildHasher,
-    {
-        #[inline]
-        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-        where
-            S: Serializer,
-        {
-            serializer.collect_seq(self)
-        }
-    }
-
-    impl<'de, T, S> Deserialize<'de> for HashSet<T, S>
-    where
-        T: Deserialize<'de> + Eq + Hash,
-        S: BuildHasher + Default,
-    {
-        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
-        where
-            D: Deserializer<'de>,
-        {
-            struct SeqVisitor<T, S> {
-                marker: PhantomData<HashSet<T, S>>,
-            }
-
-            impl<'de, T, S> Visitor<'de> for SeqVisitor<T, S>
-            where
-                T: Deserialize<'de> + Eq + Hash,
-                S: BuildHasher + Default,
-            {
-                type Value = HashSet<T, S>;
-
-                fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-                    formatter.write_str("a sequence")
-                }
-
-                #[inline]
-                fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
-                where
-                    A: SeqAccess<'de>,
-                {
-                    let mut values = HashSet::with_capacity_and_hasher(
-                        size_hint::cautious(seq.size_hint()),
-                        S::default(),
-                    );
-
-                    while let Some(value) = seq.next_element()? {
-                        values.insert(value);
-                    }
-
-                    Ok(values)
-                }
-            }
-
-            let visitor = SeqVisitor {
-                marker: PhantomData,
-            };
-            deserializer.deserialize_seq(visitor)
-        }
-
-        fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error>
-        where
-            D: Deserializer<'de>,
-        {
-            struct SeqInPlaceVisitor<'a, T, S>(&'a mut HashSet<T, S>);
-
-            impl<'a, 'de, T, S> Visitor<'de> for SeqInPlaceVisitor<'a, T, S>
-            where
-                T: Deserialize<'de> + Eq + Hash,
-                S: BuildHasher + Default,
-            {
-                type Value = ();
-
-                fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-                    formatter.write_str("a sequence")
-                }
-
-                #[inline]
-                fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
-                where
-                    A: SeqAccess<'de>,
-                {
-                    self.0.clear();
-                    self.0.reserve(size_hint::cautious(seq.size_hint()));
-
-                    while let Some(value) = seq.next_element()? {
-                        self.0.insert(value);
-                    }
-
-                    Ok(())
-                }
-            }
-
-            deserializer.deserialize_seq(SeqInPlaceVisitor(place))
-        }
-    }
-}
diff --git a/third_party/rust_crates/vendor/hashbrown/src/fx.rs b/third_party/rust_crates/vendor/hashbrown/src/fx.rs
deleted file mode 100644
index c7eb376..0000000
--- a/third_party/rust_crates/vendor/hashbrown/src/fx.rs
+++ /dev/null
@@ -1,119 +0,0 @@
-//! Fast, non-cryptographic hash used by rustc and Firefox.
-
-use core::default::Default;
-use core::hash::{BuildHasherDefault, Hasher};
-use core::mem::size_of;
-use core::ops::BitXor;
-
-/// Type alias for a `HashBuilder` using the `fx` hash algorithm.
-pub type FxHashBuilder = BuildHasherDefault<FxHasher>;
-
-/// A speedy hash algorithm for use within rustc. The hashmap in liballoc
-/// by default uses SipHash which isn't quite as speedy as we want. In the
-/// compiler we're not really worried about DOS attempts, so we use a fast
-/// non-cryptographic hash.
-///
-/// This is the same as the algorithm used by Firefox -- which is a homespun
-/// one not based on any widely-known algorithm -- though modified to produce
-/// 64-bit hash values instead of 32-bit hash values. It consistently
-/// out-performs an FNV-based hash within rustc itself -- the collision rate is
-/// similar or slightly worse than FNV, but the speed of the hash function
-/// itself is much higher because it works on up to 8 bytes at a time.
-pub struct FxHasher {
-    hash: usize,
-}
-
-#[cfg(target_pointer_width = "32")]
-const K: usize = 0x9e37_79b9;
-#[cfg(target_pointer_width = "64")]
-const K: usize = 0x517c_c1b7_2722_0a95;
-
-impl Default for FxHasher {
-    #[inline]
-    fn default() -> Self {
-        Self { hash: 0 }
-    }
-}
-
-impl FxHasher {
-    #[inline]
-    fn add_to_hash(&mut self, i: usize) {
-        self.hash = self.hash.rotate_left(5).bitxor(i).wrapping_mul(K);
-    }
-}
-
-impl Hasher for FxHasher {
-    #[inline]
-    fn write(&mut self, mut bytes: &[u8]) {
-        macro_rules! read_bytes {
-            ($ty:ty, $src:expr) => {{
-                assert!(size_of::<$ty>() <= $src.len());
-                let mut data: $ty = 0;
-                unsafe {
-                    $src.as_ptr()
-                        .copy_to_nonoverlapping(&mut data as *mut $ty as *mut u8, size_of::<$ty>());
-                }
-                data
-            }};
-        }
-
-        let mut hash = Self { hash: self.hash };
-        assert!(size_of::<usize>() <= 8);
-        while bytes.len() >= size_of::<usize>() {
-            hash.add_to_hash(read_bytes!(usize, bytes) as usize);
-            bytes = &bytes[size_of::<usize>()..];
-        }
-        if (size_of::<usize>() > 4) && (bytes.len() >= 4) {
-            hash.add_to_hash(read_bytes!(u32, bytes) as usize);
-            bytes = &bytes[4..];
-        }
-        if (size_of::<usize>() > 2) && bytes.len() >= 2 {
-            hash.add_to_hash(read_bytes!(u16, bytes) as usize);
-            bytes = &bytes[2..];
-        }
-        if (size_of::<usize>() > 1) && !bytes.is_empty() {
-            hash.add_to_hash(bytes[0] as usize);
-        }
-        self.hash = hash.hash;
-    }
-
-    #[inline]
-    fn write_u8(&mut self, i: u8) {
-        self.add_to_hash(i as usize);
-    }
-
-    #[inline]
-    fn write_u16(&mut self, i: u16) {
-        self.add_to_hash(i as usize);
-    }
-
-    #[inline]
-    fn write_u32(&mut self, i: u32) {
-        self.add_to_hash(i as usize);
-    }
-
-    #[cfg(target_pointer_width = "32")]
-    #[inline]
-    #[allow(clippy::cast_possible_truncation)]
-    fn write_u64(&mut self, i: u64) {
-        self.add_to_hash(i as usize);
-        self.add_to_hash((i >> 32) as usize);
-    }
-
-    #[cfg(target_pointer_width = "64")]
-    #[inline]
-    #[allow(clippy::cast_possible_truncation)]
-    fn write_u64(&mut self, i: u64) {
-        self.add_to_hash(i as usize);
-    }
-
-    #[inline]
-    fn write_usize(&mut self, i: usize) {
-        self.add_to_hash(i);
-    }
-
-    #[inline]
-    fn finish(&self) -> u64 {
-        self.hash as u64
-    }
-}
diff --git a/third_party/rust_crates/vendor/hashbrown/src/lib.rs b/third_party/rust_crates/vendor/hashbrown/src/lib.rs
deleted file mode 100644
index 1fe78e6..0000000
--- a/third_party/rust_crates/vendor/hashbrown/src/lib.rs
+++ /dev/null
@@ -1,93 +0,0 @@
-//! This crate is a Rust port of Google's high-performance [SwissTable] hash
-//! map, adapted to make it a drop-in replacement for Rust's standard `HashMap`
-//! and `HashSet` types.
-//!
-//! The original C++ version of [SwissTable] can be found [here], and this
-//! [CppCon talk] gives an overview of how the algorithm works.
-//!
-//! [SwissTable]: https://abseil.io/blog/20180927-swisstables
-//! [here]: https://github.com/abseil/abseil-cpp/blob/master/absl/container/internal/raw_hash_set.h
-//! [CppCon talk]: https://www.youtube.com/watch?v=ncHmEUmJZf4
-
-#![no_std]
-#![cfg_attr(
-    feature = "nightly",
-    feature(
-        alloc_layout_extra,
-        allocator_api,
-        ptr_offset_from,
-        test,
-        core_intrinsics,
-        dropck_eyepatch
-    )
-)]
-#![warn(missing_docs)]
-#![allow(clippy::module_name_repetitions)]
-#![warn(rust_2018_idioms)]
-
-#[cfg(test)]
-#[macro_use]
-extern crate std;
-
-#[cfg(feature = "nightly")]
-#[cfg_attr(test, macro_use)]
-extern crate alloc;
-#[cfg(not(feature = "nightly"))]
-extern crate std as alloc;
-
-#[macro_use]
-mod macros;
-
-mod external_trait_impls;
-mod fx;
-mod map;
-mod raw;
-#[cfg(feature = "rustc-dep-of-std")]
-mod rustc_entry;
-mod scopeguard;
-mod set;
-
-pub mod hash_map {
-    //! A hash map implemented with quadratic probing and SIMD lookup.
-    pub use crate::map::*;
-
-    #[cfg(feature = "rustc-dep-of-std")]
-    pub use crate::rustc_entry::*;
-
-    #[cfg(feature = "rayon")]
-    /// [rayon]-based parallel iterator types for hash maps.
-    /// You will rarely need to interact with it directly unless you have need
-    /// to name one of the iterator types.
-    ///
-    /// [rayon]: https://docs.rs/rayon/1.0/rayon
-    pub mod rayon {
-        pub use crate::external_trait_impls::rayon::map::*;
-    }
-}
-pub mod hash_set {
-    //! A hash set implemented as a `HashMap` where the value is `()`.
-    pub use crate::set::*;
-
-    #[cfg(feature = "rayon")]
-    /// [rayon]-based parallel iterator types for hash sets.
-    /// You will rarely need to interact with it directly unless you have need
-    /// to name one of the iterator types.
-    ///
-    /// [rayon]: https://docs.rs/rayon/1.0/rayon
-    pub mod rayon {
-        pub use crate::external_trait_impls::rayon::set::*;
-    }
-}
-
-pub use crate::map::HashMap;
-pub use crate::set::HashSet;
-
-/// Augments `AllocErr` with a `CapacityOverflow` variant.
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub enum CollectionAllocErr {
-    /// Error due to the computed capacity exceeding the collection's maximum
-    /// (usually `isize::MAX` bytes).
-    CapacityOverflow,
-    /// Error due to the allocator (see the `AllocErr` type's docs).
-    AllocErr,
-}
diff --git a/third_party/rust_crates/vendor/hashbrown/src/macros.rs b/third_party/rust_crates/vendor/hashbrown/src/macros.rs
deleted file mode 100644
index e743094..0000000
--- a/third_party/rust_crates/vendor/hashbrown/src/macros.rs
+++ /dev/null
@@ -1,54 +0,0 @@
-// See the cfg-if crate.
-macro_rules! cfg_if {
-    // match if/else chains with a final `else`
-    ($(
-        if #[cfg($($meta:meta),*)] { $($it:item)* }
-    ) else * else {
-        $($it2:item)*
-    }) => {
-        cfg_if! {
-            @__items
-            () ;
-            $( ( ($($meta),*) ($($it)*) ), )*
-            ( () ($($it2)*) ),
-        }
-    };
-
-    // match if/else chains lacking a final `else`
-    (
-        if #[cfg($($i_met:meta),*)] { $($i_it:item)* }
-        $(
-            else if #[cfg($($e_met:meta),*)] { $($e_it:item)* }
-        )*
-    ) => {
-        cfg_if! {
-            @__items
-            () ;
-            ( ($($i_met),*) ($($i_it)*) ),
-            $( ( ($($e_met),*) ($($e_it)*) ), )*
-            ( () () ),
-        }
-    };
-
-    // Internal and recursive macro to emit all the items
-    //
-    // Collects all the negated cfgs in a list at the beginning and after the
-    // semicolon is all the remaining items
-    (@__items ($($not:meta,)*) ; ) => {};
-    (@__items ($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => {
-        // Emit all items within one block, applying an approprate #[cfg]. The
-        // #[cfg] will require all `$m` matchers specified and must also negate
-        // all previous matchers.
-        cfg_if! { @__apply cfg(all($($m,)* not(any($($not),*)))), $($it)* }
-
-        // Recurse to emit all other items in `$rest`, and when we do so add all
-        // our `$m` matchers to the list of `$not` matchers as future emissions
-        // will have to negate everything we just matched as well.
-        cfg_if! { @__items ($($not,)* $($m,)*) ; $($rest)* }
-    };
-
-    // Internal macro to Apply a cfg attribute to a list of items
-    (@__apply $m:meta, $($it:item)*) => {
-        $(#[$m] $it)*
-    };
-}
diff --git a/third_party/rust_crates/vendor/hashbrown/src/map.rs b/third_party/rust_crates/vendor/hashbrown/src/map.rs
deleted file mode 100644
index 72642a9..0000000
--- a/third_party/rust_crates/vendor/hashbrown/src/map.rs
+++ /dev/null
@@ -1,3564 +0,0 @@
-use crate::raw::{Bucket, RawDrain, RawIntoIter, RawIter, RawTable};
-use crate::CollectionAllocErr;
-use core::borrow::Borrow;
-use core::fmt::{self, Debug};
-use core::hash::{BuildHasher, Hash, Hasher};
-use core::iter::{FromIterator, FusedIterator};
-use core::marker::PhantomData;
-use core::mem;
-use core::ops::Index;
-
-pub use crate::fx::FxHashBuilder as DefaultHashBuilder;
-
-/// A hash map implemented with quadratic probing and SIMD lookup.
-///
-/// The default hashing algorithm is currently `fx`, though this is
-/// subject to change at any point in the future. This hash function is very
-/// fast for all types of keys, but this algorithm will typically *not* protect
-/// against attacks such as HashDoS.
-///
-/// The hashing algorithm can be replaced on a per-`HashMap` basis using the
-/// [`default`], [`with_hasher`], and [`with_capacity_and_hasher`] methods. Many
-/// alternative algorithms are available on crates.io, such as the [`fnv`] crate.
-///
-/// It is required that the keys implement the [`Eq`] and [`Hash`] traits, although
-/// this can frequently be achieved by using `#[derive(PartialEq, Eq, Hash)]`.
-/// If you implement these yourself, it is important that the following
-/// property holds:
-///
-/// ```text
-/// k1 == k2 -> hash(k1) == hash(k2)
-/// ```
-///
-/// In other words, if two keys are equal, their hashes must be equal.
-///
-/// It is a logic error for a key to be modified in such a way that the key's
-/// hash, as determined by the [`Hash`] trait, or its equality, as determined by
-/// the [`Eq`] trait, changes while it is in the map. This is normally only
-/// possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
-///
-/// It is also a logic error for the [`Hash`] implementation of a key to panic.
-/// This is generally only possible if the trait is implemented manually. If a
-/// panic does occur then the contents of the `HashMap` may become corrupted and
-/// some items may be dropped from the table.
-///
-/// # Examples
-///
-/// ```
-/// use hashbrown::HashMap;
-///
-/// // Type inference lets us omit an explicit type signature (which
-/// // would be `HashMap<String, String>` in this example).
-/// let mut book_reviews = HashMap::new();
-///
-/// // Review some books.
-/// book_reviews.insert(
-///     "Adventures of Huckleberry Finn".to_string(),
-///     "My favorite book.".to_string(),
-/// );
-/// book_reviews.insert(
-///     "Grimms' Fairy Tales".to_string(),
-///     "Masterpiece.".to_string(),
-/// );
-/// book_reviews.insert(
-///     "Pride and Prejudice".to_string(),
-///     "Very enjoyable.".to_string(),
-/// );
-/// book_reviews.insert(
-///     "The Adventures of Sherlock Holmes".to_string(),
-///     "Eye lyked it alot.".to_string(),
-/// );
-///
-/// // Check for a specific one.
-/// // When collections store owned values (String), they can still be
-/// // queried using references (&str).
-/// if !book_reviews.contains_key("Les Misérables") {
-///     println!("We've got {} reviews, but Les Misérables ain't one.",
-///              book_reviews.len());
-/// }
-///
-/// // oops, this review has a lot of spelling mistakes, let's delete it.
-/// book_reviews.remove("The Adventures of Sherlock Holmes");
-///
-/// // Look up the values associated with some keys.
-/// let to_find = ["Pride and Prejudice", "Alice's Adventure in Wonderland"];
-/// for &book in &to_find {
-///     match book_reviews.get(book) {
-///         Some(review) => println!("{}: {}", book, review),
-///         None => println!("{} is unreviewed.", book)
-///     }
-/// }
-///
-/// // Look up the value for a key (will panic if the key is not found).
-/// println!("Review for Jane: {}", book_reviews["Pride and Prejudice"]);
-///
-/// // Iterate over everything.
-/// for (book, review) in &book_reviews {
-///     println!("{}: \"{}\"", book, review);
-/// }
-/// ```
-///
-/// `HashMap` also implements an [`Entry API`](#method.entry), which allows
-/// for more complex methods of getting, setting, updating and removing keys and
-/// their values:
-///
-/// ```
-/// use hashbrown::HashMap;
-///
-/// // type inference lets us omit an explicit type signature (which
-/// // would be `HashMap<&str, u8>` in this example).
-/// let mut player_stats = HashMap::new();
-///
-/// fn random_stat_buff() -> u8 {
-///     // could actually return some random value here - let's just return
-///     // some fixed value for now
-///     42
-/// }
-///
-/// // insert a key only if it doesn't already exist
-/// player_stats.entry("health").or_insert(100);
-///
-/// // insert a key using a function that provides a new value only if it
-/// // doesn't already exist
-/// player_stats.entry("defence").or_insert_with(random_stat_buff);
-///
-/// // update a key, guarding against the key possibly not being set
-/// let stat = player_stats.entry("attack").or_insert(100);
-/// *stat += random_stat_buff();
-/// ```
-///
-/// The easiest way to use `HashMap` with a custom key type is to derive [`Eq`] and [`Hash`].
-/// We must also derive [`PartialEq`].
-///
-/// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
-/// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
-/// [`PartialEq`]: https://doc.rust-lang.org/std/cmp/trait.PartialEq.html
-/// [`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html
-/// [`Cell`]: https://doc.rust-lang.org/std/cell/struct.Cell.html
-/// [`default`]: #method.default
-/// [`with_hasher`]: #method.with_hasher
-/// [`with_capacity_and_hasher`]: #method.with_capacity_and_hasher
-/// [`fnv`]: https://crates.io/crates/fnv
-///
-/// ```
-/// use hashbrown::HashMap;
-///
-/// #[derive(Hash, Eq, PartialEq, Debug)]
-/// struct Viking {
-///     name: String,
-///     country: String,
-/// }
-///
-/// impl Viking {
-///     /// Creates a new Viking.
-///     fn new(name: &str, country: &str) -> Viking {
-///         Viking { name: name.to_string(), country: country.to_string() }
-///     }
-/// }
-///
-/// // Use a HashMap to store the vikings' health points.
-/// let mut vikings = HashMap::new();
-///
-/// vikings.insert(Viking::new("Einar", "Norway"), 25);
-/// vikings.insert(Viking::new("Olaf", "Denmark"), 24);
-/// vikings.insert(Viking::new("Harald", "Iceland"), 12);
-///
-/// // Use derived implementation to print the status of the vikings.
-/// for (viking, health) in &vikings {
-///     println!("{:?} has {} hp", viking, health);
-/// }
-/// ```
-///
-/// A `HashMap` with fixed list of elements can be initialized from an array:
-///
-/// ```
-/// use hashbrown::HashMap;
-///
-/// fn main() {
-///     let timber_resources: HashMap<&str, i32> =
-///     [("Norway", 100),
-///      ("Denmark", 50),
-///      ("Iceland", 10)]
-///      .iter().cloned().collect();
-///     // use the values stored in map
-/// }
-/// ```
-
-#[derive(Clone)]
-pub struct HashMap<K, V, S = DefaultHashBuilder> {
-    pub(crate) hash_builder: S,
-    pub(crate) table: RawTable<(K, V)>,
-}
-
-#[inline]
-pub(crate) fn make_hash<K: Hash + ?Sized>(hash_builder: &impl BuildHasher, val: &K) -> u64 {
-    let mut state = hash_builder.build_hasher();
-    val.hash(&mut state);
-    state.finish()
-}
-
-impl<K, V> HashMap<K, V, DefaultHashBuilder> {
-    /// Creates an empty `HashMap`.
-    ///
-    /// The hash map is initially created with a capacity of 0, so it will not allocate until it
-    /// is first inserted into.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// let mut map: HashMap<&str, i32> = HashMap::new();
-    /// ```
-    #[inline]
-    pub fn new() -> Self {
-        Self::default()
-    }
-
-    /// Creates an empty `HashMap` with the specified capacity.
-    ///
-    /// The hash map will be able to hold at least `capacity` elements without
-    /// reallocating. If `capacity` is 0, the hash map will not allocate.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// let mut map: HashMap<&str, i32> = HashMap::with_capacity(10);
-    /// ```
-    #[inline]
-    pub fn with_capacity(capacity: usize) -> Self {
-        Self::with_capacity_and_hasher(capacity, DefaultHashBuilder::default())
-    }
-}
-
-impl<K, V, S> HashMap<K, V, S> {
-    /// Creates an empty `HashMap` which will use the given hash builder to hash
-    /// keys.
-    ///
-    /// The created map has the default initial capacity.
-    ///
-    /// Warning: `hash_builder` is normally randomly generated, and
-    /// is designed to allow HashMaps to be resistant to attacks that
-    /// cause many collisions and very poor performance. Setting it
-    /// manually using this function can expose a DoS attack vector.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::DefaultHashBuilder;
-    ///
-    /// let s = DefaultHashBuilder::default();
-    /// let mut map = HashMap::with_hasher(s);
-    /// map.insert(1, 2);
-    /// ```
-    #[inline]
-    pub fn with_hasher(hash_builder: S) -> Self {
-        Self {
-            hash_builder,
-            table: RawTable::new(),
-        }
-    }
-
-    /// Creates an empty `HashMap` with the specified capacity, using `hash_builder`
-    /// to hash the keys.
-    ///
-    /// The hash map will be able to hold at least `capacity` elements without
-    /// reallocating. If `capacity` is 0, the hash map will not allocate.
-    ///
-    /// Warning: `hash_builder` is normally randomly generated, and
-    /// is designed to allow HashMaps to be resistant to attacks that
-    /// cause many collisions and very poor performance. Setting it
-    /// manually using this function can expose a DoS attack vector.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::DefaultHashBuilder;
-    ///
-    /// let s = DefaultHashBuilder::default();
-    /// let mut map = HashMap::with_capacity_and_hasher(10, s);
-    /// map.insert(1, 2);
-    /// ```
-    #[inline]
-    pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self {
-        Self {
-            hash_builder,
-            table: RawTable::with_capacity(capacity),
-        }
-    }
-
-    /// Returns a reference to the map's [`BuildHasher`].
-    ///
-    /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::DefaultHashBuilder;
-    ///
-    /// let hasher = DefaultHashBuilder::default();
-    /// let map: HashMap<i32, i32> = HashMap::with_hasher(hasher);
-    /// let hasher: &DefaultHashBuilder = map.hasher();
-    /// ```
-    #[inline]
-    pub fn hasher(&self) -> &S {
-        &self.hash_builder
-    }
-
-    /// Returns the number of elements the map can hold without reallocating.
-    ///
-    /// This number is a lower bound; the `HashMap<K, V>` might be able to hold
-    /// more, but is guaranteed to be able to hold at least this many.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// let map: HashMap<i32, i32> = HashMap::with_capacity(100);
-    /// assert!(map.capacity() >= 100);
-    /// ```
-    #[inline]
-    pub fn capacity(&self) -> usize {
-        self.table.capacity()
-    }
-
-    /// An iterator visiting all keys in arbitrary order.
-    /// The iterator element type is `&'a K`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert("a", 1);
-    /// map.insert("b", 2);
-    /// map.insert("c", 3);
-    ///
-    /// for key in map.keys() {
-    ///     println!("{}", key);
-    /// }
-    /// ```
-    #[inline]
-    pub fn keys(&self) -> Keys<'_, K, V> {
-        Keys { inner: self.iter() }
-    }
-
-    /// An iterator visiting all values in arbitrary order.
-    /// The iterator element type is `&'a V`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert("a", 1);
-    /// map.insert("b", 2);
-    /// map.insert("c", 3);
-    ///
-    /// for val in map.values() {
-    ///     println!("{}", val);
-    /// }
-    /// ```
-    #[inline]
-    pub fn values(&self) -> Values<'_, K, V> {
-        Values { inner: self.iter() }
-    }
-
-    /// An iterator visiting all values mutably in arbitrary order.
-    /// The iterator element type is `&'a mut V`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    ///
-    /// map.insert("a", 1);
-    /// map.insert("b", 2);
-    /// map.insert("c", 3);
-    ///
-    /// for val in map.values_mut() {
-    ///     *val = *val + 10;
-    /// }
-    ///
-    /// for val in map.values() {
-    ///     println!("{}", val);
-    /// }
-    /// ```
-    #[inline]
-    pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> {
-        ValuesMut {
-            inner: self.iter_mut(),
-        }
-    }
-
-    /// An iterator visiting all key-value pairs in arbitrary order.
-    /// The iterator element type is `(&'a K, &'a V)`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert("a", 1);
-    /// map.insert("b", 2);
-    /// map.insert("c", 3);
-    ///
-    /// for (key, val) in map.iter() {
-    ///     println!("key: {} val: {}", key, val);
-    /// }
-    /// ```
-    #[inline]
-    pub fn iter(&self) -> Iter<'_, K, V> {
-        // Here we tie the lifetime of self to the iter.
-        unsafe {
-            Iter {
-                inner: self.table.iter(),
-                marker: PhantomData,
-            }
-        }
-    }
-
-    /// An iterator visiting all key-value pairs in arbitrary order,
-    /// with mutable references to the values.
-    /// The iterator element type is `(&'a K, &'a mut V)`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert("a", 1);
-    /// map.insert("b", 2);
-    /// map.insert("c", 3);
-    ///
-    /// // Update all values
-    /// for (_, val) in map.iter_mut() {
-    ///     *val *= 2;
-    /// }
-    ///
-    /// for (key, val) in &map {
-    ///     println!("key: {} val: {}", key, val);
-    /// }
-    /// ```
-    #[inline]
-    pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
-        // Here we tie the lifetime of self to the iter.
-        unsafe {
-            IterMut {
-                inner: self.table.iter(),
-                marker: PhantomData,
-            }
-        }
-    }
-
-    #[cfg(test)]
-    #[inline]
-    fn raw_capacity(&self) -> usize {
-        self.table.buckets()
-    }
-
-    /// Returns the number of elements in the map.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut a = HashMap::new();
-    /// assert_eq!(a.len(), 0);
-    /// a.insert(1, "a");
-    /// assert_eq!(a.len(), 1);
-    /// ```
-    #[inline]
-    pub fn len(&self) -> usize {
-        self.table.len()
-    }
-
-    /// Returns `true` if the map contains no elements.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut a = HashMap::new();
-    /// assert!(a.is_empty());
-    /// a.insert(1, "a");
-    /// assert!(!a.is_empty());
-    /// ```
-    #[inline]
-    pub fn is_empty(&self) -> bool {
-        self.len() == 0
-    }
-
-    /// Clears the map, returning all key-value pairs as an iterator. Keeps the
-    /// allocated memory for reuse.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut a = HashMap::new();
-    /// a.insert(1, "a");
-    /// a.insert(2, "b");
-    ///
-    /// for (k, v) in a.drain().take(1) {
-    ///     assert!(k == 1 || k == 2);
-    ///     assert!(v == "a" || v == "b");
-    /// }
-    ///
-    /// assert!(a.is_empty());
-    /// ```
-    #[inline]
-    pub fn drain(&mut self) -> Drain<'_, K, V> {
-        // Here we tie the lifetime of self to the iter.
-        unsafe {
-            Drain {
-                inner: self.table.drain(),
-            }
-        }
-    }
-
-    /// Clears the map, removing all key-value pairs. Keeps the allocated memory
-    /// for reuse.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut a = HashMap::new();
-    /// a.insert(1, "a");
-    /// a.clear();
-    /// assert!(a.is_empty());
-    /// ```
-    #[inline]
-    pub fn clear(&mut self) {
-        self.table.clear();
-    }
-}
-
-impl<K, V, S> HashMap<K, V, S>
-where
-    K: Eq + Hash,
-    S: BuildHasher,
-{
-    /// Reserves capacity for at least `additional` more elements to be inserted
-    /// in the `HashMap`. The collection may reserve more space to avoid
-    /// frequent reallocations.
-    ///
-    /// # Panics
-    ///
-    /// Panics if the new allocation size overflows [`usize`].
-    ///
-    /// [`usize`]: https://doc.rust-lang.org/std/primitive.usize.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// let mut map: HashMap<&str, i32> = HashMap::new();
-    /// map.reserve(10);
-    /// ```
-    #[inline]
-    pub fn reserve(&mut self, additional: usize) {
-        let hash_builder = &self.hash_builder;
-        self.table
-            .reserve(additional, |x| make_hash(hash_builder, &x.0));
-    }
-
-    /// Tries to reserve capacity for at least `additional` more elements to be inserted
-    /// in the given `HashMap<K,V>`. The collection may reserve more space to avoid
-    /// frequent reallocations.
-    ///
-    /// # Errors
-    ///
-    /// If the capacity overflows, or the allocator reports a failure, then an error
-    /// is returned.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// let mut map: HashMap<&str, isize> = HashMap::new();
-    /// map.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?");
-    /// ```
-    #[inline]
-    pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
-        let hash_builder = &self.hash_builder;
-        self.table
-            .try_reserve(additional, |x| make_hash(hash_builder, &x.0))
-    }
-
-    /// Shrinks the capacity of the map as much as possible. It will drop
-    /// down as much as possible while maintaining the internal rules
-    /// and possibly leaving some space in accordance with the resize policy.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<i32, i32> = HashMap::with_capacity(100);
-    /// map.insert(1, 2);
-    /// map.insert(3, 4);
-    /// assert!(map.capacity() >= 100);
-    /// map.shrink_to_fit();
-    /// assert!(map.capacity() >= 2);
-    /// ```
-    #[inline]
-    pub fn shrink_to_fit(&mut self) {
-        let hash_builder = &self.hash_builder;
-        self.table.shrink_to(0, |x| make_hash(hash_builder, &x.0));
-    }
-
-    /// Shrinks the capacity of the map with a lower limit. It will drop
-    /// down no lower than the supplied limit while maintaining the internal rules
-    /// and possibly leaving some space in accordance with the resize policy.
-    ///
-    /// Panics if the current capacity is smaller than the supplied
-    /// minimum capacity.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<i32, i32> = HashMap::with_capacity(100);
-    /// map.insert(1, 2);
-    /// map.insert(3, 4);
-    /// assert!(map.capacity() >= 100);
-    /// map.shrink_to(10);
-    /// assert!(map.capacity() >= 10);
-    /// map.shrink_to(0);
-    /// assert!(map.capacity() >= 2);
-    /// ```
-    #[inline]
-    pub fn shrink_to(&mut self, min_capacity: usize) {
-        assert!(
-            self.capacity() >= min_capacity,
-            "Tried to shrink to a larger capacity"
-        );
-
-        let hash_builder = &self.hash_builder;
-        self.table
-            .shrink_to(min_capacity, |x| make_hash(hash_builder, &x.0));
-    }
-
-    /// Gets the given key's corresponding entry in the map for in-place manipulation.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut letters = HashMap::new();
-    ///
-    /// for ch in "a short treatise on fungi".chars() {
-    ///     let counter = letters.entry(ch).or_insert(0);
-    ///     *counter += 1;
-    /// }
-    ///
-    /// assert_eq!(letters[&'s'], 2);
-    /// assert_eq!(letters[&'t'], 3);
-    /// assert_eq!(letters[&'u'], 1);
-    /// assert_eq!(letters.get(&'y'), None);
-    /// ```
-    #[inline]
-    pub fn entry(&mut self, key: K) -> Entry<'_, K, V, S> {
-        let hash = make_hash(&self.hash_builder, &key);
-        if let Some(elem) = self.table.find(hash, |q| q.0.eq(&key)) {
-            Entry::Occupied(OccupiedEntry {
-                key: Some(key),
-                elem,
-                table: self,
-            })
-        } else {
-            Entry::Vacant(VacantEntry {
-                hash,
-                key,
-                table: self,
-            })
-        }
-    }
-
-    /// Returns a reference to the value corresponding to the key.
-    ///
-    /// The key may be any borrowed form of the map's key type, but
-    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
-    /// the key type.
-    ///
-    /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
-    /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert(1, "a");
-    /// assert_eq!(map.get(&1), Some(&"a"));
-    /// assert_eq!(map.get(&2), None);
-    /// ```
-    #[inline]
-    pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
-    where
-        K: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        self.get_key_value(k).map(|(_, v)| v)
-    }
-
-    /// Returns the key-value pair corresponding to the supplied key.
-    ///
-    /// The supplied key may be any borrowed form of the map's key type, but
-    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
-    /// the key type.
-    ///
-    /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
-    /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert(1, "a");
-    /// assert_eq!(map.get_key_value(&1), Some((&1, &"a")));
-    /// assert_eq!(map.get_key_value(&2), None);
-    /// ```
-    #[inline]
-    pub fn get_key_value<Q: ?Sized>(&self, k: &Q) -> Option<(&K, &V)>
-    where
-        K: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        let hash = make_hash(&self.hash_builder, k);
-        self.table
-            .find(hash, |x| k.eq(x.0.borrow()))
-            .map(|item| unsafe {
-                let &(ref key, ref value) = item.as_ref();
-                (key, value)
-            })
-    }
-
-    /// Returns `true` if the map contains a value for the specified key.
-    ///
-    /// The key may be any borrowed form of the map's key type, but
-    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
-    /// the key type.
-    ///
-    /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
-    /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert(1, "a");
-    /// assert_eq!(map.contains_key(&1), true);
-    /// assert_eq!(map.contains_key(&2), false);
-    /// ```
-    #[inline]
-    pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
-    where
-        K: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        self.get(k).is_some()
-    }
-
-    /// Returns a mutable reference to the value corresponding to the key.
-    ///
-    /// The key may be any borrowed form of the map's key type, but
-    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
-    /// the key type.
-    ///
-    /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
-    /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert(1, "a");
-    /// if let Some(x) = map.get_mut(&1) {
-    ///     *x = "b";
-    /// }
-    /// assert_eq!(map[&1], "b");
-    /// ```
-    #[inline]
-    pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
-    where
-        K: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        let hash = make_hash(&self.hash_builder, k);
-        self.table
-            .find(hash, |x| k.eq(x.0.borrow()))
-            .map(|item| unsafe { &mut item.as_mut().1 })
-    }
-
-    /// Inserts a key-value pair into the map.
-    ///
-    /// If the map did not have this key present, [`None`] is returned.
-    ///
-    /// If the map did have this key present, the value is updated, and the old
-    /// value is returned. The key is not updated, though; this matters for
-    /// types that can be `==` without being identical. See the [module-level
-    /// documentation] for more.
-    ///
-    /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None
-    /// [module-level documentation]: index.html#insert-and-complex-keys
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// assert_eq!(map.insert(37, "a"), None);
-    /// assert_eq!(map.is_empty(), false);
-    ///
-    /// map.insert(37, "b");
-    /// assert_eq!(map.insert(37, "c"), Some("b"));
-    /// assert_eq!(map[&37], "c");
-    /// ```
-    #[inline]
-    pub fn insert(&mut self, k: K, v: V) -> Option<V> {
-        unsafe {
-            let hash = make_hash(&self.hash_builder, &k);
-            if let Some(item) = self.table.find(hash, |x| k.eq(&x.0)) {
-                Some(mem::replace(&mut item.as_mut().1, v))
-            } else {
-                let hash_builder = &self.hash_builder;
-                self.table
-                    .insert(hash, (k, v), |x| make_hash(hash_builder, &x.0));
-                None
-            }
-        }
-    }
-
-    /// Removes a key from the map, returning the value at the key if the key
-    /// was previously in the map.
-    ///
-    /// The key may be any borrowed form of the map's key type, but
-    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
-    /// the key type.
-    ///
-    /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
-    /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert(1, "a");
-    /// assert_eq!(map.remove(&1), Some("a"));
-    /// assert_eq!(map.remove(&1), None);
-    /// ```
-    #[inline]
-    pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
-    where
-        K: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        self.remove_entry(k).map(|(_, v)| v)
-    }
-
-    /// Removes a key from the map, returning the stored key and value if the
-    /// key was previously in the map.
-    ///
-    /// The key may be any borrowed form of the map's key type, but
-    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
-    /// the key type.
-    ///
-    /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
-    /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// # fn main() {
-    /// let mut map = HashMap::new();
-    /// map.insert(1, "a");
-    /// assert_eq!(map.remove_entry(&1), Some((1, "a")));
-    /// assert_eq!(map.remove(&1), None);
-    /// # }
-    /// ```
-    #[inline]
-    pub fn remove_entry<Q: ?Sized>(&mut self, k: &Q) -> Option<(K, V)>
-    where
-        K: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        unsafe {
-            let hash = make_hash(&self.hash_builder, &k);
-            if let Some(item) = self.table.find(hash, |x| k.eq(x.0.borrow())) {
-                self.table.erase_no_drop(&item);
-                Some(item.read())
-            } else {
-                None
-            }
-        }
-    }
-
-    /// Retains only the elements specified by the predicate.
-    ///
-    /// In other words, remove all pairs `(k, v)` such that `f(&k,&mut v)` returns `false`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<i32, i32> = (0..8).map(|x|(x, x*10)).collect();
-    /// map.retain(|&k, _| k % 2 == 0);
-    /// assert_eq!(map.len(), 4);
-    /// ```
-    pub fn retain<F>(&mut self, mut f: F)
-    where
-        F: FnMut(&K, &mut V) -> bool,
-    {
-        // Here we only use `iter` as a temporary, preventing use-after-free
-        unsafe {
-            for item in self.table.iter() {
-                let &mut (ref key, ref mut value) = item.as_mut();
-                if !f(key, value) {
-                    // Erase the element from the table first since drop might panic.
-                    self.table.erase_no_drop(&item);
-                    item.drop();
-                }
-            }
-        }
-    }
-}
-
-impl<K, V, S> HashMap<K, V, S>
-where
-    S: BuildHasher,
-{
-    /// Creates a raw entry builder for the HashMap.
-    ///
-    /// Raw entries provide the lowest level of control for searching and
-    /// manipulating a map. They must be manually initialized with a hash and
-    /// then manually searched. After this, insertions into a vacant entry
-    /// still require an owned key to be provided.
-    ///
-    /// Raw entries are useful for such exotic situations as:
-    ///
-    /// * Hash memoization
-    /// * Deferring the creation of an owned key until it is known to be required
-    /// * Using a search key that doesn't work with the Borrow trait
-    /// * Using custom comparison logic without newtype wrappers
-    ///
-    /// Because raw entries provide much more low-level control, it's much easier
-    /// to put the HashMap into an inconsistent state which, while memory-safe,
-    /// will cause the map to produce seemingly random results. Higher-level and
-    /// more foolproof APIs like `entry` should be preferred when possible.
-    ///
-    /// In particular, the hash used to initialized the raw entry must still be
-    /// consistent with the hash of the key that is ultimately stored in the entry.
-    /// This is because implementations of HashMap may need to recompute hashes
-    /// when resizing, at which point only the keys are available.
-    ///
-    /// Raw entries give mutable access to the keys. This must not be used
-    /// to modify how the key would compare or hash, as the map will not re-evaluate
-    /// where the key should go, meaning the keys may become "lost" if their
-    /// location does not reflect their state. For instance, if you change a key
-    /// so that the map now contains keys which compare equal, search may start
-    /// acting erratically, with two keys randomly masking each other. Implementations
-    /// are free to assume this doesn't happen (within the limits of memory-safety).
-    #[inline]
-    pub fn raw_entry_mut(&mut self) -> RawEntryBuilderMut<'_, K, V, S> {
-        RawEntryBuilderMut { map: self }
-    }
-
-    /// Creates a raw immutable entry builder for the HashMap.
-    ///
-    /// Raw entries provide the lowest level of control for searching and
-    /// manipulating a map. They must be manually initialized with a hash and
-    /// then manually searched.
-    ///
-    /// This is useful for
-    /// * Hash memoization
-    /// * Using a search key that doesn't work with the Borrow trait
-    /// * Using custom comparison logic without newtype wrappers
-    ///
-    /// Unless you are in such a situation, higher-level and more foolproof APIs like
-    /// `get` should be preferred.
-    ///
-    /// Immutable raw entries have very limited use; you might instead want `raw_entry_mut`.
-    #[inline]
-    pub fn raw_entry(&self) -> RawEntryBuilder<'_, K, V, S> {
-        RawEntryBuilder { map: self }
-    }
-}
-
-impl<K, V, S> PartialEq for HashMap<K, V, S>
-where
-    K: Eq + Hash,
-    V: PartialEq,
-    S: BuildHasher,
-{
-    fn eq(&self, other: &Self) -> bool {
-        if self.len() != other.len() {
-            return false;
-        }
-
-        self.iter()
-            .all(|(key, value)| other.get(key).map_or(false, |v| *value == *v))
-    }
-}
-
-impl<K, V, S> Eq for HashMap<K, V, S>
-where
-    K: Eq + Hash,
-    V: Eq,
-    S: BuildHasher,
-{
-}
-
-impl<K, V, S> Debug for HashMap<K, V, S>
-where
-    K: Debug,
-    V: Debug,
-    S: BuildHasher,
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_map().entries(self.iter()).finish()
-    }
-}
-
-impl<K, V, S> Default for HashMap<K, V, S>
-where
-    S: BuildHasher + Default,
-{
-    /// Creates an empty `HashMap<K, V, S>`, with the `Default` value for the hasher.
-    #[inline]
-    fn default() -> Self {
-        Self::with_hasher(Default::default())
-    }
-}
-
-impl<K, Q: ?Sized, V, S> Index<&Q> for HashMap<K, V, S>
-where
-    K: Eq + Hash + Borrow<Q>,
-    Q: Eq + Hash,
-    S: BuildHasher,
-{
-    type Output = V;
-
-    /// Returns a reference to the value corresponding to the supplied key.
-    ///
-    /// # Panics
-    ///
-    /// Panics if the key is not present in the `HashMap`.
-    #[inline]
-    fn index(&self, key: &Q) -> &V {
-        self.get(key).expect("no entry found for key")
-    }
-}
-
-/// An iterator over the entries of a `HashMap`.
-///
-/// This `struct` is created by the [`iter`] method on [`HashMap`]. See its
-/// documentation for more.
-///
-/// [`iter`]: struct.HashMap.html#method.iter
-/// [`HashMap`]: struct.HashMap.html
-pub struct Iter<'a, K, V> {
-    inner: RawIter<(K, V)>,
-    marker: PhantomData<(&'a K, &'a V)>,
-}
-
-// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
-impl<K, V> Clone for Iter<'_, K, V> {
-    #[inline]
-    fn clone(&self) -> Self {
-        Iter {
-            inner: self.inner.clone(),
-            marker: PhantomData,
-        }
-    }
-}
-
-impl<K: Debug, V: Debug> fmt::Debug for Iter<'_, K, V> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().entries(self.clone()).finish()
-    }
-}
-
-/// A mutable iterator over the entries of a `HashMap`.
-///
-/// This `struct` is created by the [`iter_mut`] method on [`HashMap`]. See its
-/// documentation for more.
-///
-/// [`iter_mut`]: struct.HashMap.html#method.iter_mut
-/// [`HashMap`]: struct.HashMap.html
-pub struct IterMut<'a, K, V> {
-    inner: RawIter<(K, V)>,
-    // To ensure invariance with respect to V
-    marker: PhantomData<(&'a K, &'a mut V)>,
-}
-
-impl<K, V> IterMut<'_, K, V> {
-    /// Returns a iterator of references over the remaining items.
-    #[inline]
-    pub(super) fn iter(&self) -> Iter<'_, K, V> {
-        Iter {
-            inner: self.inner.clone(),
-            marker: PhantomData,
-        }
-    }
-}
-
-/// An owning iterator over the entries of a `HashMap`.
-///
-/// This `struct` is created by the [`into_iter`] method on [`HashMap`][`HashMap`]
-/// (provided by the `IntoIterator` trait). See its documentation for more.
-///
-/// [`into_iter`]: struct.HashMap.html#method.into_iter
-/// [`HashMap`]: struct.HashMap.html
-pub struct IntoIter<K, V> {
-    inner: RawIntoIter<(K, V)>,
-}
-
-impl<K, V> IntoIter<K, V> {
-    /// Returns a iterator of references over the remaining items.
-    #[inline]
-    pub(super) fn iter(&self) -> Iter<'_, K, V> {
-        Iter {
-            inner: self.inner.iter(),
-            marker: PhantomData,
-        }
-    }
-}
-
-/// An iterator over the keys of a `HashMap`.
-///
-/// This `struct` is created by the [`keys`] method on [`HashMap`]. See its
-/// documentation for more.
-///
-/// [`keys`]: struct.HashMap.html#method.keys
-/// [`HashMap`]: struct.HashMap.html
-pub struct Keys<'a, K, V> {
-    inner: Iter<'a, K, V>,
-}
-
-// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
-impl<K, V> Clone for Keys<'_, K, V> {
-    #[inline]
-    fn clone(&self) -> Self {
-        Keys {
-            inner: self.inner.clone(),
-        }
-    }
-}
-
-impl<K: Debug, V> fmt::Debug for Keys<'_, K, V> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().entries(self.clone()).finish()
-    }
-}
-
-/// An iterator over the values of a `HashMap`.
-///
-/// This `struct` is created by the [`values`] method on [`HashMap`]. See its
-/// documentation for more.
-///
-/// [`values`]: struct.HashMap.html#method.values
-/// [`HashMap`]: struct.HashMap.html
-pub struct Values<'a, K, V> {
-    inner: Iter<'a, K, V>,
-}
-
-// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
-impl<K, V> Clone for Values<'_, K, V> {
-    #[inline]
-    fn clone(&self) -> Self {
-        Values {
-            inner: self.inner.clone(),
-        }
-    }
-}
-
-impl<K, V: Debug> fmt::Debug for Values<'_, K, V> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().entries(self.clone()).finish()
-    }
-}
-
-/// A draining iterator over the entries of a `HashMap`.
-///
-/// This `struct` is created by the [`drain`] method on [`HashMap`]. See its
-/// documentation for more.
-///
-/// [`drain`]: struct.HashMap.html#method.drain
-/// [`HashMap`]: struct.HashMap.html
-pub struct Drain<'a, K, V> {
-    inner: RawDrain<'a, (K, V)>,
-}
-
-impl<K, V> Drain<'_, K, V> {
-    /// Returns a iterator of references over the remaining items.
-    #[inline]
-    pub(super) fn iter(&self) -> Iter<'_, K, V> {
-        Iter {
-            inner: self.inner.iter(),
-            marker: PhantomData,
-        }
-    }
-}
-
-/// A mutable iterator over the values of a `HashMap`.
-///
-/// This `struct` is created by the [`values_mut`] method on [`HashMap`]. See its
-/// documentation for more.
-///
-/// [`values_mut`]: struct.HashMap.html#method.values_mut
-/// [`HashMap`]: struct.HashMap.html
-pub struct ValuesMut<'a, K, V> {
-    inner: IterMut<'a, K, V>,
-}
-
-/// A builder for computing where in a [`HashMap`] a key-value pair would be stored.
-///
-/// See the [`HashMap::raw_entry_mut`] docs for usage examples.
-///
-/// [`HashMap::raw_entry_mut`]: struct.HashMap.html#method.raw_entry_mut
-pub struct RawEntryBuilderMut<'a, K, V, S> {
-    map: &'a mut HashMap<K, V, S>,
-}
-
-/// A view into a single entry in a map, which may either be vacant or occupied.
-///
-/// This is a lower-level version of [`Entry`].
-///
-/// This `enum` is constructed from the [`raw_entry`] method on [`HashMap`].
-///
-/// [`HashMap`]: struct.HashMap.html
-/// [`Entry`]: enum.Entry.html
-/// [`raw_entry`]: struct.HashMap.html#method.raw_entry
-pub enum RawEntryMut<'a, K: 'a, V: 'a, S: 'a> {
-    /// An occupied entry.
-    Occupied(RawOccupiedEntryMut<'a, K, V>),
-    /// A vacant entry.
-    Vacant(RawVacantEntryMut<'a, K, V, S>),
-}
-
-/// A view into an occupied entry in a `HashMap`.
-/// It is part of the [`RawEntryMut`] enum.
-///
-/// [`RawEntryMut`]: enum.RawEntryMut.html
-pub struct RawOccupiedEntryMut<'a, K, V> {
-    elem: Bucket<(K, V)>,
-    table: &'a mut RawTable<(K, V)>,
-}
-
-/// A view into a vacant entry in a `HashMap`.
-/// It is part of the [`RawEntryMut`] enum.
-///
-/// [`RawEntryMut`]: enum.RawEntryMut.html
-pub struct RawVacantEntryMut<'a, K, V, S> {
-    table: &'a mut RawTable<(K, V)>,
-    hash_builder: &'a S,
-}
-
-/// A builder for computing where in a [`HashMap`] a key-value pair would be stored.
-///
-/// See the [`HashMap::raw_entry`] docs for usage examples.
-///
-/// [`HashMap::raw_entry`]: struct.HashMap.html#method.raw_entry
-pub struct RawEntryBuilder<'a, K, V, S> {
-    map: &'a HashMap<K, V, S>,
-}
-
-impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S>
-where
-    S: BuildHasher,
-{
-    /// Creates a `RawEntryMut` from the given key.
-    #[inline]
-    #[allow(clippy::wrong_self_convention)]
-    pub fn from_key<Q: ?Sized>(self, k: &Q) -> RawEntryMut<'a, K, V, S>
-    where
-        K: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        let mut hasher = self.map.hash_builder.build_hasher();
-        k.hash(&mut hasher);
-        self.from_key_hashed_nocheck(hasher.finish(), k)
-    }
-
-    /// Creates a `RawEntryMut` from the given key and its hash.
-    #[inline]
-    #[allow(clippy::wrong_self_convention)]
-    pub fn from_key_hashed_nocheck<Q: ?Sized>(self, hash: u64, k: &Q) -> RawEntryMut<'a, K, V, S>
-    where
-        K: Borrow<Q>,
-        Q: Eq,
-    {
-        self.from_hash(hash, |q| q.borrow().eq(k))
-    }
-}
-
-impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S>
-where
-    S: BuildHasher,
-{
-    /// Creates a `RawEntryMut` from the given hash.
-    #[inline]
-    #[allow(clippy::wrong_self_convention)]
-    pub fn from_hash<F>(self, hash: u64, is_match: F) -> RawEntryMut<'a, K, V, S>
-    where
-        for<'b> F: FnMut(&'b K) -> bool,
-    {
-        self.search(hash, is_match)
-    }
-
-    #[inline]
-    fn search<F>(self, hash: u64, mut is_match: F) -> RawEntryMut<'a, K, V, S>
-    where
-        for<'b> F: FnMut(&'b K) -> bool,
-    {
-        match self.map.table.find(hash, |(k, _)| is_match(k)) {
-            Some(elem) => RawEntryMut::Occupied(RawOccupiedEntryMut {
-                elem,
-                table: &mut self.map.table,
-            }),
-            None => RawEntryMut::Vacant(RawVacantEntryMut {
-                table: &mut self.map.table,
-                hash_builder: &self.map.hash_builder,
-            }),
-        }
-    }
-}
-
-impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S>
-where
-    S: BuildHasher,
-{
-    /// Access an entry by key.
-    #[inline]
-    #[allow(clippy::wrong_self_convention)]
-    pub fn from_key<Q: ?Sized>(self, k: &Q) -> Option<(&'a K, &'a V)>
-    where
-        K: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        let mut hasher = self.map.hash_builder.build_hasher();
-        k.hash(&mut hasher);
-        self.from_key_hashed_nocheck(hasher.finish(), k)
-    }
-
-    /// Access an entry by a key and its hash.
-    #[inline]
-    #[allow(clippy::wrong_self_convention)]
-    pub fn from_key_hashed_nocheck<Q: ?Sized>(self, hash: u64, k: &Q) -> Option<(&'a K, &'a V)>
-    where
-        K: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        self.from_hash(hash, |q| q.borrow().eq(k))
-    }
-
-    #[inline]
-    fn search<F>(self, hash: u64, mut is_match: F) -> Option<(&'a K, &'a V)>
-    where
-        F: FnMut(&K) -> bool,
-    {
-        self.map
-            .table
-            .find(hash, |(k, _)| is_match(k))
-            .map(|item| unsafe {
-                let &(ref key, ref value) = item.as_ref();
-                (key, value)
-            })
-    }
-
-    /// Access an entry by hash.
-    #[inline]
-    #[allow(clippy::wrong_self_convention)]
-    pub fn from_hash<F>(self, hash: u64, is_match: F) -> Option<(&'a K, &'a V)>
-    where
-        F: FnMut(&K) -> bool,
-    {
-        self.search(hash, is_match)
-    }
-}
-
-impl<'a, K, V, S> RawEntryMut<'a, K, V, S> {
-    /// Ensures a value is in the entry by inserting the default if empty, and returns
-    /// mutable references to the key and value in the entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    ///
-    /// map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 3);
-    /// assert_eq!(map["poneyland"], 3);
-    ///
-    /// *map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 10).1 *= 2;
-    /// assert_eq!(map["poneyland"], 6);
-    /// ```
-    #[inline]
-    pub fn or_insert(self, default_key: K, default_val: V) -> (&'a mut K, &'a mut V)
-    where
-        K: Hash,
-        S: BuildHasher,
-    {
-        match self {
-            RawEntryMut::Occupied(entry) => entry.into_key_value(),
-            RawEntryMut::Vacant(entry) => entry.insert(default_key, default_val),
-        }
-    }
-
-    /// Ensures a value is in the entry by inserting the result of the default function if empty,
-    /// and returns mutable references to the key and value in the entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, String> = HashMap::new();
-    ///
-    /// map.raw_entry_mut().from_key("poneyland").or_insert_with(|| {
-    ///     ("poneyland", "hoho".to_string())
-    /// });
-    ///
-    /// assert_eq!(map["poneyland"], "hoho".to_string());
-    /// ```
-    #[inline]
-    pub fn or_insert_with<F>(self, default: F) -> (&'a mut K, &'a mut V)
-    where
-        F: FnOnce() -> (K, V),
-        K: Hash,
-        S: BuildHasher,
-    {
-        match self {
-            RawEntryMut::Occupied(entry) => entry.into_key_value(),
-            RawEntryMut::Vacant(entry) => {
-                let (k, v) = default();
-                entry.insert(k, v)
-            }
-        }
-    }
-
-    /// Provides in-place mutable access to an occupied entry before any
-    /// potential inserts into the map.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    ///
-    /// map.raw_entry_mut()
-    ///    .from_key("poneyland")
-    ///    .and_modify(|_k, v| { *v += 1 })
-    ///    .or_insert("poneyland", 42);
-    /// assert_eq!(map["poneyland"], 42);
-    ///
-    /// map.raw_entry_mut()
-    ///    .from_key("poneyland")
-    ///    .and_modify(|_k, v| { *v += 1 })
-    ///    .or_insert("poneyland", 0);
-    /// assert_eq!(map["poneyland"], 43);
-    /// ```
-    #[inline]
-    pub fn and_modify<F>(self, f: F) -> Self
-    where
-        F: FnOnce(&mut K, &mut V),
-    {
-        match self {
-            RawEntryMut::Occupied(mut entry) => {
-                {
-                    let (k, v) = entry.get_key_value_mut();
-                    f(k, v);
-                }
-                RawEntryMut::Occupied(entry)
-            }
-            RawEntryMut::Vacant(entry) => RawEntryMut::Vacant(entry),
-        }
-    }
-}
-
-impl<'a, K, V> RawOccupiedEntryMut<'a, K, V> {
-    /// Gets a reference to the key in the entry.
-    #[inline]
-    pub fn key(&self) -> &K {
-        unsafe { &self.elem.as_ref().0 }
-    }
-
-    /// Gets a mutable reference to the key in the entry.
-    #[inline]
-    pub fn key_mut(&mut self) -> &mut K {
-        unsafe { &mut self.elem.as_mut().0 }
-    }
-
-    /// Converts the entry into a mutable reference to the key in the entry
-    /// with a lifetime bound to the map itself.
-    #[inline]
-    pub fn into_key(self) -> &'a mut K {
-        unsafe { &mut self.elem.as_mut().0 }
-    }
-
-    /// Gets a reference to the value in the entry.
-    #[inline]
-    pub fn get(&self) -> &V {
-        unsafe { &self.elem.as_ref().1 }
-    }
-
-    /// Converts the OccupiedEntry into a mutable reference to the value in the entry
-    /// with a lifetime bound to the map itself.
-    #[inline]
-    pub fn into_mut(self) -> &'a mut V {
-        unsafe { &mut self.elem.as_mut().1 }
-    }
-
-    /// Gets a mutable reference to the value in the entry.
-    #[inline]
-    pub fn get_mut(&mut self) -> &mut V {
-        unsafe { &mut self.elem.as_mut().1 }
-    }
-
-    /// Gets a reference to the key and value in the entry.
-    #[inline]
-    pub fn get_key_value(&mut self) -> (&K, &V) {
-        unsafe {
-            let &(ref key, ref value) = self.elem.as_ref();
-            (key, value)
-        }
-    }
-
-    /// Gets a mutable reference to the key and value in the entry.
-    #[inline]
-    pub fn get_key_value_mut(&mut self) -> (&mut K, &mut V) {
-        unsafe {
-            let &mut (ref mut key, ref mut value) = self.elem.as_mut();
-            (key, value)
-        }
-    }
-
-    /// Converts the OccupiedEntry into a mutable reference to the key and value in the entry
-    /// with a lifetime bound to the map itself.
-    #[inline]
-    pub fn into_key_value(self) -> (&'a mut K, &'a mut V) {
-        unsafe {
-            let &mut (ref mut key, ref mut value) = self.elem.as_mut();
-            (key, value)
-        }
-    }
-
-    /// Sets the value of the entry, and returns the entry's old value.
-    #[inline]
-    pub fn insert(&mut self, value: V) -> V {
-        mem::replace(self.get_mut(), value)
-    }
-
-    /// Sets the value of the entry, and returns the entry's old value.
-    #[inline]
-    pub fn insert_key(&mut self, key: K) -> K {
-        mem::replace(self.key_mut(), key)
-    }
-
-    /// Takes the value out of the entry, and returns it.
-    #[inline]
-    pub fn remove(self) -> V {
-        self.remove_entry().1
-    }
-
-    /// Take the ownership of the key and value from the map.
-    #[inline]
-    pub fn remove_entry(self) -> (K, V) {
-        unsafe {
-            self.table.erase_no_drop(&self.elem);
-            self.elem.read()
-        }
-    }
-}
-
-impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> {
-    /// Sets the value of the entry with the VacantEntry's key,
-    /// and returns a mutable reference to it.
-    #[inline]
-    pub fn insert(self, key: K, value: V) -> (&'a mut K, &'a mut V)
-    where
-        K: Hash,
-        S: BuildHasher,
-    {
-        let mut hasher = self.hash_builder.build_hasher();
-        key.hash(&mut hasher);
-        self.insert_hashed_nocheck(hasher.finish(), key, value)
-    }
-
-    /// Sets the value of the entry with the VacantEntry's key,
-    /// and returns a mutable reference to it.
-    #[inline]
-    #[allow(clippy::shadow_unrelated)]
-    pub fn insert_hashed_nocheck(self, hash: u64, key: K, value: V) -> (&'a mut K, &'a mut V)
-    where
-        K: Hash,
-        S: BuildHasher,
-    {
-        let hash_builder = self.hash_builder;
-        self.insert_with_hasher(hash, key, value, |k| make_hash(hash_builder, k))
-    }
-
-    /// Set the value of an entry with a custom hasher function.
-    #[inline]
-    pub fn insert_with_hasher<H>(
-        self,
-        hash: u64,
-        key: K,
-        value: V,
-        hasher: H,
-    ) -> (&'a mut K, &'a mut V)
-    where
-        S: BuildHasher,
-        H: Fn(&K) -> u64,
-    {
-        unsafe {
-            let elem = self.table.insert(hash, (key, value), |x| hasher(&x.0));
-            let &mut (ref mut k, ref mut v) = elem.as_mut();
-            (k, v)
-        }
-    }
-}
-
-impl<K, V, S> Debug for RawEntryBuilderMut<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("RawEntryBuilder").finish()
-    }
-}
-
-impl<K: Debug, V: Debug, S> Debug for RawEntryMut<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match *self {
-            RawEntryMut::Vacant(ref v) => f.debug_tuple("RawEntry").field(v).finish(),
-            RawEntryMut::Occupied(ref o) => f.debug_tuple("RawEntry").field(o).finish(),
-        }
-    }
-}
-
-impl<K: Debug, V: Debug> Debug for RawOccupiedEntryMut<'_, K, V> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("RawOccupiedEntryMut")
-            .field("key", self.key())
-            .field("value", self.get())
-            .finish()
-    }
-}
-
-impl<K, V, S> Debug for RawVacantEntryMut<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("RawVacantEntryMut").finish()
-    }
-}
-
-impl<K, V, S> Debug for RawEntryBuilder<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("RawEntryBuilder").finish()
-    }
-}
-
-/// A view into a single entry in a map, which may either be vacant or occupied.
-///
-/// This `enum` is constructed from the [`entry`] method on [`HashMap`].
-///
-/// [`HashMap`]: struct.HashMap.html
-/// [`entry`]: struct.HashMap.html#method.entry
-pub enum Entry<'a, K: 'a, V: 'a, S: 'a> {
-    /// An occupied entry.
-    Occupied(OccupiedEntry<'a, K, V, S>),
-
-    /// A vacant entry.
-    Vacant(VacantEntry<'a, K, V, S>),
-}
-
-impl<K: Debug, V: Debug, S> Debug for Entry<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match *self {
-            Entry::Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(),
-            Entry::Occupied(ref o) => f.debug_tuple("Entry").field(o).finish(),
-        }
-    }
-}
-
-/// A view into an occupied entry in a `HashMap`.
-/// It is part of the [`Entry`] enum.
-///
-/// [`Entry`]: enum.Entry.html
-pub struct OccupiedEntry<'a, K, V, S> {
-    key: Option<K>,
-    elem: Bucket<(K, V)>,
-    table: &'a mut HashMap<K, V, S>,
-}
-
-unsafe impl<K, V, S> Send for OccupiedEntry<'_, K, V, S>
-where
-    K: Send,
-    V: Send,
-    S: Send,
-{
-}
-unsafe impl<K, V, S> Sync for OccupiedEntry<'_, K, V, S>
-where
-    K: Sync,
-    V: Sync,
-    S: Sync,
-{
-}
-
-impl<K: Debug, V: Debug, S> Debug for OccupiedEntry<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("OccupiedEntry")
-            .field("key", self.key())
-            .field("value", self.get())
-            .finish()
-    }
-}
-
-/// A view into a vacant entry in a `HashMap`.
-/// It is part of the [`Entry`] enum.
-///
-/// [`Entry`]: enum.Entry.html
-pub struct VacantEntry<'a, K, V, S> {
-    hash: u64,
-    key: K,
-    table: &'a mut HashMap<K, V, S>,
-}
-
-impl<K: Debug, V, S> Debug for VacantEntry<'_, K, V, S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_tuple("VacantEntry").field(self.key()).finish()
-    }
-}
-
-impl<'a, K, V, S> IntoIterator for &'a HashMap<K, V, S> {
-    type Item = (&'a K, &'a V);
-    type IntoIter = Iter<'a, K, V>;
-
-    #[inline]
-    fn into_iter(self) -> Iter<'a, K, V> {
-        self.iter()
-    }
-}
-
-impl<'a, K, V, S> IntoIterator for &'a mut HashMap<K, V, S> {
-    type Item = (&'a K, &'a mut V);
-    type IntoIter = IterMut<'a, K, V>;
-
-    #[inline]
-    fn into_iter(self) -> IterMut<'a, K, V> {
-        self.iter_mut()
-    }
-}
-
-impl<K, V, S> IntoIterator for HashMap<K, V, S> {
-    type Item = (K, V);
-    type IntoIter = IntoIter<K, V>;
-
-    /// Creates a consuming iterator, that is, one that moves each key-value
-    /// pair out of the map in arbitrary order. The map cannot be used after
-    /// calling this.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert("a", 1);
-    /// map.insert("b", 2);
-    /// map.insert("c", 3);
-    ///
-    /// // Not possible with .iter()
-    /// let vec: Vec<(&str, i32)> = map.into_iter().collect();
-    /// ```
-    #[inline]
-    fn into_iter(self) -> IntoIter<K, V> {
-        IntoIter {
-            inner: self.table.into_iter(),
-        }
-    }
-}
-
-impl<'a, K, V> Iterator for Iter<'a, K, V> {
-    type Item = (&'a K, &'a V);
-
-    #[inline]
-    fn next(&mut self) -> Option<(&'a K, &'a V)> {
-        self.inner.next().map(|x| unsafe {
-            let r = x.as_ref();
-            (&r.0, &r.1)
-        })
-    }
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.inner.size_hint()
-    }
-}
-impl<K, V> ExactSizeIterator for Iter<'_, K, V> {
-    #[inline]
-    fn len(&self) -> usize {
-        self.inner.len()
-    }
-}
-
-impl<K, V> FusedIterator for Iter<'_, K, V> {}
-
-impl<'a, K, V> Iterator for IterMut<'a, K, V> {
-    type Item = (&'a K, &'a mut V);
-
-    #[inline]
-    fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
-        self.inner.next().map(|x| unsafe {
-            let r = x.as_mut();
-            (&r.0, &mut r.1)
-        })
-    }
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.inner.size_hint()
-    }
-}
-impl<K, V> ExactSizeIterator for IterMut<'_, K, V> {
-    #[inline]
-    fn len(&self) -> usize {
-        self.inner.len()
-    }
-}
-impl<K, V> FusedIterator for IterMut<'_, K, V> {}
-
-impl<K, V> fmt::Debug for IterMut<'_, K, V>
-where
-    K: fmt::Debug,
-    V: fmt::Debug,
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().entries(self.iter()).finish()
-    }
-}
-
-impl<K, V> Iterator for IntoIter<K, V> {
-    type Item = (K, V);
-
-    #[inline]
-    fn next(&mut self) -> Option<(K, V)> {
-        self.inner.next()
-    }
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.inner.size_hint()
-    }
-}
-impl<K, V> ExactSizeIterator for IntoIter<K, V> {
-    #[inline]
-    fn len(&self) -> usize {
-        self.inner.len()
-    }
-}
-impl<K, V> FusedIterator for IntoIter<K, V> {}
-
-impl<K: Debug, V: Debug> fmt::Debug for IntoIter<K, V> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().entries(self.iter()).finish()
-    }
-}
-
-impl<'a, K, V> Iterator for Keys<'a, K, V> {
-    type Item = &'a K;
-
-    #[inline]
-    fn next(&mut self) -> Option<(&'a K)> {
-        self.inner.next().map(|(k, _)| k)
-    }
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.inner.size_hint()
-    }
-}
-impl<K, V> ExactSizeIterator for Keys<'_, K, V> {
-    #[inline]
-    fn len(&self) -> usize {
-        self.inner.len()
-    }
-}
-impl<K, V> FusedIterator for Keys<'_, K, V> {}
-
-impl<'a, K, V> Iterator for Values<'a, K, V> {
-    type Item = &'a V;
-
-    #[inline]
-    fn next(&mut self) -> Option<(&'a V)> {
-        self.inner.next().map(|(_, v)| v)
-    }
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.inner.size_hint()
-    }
-}
-impl<K, V> ExactSizeIterator for Values<'_, K, V> {
-    #[inline]
-    fn len(&self) -> usize {
-        self.inner.len()
-    }
-}
-impl<K, V> FusedIterator for Values<'_, K, V> {}
-
-impl<'a, K, V> Iterator for ValuesMut<'a, K, V> {
-    type Item = &'a mut V;
-
-    #[inline]
-    fn next(&mut self) -> Option<(&'a mut V)> {
-        self.inner.next().map(|(_, v)| v)
-    }
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.inner.size_hint()
-    }
-}
-impl<K, V> ExactSizeIterator for ValuesMut<'_, K, V> {
-    #[inline]
-    fn len(&self) -> usize {
-        self.inner.len()
-    }
-}
-impl<K, V> FusedIterator for ValuesMut<'_, K, V> {}
-
-impl<K, V> fmt::Debug for ValuesMut<'_, K, V>
-where
-    K: fmt::Debug,
-    V: fmt::Debug,
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().entries(self.inner.iter()).finish()
-    }
-}
-
-impl<'a, K, V> Iterator for Drain<'a, K, V> {
-    type Item = (K, V);
-
-    #[inline]
-    fn next(&mut self) -> Option<(K, V)> {
-        self.inner.next()
-    }
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.inner.size_hint()
-    }
-}
-impl<K, V> ExactSizeIterator for Drain<'_, K, V> {
-    #[inline]
-    fn len(&self) -> usize {
-        self.inner.len()
-    }
-}
-impl<K, V> FusedIterator for Drain<'_, K, V> {}
-
-impl<K, V> fmt::Debug for Drain<'_, K, V>
-where
-    K: fmt::Debug,
-    V: fmt::Debug,
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().entries(self.iter()).finish()
-    }
-}
-
-impl<'a, K, V, S> Entry<'a, K, V, S> {
-    /// Ensures a value is in the entry by inserting the default if empty, and returns
-    /// a mutable reference to the value in the entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    ///
-    /// map.entry("poneyland").or_insert(3);
-    /// assert_eq!(map["poneyland"], 3);
-    ///
-    /// *map.entry("poneyland").or_insert(10) *= 2;
-    /// assert_eq!(map["poneyland"], 6);
-    /// ```
-    #[inline]
-    pub fn or_insert(self, default: V) -> &'a mut V
-    where
-        K: Hash,
-        S: BuildHasher,
-    {
-        match self {
-            Entry::Occupied(entry) => entry.into_mut(),
-            Entry::Vacant(entry) => entry.insert(default),
-        }
-    }
-
-    /// Ensures a value is in the entry by inserting the result of the default function if empty,
-    /// and returns a mutable reference to the value in the entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, String> = HashMap::new();
-    /// let s = "hoho".to_string();
-    ///
-    /// map.entry("poneyland").or_insert_with(|| s);
-    ///
-    /// assert_eq!(map["poneyland"], "hoho".to_string());
-    /// ```
-    #[inline]
-    pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V
-    where
-        K: Hash,
-        S: BuildHasher,
-    {
-        match self {
-            Entry::Occupied(entry) => entry.into_mut(),
-            Entry::Vacant(entry) => entry.insert(default()),
-        }
-    }
-
-    /// Returns a reference to this entry's key.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// assert_eq!(map.entry("poneyland").key(), &"poneyland");
-    /// ```
-    #[inline]
-    pub fn key(&self) -> &K {
-        match *self {
-            Entry::Occupied(ref entry) => entry.key(),
-            Entry::Vacant(ref entry) => entry.key(),
-        }
-    }
-
-    /// Provides in-place mutable access to an occupied entry before any
-    /// potential inserts into the map.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    ///
-    /// map.entry("poneyland")
-    ///    .and_modify(|e| { *e += 1 })
-    ///    .or_insert(42);
-    /// assert_eq!(map["poneyland"], 42);
-    ///
-    /// map.entry("poneyland")
-    ///    .and_modify(|e| { *e += 1 })
-    ///    .or_insert(42);
-    /// assert_eq!(map["poneyland"], 43);
-    /// ```
-    #[inline]
-    pub fn and_modify<F>(self, f: F) -> Self
-    where
-        F: FnOnce(&mut V),
-    {
-        match self {
-            Entry::Occupied(mut entry) => {
-                f(entry.get_mut());
-                Entry::Occupied(entry)
-            }
-            Entry::Vacant(entry) => Entry::Vacant(entry),
-        }
-    }
-}
-
-impl<'a, K, V: Default, S> Entry<'a, K, V, S> {
-    /// Ensures a value is in the entry by inserting the default value if empty,
-    /// and returns a mutable reference to the value in the entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # fn main() {
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, Option<u32>> = HashMap::new();
-    /// map.entry("poneyland").or_default();
-    ///
-    /// assert_eq!(map["poneyland"], None);
-    /// # }
-    /// ```
-    #[inline]
-    pub fn or_default(self) -> &'a mut V
-    where
-        K: Hash,
-        S: BuildHasher,
-    {
-        match self {
-            Entry::Occupied(entry) => entry.into_mut(),
-            Entry::Vacant(entry) => entry.insert(Default::default()),
-        }
-    }
-}
-
-impl<'a, K, V, S> OccupiedEntry<'a, K, V, S> {
-    /// Gets a reference to the key in the entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.entry("poneyland").or_insert(12);
-    /// assert_eq!(map.entry("poneyland").key(), &"poneyland");
-    /// ```
-    #[inline]
-    pub fn key(&self) -> &K {
-        unsafe { &self.elem.as_ref().0 }
-    }
-
-    /// Take the ownership of the key and value from the map.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::Entry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.entry("poneyland").or_insert(12);
-    ///
-    /// if let Entry::Occupied(o) = map.entry("poneyland") {
-    ///     // We delete the entry from the map.
-    ///     o.remove_entry();
-    /// }
-    ///
-    /// assert_eq!(map.contains_key("poneyland"), false);
-    /// ```
-    #[inline]
-    pub fn remove_entry(self) -> (K, V) {
-        unsafe {
-            self.table.table.erase_no_drop(&self.elem);
-            self.elem.read()
-        }
-    }
-
-    /// Gets a reference to the value in the entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::Entry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.entry("poneyland").or_insert(12);
-    ///
-    /// if let Entry::Occupied(o) = map.entry("poneyland") {
-    ///     assert_eq!(o.get(), &12);
-    /// }
-    /// ```
-    #[inline]
-    pub fn get(&self) -> &V {
-        unsafe { &self.elem.as_ref().1 }
-    }
-
-    /// Gets a mutable reference to the value in the entry.
-    ///
-    /// If you need a reference to the `OccupiedEntry` which may outlive the
-    /// destruction of the `Entry` value, see [`into_mut`].
-    ///
-    /// [`into_mut`]: #method.into_mut
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::Entry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.entry("poneyland").or_insert(12);
-    ///
-    /// assert_eq!(map["poneyland"], 12);
-    /// if let Entry::Occupied(mut o) = map.entry("poneyland") {
-    ///     *o.get_mut() += 10;
-    ///     assert_eq!(*o.get(), 22);
-    ///
-    ///     // We can use the same Entry multiple times.
-    ///     *o.get_mut() += 2;
-    /// }
-    ///
-    /// assert_eq!(map["poneyland"], 24);
-    /// ```
-    #[inline]
-    pub fn get_mut(&mut self) -> &mut V {
-        unsafe { &mut self.elem.as_mut().1 }
-    }
-
-    /// Converts the OccupiedEntry into a mutable reference to the value in the entry
-    /// with a lifetime bound to the map itself.
-    ///
-    /// If you need multiple references to the `OccupiedEntry`, see [`get_mut`].
-    ///
-    /// [`get_mut`]: #method.get_mut
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::Entry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.entry("poneyland").or_insert(12);
-    ///
-    /// assert_eq!(map["poneyland"], 12);
-    /// if let Entry::Occupied(o) = map.entry("poneyland") {
-    ///     *o.into_mut() += 10;
-    /// }
-    ///
-    /// assert_eq!(map["poneyland"], 22);
-    /// ```
-    #[inline]
-    pub fn into_mut(self) -> &'a mut V {
-        unsafe { &mut self.elem.as_mut().1 }
-    }
-
-    /// Sets the value of the entry, and returns the entry's old value.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::Entry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.entry("poneyland").or_insert(12);
-    ///
-    /// if let Entry::Occupied(mut o) = map.entry("poneyland") {
-    ///     assert_eq!(o.insert(15), 12);
-    /// }
-    ///
-    /// assert_eq!(map["poneyland"], 15);
-    /// ```
-    #[inline]
-    pub fn insert(&mut self, mut value: V) -> V {
-        let old_value = self.get_mut();
-        mem::swap(&mut value, old_value);
-        value
-    }
-
-    /// Takes the value out of the entry, and returns it.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::Entry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.entry("poneyland").or_insert(12);
-    ///
-    /// if let Entry::Occupied(o) = map.entry("poneyland") {
-    ///     assert_eq!(o.remove(), 12);
-    /// }
-    ///
-    /// assert_eq!(map.contains_key("poneyland"), false);
-    /// ```
-    #[inline]
-    pub fn remove(self) -> V {
-        self.remove_entry().1
-    }
-
-    /// Replaces the entry, returning the old key and value. The new key in the hash map will be
-    /// the key used to create this entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::hash_map::{Entry, HashMap};
-    /// use std::rc::Rc;
-    ///
-    /// let mut map: HashMap<Rc<String>, u32> = HashMap::new();
-    /// map.insert(Rc::new("Stringthing".to_string()), 15);
-    ///
-    /// let my_key = Rc::new("Stringthing".to_string());
-    ///
-    /// if let Entry::Occupied(entry) = map.entry(my_key) {
-    ///     // Also replace the key with a handle to our other key.
-    ///     let (old_key, old_value): (Rc<String>, u32) = entry.replace_entry(16);
-    /// }
-    ///
-    /// ```
-    #[inline]
-    pub fn replace_entry(self, value: V) -> (K, V) {
-        let entry = unsafe { self.elem.as_mut() };
-
-        let old_key = mem::replace(&mut entry.0, self.key.unwrap());
-        let old_value = mem::replace(&mut entry.1, value);
-
-        (old_key, old_value)
-    }
-
-    /// Replaces the key in the hash map with the key used to create this entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::hash_map::{Entry, HashMap};
-    /// use std::rc::Rc;
-    ///
-    /// let mut map: HashMap<Rc<String>, u32> = HashMap::new();
-    /// let mut known_strings: Vec<Rc<String>> = Vec::new();
-    ///
-    /// // Initialise known strings, run program, etc.
-    ///
-    /// reclaim_memory(&mut map, &known_strings);
-    ///
-    /// fn reclaim_memory(map: &mut HashMap<Rc<String>, u32>, known_strings: &[Rc<String>] ) {
-    ///     for s in known_strings {
-    ///         if let Entry::Occupied(entry) = map.entry(s.clone()) {
-    ///             // Replaces the entry's key with our version of it in `known_strings`.
-    ///             entry.replace_key();
-    ///         }
-    ///     }
-    /// }
-    /// ```
-    #[inline]
-    pub fn replace_key(self) -> K {
-        let entry = unsafe { self.elem.as_mut() };
-        mem::replace(&mut entry.0, self.key.unwrap())
-    }
-}
-
-impl<'a, K, V, S> VacantEntry<'a, K, V, S> {
-    /// Gets a reference to the key that would be used when inserting a value
-    /// through the `VacantEntry`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// assert_eq!(map.entry("poneyland").key(), &"poneyland");
-    /// ```
-    #[inline]
-    pub fn key(&self) -> &K {
-        &self.key
-    }
-
-    /// Take ownership of the key.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::Entry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    ///
-    /// if let Entry::Vacant(v) = map.entry("poneyland") {
-    ///     v.into_key();
-    /// }
-    /// ```
-    #[inline]
-    pub fn into_key(self) -> K {
-        self.key
-    }
-
-    /// Sets the value of the entry with the VacantEntry's key,
-    /// and returns a mutable reference to it.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::Entry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    ///
-    /// if let Entry::Vacant(o) = map.entry("poneyland") {
-    ///     o.insert(37);
-    /// }
-    /// assert_eq!(map["poneyland"], 37);
-    /// ```
-    #[inline]
-    pub fn insert(self, value: V) -> &'a mut V
-    where
-        K: Hash,
-        S: BuildHasher,
-    {
-        let hash_builder = &self.table.hash_builder;
-        let bucket = self.table.table.insert(self.hash, (self.key, value), |x| {
-            make_hash(hash_builder, &x.0)
-        });
-        unsafe { &mut bucket.as_mut().1 }
-    }
-}
-
-impl<K, V, S> FromIterator<(K, V)> for HashMap<K, V, S>
-where
-    K: Eq + Hash,
-    S: BuildHasher + Default,
-{
-    #[inline]
-    fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
-        let iter = iter.into_iter();
-        let mut map = Self::with_capacity_and_hasher(iter.size_hint().0, S::default());
-        iter.for_each(|(k, v)| {
-            map.insert(k, v);
-        });
-        map
-    }
-}
-
-impl<K, V, S> Extend<(K, V)> for HashMap<K, V, S>
-where
-    K: Eq + Hash,
-    S: BuildHasher,
-{
-    #[inline]
-    fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
-        // Keys may be already present or show multiple times in the iterator.
-        // Reserve the entire hint lower bound if the map is empty.
-        // Otherwise reserve half the hint (rounded up), so the map
-        // will only resize twice in the worst case.
-        let iter = iter.into_iter();
-        let reserve = if self.is_empty() {
-            iter.size_hint().0
-        } else {
-            (iter.size_hint().0 + 1) / 2
-        };
-        self.reserve(reserve);
-        iter.for_each(move |(k, v)| {
-            self.insert(k, v);
-        });
-    }
-}
-
-impl<'a, K, V, S> Extend<(&'a K, &'a V)> for HashMap<K, V, S>
-where
-    K: Eq + Hash + Copy,
-    V: Copy,
-    S: BuildHasher,
-{
-    #[inline]
-    fn extend<T: IntoIterator<Item = (&'a K, &'a V)>>(&mut self, iter: T) {
-        self.extend(iter.into_iter().map(|(&key, &value)| (key, value)));
-    }
-}
-
-#[allow(dead_code)]
-fn assert_covariance() {
-    fn map_key<'new>(v: HashMap<&'static str, u8>) -> HashMap<&'new str, u8> {
-        v
-    }
-    fn map_val<'new>(v: HashMap<u8, &'static str>) -> HashMap<u8, &'new str> {
-        v
-    }
-    fn iter_key<'a, 'new>(v: Iter<'a, &'static str, u8>) -> Iter<'a, &'new str, u8> {
-        v
-    }
-    fn iter_val<'a, 'new>(v: Iter<'a, u8, &'static str>) -> Iter<'a, u8, &'new str> {
-        v
-    }
-    fn into_iter_key<'new>(v: IntoIter<&'static str, u8>) -> IntoIter<&'new str, u8> {
-        v
-    }
-    fn into_iter_val<'new>(v: IntoIter<u8, &'static str>) -> IntoIter<u8, &'new str> {
-        v
-    }
-    fn keys_key<'a, 'new>(v: Keys<'a, &'static str, u8>) -> Keys<'a, &'new str, u8> {
-        v
-    }
-    fn keys_val<'a, 'new>(v: Keys<'a, u8, &'static str>) -> Keys<'a, u8, &'new str> {
-        v
-    }
-    fn values_key<'a, 'new>(v: Values<'a, &'static str, u8>) -> Values<'a, &'new str, u8> {
-        v
-    }
-    fn values_val<'a, 'new>(v: Values<'a, u8, &'static str>) -> Values<'a, u8, &'new str> {
-        v
-    }
-    fn drain<'new>(
-        d: Drain<'static, &'static str, &'static str>,
-    ) -> Drain<'new, &'new str, &'new str> {
-        d
-    }
-}
-
-#[cfg(test)]
-mod test_map {
-    use super::DefaultHashBuilder;
-    use super::Entry::{Occupied, Vacant};
-    use super::{HashMap, RawEntryMut};
-    #[cfg(not(miri))]
-    use crate::CollectionAllocErr::*;
-    use rand::{rngs::SmallRng, Rng, SeedableRng};
-    use std::cell::RefCell;
-    use std::usize;
-    use std::vec::Vec;
-
-    #[test]
-    fn test_zero_capacities() {
-        type HM = HashMap<i32, i32>;
-
-        let m = HM::new();
-        assert_eq!(m.capacity(), 0);
-
-        let m = HM::default();
-        assert_eq!(m.capacity(), 0);
-
-        let m = HM::with_hasher(DefaultHashBuilder::default());
-        assert_eq!(m.capacity(), 0);
-
-        let m = HM::with_capacity(0);
-        assert_eq!(m.capacity(), 0);
-
-        let m = HM::with_capacity_and_hasher(0, DefaultHashBuilder::default());
-        assert_eq!(m.capacity(), 0);
-
-        let mut m = HM::new();
-        m.insert(1, 1);
-        m.insert(2, 2);
-        m.remove(&1);
-        m.remove(&2);
-        m.shrink_to_fit();
-        assert_eq!(m.capacity(), 0);
-
-        let mut m = HM::new();
-        m.reserve(0);
-        assert_eq!(m.capacity(), 0);
-    }
-
-    #[test]
-    fn test_create_capacity_zero() {
-        let mut m = HashMap::with_capacity(0);
-
-        assert!(m.insert(1, 1).is_none());
-
-        assert!(m.contains_key(&1));
-        assert!(!m.contains_key(&0));
-    }
-
-    #[test]
-    fn test_insert() {
-        let mut m = HashMap::new();
-        assert_eq!(m.len(), 0);
-        assert!(m.insert(1, 2).is_none());
-        assert_eq!(m.len(), 1);
-        assert!(m.insert(2, 4).is_none());
-        assert_eq!(m.len(), 2);
-        assert_eq!(*m.get(&1).unwrap(), 2);
-        assert_eq!(*m.get(&2).unwrap(), 4);
-    }
-
-    #[test]
-    fn test_clone() {
-        let mut m = HashMap::new();
-        assert_eq!(m.len(), 0);
-        assert!(m.insert(1, 2).is_none());
-        assert_eq!(m.len(), 1);
-        assert!(m.insert(2, 4).is_none());
-        assert_eq!(m.len(), 2);
-        let m2 = m.clone();
-        assert_eq!(*m2.get(&1).unwrap(), 2);
-        assert_eq!(*m2.get(&2).unwrap(), 4);
-        assert_eq!(m2.len(), 2);
-    }
-
-    thread_local! { static DROP_VECTOR: RefCell<Vec<i32>> = RefCell::new(Vec::new()) }
-
-    #[derive(Hash, PartialEq, Eq)]
-    struct Droppable {
-        k: usize,
-    }
-
-    impl Droppable {
-        fn new(k: usize) -> Droppable {
-            DROP_VECTOR.with(|slot| {
-                slot.borrow_mut()[k] += 1;
-            });
-
-            Droppable { k }
-        }
-    }
-
-    impl Drop for Droppable {
-        fn drop(&mut self) {
-            DROP_VECTOR.with(|slot| {
-                slot.borrow_mut()[self.k] -= 1;
-            });
-        }
-    }
-
-    impl Clone for Droppable {
-        fn clone(&self) -> Self {
-            Droppable::new(self.k)
-        }
-    }
-
-    #[test]
-    fn test_drops() {
-        DROP_VECTOR.with(|slot| {
-            *slot.borrow_mut() = vec![0; 200];
-        });
-
-        {
-            let mut m = HashMap::new();
-
-            DROP_VECTOR.with(|v| {
-                for i in 0..200 {
-                    assert_eq!(v.borrow()[i], 0);
-                }
-            });
-
-            for i in 0..100 {
-                let d1 = Droppable::new(i);
-                let d2 = Droppable::new(i + 100);
-                m.insert(d1, d2);
-            }
-
-            DROP_VECTOR.with(|v| {
-                for i in 0..200 {
-                    assert_eq!(v.borrow()[i], 1);
-                }
-            });
-
-            for i in 0..50 {
-                let k = Droppable::new(i);
-                let v = m.remove(&k);
-
-                assert!(v.is_some());
-
-                DROP_VECTOR.with(|v| {
-                    assert_eq!(v.borrow()[i], 1);
-                    assert_eq!(v.borrow()[i + 100], 1);
-                });
-            }
-
-            DROP_VECTOR.with(|v| {
-                for i in 0..50 {
-                    assert_eq!(v.borrow()[i], 0);
-                    assert_eq!(v.borrow()[i + 100], 0);
-                }
-
-                for i in 50..100 {
-                    assert_eq!(v.borrow()[i], 1);
-                    assert_eq!(v.borrow()[i + 100], 1);
-                }
-            });
-        }
-
-        DROP_VECTOR.with(|v| {
-            for i in 0..200 {
-                assert_eq!(v.borrow()[i], 0);
-            }
-        });
-    }
-
-    #[test]
-    fn test_into_iter_drops() {
-        DROP_VECTOR.with(|v| {
-            *v.borrow_mut() = vec![0; 200];
-        });
-
-        let hm = {
-            let mut hm = HashMap::new();
-
-            DROP_VECTOR.with(|v| {
-                for i in 0..200 {
-                    assert_eq!(v.borrow()[i], 0);
-                }
-            });
-
-            for i in 0..100 {
-                let d1 = Droppable::new(i);
-                let d2 = Droppable::new(i + 100);
-                hm.insert(d1, d2);
-            }
-
-            DROP_VECTOR.with(|v| {
-                for i in 0..200 {
-                    assert_eq!(v.borrow()[i], 1);
-                }
-            });
-
-            hm
-        };
-
-        // By the way, ensure that cloning doesn't screw up the dropping.
-        drop(hm.clone());
-
-        {
-            let mut half = hm.into_iter().take(50);
-
-            DROP_VECTOR.with(|v| {
-                for i in 0..200 {
-                    assert_eq!(v.borrow()[i], 1);
-                }
-            });
-
-            for _ in half.by_ref() {}
-
-            DROP_VECTOR.with(|v| {
-                let nk = (0..100).filter(|&i| v.borrow()[i] == 1).count();
-
-                let nv = (0..100).filter(|&i| v.borrow()[i + 100] == 1).count();
-
-                assert_eq!(nk, 50);
-                assert_eq!(nv, 50);
-            });
-        };
-
-        DROP_VECTOR.with(|v| {
-            for i in 0..200 {
-                assert_eq!(v.borrow()[i], 0);
-            }
-        });
-    }
-
-    #[test]
-    fn test_empty_remove() {
-        let mut m: HashMap<i32, bool> = HashMap::new();
-        assert_eq!(m.remove(&0), None);
-    }
-
-    #[test]
-    fn test_empty_entry() {
-        let mut m: HashMap<i32, bool> = HashMap::new();
-        match m.entry(0) {
-            Occupied(_) => panic!(),
-            Vacant(_) => {}
-        }
-        assert!(*m.entry(0).or_insert(true));
-        assert_eq!(m.len(), 1);
-    }
-
-    #[test]
-    fn test_empty_iter() {
-        let mut m: HashMap<i32, bool> = HashMap::new();
-        assert_eq!(m.drain().next(), None);
-        assert_eq!(m.keys().next(), None);
-        assert_eq!(m.values().next(), None);
-        assert_eq!(m.values_mut().next(), None);
-        assert_eq!(m.iter().next(), None);
-        assert_eq!(m.iter_mut().next(), None);
-        assert_eq!(m.len(), 0);
-        assert!(m.is_empty());
-        assert_eq!(m.into_iter().next(), None);
-    }
-
-    #[test]
-    #[cfg(not(miri))] // FIXME: https://github.com/rust-lang/miri/issues/654
-    fn test_lots_of_insertions() {
-        let mut m = HashMap::new();
-
-        // Try this a few times to make sure we never screw up the hashmap's
-        // internal state.
-        for _ in 0..10 {
-            assert!(m.is_empty());
-
-            for i in 1..1001 {
-                assert!(m.insert(i, i).is_none());
-
-                for j in 1..=i {
-                    let r = m.get(&j);
-                    assert_eq!(r, Some(&j));
-                }
-
-                for j in i + 1..1001 {
-                    let r = m.get(&j);
-                    assert_eq!(r, None);
-                }
-            }
-
-            for i in 1001..2001 {
-                assert!(!m.contains_key(&i));
-            }
-
-            // remove forwards
-            for i in 1..1001 {
-                assert!(m.remove(&i).is_some());
-
-                for j in 1..=i {
-                    assert!(!m.contains_key(&j));
-                }
-
-                for j in i + 1..1001 {
-                    assert!(m.contains_key(&j));
-                }
-            }
-
-            for i in 1..1001 {
-                assert!(!m.contains_key(&i));
-            }
-
-            for i in 1..1001 {
-                assert!(m.insert(i, i).is_none());
-            }
-
-            // remove backwards
-            for i in (1..1001).rev() {
-                assert!(m.remove(&i).is_some());
-
-                for j in i..1001 {
-                    assert!(!m.contains_key(&j));
-                }
-
-                for j in 1..i {
-                    assert!(m.contains_key(&j));
-                }
-            }
-        }
-    }
-
-    #[test]
-    fn test_find_mut() {
-        let mut m = HashMap::new();
-        assert!(m.insert(1, 12).is_none());
-        assert!(m.insert(2, 8).is_none());
-        assert!(m.insert(5, 14).is_none());
-        let new = 100;
-        match m.get_mut(&5) {
-            None => panic!(),
-            Some(x) => *x = new,
-        }
-        assert_eq!(m.get(&5), Some(&new));
-    }
-
-    #[test]
-    fn test_insert_overwrite() {
-        let mut m = HashMap::new();
-        assert!(m.insert(1, 2).is_none());
-        assert_eq!(*m.get(&1).unwrap(), 2);
-        assert!(!m.insert(1, 3).is_none());
-        assert_eq!(*m.get(&1).unwrap(), 3);
-    }
-
-    #[test]
-    fn test_insert_conflicts() {
-        let mut m = HashMap::with_capacity(4);
-        assert!(m.insert(1, 2).is_none());
-        assert!(m.insert(5, 3).is_none());
-        assert!(m.insert(9, 4).is_none());
-        assert_eq!(*m.get(&9).unwrap(), 4);
-        assert_eq!(*m.get(&5).unwrap(), 3);
-        assert_eq!(*m.get(&1).unwrap(), 2);
-    }
-
-    #[test]
-    fn test_conflict_remove() {
-        let mut m = HashMap::with_capacity(4);
-        assert!(m.insert(1, 2).is_none());
-        assert_eq!(*m.get(&1).unwrap(), 2);
-        assert!(m.insert(5, 3).is_none());
-        assert_eq!(*m.get(&1).unwrap(), 2);
-        assert_eq!(*m.get(&5).unwrap(), 3);
-        assert!(m.insert(9, 4).is_none());
-        assert_eq!(*m.get(&1).unwrap(), 2);
-        assert_eq!(*m.get(&5).unwrap(), 3);
-        assert_eq!(*m.get(&9).unwrap(), 4);
-        assert!(m.remove(&1).is_some());
-        assert_eq!(*m.get(&9).unwrap(), 4);
-        assert_eq!(*m.get(&5).unwrap(), 3);
-    }
-
-    #[test]
-    fn test_is_empty() {
-        let mut m = HashMap::with_capacity(4);
-        assert!(m.insert(1, 2).is_none());
-        assert!(!m.is_empty());
-        assert!(m.remove(&1).is_some());
-        assert!(m.is_empty());
-    }
-
-    #[test]
-    fn test_remove() {
-        let mut m = HashMap::new();
-        m.insert(1, 2);
-        assert_eq!(m.remove(&1), Some(2));
-        assert_eq!(m.remove(&1), None);
-    }
-
-    #[test]
-    fn test_remove_entry() {
-        let mut m = HashMap::new();
-        m.insert(1, 2);
-        assert_eq!(m.remove_entry(&1), Some((1, 2)));
-        assert_eq!(m.remove(&1), None);
-    }
-
-    #[test]
-    fn test_iterate() {
-        let mut m = HashMap::with_capacity(4);
-        for i in 0..32 {
-            assert!(m.insert(i, i * 2).is_none());
-        }
-        assert_eq!(m.len(), 32);
-
-        let mut observed: u32 = 0;
-
-        for (k, v) in &m {
-            assert_eq!(*v, *k * 2);
-            observed |= 1 << *k;
-        }
-        assert_eq!(observed, 0xFFFF_FFFF);
-    }
-
-    #[test]
-    fn test_keys() {
-        let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
-        let map: HashMap<_, _> = vec.into_iter().collect();
-        let keys: Vec<_> = map.keys().cloned().collect();
-        assert_eq!(keys.len(), 3);
-        assert!(keys.contains(&1));
-        assert!(keys.contains(&2));
-        assert!(keys.contains(&3));
-    }
-
-    #[test]
-    fn test_values() {
-        let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
-        let map: HashMap<_, _> = vec.into_iter().collect();
-        let values: Vec<_> = map.values().cloned().collect();
-        assert_eq!(values.len(), 3);
-        assert!(values.contains(&'a'));
-        assert!(values.contains(&'b'));
-        assert!(values.contains(&'c'));
-    }
-
-    #[test]
-    fn test_values_mut() {
-        let vec = vec![(1, 1), (2, 2), (3, 3)];
-        let mut map: HashMap<_, _> = vec.into_iter().collect();
-        for value in map.values_mut() {
-            *value = (*value) * 2
-        }
-        let values: Vec<_> = map.values().cloned().collect();
-        assert_eq!(values.len(), 3);
-        assert!(values.contains(&2));
-        assert!(values.contains(&4));
-        assert!(values.contains(&6));
-    }
-
-    #[test]
-    fn test_find() {
-        let mut m = HashMap::new();
-        assert!(m.get(&1).is_none());
-        m.insert(1, 2);
-        match m.get(&1) {
-            None => panic!(),
-            Some(v) => assert_eq!(*v, 2),
-        }
-    }
-
-    #[test]
-    fn test_eq() {
-        let mut m1 = HashMap::new();
-        m1.insert(1, 2);
-        m1.insert(2, 3);
-        m1.insert(3, 4);
-
-        let mut m2 = HashMap::new();
-        m2.insert(1, 2);
-        m2.insert(2, 3);
-
-        assert!(m1 != m2);
-
-        m2.insert(3, 4);
-
-        assert_eq!(m1, m2);
-    }
-
-    #[test]
-    fn test_show() {
-        let mut map = HashMap::new();
-        let empty: HashMap<i32, i32> = HashMap::new();
-
-        map.insert(1, 2);
-        map.insert(3, 4);
-
-        let map_str = format!("{:?}", map);
-
-        assert!(map_str == "{1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}");
-        assert_eq!(format!("{:?}", empty), "{}");
-    }
-
-    #[test]
-    fn test_expand() {
-        let mut m = HashMap::new();
-
-        assert_eq!(m.len(), 0);
-        assert!(m.is_empty());
-
-        let mut i = 0;
-        let old_raw_cap = m.raw_capacity();
-        while old_raw_cap == m.raw_capacity() {
-            m.insert(i, i);
-            i += 1;
-        }
-
-        assert_eq!(m.len(), i);
-        assert!(!m.is_empty());
-    }
-
-    #[test]
-    fn test_behavior_resize_policy() {
-        let mut m = HashMap::new();
-
-        assert_eq!(m.len(), 0);
-        assert_eq!(m.raw_capacity(), 1);
-        assert!(m.is_empty());
-
-        m.insert(0, 0);
-        m.remove(&0);
-        assert!(m.is_empty());
-        let initial_raw_cap = m.raw_capacity();
-        m.reserve(initial_raw_cap);
-        let raw_cap = m.raw_capacity();
-
-        assert_eq!(raw_cap, initial_raw_cap * 2);
-
-        let mut i = 0;
-        for _ in 0..raw_cap * 3 / 4 {
-            m.insert(i, i);
-            i += 1;
-        }
-        // three quarters full
-
-        assert_eq!(m.len(), i);
-        assert_eq!(m.raw_capacity(), raw_cap);
-
-        for _ in 0..raw_cap / 4 {
-            m.insert(i, i);
-            i += 1;
-        }
-        // half full
-
-        let new_raw_cap = m.raw_capacity();
-        assert_eq!(new_raw_cap, raw_cap * 2);
-
-        for _ in 0..raw_cap / 2 - 1 {
-            i -= 1;
-            m.remove(&i);
-            assert_eq!(m.raw_capacity(), new_raw_cap);
-        }
-        // A little more than one quarter full.
-        m.shrink_to_fit();
-        assert_eq!(m.raw_capacity(), raw_cap);
-        // again, a little more than half full
-        for _ in 0..raw_cap / 2 {
-            i -= 1;
-            m.remove(&i);
-        }
-        m.shrink_to_fit();
-
-        assert_eq!(m.len(), i);
-        assert!(!m.is_empty());
-        assert_eq!(m.raw_capacity(), initial_raw_cap);
-    }
-
-    #[test]
-    fn test_reserve_shrink_to_fit() {
-        let mut m = HashMap::new();
-        m.insert(0, 0);
-        m.remove(&0);
-        assert!(m.capacity() >= m.len());
-        for i in 0..128 {
-            m.insert(i, i);
-        }
-        m.reserve(256);
-
-        let usable_cap = m.capacity();
-        for i in 128..(128 + 256) {
-            m.insert(i, i);
-            assert_eq!(m.capacity(), usable_cap);
-        }
-
-        for i in 100..(128 + 256) {
-            assert_eq!(m.remove(&i), Some(i));
-        }
-        m.shrink_to_fit();
-
-        assert_eq!(m.len(), 100);
-        assert!(!m.is_empty());
-        assert!(m.capacity() >= m.len());
-
-        for i in 0..100 {
-            assert_eq!(m.remove(&i), Some(i));
-        }
-        m.shrink_to_fit();
-        m.insert(0, 0);
-
-        assert_eq!(m.len(), 1);
-        assert!(m.capacity() >= m.len());
-        assert_eq!(m.remove(&0), Some(0));
-    }
-
-    #[test]
-    fn test_from_iter() {
-        let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
-
-        let map: HashMap<_, _> = xs.iter().cloned().collect();
-
-        for &(k, v) in &xs {
-            assert_eq!(map.get(&k), Some(&v));
-        }
-    }
-
-    #[test]
-    fn test_size_hint() {
-        let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
-
-        let map: HashMap<_, _> = xs.iter().cloned().collect();
-
-        let mut iter = map.iter();
-
-        for _ in iter.by_ref().take(3) {}
-
-        assert_eq!(iter.size_hint(), (3, Some(3)));
-    }
-
-    #[test]
-    fn test_iter_len() {
-        let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
-
-        let map: HashMap<_, _> = xs.iter().cloned().collect();
-
-        let mut iter = map.iter();
-
-        for _ in iter.by_ref().take(3) {}
-
-        assert_eq!(iter.len(), 3);
-    }
-
-    #[test]
-    fn test_mut_size_hint() {
-        let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
-
-        let mut map: HashMap<_, _> = xs.iter().cloned().collect();
-
-        let mut iter = map.iter_mut();
-
-        for _ in iter.by_ref().take(3) {}
-
-        assert_eq!(iter.size_hint(), (3, Some(3)));
-    }
-
-    #[test]
-    fn test_iter_mut_len() {
-        let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
-
-        let mut map: HashMap<_, _> = xs.iter().cloned().collect();
-
-        let mut iter = map.iter_mut();
-
-        for _ in iter.by_ref().take(3) {}
-
-        assert_eq!(iter.len(), 3);
-    }
-
-    #[test]
-    fn test_index() {
-        let mut map = HashMap::new();
-
-        map.insert(1, 2);
-        map.insert(2, 1);
-        map.insert(3, 4);
-
-        assert_eq!(map[&2], 1);
-    }
-
-    #[test]
-    #[should_panic]
-    fn test_index_nonexistent() {
-        let mut map = HashMap::new();
-
-        map.insert(1, 2);
-        map.insert(2, 1);
-        map.insert(3, 4);
-
-        map[&4];
-    }
-
-    #[test]
-    fn test_entry() {
-        let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)];
-
-        let mut map: HashMap<_, _> = xs.iter().cloned().collect();
-
-        // Existing key (insert)
-        match map.entry(1) {
-            Vacant(_) => unreachable!(),
-            Occupied(mut view) => {
-                assert_eq!(view.get(), &10);
-                assert_eq!(view.insert(100), 10);
-            }
-        }
-        assert_eq!(map.get(&1).unwrap(), &100);
-        assert_eq!(map.len(), 6);
-
-        // Existing key (update)
-        match map.entry(2) {
-            Vacant(_) => unreachable!(),
-            Occupied(mut view) => {
-                let v = view.get_mut();
-                let new_v = (*v) * 10;
-                *v = new_v;
-            }
-        }
-        assert_eq!(map.get(&2).unwrap(), &200);
-        assert_eq!(map.len(), 6);
-
-        // Existing key (take)
-        match map.entry(3) {
-            Vacant(_) => unreachable!(),
-            Occupied(view) => {
-                assert_eq!(view.remove(), 30);
-            }
-        }
-        assert_eq!(map.get(&3), None);
-        assert_eq!(map.len(), 5);
-
-        // Inexistent key (insert)
-        match map.entry(10) {
-            Occupied(_) => unreachable!(),
-            Vacant(view) => {
-                assert_eq!(*view.insert(1000), 1000);
-            }
-        }
-        assert_eq!(map.get(&10).unwrap(), &1000);
-        assert_eq!(map.len(), 6);
-    }
-
-    #[test]
-    fn test_entry_take_doesnt_corrupt() {
-        #![allow(deprecated)] //rand
-                              // Test for #19292
-        fn check(m: &HashMap<i32, ()>) {
-            for k in m.keys() {
-                assert!(m.contains_key(k), "{} is in keys() but not in the map?", k);
-            }
-        }
-
-        let mut m = HashMap::new();
-
-        // FIXME: https://github.com/rust-lang/miri/issues/653
-        let mut rng = {
-            let seed = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
-            SmallRng::from_seed(seed)
-        };
-
-        // Populate the map with some items.
-        for _ in 0..50 {
-            let x = rng.gen_range(-10, 10);
-            m.insert(x, ());
-        }
-
-        for _ in 0..1000 {
-            let x = rng.gen_range(-10, 10);
-            match m.entry(x) {
-                Vacant(_) => {}
-                Occupied(e) => {
-                    e.remove();
-                }
-            }
-
-            check(&m);
-        }
-    }
-
-    #[test]
-    fn test_extend_ref() {
-        let mut a = HashMap::new();
-        a.insert(1, "one");
-        let mut b = HashMap::new();
-        b.insert(2, "two");
-        b.insert(3, "three");
-
-        a.extend(&b);
-
-        assert_eq!(a.len(), 3);
-        assert_eq!(a[&1], "one");
-        assert_eq!(a[&2], "two");
-        assert_eq!(a[&3], "three");
-    }
-
-    #[test]
-    fn test_capacity_not_less_than_len() {
-        let mut a = HashMap::new();
-        let mut item = 0;
-
-        for _ in 0..116 {
-            a.insert(item, 0);
-            item += 1;
-        }
-
-        assert!(a.capacity() > a.len());
-
-        let free = a.capacity() - a.len();
-        for _ in 0..free {
-            a.insert(item, 0);
-            item += 1;
-        }
-
-        assert_eq!(a.len(), a.capacity());
-
-        // Insert at capacity should cause allocation.
-        a.insert(item, 0);
-        assert!(a.capacity() > a.len());
-    }
-
-    #[test]
-    fn test_occupied_entry_key() {
-        let mut a = HashMap::new();
-        let key = "hello there";
-        let value = "value goes here";
-        assert!(a.is_empty());
-        a.insert(key.clone(), value.clone());
-        assert_eq!(a.len(), 1);
-        assert_eq!(a[key], value);
-
-        match a.entry(key.clone()) {
-            Vacant(_) => panic!(),
-            Occupied(e) => assert_eq!(key, *e.key()),
-        }
-        assert_eq!(a.len(), 1);
-        assert_eq!(a[key], value);
-    }
-
-    #[test]
-    fn test_vacant_entry_key() {
-        let mut a = HashMap::new();
-        let key = "hello there";
-        let value = "value goes here";
-
-        assert!(a.is_empty());
-        match a.entry(key.clone()) {
-            Occupied(_) => panic!(),
-            Vacant(e) => {
-                assert_eq!(key, *e.key());
-                e.insert(value.clone());
-            }
-        }
-        assert_eq!(a.len(), 1);
-        assert_eq!(a[key], value);
-    }
-
-    #[test]
-    fn test_retain() {
-        let mut map: HashMap<i32, i32> = (0..100).map(|x| (x, x * 10)).collect();
-
-        map.retain(|&k, _| k % 2 == 0);
-        assert_eq!(map.len(), 50);
-        assert_eq!(map[&2], 20);
-        assert_eq!(map[&4], 40);
-        assert_eq!(map[&6], 60);
-    }
-
-    #[test]
-    #[cfg(not(miri))] // FIXME: https://github.com/rust-lang/miri/issues/655
-    fn test_try_reserve() {
-        let mut empty_bytes: HashMap<u8, u8> = HashMap::new();
-
-        const MAX_USIZE: usize = usize::MAX;
-
-        if let Err(CapacityOverflow) = empty_bytes.try_reserve(MAX_USIZE) {
-        } else {
-            panic!("usize::MAX should trigger an overflow!");
-        }
-
-        if let Err(AllocErr) = empty_bytes.try_reserve(MAX_USIZE / 8) {
-        } else {
-            // This may succeed if there is enough free memory. Attempt to
-            // allocate a second hashmap to ensure the allocation will fail.
-            let mut empty_bytes2: HashMap<u8, u8> = HashMap::new();
-            if let Err(AllocErr) = empty_bytes2.try_reserve(MAX_USIZE / 8) {
-            } else {
-                panic!("usize::MAX / 8 should trigger an OOM!");
-            }
-        }
-    }
-
-    #[test]
-    fn test_raw_entry() {
-        use super::RawEntryMut::{Occupied, Vacant};
-
-        let xs = [(1i32, 10i32), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)];
-
-        let mut map: HashMap<_, _> = xs.iter().cloned().collect();
-
-        let compute_hash = |map: &HashMap<i32, i32>, k: i32| -> u64 {
-            use core::hash::{BuildHasher, Hash, Hasher};
-
-            let mut hasher = map.hasher().build_hasher();
-            k.hash(&mut hasher);
-            hasher.finish()
-        };
-
-        // Existing key (insert)
-        match map.raw_entry_mut().from_key(&1) {
-            Vacant(_) => unreachable!(),
-            Occupied(mut view) => {
-                assert_eq!(view.get(), &10);
-                assert_eq!(view.insert(100), 10);
-            }
-        }
-        let hash1 = compute_hash(&map, 1);
-        assert_eq!(map.raw_entry().from_key(&1).unwrap(), (&1, &100));
-        assert_eq!(
-            map.raw_entry().from_hash(hash1, |k| *k == 1).unwrap(),
-            (&1, &100)
-        );
-        assert_eq!(
-            map.raw_entry().from_key_hashed_nocheck(hash1, &1).unwrap(),
-            (&1, &100)
-        );
-        assert_eq!(map.len(), 6);
-
-        // Existing key (update)
-        match map.raw_entry_mut().from_key(&2) {
-            Vacant(_) => unreachable!(),
-            Occupied(mut view) => {
-                let v = view.get_mut();
-                let new_v = (*v) * 10;
-                *v = new_v;
-            }
-        }
-        let hash2 = compute_hash(&map, 2);
-        assert_eq!(map.raw_entry().from_key(&2).unwrap(), (&2, &200));
-        assert_eq!(
-            map.raw_entry().from_hash(hash2, |k| *k == 2).unwrap(),
-            (&2, &200)
-        );
-        assert_eq!(
-            map.raw_entry().from_key_hashed_nocheck(hash2, &2).unwrap(),
-            (&2, &200)
-        );
-        assert_eq!(map.len(), 6);
-
-        // Existing key (take)
-        let hash3 = compute_hash(&map, 3);
-        match map.raw_entry_mut().from_key_hashed_nocheck(hash3, &3) {
-            Vacant(_) => unreachable!(),
-            Occupied(view) => {
-                assert_eq!(view.remove_entry(), (3, 30));
-            }
-        }
-        assert_eq!(map.raw_entry().from_key(&3), None);
-        assert_eq!(map.raw_entry().from_hash(hash3, |k| *k == 3), None);
-        assert_eq!(map.raw_entry().from_key_hashed_nocheck(hash3, &3), None);
-        assert_eq!(map.len(), 5);
-
-        // Nonexistent key (insert)
-        match map.raw_entry_mut().from_key(&10) {
-            Occupied(_) => unreachable!(),
-            Vacant(view) => {
-                assert_eq!(view.insert(10, 1000), (&mut 10, &mut 1000));
-            }
-        }
-        assert_eq!(map.raw_entry().from_key(&10).unwrap(), (&10, &1000));
-        assert_eq!(map.len(), 6);
-
-        // Ensure all lookup methods produce equivalent results.
-        for k in 0..12 {
-            let hash = compute_hash(&map, k);
-            let v = map.get(&k).cloned();
-            let kv = v.as_ref().map(|v| (&k, v));
-
-            assert_eq!(map.raw_entry().from_key(&k), kv);
-            assert_eq!(map.raw_entry().from_hash(hash, |q| *q == k), kv);
-            assert_eq!(map.raw_entry().from_key_hashed_nocheck(hash, &k), kv);
-
-            match map.raw_entry_mut().from_key(&k) {
-                Occupied(mut o) => assert_eq!(Some(o.get_key_value()), kv),
-                Vacant(_) => assert_eq!(v, None),
-            }
-            match map.raw_entry_mut().from_key_hashed_nocheck(hash, &k) {
-                Occupied(mut o) => assert_eq!(Some(o.get_key_value()), kv),
-                Vacant(_) => assert_eq!(v, None),
-            }
-            match map.raw_entry_mut().from_hash(hash, |q| *q == k) {
-                Occupied(mut o) => assert_eq!(Some(o.get_key_value()), kv),
-                Vacant(_) => assert_eq!(v, None),
-            }
-        }
-    }
-
-    #[test]
-    fn test_key_without_hash_impl() {
-        #[derive(Debug)]
-        struct IntWrapper(u64);
-
-        let mut m: HashMap<IntWrapper, ()> = HashMap::new();
-        {
-            assert!(m.raw_entry().from_hash(0, |k| k.0 == 0).is_none());
-        }
-        {
-            let vacant_entry = match m.raw_entry_mut().from_hash(0, |k| k.0 == 0) {
-                RawEntryMut::Occupied(..) => panic!("Found entry for key 0"),
-                RawEntryMut::Vacant(e) => e,
-            };
-            vacant_entry.insert_with_hasher(0, IntWrapper(0), (), |k| k.0);
-        }
-        {
-            assert!(m.raw_entry().from_hash(0, |k| k.0 == 0).is_some());
-            assert!(m.raw_entry().from_hash(1, |k| k.0 == 1).is_none());
-            assert!(m.raw_entry().from_hash(2, |k| k.0 == 2).is_none());
-        }
-        {
-            let vacant_entry = match m.raw_entry_mut().from_hash(1, |k| k.0 == 1) {
-                RawEntryMut::Occupied(..) => panic!("Found entry for key 1"),
-                RawEntryMut::Vacant(e) => e,
-            };
-            vacant_entry.insert_with_hasher(1, IntWrapper(1), (), |k| k.0);
-        }
-        {
-            assert!(m.raw_entry().from_hash(0, |k| k.0 == 0).is_some());
-            assert!(m.raw_entry().from_hash(1, |k| k.0 == 1).is_some());
-            assert!(m.raw_entry().from_hash(2, |k| k.0 == 2).is_none());
-        }
-        {
-            let occupied_entry = match m.raw_entry_mut().from_hash(0, |k| k.0 == 0) {
-                RawEntryMut::Occupied(e) => e,
-                RawEntryMut::Vacant(..) => panic!("Couldn't find entry for key 0"),
-            };
-            occupied_entry.remove();
-        }
-        assert!(m.raw_entry().from_hash(0, |k| k.0 == 0).is_none());
-        assert!(m.raw_entry().from_hash(1, |k| k.0 == 1).is_some());
-        assert!(m.raw_entry().from_hash(2, |k| k.0 == 2).is_none());
-    }
-}
diff --git a/third_party/rust_crates/vendor/hashbrown/src/raw/bitmask.rs b/third_party/rust_crates/vendor/hashbrown/src/raw/bitmask.rs
deleted file mode 100644
index 6e61d43..0000000
--- a/third_party/rust_crates/vendor/hashbrown/src/raw/bitmask.rs
+++ /dev/null
@@ -1,108 +0,0 @@
-use super::imp::{BitMaskWord, BITMASK_MASK, BITMASK_STRIDE};
-#[cfg(feature = "nightly")]
-use core::intrinsics;
-
-/// A bit mask which contains the result of a `Match` operation on a `Group` and
-/// allows iterating through them.
-///
-/// The bit mask is arranged so that low-order bits represent lower memory
-/// addresses for group match results.
-///
-/// For implementation reasons, the bits in the set may be sparsely packed, so
-/// that there is only one bit-per-byte used (the high bit, 7). If this is the
-/// case, `BITMASK_STRIDE` will be 8 to indicate a divide-by-8 should be
-/// performed on counts/indices to normalize this difference. `BITMASK_MASK` is
-/// similarly a mask of all the actually-used bits.
-#[derive(Copy, Clone)]
-pub struct BitMask(pub BitMaskWord);
-
-#[allow(clippy::use_self)]
-impl BitMask {
-    /// Returns a new `BitMask` with all bits inverted.
-    #[inline]
-    #[must_use]
-    pub fn invert(self) -> Self {
-        BitMask(self.0 ^ BITMASK_MASK)
-    }
-
-    /// Returns a new `BitMask` with the lowest bit removed.
-    #[inline]
-    #[must_use]
-    pub fn remove_lowest_bit(self) -> Self {
-        BitMask(self.0 & (self.0 - 1))
-    }
-    /// Returns whether the `BitMask` has at least one set bit.
-    #[inline]
-    pub fn any_bit_set(self) -> bool {
-        self.0 != 0
-    }
-
-    /// Returns the first set bit in the `BitMask`, if there is one.
-    #[inline]
-    pub fn lowest_set_bit(self) -> Option<usize> {
-        if self.0 == 0 {
-            None
-        } else {
-            Some(unsafe { self.lowest_set_bit_nonzero() })
-        }
-    }
-
-    /// Returns the first set bit in the `BitMask`, if there is one. The
-    /// bitmask must not be empty.
-    #[inline]
-    #[cfg(feature = "nightly")]
-    pub unsafe fn lowest_set_bit_nonzero(self) -> usize {
-        intrinsics::cttz_nonzero(self.0) as usize / BITMASK_STRIDE
-    }
-    #[inline]
-    #[cfg(not(feature = "nightly"))]
-    pub unsafe fn lowest_set_bit_nonzero(self) -> usize {
-        self.trailing_zeros()
-    }
-
-    /// Returns the number of trailing zeroes in the `BitMask`.
-    #[inline]
-    pub fn trailing_zeros(self) -> usize {
-        // ARM doesn't have a trailing_zeroes instruction, and instead uses
-        // reverse_bits (RBIT) + leading_zeroes (CLZ). However older ARM
-        // versions (pre-ARMv7) don't have RBIT and need to emulate it
-        // instead. Since we only have 1 bit set in each byte on ARM, we can
-        // use swap_bytes (REV) + leading_zeroes instead.
-        if cfg!(target_arch = "arm") && BITMASK_STRIDE % 8 == 0 {
-            self.0.swap_bytes().leading_zeros() as usize / BITMASK_STRIDE
-        } else {
-            self.0.trailing_zeros() as usize / BITMASK_STRIDE
-        }
-    }
-
-    /// Returns the number of leading zeroes in the `BitMask`.
-    #[inline]
-    pub fn leading_zeros(self) -> usize {
-        self.0.leading_zeros() as usize / BITMASK_STRIDE
-    }
-}
-
-impl IntoIterator for BitMask {
-    type Item = usize;
-    type IntoIter = BitMaskIter;
-
-    #[inline]
-    fn into_iter(self) -> BitMaskIter {
-        BitMaskIter(self)
-    }
-}
-
-/// Iterator over the contents of a `BitMask`, returning the indicies of set
-/// bits.
-pub struct BitMaskIter(BitMask);
-
-impl Iterator for BitMaskIter {
-    type Item = usize;
-
-    #[inline]
-    fn next(&mut self) -> Option<usize> {
-        let bit = self.0.lowest_set_bit()?;
-        self.0 = self.0.remove_lowest_bit();
-        Some(bit)
-    }
-}
diff --git a/third_party/rust_crates/vendor/hashbrown/src/raw/generic.rs b/third_party/rust_crates/vendor/hashbrown/src/raw/generic.rs
deleted file mode 100644
index 2dee2ea5..0000000
--- a/third_party/rust_crates/vendor/hashbrown/src/raw/generic.rs
+++ /dev/null
@@ -1,157 +0,0 @@
-use super::bitmask::BitMask;
-use super::EMPTY;
-use core::{mem, ptr};
-
-// Use the native word size as the group size. Using a 64-bit group size on
-// a 32-bit architecture will just end up being more expensive because
-// shifts and multiplies will need to be emulated.
-#[cfg(any(
-    target_pointer_width = "64",
-    target_arch = "aarch64",
-    target_arch = "x86_64",
-))]
-type GroupWord = u64;
-#[cfg(all(
-    target_pointer_width = "32",
-    not(target_arch = "aarch64"),
-    not(target_arch = "x86_64"),
-))]
-type GroupWord = u32;
-
-pub type BitMaskWord = GroupWord;
-pub const BITMASK_STRIDE: usize = 8;
-// We only care about the highest bit of each byte for the mask.
-#[allow(
-    clippy::cast_possible_truncation,
-    clippy::unnecessary_cast,
-)]
-pub const BITMASK_MASK: BitMaskWord = 0x8080_8080_8080_8080_u64 as GroupWord;
-
-/// Helper function to replicate a byte across a `GroupWord`.
-#[inline]
-fn repeat(byte: u8) -> GroupWord {
-    let repeat = GroupWord::from(byte);
-    let repeat = repeat | repeat.wrapping_shl(8);
-    let repeat = repeat | repeat.wrapping_shl(16);
-    // This last line is a no-op with a 32-bit GroupWord
-    repeat | repeat.wrapping_shl(32)
-}
-
-/// Abstraction over a group of control bytes which can be scanned in
-/// parallel.
-///
-/// This implementation uses a word-sized integer.
-#[derive(Copy, Clone)]
-pub struct Group(GroupWord);
-
-// We perform all operations in the native endianess, and convert to
-// little-endian just before creating a BitMask. The can potentially
-// enable the compiler to eliminate unnecessary byte swaps if we are
-// only checking whether a BitMask is empty.
-#[allow(clippy::use_self)]
-impl Group {
-    /// Number of bytes in the group.
-    pub const WIDTH: usize = mem::size_of::<Self>();
-
-    /// Returns a full group of empty bytes, suitable for use as the initial
-    /// value for an empty hash table.
-    ///
-    /// This is guaranteed to be aligned to the group size.
-    #[inline]
-    pub fn static_empty() -> &'static [u8] {
-        union AlignedBytes {
-            _align: Group,
-            bytes: [u8; Group::WIDTH],
-        };
-        const ALIGNED_BYTES: AlignedBytes = AlignedBytes {
-            bytes: [EMPTY; Group::WIDTH],
-        };
-        unsafe { &ALIGNED_BYTES.bytes }
-    }
-
-    /// Loads a group of bytes starting at the given address.
-    #[inline]
-    #[allow(clippy::cast_ptr_alignment)] // unaligned load
-    pub unsafe fn load(ptr: *const u8) -> Self {
-        Group(ptr::read_unaligned(ptr as *const _))
-    }
-
-    /// Loads a group of bytes starting at the given address, which must be
-    /// aligned to `mem::align_of::<Group>()`.
-    #[inline]
-    #[allow(clippy::cast_ptr_alignment)]
-    pub unsafe fn load_aligned(ptr: *const u8) -> Self {
-        // FIXME: use align_offset once it stabilizes
-        debug_assert_eq!(ptr as usize & (mem::align_of::<Self>() - 1), 0);
-        Group(ptr::read(ptr as *const _))
-    }
-
-    /// Stores the group of bytes to the given address, which must be
-    /// aligned to `mem::align_of::<Group>()`.
-    #[inline]
-    #[allow(clippy::cast_ptr_alignment)]
-    pub unsafe fn store_aligned(self, ptr: *mut u8) {
-        // FIXME: use align_offset once it stabilizes
-        debug_assert_eq!(ptr as usize & (mem::align_of::<Self>() - 1), 0);
-        ptr::write(ptr as *mut _, self.0);
-    }
-
-    /// Returns a `BitMask` indicating all bytes in the group which *may*
-    /// have the given value.
-    ///
-    /// This function may return a false positive in certain cases where
-    /// the byte in the group differs from the searched value only in its
-    /// lowest bit. This is fine because:
-    /// - This never happens for `EMPTY` and `DELETED`, only full entries.
-    /// - The check for key equality will catch these.
-    /// - This only happens if there is at least 1 true match.
-    /// - The chance of this happening is very low (< 1% chance per byte).
-    #[inline]
-    pub fn match_byte(self, byte: u8) -> BitMask {
-        // This algorithm is derived from
-        // http://graphics.stanford.edu/~seander/bithacks.html##ValueInWord
-        let cmp = self.0 ^ repeat(byte);
-        BitMask((cmp.wrapping_sub(repeat(0x01)) & !cmp & repeat(0x80)).to_le())
-    }
-
-    /// Returns a `BitMask` indicating all bytes in the group which are
-    /// `EMPTY`.
-    #[inline]
-    pub fn match_empty(self) -> BitMask {
-        // If the high bit is set, then the byte must be either:
-        // 1111_1111 (EMPTY) or 1000_0000 (DELETED).
-        // So we can just check if the top two bits are 1 by ANDing them.
-        BitMask((self.0 & (self.0 << 1) & repeat(0x80)).to_le())
-    }
-
-    /// Returns a `BitMask` indicating all bytes in the group which are
-    /// `EMPTY` or `DELETED`.
-    #[inline]
-    pub fn match_empty_or_deleted(self) -> BitMask {
-        // A byte is EMPTY or DELETED iff the high bit is set
-        BitMask((self.0 & repeat(0x80)).to_le())
-    }
-
-    /// Returns a `BitMask` indicating all bytes in the group which are full.
-    #[inline]
-    pub fn match_full(&self) -> BitMask {
-        self.match_empty_or_deleted().invert()
-    }
-
-    /// Performs the following transformation on all bytes in the group:
-    /// - `EMPTY => EMPTY`
-    /// - `DELETED => EMPTY`
-    /// - `FULL => DELETED`
-    #[inline]
-    pub fn convert_special_to_empty_and_full_to_deleted(self) -> Self {
-        // Map high_bit = 1 (EMPTY or DELETED) to 1111_1111
-        // and high_bit = 0 (FULL) to 1000_0000
-        //
-        // Here's this logic expanded to concrete values:
-        //   let full = 1000_0000 (true) or 0000_0000 (false)
-        //   !1000_0000 + 1 = 0111_1111 + 1 = 1000_0000 (no carry)
-        //   !0000_0000 + 0 = 1111_1111 + 0 = 1111_1111 (no carry)
-        let full = !self.0 & repeat(0x80);
-        Group(!full + (full >> 7))
-    }
-}
diff --git a/third_party/rust_crates/vendor/hashbrown/src/raw/mod.rs b/third_party/rust_crates/vendor/hashbrown/src/raw/mod.rs
deleted file mode 100644
index 2dec098..0000000
--- a/third_party/rust_crates/vendor/hashbrown/src/raw/mod.rs
+++ /dev/null
@@ -1,1373 +0,0 @@
-use crate::alloc::alloc::{alloc, dealloc, handle_alloc_error};
-use crate::scopeguard::guard;
-use crate::CollectionAllocErr;
-use core::alloc::Layout;
-use core::hint;
-use core::iter::FusedIterator;
-use core::marker::PhantomData;
-use core::mem;
-use core::mem::ManuallyDrop;
-use core::ptr::NonNull;
-
-cfg_if! {
-    // Use the SSE2 implementation if possible: it allows us to scan 16 buckets
-    // at once instead of 8. We don't bother with AVX since it would require
-    // runtime dispatch and wouldn't gain us much anyways: the probability of
-    // finding a match drops off drastically after the first few buckets.
-    //
-    // I attempted an implementation on ARM using NEON instructions, but it
-    // turns out that most NEON instructions have multi-cycle latency, which in
-    // the end outweighs any gains over the generic implementation.
-    if #[cfg(all(
-        target_feature = "sse2",
-        any(target_arch = "x86", target_arch = "x86_64"),
-        not(miri)
-    ))] {
-        #[path = "sse2.rs"]
-        mod imp;
-    } else {
-        #[path = "generic.rs"]
-        mod imp;
-    }
-}
-
-mod bitmask;
-
-use self::bitmask::BitMask;
-use self::imp::Group;
-
-// Branch prediction hint. This is currently only available on nightly but it
-// consistently improves performance by 10-15%.
-#[cfg(feature = "nightly")]
-use core::intrinsics::{likely, unlikely};
-#[cfg(not(feature = "nightly"))]
-#[inline]
-fn likely(b: bool) -> bool {
-    b
-}
-#[cfg(not(feature = "nightly"))]
-#[inline]
-fn unlikely(b: bool) -> bool {
-    b
-}
-
-#[cfg(feature = "nightly")]
-#[inline]
-unsafe fn offset_from<T>(to: *const T, from: *const T) -> usize {
-    to.offset_from(from) as usize
-}
-#[cfg(not(feature = "nightly"))]
-#[inline]
-unsafe fn offset_from<T>(to: *const T, from: *const T) -> usize {
-    (to as usize - from as usize) / mem::size_of::<T>()
-}
-
-/// Whether memory allocation errors should return an error or abort.
-#[derive(Copy, Clone)]
-enum Fallibility {
-    Fallible,
-    Infallible,
-}
-
-impl Fallibility {
-    /// Error to return on capacity overflow.
-    #[inline]
-    fn capacity_overflow(self) -> CollectionAllocErr {
-        match self {
-            Fallibility::Fallible => CollectionAllocErr::CapacityOverflow,
-            Fallibility::Infallible => panic!("Hash table capacity overflow"),
-        }
-    }
-
-    /// Error to return on allocation error.
-    #[inline]
-    fn alloc_err(self, layout: Layout) -> CollectionAllocErr {
-        match self {
-            Fallibility::Fallible => CollectionAllocErr::AllocErr,
-            Fallibility::Infallible => handle_alloc_error(layout),
-        }
-    }
-}
-
-/// Control byte value for an empty bucket.
-const EMPTY: u8 = 0b1111_1111;
-
-/// Control byte value for a deleted bucket.
-const DELETED: u8 = 0b1000_0000;
-
-/// Checks whether a control byte represents a full bucket (top bit is clear).
-#[inline]
-fn is_full(ctrl: u8) -> bool {
-    ctrl & 0x80 == 0
-}
-
-/// Checks whether a control byte represents a special value (top bit is set).
-#[inline]
-fn is_special(ctrl: u8) -> bool {
-    ctrl & 0x80 != 0
-}
-
-/// Checks whether a special control value is EMPTY (just check 1 bit).
-#[inline]
-fn special_is_empty(ctrl: u8) -> bool {
-    debug_assert!(is_special(ctrl));
-    ctrl & 0x01 != 0
-}
-
-/// Primary hash function, used to select the initial bucket to probe from.
-#[inline]
-#[allow(clippy::cast_possible_truncation)]
-fn h1(hash: u64) -> usize {
-    // On 32-bit platforms we simply ignore the higher hash bits.
-    hash as usize
-}
-
-/// Secondary hash function, saved in the low 7 bits of the control byte.
-#[inline]
-#[allow(clippy::cast_possible_truncation)]
-fn h2(hash: u64) -> u8 {
-    // Grab the top 7 bits of the hash. While the hash is normally a full 64-bit
-    // value, some hash functions (such as FxHash) produce a usize result
-    // instead, which means that the top 32 bits are 0 on 32-bit platforms.
-    let hash_len = usize::min(mem::size_of::<usize>(), mem::size_of::<u64>());
-    let top7 = hash >> (hash_len * 8 - 7);
-    (top7 & 0x7f) as u8 // truncation
-}
-
-/// Probe sequence based on triangular numbers, which is guaranteed (since our
-/// table size is a power of two) to visit every group of elements exactly once.
-///
-/// A triangular probe has us jump by 1 more group every time. So first we
-/// jump by 1 group (meaning we just continue our linear scan), then 2 groups
-/// (skipping over 1 group), then 3 groups (skipping over 2 groups), and so on.
-///
-/// Proof that the probe will visit every group in the table:
-/// <https://fgiesen.wordpress.com/2015/02/22/triangular-numbers-mod-2n/>
-struct ProbeSeq {
-    bucket_mask: usize,
-    pos: usize,
-    stride: usize,
-}
-
-impl Iterator for ProbeSeq {
-    type Item = usize;
-
-    #[inline]
-    fn next(&mut self) -> Option<usize> {
-        // We should have found an empty bucket by now and ended the probe.
-        debug_assert!(
-            self.stride <= self.bucket_mask,
-            "Went past end of probe sequence"
-        );
-
-        let result = self.pos;
-        self.stride += Group::WIDTH;
-        self.pos += self.stride;
-        self.pos &= self.bucket_mask;
-        Some(result)
-    }
-}
-
-/// Returns the number of buckets needed to hold the given number of items,
-/// taking the maximum load factor into account.
-///
-/// Returns `None` if an overflow occurs.
-#[inline]
-fn capacity_to_buckets(cap: usize) -> Option<usize> {
-    let adjusted_cap = if cap < 8 {
-        // Need at least 1 free bucket on small tables
-        cap + 1
-    } else {
-        // Otherwise require 1/8 buckets to be empty (87.5% load)
-        //
-        // Be careful when modifying this, calculate_layout relies on the
-        // overflow check here.
-        cap.checked_mul(8)? / 7
-    };
-
-    // Any overflows will have been caught by the checked_mul. Also, any
-    // rounding errors from the division above will be cleaned up by
-    // next_power_of_two (which can't overflow because of the previous divison).
-    Some(adjusted_cap.next_power_of_two())
-}
-
-/// Returns the maximum effective capacity for the given bucket mask, taking
-/// the maximum load factor into account.
-#[inline]
-fn bucket_mask_to_capacity(bucket_mask: usize) -> usize {
-    if bucket_mask < 8 {
-        // For tables with 1/2/4/8 buckets, we always reserve one empty slot.
-        // Keep in mind that the bucket mask is one less than the bucket count.
-        bucket_mask
-    } else {
-        // For larger tables we reserve 12.5% of the slots as empty.
-        ((bucket_mask + 1) / 8) * 7
-    }
-}
-
-// Returns a Layout which describes the allocation required for a hash table,
-// and the offset of the buckets in the allocation.
-///
-/// Returns `None` if an overflow occurs.
-#[inline]
-#[cfg(feature = "nightly")]
-fn calculate_layout<T>(buckets: usize) -> Option<(Layout, usize)> {
-    debug_assert!(buckets.is_power_of_two());
-
-    // Array of buckets
-    let data = Layout::array::<T>(buckets).ok()?;
-
-    // Array of control bytes. This must be aligned to the group size.
-    //
-    // We add `Group::WIDTH` control bytes at the end of the array which
-    // replicate the bytes at the start of the array and thus avoids the need to
-    // perform bounds-checking while probing.
-    //
-    // There is no possible overflow here since buckets is a power of two and
-    // Group::WIDTH is a small number.
-    let ctrl = unsafe { Layout::from_size_align_unchecked(buckets + Group::WIDTH, Group::WIDTH) };
-
-    ctrl.extend(data).ok()
-}
-
-// Returns a Layout which describes the allocation required for a hash table,
-// and the offset of the buckets in the allocation.
-#[inline]
-#[cfg(not(feature = "nightly"))]
-fn calculate_layout<T>(buckets: usize) -> Option<(Layout, usize)> {
-    debug_assert!(buckets.is_power_of_two());
-
-    // Manual layout calculation since Layout methods are not yet stable.
-    let data_align = usize::max(mem::align_of::<T>(), Group::WIDTH);
-    let data_offset = (buckets + Group::WIDTH).checked_add(data_align - 1)? & !(data_align - 1);
-    let len = data_offset.checked_add(mem::size_of::<T>().checked_mul(buckets)?)?;
-
-    Some((
-        unsafe { Layout::from_size_align_unchecked(len, data_align) },
-        data_offset,
-    ))
-}
-
-/// A reference to a hash table bucket containing a `T`.
-///
-/// This is usually just a pointer to the element itself. However if the element
-/// is a ZST, then we instead track the index of the element in the table so
-/// that `erase` works properly.
-pub struct Bucket<T> {
-    // Using *const for variance
-    ptr: *const T,
-}
-
-// This Send impl is needed for rayon support. This is safe since Bucket is
-// never exposed in a public API.
-unsafe impl<T> Send for Bucket<T> {}
-
-impl<T> Clone for Bucket<T> {
-    #[inline]
-    fn clone(&self) -> Self {
-        Self { ptr: self.ptr }
-    }
-}
-
-impl<T> Bucket<T> {
-    #[inline]
-    unsafe fn from_base_index(base: *const T, index: usize) -> Self {
-        let ptr = if mem::size_of::<T>() == 0 {
-            index as *const T
-        } else {
-            base.add(index)
-        };
-        Self { ptr }
-    }
-    #[inline]
-    pub unsafe fn as_ptr(&self) -> *mut T {
-        if mem::size_of::<T>() == 0 {
-            // Just return an arbitrary ZST pointer which is properly aligned
-            mem::align_of::<T>() as *mut T
-        } else {
-            self.ptr as *mut T
-        }
-    }
-    #[inline]
-    unsafe fn add(&self, offset: usize) -> Self {
-        let ptr = if mem::size_of::<T>() == 0 {
-            (self.ptr as usize + offset) as *const T
-        } else {
-            self.ptr.add(offset)
-        };
-        Self { ptr }
-    }
-    #[inline]
-    pub unsafe fn drop(&self) {
-        self.as_ptr().drop_in_place();
-    }
-    #[inline]
-    pub unsafe fn read(&self) -> T {
-        self.as_ptr().read()
-    }
-    #[inline]
-    pub unsafe fn write(&self, val: T) {
-        self.as_ptr().write(val);
-    }
-    #[inline]
-    pub unsafe fn as_ref<'a>(&self) -> &'a T {
-        &*self.as_ptr()
-    }
-    #[inline]
-    pub unsafe fn as_mut<'a>(&self) -> &'a mut T {
-        &mut *self.as_ptr()
-    }
-    #[inline]
-    pub unsafe fn copy_from_nonoverlapping(&self, other: &Self) {
-        self.as_ptr().copy_from_nonoverlapping(other.as_ptr(), 1);
-    }
-}
-
-/// A raw hash table with an unsafe API.
-pub struct RawTable<T> {
-    // Mask to get an index from a hash value. The value is one less than the
-    // number of buckets in the table.
-    bucket_mask: usize,
-
-    // Pointer to the array of control bytes
-    ctrl: NonNull<u8>,
-
-    // Pointer to the array of buckets
-    data: NonNull<T>,
-
-    // Number of elements that can be inserted before we need to grow the table
-    growth_left: usize,
-
-    // Number of elements in the table, only really used by len()
-    items: usize,
-
-    // Tell dropck that we own instances of T.
-    marker: PhantomData<T>,
-}
-
-impl<T> RawTable<T> {
-    /// Creates a new empty hash table without allocating any memory.
-    ///
-    /// In effect this returns a table with exactly 1 bucket. However we can
-    /// leave the data pointer dangling since that bucket is never written to
-    /// due to our load factor forcing us to always have at least 1 free bucket.
-    #[inline]
-    pub fn new() -> Self {
-        Self {
-            data: NonNull::dangling(),
-            ctrl: NonNull::from(&Group::static_empty()[0]),
-            bucket_mask: 0,
-            items: 0,
-            growth_left: 0,
-            marker: PhantomData,
-        }
-    }
-
-    /// Allocates a new hash table with the given number of buckets.
-    ///
-    /// The control bytes are left uninitialized.
-    #[inline]
-    unsafe fn new_uninitialized(
-        buckets: usize,
-        fallability: Fallibility,
-    ) -> Result<Self, CollectionAllocErr> {
-        let (layout, data_offset) =
-            calculate_layout::<T>(buckets).ok_or_else(|| fallability.capacity_overflow())?;
-        let ctrl = NonNull::new(alloc(layout)).ok_or_else(|| fallability.alloc_err(layout))?;
-        let data = NonNull::new_unchecked(ctrl.as_ptr().add(data_offset) as *mut T);
-        Ok(Self {
-            data,
-            ctrl,
-            bucket_mask: buckets - 1,
-            items: 0,
-            growth_left: bucket_mask_to_capacity(buckets - 1),
-            marker: PhantomData,
-        })
-    }
-
-    /// Attempts to allocate a new hash table with at least enough capacity
-    /// for inserting the given number of elements without reallocating.
-    fn try_with_capacity(
-        capacity: usize,
-        fallability: Fallibility,
-    ) -> Result<Self, CollectionAllocErr> {
-        if capacity == 0 {
-            Ok(Self::new())
-        } else {
-            unsafe {
-                let buckets =
-                    capacity_to_buckets(capacity).ok_or_else(|| fallability.capacity_overflow())?;
-                let result = Self::new_uninitialized(buckets, fallability)?;
-                result.ctrl(0).write_bytes(EMPTY, result.num_ctrl_bytes());
-
-                Ok(result)
-            }
-        }
-    }
-
-    /// Allocates a new hash table with at least enough capacity for inserting
-    /// the given number of elements without reallocating.
-    pub fn with_capacity(capacity: usize) -> Self {
-        Self::try_with_capacity(capacity, Fallibility::Infallible)
-            .unwrap_or_else(|_| unsafe { hint::unreachable_unchecked() })
-    }
-
-    /// Deallocates the table without dropping any entries.
-    #[inline]
-    unsafe fn free_buckets(&mut self) {
-        let (layout, _) =
-            calculate_layout::<T>(self.buckets()).unwrap_or_else(|| hint::unreachable_unchecked());
-        dealloc(self.ctrl.as_ptr(), layout);
-    }
-
-    /// Returns the index of a bucket from a `Bucket`.
-    #[inline]
-    unsafe fn bucket_index(&self, bucket: &Bucket<T>) -> usize {
-        if mem::size_of::<T>() == 0 {
-            bucket.ptr as usize
-        } else {
-            offset_from(bucket.ptr, self.data.as_ptr())
-        }
-    }
-
-    /// Returns a pointer to a control byte.
-    #[inline]
-    unsafe fn ctrl(&self, index: usize) -> *mut u8 {
-        debug_assert!(index < self.num_ctrl_bytes());
-        self.ctrl.as_ptr().add(index)
-    }
-
-    /// Returns a pointer to an element in the table.
-    #[inline]
-    pub unsafe fn bucket(&self, index: usize) -> Bucket<T> {
-        debug_assert_ne!(self.bucket_mask, 0);
-        debug_assert!(index < self.buckets());
-        Bucket::from_base_index(self.data.as_ptr(), index)
-    }
-
-    /// Erases an element from the table without dropping it.
-    #[inline]
-    pub unsafe fn erase_no_drop(&mut self, item: &Bucket<T>) {
-        let index = self.bucket_index(item);
-        let index_before = index.wrapping_sub(Group::WIDTH) & self.bucket_mask;
-        let empty_before = Group::load(self.ctrl(index_before)).match_empty();
-        let empty_after = Group::load(self.ctrl(index)).match_empty();
-
-        // If we are inside a continuous block of Group::WIDTH full or deleted
-        // cells then a probe window may have seen a full block when trying to
-        // insert. We therefore need to keep that block non-empty so that
-        // lookups will continue searching to the next probe window.
-        //
-        // Note that in this context `leading_zeros` refers to the bytes at the
-        // end of a group, while `trailing_zeros` refers to the bytes at the
-        // begining of a group.
-        let ctrl = if empty_before.leading_zeros() + empty_after.trailing_zeros() >= Group::WIDTH {
-            DELETED
-        } else {
-            self.growth_left += 1;
-            EMPTY
-        };
-        self.set_ctrl(index, ctrl);
-        self.items -= 1;
-    }
-
-    /// Returns an iterator for a probe sequence on the table.
-    ///
-    /// This iterator never terminates, but is guaranteed to visit each bucket
-    /// group exactly once. The loop using `probe_seq` must terminate upon
-    /// reaching a group containing an empty bucket.
-    #[inline]
-    fn probe_seq(&self, hash: u64) -> ProbeSeq {
-        ProbeSeq {
-            bucket_mask: self.bucket_mask,
-            pos: h1(hash) & self.bucket_mask,
-            stride: 0,
-        }
-    }
-
-    /// Sets a control byte, and possibly also the replicated control byte at
-    /// the end of the array.
-    #[inline]
-    unsafe fn set_ctrl(&self, index: usize, ctrl: u8) {
-        // Replicate the first Group::WIDTH control bytes at the end of
-        // the array without using a branch:
-        // - If index >= Group::WIDTH then index == index2.
-        // - Otherwise index2 == self.bucket_mask + 1 + index.
-        //
-        // The very last replicated control byte is never actually read because
-        // we mask the initial index for unaligned loads, but we write it
-        // anyways because it makes the set_ctrl implementation simpler.
-        //
-        // If there are fewer buckets than Group::WIDTH then this code will
-        // replicate the buckets at the end of the trailing group. For example
-        // with 2 buckets and a group size of 4, the control bytes will look
-        // like this:
-        //
-        //     Real    |             Replicated
-        // ---------------------------------------------
-        // | [A] | [B] | [EMPTY] | [EMPTY] | [A] | [B] |
-        // ---------------------------------------------
-        let index2 = ((index.wrapping_sub(Group::WIDTH)) & self.bucket_mask) + Group::WIDTH;
-
-        *self.ctrl(index) = ctrl;
-        *self.ctrl(index2) = ctrl;
-    }
-
-    /// Searches for an empty or deleted bucket which is suitable for inserting
-    /// a new element.
-    ///
-    /// There must be at least 1 empty bucket in the table.
-    #[inline]
-    fn find_insert_slot(&self, hash: u64) -> usize {
-        for pos in self.probe_seq(hash) {
-            unsafe {
-                let group = Group::load(self.ctrl(pos));
-                if let Some(bit) = group.match_empty_or_deleted().lowest_set_bit() {
-                    let result = (pos + bit) & self.bucket_mask;
-
-                    // In tables smaller than the group width, trailing control
-                    // bytes outside the range of the table are filled with
-                    // EMPTY entries. These will unfortunately trigger a
-                    // match, but once masked may point to a full bucket that
-                    // is already occupied. We detect this situation here and
-                    // perform a second scan starting at the begining of the
-                    // table. This second scan is guaranteed to find an empty
-                    // slot (due to the load factor) before hitting the trailing
-                    // control bytes (containing EMPTY).
-                    if unlikely(is_full(*self.ctrl(result))) {
-                        debug_assert!(self.bucket_mask < Group::WIDTH);
-                        debug_assert_ne!(pos, 0);
-                        return Group::load_aligned(self.ctrl(0))
-                            .match_empty_or_deleted()
-                            .lowest_set_bit_nonzero();
-                    } else {
-                        return result;
-                    }
-                }
-            }
-        }
-
-        // probe_seq never returns.
-        unreachable!();
-    }
-
-    /// Marks all table buckets as empty without dropping their contents.
-    #[inline]
-    pub fn clear_no_drop(&mut self) {
-        if !self.is_empty_singleton() {
-            unsafe {
-                self.ctrl(0).write_bytes(EMPTY, self.num_ctrl_bytes());
-            }
-        }
-        self.items = 0;
-        self.growth_left = bucket_mask_to_capacity(self.bucket_mask);
-    }
-
-    /// Removes all elements from the table without freeing the backing memory.
-    #[inline]
-    pub fn clear(&mut self) {
-        // Ensure that the table is reset even if one of the drops panic
-        let self_ = guard(self, |self_| self_.clear_no_drop());
-
-        if mem::needs_drop::<T>() {
-            unsafe {
-                for item in self_.iter() {
-                    item.drop();
-                }
-            }
-        }
-    }
-
-    /// Shrinks the table to fit `max(self.len(), min_size)` elements.
-    #[inline]
-    pub fn shrink_to(&mut self, min_size: usize, hasher: impl Fn(&T) -> u64) {
-        // Calculate the minimal number of elements that we need to reserve
-        // space for.
-        let min_size = usize::max(self.items, min_size);
-        if min_size == 0 {
-            *self = Self::new();
-            return;
-        }
-
-        // Calculate the number of buckets that we need for this number of
-        // elements. If the calculation overflows then the requested bucket
-        // count must be larger than what we have right and nothing needs to be
-        // done.
-        let min_buckets = match capacity_to_buckets(min_size) {
-            Some(buckets) => buckets,
-            None => return,
-        };
-
-        // If we have more buckets than we need, shrink the table.
-        if min_buckets != self.buckets() {
-            debug_assert!(min_buckets < self.buckets());
-
-            // Fast path if the table is empty
-            if self.items == 0 {
-                *self = Self::with_capacity(min_size)
-            } else {
-                self.resize(min_size, hasher, Fallibility::Infallible)
-                    .unwrap_or_else(|_| unsafe { hint::unreachable_unchecked() });
-            }
-        }
-    }
-
-    /// Ensures that at least `additional` items can be inserted into the table
-    /// without reallocation.
-    #[inline]
-    pub fn reserve(&mut self, additional: usize, hasher: impl Fn(&T) -> u64) {
-        if additional > self.growth_left {
-            self.reserve_rehash(additional, hasher, Fallibility::Infallible)
-                .unwrap_or_else(|_| unsafe { hint::unreachable_unchecked() });
-        }
-    }
-
-    /// Tries to ensure that at least `additional` items can be inserted into
-    /// the table without reallocation.
-    #[inline]
-    pub fn try_reserve(
-        &mut self,
-        additional: usize,
-        hasher: impl Fn(&T) -> u64,
-    ) -> Result<(), CollectionAllocErr> {
-        if additional > self.growth_left {
-            self.reserve_rehash(additional, hasher, Fallibility::Fallible)
-        } else {
-            Ok(())
-        }
-    }
-
-    /// Out-of-line slow path for `reserve` and `try_reserve`.
-    #[cold]
-    #[inline(never)]
-    fn reserve_rehash(
-        &mut self,
-        additional: usize,
-        hasher: impl Fn(&T) -> u64,
-        fallability: Fallibility,
-    ) -> Result<(), CollectionAllocErr> {
-        let new_items = self
-            .items
-            .checked_add(additional)
-            .ok_or_else(|| fallability.capacity_overflow())?;
-
-        // Rehash in-place without re-allocating if we have plenty of spare
-        // capacity that is locked up due to DELETED entries.
-        if new_items < bucket_mask_to_capacity(self.bucket_mask) / 2 {
-            self.rehash_in_place(hasher);
-            Ok(())
-        } else {
-            self.resize(new_items, hasher, fallability)
-        }
-    }
-
-    /// Rehashes the contents of the table in place (i.e. without changing the
-    /// allocation).
-    ///
-    /// If `hasher` panics then some the table's contents may be lost.
-    fn rehash_in_place(&mut self, hasher: impl Fn(&T) -> u64) {
-        unsafe {
-            // Bulk convert all full control bytes to DELETED, and all DELETED
-            // control bytes to EMPTY. This effectively frees up all buckets
-            // containing a DELETED entry.
-            for i in (0..self.buckets()).step_by(Group::WIDTH) {
-                let group = Group::load_aligned(self.ctrl(i));
-                let group = group.convert_special_to_empty_and_full_to_deleted();
-                group.store_aligned(self.ctrl(i));
-            }
-
-            // Fix up the trailing control bytes. See the comments in set_ctrl
-            // for the handling of tables smaller than the group width.
-            if self.buckets() < Group::WIDTH {
-                self.ctrl(0)
-                    .copy_to(self.ctrl(Group::WIDTH), self.buckets());
-            } else {
-                self.ctrl(0)
-                    .copy_to(self.ctrl(self.buckets()), Group::WIDTH);
-            }
-
-            // If the hash function panics then properly clean up any elements
-            // that we haven't rehashed yet. We unfortunately can't preserve the
-            // element since we lost their hash and have no way of recovering it
-            // without risking another panic.
-            let mut guard = guard(self, |self_| {
-                if mem::needs_drop::<T>() {
-                    for i in 0..self_.buckets() {
-                        if *self_.ctrl(i) == DELETED {
-                            self_.set_ctrl(i, EMPTY);
-                            self_.bucket(i).drop();
-                            self_.items -= 1;
-                        }
-                    }
-                }
-                self_.growth_left = bucket_mask_to_capacity(self_.bucket_mask) - self_.items;
-            });
-
-            // At this point, DELETED elements are elements that we haven't
-            // rehashed yet. Find them and re-insert them at their ideal
-            // position.
-            'outer: for i in 0..guard.buckets() {
-                if *guard.ctrl(i) != DELETED {
-                    continue;
-                }
-                'inner: loop {
-                    // Hash the current item
-                    let item = guard.bucket(i);
-                    let hash = hasher(item.as_ref());
-
-                    // Search for a suitable place to put it
-                    let new_i = guard.find_insert_slot(hash);
-
-                    // Probing works by scanning through all of the control
-                    // bytes in groups, which may not be aligned to the group
-                    // size. If both the new and old position fall within the
-                    // same unaligned group, then there is no benefit in moving
-                    // it and we can just continue to the next item.
-                    let probe_index = |pos: usize| {
-                        (pos.wrapping_sub(guard.probe_seq(hash).pos) & guard.bucket_mask)
-                            / Group::WIDTH
-                    };
-                    if likely(probe_index(i) == probe_index(new_i)) {
-                        guard.set_ctrl(i, h2(hash));
-                        continue 'outer;
-                    }
-
-                    // We are moving the current item to a new position. Write
-                    // our H2 to the control byte of the new position.
-                    let prev_ctrl = *guard.ctrl(new_i);
-                    guard.set_ctrl(new_i, h2(hash));
-
-                    if prev_ctrl == EMPTY {
-                        // If the target slot is empty, simply move the current
-                        // element into the new slot and clear the old control
-                        // byte.
-                        guard.set_ctrl(i, EMPTY);
-                        guard.bucket(new_i).copy_from_nonoverlapping(&item);
-                        continue 'outer;
-                    } else {
-                        // If the target slot is occupied, swap the two elements
-                        // and then continue processing the element that we just
-                        // swapped into the old slot.
-                        debug_assert_eq!(prev_ctrl, DELETED);
-                        mem::swap(guard.bucket(new_i).as_mut(), item.as_mut());
-                        continue 'inner;
-                    }
-                }
-            }
-
-            guard.growth_left = bucket_mask_to_capacity(guard.bucket_mask) - guard.items;
-            mem::forget(guard);
-        }
-    }
-
-    /// Allocates a new table of a different size and moves the contents of the
-    /// current table into it.
-    fn resize(
-        &mut self,
-        capacity: usize,
-        hasher: impl Fn(&T) -> u64,
-        fallability: Fallibility,
-    ) -> Result<(), CollectionAllocErr> {
-        unsafe {
-            debug_assert!(self.items <= capacity);
-
-            // Allocate and initialize the new table.
-            let mut new_table = Self::try_with_capacity(capacity, fallability)?;
-            new_table.growth_left -= self.items;
-            new_table.items = self.items;
-
-            // The hash function may panic, in which case we simply free the new
-            // table without dropping any elements that may have been copied into
-            // it.
-            //
-            // This guard is also used to free the old table on success, see
-            // the comment at the bottom of this function.
-            let mut new_table = guard(ManuallyDrop::new(new_table), |new_table| {
-                if !new_table.is_empty_singleton() {
-                    new_table.free_buckets();
-                }
-            });
-
-            // Copy all elements to the new table.
-            for item in self.iter() {
-                // This may panic.
-                let hash = hasher(item.as_ref());
-
-                // We can use a simpler version of insert() here since:
-                // - there are no DELETED entries.
-                // - we know there is enough space in the table.
-                // - all elements are unique.
-                let index = new_table.find_insert_slot(hash);
-                new_table.set_ctrl(index, h2(hash));
-                new_table.bucket(index).copy_from_nonoverlapping(&item);
-            }
-
-            // We successfully copied all elements without panicking. Now replace
-            // self with the new table. The old table will have its memory freed but
-            // the items will not be dropped (since they have been moved into the
-            // new table).
-            mem::swap(self, &mut new_table);
-
-            Ok(())
-        }
-    }
-
-    /// Inserts a new element into the table.
-    ///
-    /// This does not check if the given element already exists in the table.
-    #[inline]
-    pub fn insert(&mut self, hash: u64, value: T, hasher: impl Fn(&T) -> u64) -> Bucket<T> {
-        self.reserve(1, hasher);
-        self.insert_no_grow(hash, value)
-    }
-
-    /// Inserts a new element into the table, without growing the table.
-    ///
-    /// There must be enough space in the table to insert the new element.
-    ///
-    /// This does not check if the given element already exists in the table.
-    #[inline]
-    pub fn insert_no_grow(&mut self, hash: u64, value: T) -> Bucket<T> {
-        unsafe {
-            let index = self.find_insert_slot(hash);
-            let bucket = self.bucket(index);
-
-            // If we are replacing a DELETED entry then we don't need to update
-            // the load counter.
-            let old_ctrl = *self.ctrl(index);
-            self.growth_left -= special_is_empty(old_ctrl) as usize;
-
-            self.set_ctrl(index, h2(hash));
-            bucket.write(value);
-            self.items += 1;
-            bucket
-        }
-    }
-
-    /// Searches for an element in the table.
-    #[inline]
-    pub fn find(&self, hash: u64, mut eq: impl FnMut(&T) -> bool) -> Option<Bucket<T>> {
-        unsafe {
-            for pos in self.probe_seq(hash) {
-                let group = Group::load(self.ctrl(pos));
-                for bit in group.match_byte(h2(hash)) {
-                    let index = (pos + bit) & self.bucket_mask;
-                    let bucket = self.bucket(index);
-                    if likely(eq(bucket.as_ref())) {
-                        return Some(bucket);
-                    }
-                }
-                if likely(group.match_empty().any_bit_set()) {
-                    return None;
-                }
-            }
-        }
-
-        // probe_seq never returns.
-        unreachable!();
-    }
-
-    /// Returns the number of elements the map can hold without reallocating.
-    ///
-    /// This number is a lower bound; the table might be able to hold
-    /// more, but is guaranteed to be able to hold at least this many.
-    #[inline]
-    pub fn capacity(&self) -> usize {
-        self.items + self.growth_left
-    }
-
-    /// Returns the number of elements in the table.
-    #[inline]
-    pub fn len(&self) -> usize {
-        self.items
-    }
-
-    /// Returns the number of buckets in the table.
-    #[inline]
-    pub fn buckets(&self) -> usize {
-        self.bucket_mask + 1
-    }
-
-    /// Returns the number of control bytes in the table.
-    #[inline]
-    fn num_ctrl_bytes(&self) -> usize {
-        self.bucket_mask + 1 + Group::WIDTH
-    }
-
-    /// Returns whether this table points to the empty singleton with a capacity
-    /// of 0.
-    #[inline]
-    fn is_empty_singleton(&self) -> bool {
-        self.bucket_mask == 0
-    }
-
-    /// Returns an iterator over every element in the table. It is up to
-    /// the caller to ensure that the `RawTable` outlives the `RawIter`.
-    /// Because we cannot make the `next` method unsafe on the `RawIter`
-    /// struct, we have to make the `iter` method unsafe.
-    #[inline]
-    pub unsafe fn iter(&self) -> RawIter<T> {
-        let data = Bucket::from_base_index(self.data.as_ptr(), 0);
-        RawIter {
-            iter: RawIterRange::new(self.ctrl.as_ptr(), data, self.buckets()),
-            items: self.items,
-        }
-    }
-
-    /// Returns an iterator which removes all elements from the table without
-    /// freeing the memory. It is up to the caller to ensure that the `RawTable`
-    /// outlives the `RawDrain`. Because we cannot make the `next` method unsafe
-    /// on the `RawDrain`, we have to make the `drain` method unsafe.
-    #[inline]
-    pub unsafe fn drain(&mut self) -> RawDrain<'_, T> {
-        RawDrain {
-            iter: self.iter(),
-            table: ManuallyDrop::new(mem::replace(self, Self::new())),
-            orig_table: NonNull::from(self),
-            marker: PhantomData,
-        }
-    }
-
-    /// Converts the table into a raw allocation. The contents of the table
-    /// should be dropped using a `RawIter` before freeing the allocation.
-    #[inline]
-    pub fn into_alloc(self) -> Option<(NonNull<u8>, Layout)> {
-        let alloc = if self.is_empty_singleton() {
-            None
-        } else {
-            let (layout, _) = calculate_layout::<T>(self.buckets())
-                .unwrap_or_else(|| unsafe { hint::unreachable_unchecked() });
-            Some((self.ctrl.cast(), layout))
-        };
-        mem::forget(self);
-        alloc
-    }
-}
-
-unsafe impl<T> Send for RawTable<T> where T: Send {}
-unsafe impl<T> Sync for RawTable<T> where T: Sync {}
-
-impl<T: Clone> Clone for RawTable<T> {
-    fn clone(&self) -> Self {
-        if self.is_empty_singleton() {
-            Self::new()
-        } else {
-            unsafe {
-                let mut new_table = ManuallyDrop::new(
-                    Self::new_uninitialized(self.buckets(), Fallibility::Infallible)
-                        .unwrap_or_else(|_| hint::unreachable_unchecked()),
-                );
-
-                // Copy the control bytes unchanged. We do this in a single pass
-                self.ctrl(0)
-                    .copy_to_nonoverlapping(new_table.ctrl(0), self.num_ctrl_bytes());
-
-                {
-                    // The cloning of elements may panic, in which case we need
-                    // to make sure we drop only the elements that have been
-                    // cloned so far.
-                    let mut guard = guard((0, &mut new_table), |(index, new_table)| {
-                        if mem::needs_drop::<T>() {
-                            for i in 0..=*index {
-                                if is_full(*new_table.ctrl(i)) {
-                                    new_table.bucket(i).drop();
-                                }
-                            }
-                        }
-                        new_table.free_buckets();
-                    });
-
-                    for from in self.iter() {
-                        let index = self.bucket_index(&from);
-                        let to = guard.1.bucket(index);
-                        to.write(from.as_ref().clone());
-
-                        // Update the index in case we need to unwind.
-                        guard.0 = index;
-                    }
-
-                    // Successfully cloned all items, no need to clean up.
-                    mem::forget(guard);
-                }
-
-                // Return the newly created table.
-                new_table.items = self.items;
-                new_table.growth_left = self.growth_left;
-                ManuallyDrop::into_inner(new_table)
-            }
-        }
-    }
-}
-
-#[cfg(feature = "nightly")]
-unsafe impl<#[may_dangle] T> Drop for RawTable<T> {
-    #[inline]
-    fn drop(&mut self) {
-        if !self.is_empty_singleton() {
-            unsafe {
-                if mem::needs_drop::<T>() {
-                    for item in self.iter() {
-                        item.drop();
-                    }
-                }
-                self.free_buckets();
-            }
-        }
-    }
-}
-#[cfg(not(feature = "nightly"))]
-impl<T> Drop for RawTable<T> {
-    #[inline]
-    fn drop(&mut self) {
-        if !self.is_empty_singleton() {
-            unsafe {
-                if mem::needs_drop::<T>() {
-                    for item in self.iter() {
-                        item.drop();
-                    }
-                }
-                self.free_buckets();
-            }
-        }
-    }
-}
-
-impl<T> IntoIterator for RawTable<T> {
-    type Item = T;
-    type IntoIter = RawIntoIter<T>;
-
-    #[inline]
-    fn into_iter(self) -> RawIntoIter<T> {
-        unsafe {
-            let iter = self.iter();
-            let alloc = self.into_alloc();
-            RawIntoIter {
-                iter,
-                alloc,
-                marker: PhantomData,
-            }
-        }
-    }
-}
-
-/// Iterator over a sub-range of a table. Unlike `RawIter` this iterator does
-/// not track an item count.
-pub struct RawIterRange<T> {
-    // Mask of full buckets in the current group. Bits are cleared from this
-    // mask as each element is processed.
-    current_group: BitMask,
-
-    // Pointer to the buckets for the current group.
-    data: Bucket<T>,
-
-    // Pointer to the next group of control bytes,
-    // Must be aligned to the group size.
-    next_ctrl: *const u8,
-
-    // Pointer one past the last control byte of this range.
-    end: *const u8,
-}
-
-impl<T> RawIterRange<T> {
-    /// Returns a `RawIterRange` covering a subset of a table.
-    ///
-    /// The control byte address must be aligned to the group size.
-    #[inline]
-    unsafe fn new(ctrl: *const u8, data: Bucket<T>, len: usize) -> Self {
-        debug_assert_ne!(len, 0);
-        debug_assert_eq!(ctrl as usize % Group::WIDTH, 0);
-        let end = ctrl.add(len);
-
-        // Load the first group and advance ctrl to point to the next group
-        let current_group = Group::load_aligned(ctrl).match_full();
-        let next_ctrl = ctrl.add(Group::WIDTH);
-
-        Self {
-            current_group,
-            data,
-            next_ctrl,
-            end,
-        }
-    }
-
-    /// Splits a `RawIterRange` into two halves.
-    ///
-    /// Returns `None` if the remaining range is smaller than or equal to the
-    /// group width.
-    #[inline]
-    #[cfg(feature = "rayon")]
-    pub fn split(mut self) -> (Self, Option<RawIterRange<T>>) {
-        unsafe {
-            if self.end <= self.next_ctrl {
-                // Nothing to split if the group that we are current processing
-                // is the last one.
-                (self, None)
-            } else {
-                // len is the remaining number of elements after the group that
-                // we are currently processing. It must be a multiple of the
-                // group size (small tables are caught by the check above).
-                let len = offset_from(self.end, self.next_ctrl);
-                debug_assert_eq!(len % Group::WIDTH, 0);
-
-                // Split the remaining elements into two halves, but round the
-                // midpoint down in case there is an odd number of groups
-                // remaining. This ensures that:
-                // - The tail is at least 1 group long.
-                // - The split is roughly even considering we still have the
-                //   current group to process.
-                let mid = (len / 2) & !(Group::WIDTH - 1);
-
-                let tail = Self::new(
-                    self.next_ctrl.add(mid),
-                    self.data.add(Group::WIDTH).add(mid),
-                    len - mid,
-                );
-                debug_assert_eq!(self.data.add(Group::WIDTH).add(mid).ptr, tail.data.ptr);
-                debug_assert_eq!(self.end, tail.end);
-                self.end = self.next_ctrl.add(mid);
-                debug_assert_eq!(self.end.add(Group::WIDTH), tail.next_ctrl);
-                (self, Some(tail))
-            }
-        }
-    }
-}
-
-// We make raw iterators unconditionally Send and Sync, and let the PhantomData
-// in the actual iterator implementations determine the real Send/Sync bounds.
-unsafe impl<T> Send for RawIterRange<T> {}
-unsafe impl<T> Sync for RawIterRange<T> {}
-
-impl<T> Clone for RawIterRange<T> {
-    #[inline]
-    fn clone(&self) -> Self {
-        Self {
-            data: self.data.clone(),
-            next_ctrl: self.next_ctrl,
-            current_group: self.current_group,
-            end: self.end,
-        }
-    }
-}
-
-impl<T> Iterator for RawIterRange<T> {
-    type Item = Bucket<T>;
-
-    #[inline]
-    fn next(&mut self) -> Option<Bucket<T>> {
-        unsafe {
-            loop {
-                if let Some(index) = self.current_group.lowest_set_bit() {
-                    self.current_group = self.current_group.remove_lowest_bit();
-                    return Some(self.data.add(index));
-                }
-
-                if self.next_ctrl >= self.end {
-                    return None;
-                }
-
-                // We might read past self.end up to the next group boundary,
-                // but this is fine because it only occurs on tables smaller
-                // than the group size where the trailing control bytes are all
-                // EMPTY. On larger tables self.end is guaranteed to be aligned
-                // to the group size (since tables are power-of-two sized).
-                self.current_group = Group::load_aligned(self.next_ctrl).match_full();
-                self.data = self.data.add(Group::WIDTH);
-                self.next_ctrl = self.next_ctrl.add(Group::WIDTH);
-            }
-        }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        // We don't have an item count, so just guess based on the range size.
-        (
-            0,
-            Some(unsafe { offset_from(self.end, self.next_ctrl) + Group::WIDTH }),
-        )
-    }
-}
-
-impl<T> FusedIterator for RawIterRange<T> {}
-
-/// Iterator which returns a raw pointer to every full bucket in the table.
-pub struct RawIter<T> {
-    pub iter: RawIterRange<T>,
-    items: usize,
-}
-
-impl<T> Clone for RawIter<T> {
-    #[inline]
-    fn clone(&self) -> Self {
-        Self {
-            iter: self.iter.clone(),
-            items: self.items,
-        }
-    }
-}
-
-impl<T> Iterator for RawIter<T> {
-    type Item = Bucket<T>;
-
-    #[inline]
-    fn next(&mut self) -> Option<Bucket<T>> {
-        if let Some(b) = self.iter.next() {
-            self.items -= 1;
-            Some(b)
-        } else {
-            // We don't check against items == 0 here to allow the
-            // compiler to optimize away the item count entirely if the
-            // iterator length is never queried.
-            debug_assert_eq!(self.items, 0);
-            None
-        }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        (self.items, Some(self.items))
-    }
-}
-
-impl<T> ExactSizeIterator for RawIter<T> {}
-impl<T> FusedIterator for RawIter<T> {}
-
-/// Iterator which consumes a table and returns elements.
-pub struct RawIntoIter<T> {
-    iter: RawIter<T>,
-    alloc: Option<(NonNull<u8>, Layout)>,
-    marker: PhantomData<T>,
-}
-
-impl<T> RawIntoIter<T> {
-    #[inline]
-    pub fn iter(&self) -> RawIter<T> {
-        self.iter.clone()
-    }
-}
-
-unsafe impl<T> Send for RawIntoIter<T> where T: Send {}
-unsafe impl<T> Sync for RawIntoIter<T> where T: Sync {}
-
-#[cfg(feature = "nightly")]
-unsafe impl<#[may_dangle] T> Drop for RawIntoIter<T> {
-    #[inline]
-    fn drop(&mut self) {
-        unsafe {
-            // Drop all remaining elements
-            if mem::needs_drop::<T>() {
-                while let Some(item) = self.iter.next() {
-                    item.drop();
-                }
-            }
-
-            // Free the table
-            if let Some((ptr, layout)) = self.alloc {
-                dealloc(ptr.as_ptr(), layout);
-            }
-        }
-    }
-}
-#[cfg(not(feature = "nightly"))]
-impl<T> Drop for RawIntoIter<T> {
-    #[inline]
-    fn drop(&mut self) {
-        unsafe {
-            // Drop all remaining elements
-            if mem::needs_drop::<T>() {
-                while let Some(item) = self.iter.next() {
-                    item.drop();
-                }
-            }
-
-            // Free the table
-            if let Some((ptr, layout)) = self.alloc {
-                dealloc(ptr.as_ptr(), layout);
-            }
-        }
-    }
-}
-
-impl<T> Iterator for RawIntoIter<T> {
-    type Item = T;
-
-    #[inline]
-    fn next(&mut self) -> Option<T> {
-        unsafe { Some(self.iter.next()?.read()) }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-
-impl<T> ExactSizeIterator for RawIntoIter<T> {}
-impl<T> FusedIterator for RawIntoIter<T> {}
-
-/// Iterator which consumes elements without freeing the table storage.
-pub struct RawDrain<'a, T> {
-    iter: RawIter<T>,
-
-    // The table is moved into the iterator for the duration of the drain. This
-    // ensures that an empty table is left if the drain iterator is leaked
-    // without dropping.
-    table: ManuallyDrop<RawTable<T>>,
-    orig_table: NonNull<RawTable<T>>,
-
-    // We don't use a &'a mut RawTable<T> because we want RawDrain to be
-    // covariant over T.
-    marker: PhantomData<&'a RawTable<T>>,
-}
-
-impl<T> RawDrain<'_, T> {
-    #[inline]
-    pub fn iter(&self) -> RawIter<T> {
-        self.iter.clone()
-    }
-}
-
-unsafe impl<T> Send for RawDrain<'_, T> where T: Send {}
-unsafe impl<T> Sync for RawDrain<'_, T> where T: Sync {}
-
-impl<T> Drop for RawDrain<'_, T> {
-    #[inline]
-    fn drop(&mut self) {
-        unsafe {
-            // Drop all remaining elements. Note that this may panic.
-            if mem::needs_drop::<T>() {
-                while let Some(item) = self.iter.next() {
-                    item.drop();
-                }
-            }
-
-            // Reset the contents of the table now that all elements have been
-            // dropped.
-            self.table.clear_no_drop();
-
-            // Move the now empty table back to its original location.
-            self.orig_table
-                .as_ptr()
-                .copy_from_nonoverlapping(&*self.table, 1);
-        }
-    }
-}
-
-impl<T> Iterator for RawDrain<'_, T> {
-    type Item = T;
-
-    #[inline]
-    fn next(&mut self) -> Option<T> {
-        unsafe {
-            let item = self.iter.next()?;
-            Some(item.read())
-        }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-
-impl<T> ExactSizeIterator for RawDrain<'_, T> {}
-impl<T> FusedIterator for RawDrain<'_, T> {}
diff --git a/third_party/rust_crates/vendor/hashbrown/src/raw/sse2.rs b/third_party/rust_crates/vendor/hashbrown/src/raw/sse2.rs
deleted file mode 100644
index c9a1c54..0000000
--- a/third_party/rust_crates/vendor/hashbrown/src/raw/sse2.rs
+++ /dev/null
@@ -1,140 +0,0 @@
-use super::bitmask::BitMask;
-use super::EMPTY;
-use core::mem;
-
-#[cfg(target_arch = "x86")]
-use core::arch::x86;
-#[cfg(target_arch = "x86_64")]
-use core::arch::x86_64 as x86;
-
-pub type BitMaskWord = u16;
-pub const BITMASK_STRIDE: usize = 1;
-pub const BITMASK_MASK: BitMaskWord = 0xffff;
-
-/// Abstraction over a group of control bytes which can be scanned in
-/// parallel.
-///
-/// This implementation uses a 128-bit SSE value.
-#[derive(Copy, Clone)]
-pub struct Group(x86::__m128i);
-
-// FIXME: https://github.com/rust-lang/rust-clippy/issues/3859
-#[allow(clippy::use_self)] 
-impl Group {
-    /// Number of bytes in the group.
-    pub const WIDTH: usize = mem::size_of::<Self>();
-
-    /// Returns a full group of empty bytes, suitable for use as the initial
-    /// value for an empty hash table.
-    ///
-    /// This is guaranteed to be aligned to the group size.
-    #[inline]
-    pub fn static_empty() -> &'static [u8] {
-        union AlignedBytes {
-            _align: Group,
-            bytes: [u8; Group::WIDTH],
-        };
-        const ALIGNED_BYTES: AlignedBytes = AlignedBytes {
-            bytes: [EMPTY; Group::WIDTH],
-        };
-        unsafe { &ALIGNED_BYTES.bytes }
-    }
-
-    /// Loads a group of bytes starting at the given address.
-    #[inline]
-    #[allow(clippy::cast_ptr_alignment)] // unaligned load
-    pub unsafe fn load(ptr: *const u8) -> Self {
-        Group(x86::_mm_loadu_si128(ptr as *const _))
-    }
-
-    /// Loads a group of bytes starting at the given address, which must be
-    /// aligned to `mem::align_of::<Group>()`.
-    #[inline]
-    #[allow(clippy::cast_ptr_alignment)]
-    pub unsafe fn load_aligned(ptr: *const u8) -> Self {
-        // FIXME: use align_offset once it stabilizes
-        debug_assert_eq!(ptr as usize & (mem::align_of::<Self>() - 1), 0);
-        Group(x86::_mm_load_si128(ptr as *const _))
-    }
-
-    /// Stores the group of bytes to the given address, which must be
-    /// aligned to `mem::align_of::<Group>()`.
-    #[inline]
-    #[allow(clippy::cast_ptr_alignment)]
-    pub unsafe fn store_aligned(self, ptr: *mut u8) {
-        // FIXME: use align_offset once it stabilizes
-        debug_assert_eq!(ptr as usize & (mem::align_of::<Self>() - 1), 0);
-        x86::_mm_store_si128(ptr as *mut _, self.0);
-    }
-
-    /// Returns a `BitMask` indicating all bytes in the group which have
-    /// the given value.
-    #[inline]
-    pub fn match_byte(self, byte: u8) -> BitMask {
-        #[allow(
-            clippy::cast_possible_wrap, // byte: u8 as i8
-            // byte: i32 as u16
-            //   note: _mm_movemask_epi8 returns a 16-bit mask in a i32, the
-            //   upper 16-bits of the i32 are zeroed:
-            clippy::cast_sign_loss,
-            clippy::cast_possible_truncation
-        )]
-        unsafe {
-            let cmp = x86::_mm_cmpeq_epi8(self.0, x86::_mm_set1_epi8(byte as i8));
-            BitMask(x86::_mm_movemask_epi8(cmp) as u16)
-        }
-    }
-
-    /// Returns a `BitMask` indicating all bytes in the group which are
-    /// `EMPTY`.
-    #[inline]
-    pub fn match_empty(self) -> BitMask {
-        self.match_byte(EMPTY)
-    }
-
-    /// Returns a `BitMask` indicating all bytes in the group which are
-    /// `EMPTY` or `DELETED`.
-    #[inline]
-    pub fn match_empty_or_deleted(self) -> BitMask {
-        #[allow(
-            // byte: i32 as u16
-            //   note: _mm_movemask_epi8 returns a 16-bit mask in a i32, the
-            //   upper 16-bits of the i32 are zeroed:
-            clippy::cast_sign_loss,
-            clippy::cast_possible_truncation
-        )]
-        unsafe {
-            // A byte is EMPTY or DELETED iff the high bit is set
-            BitMask(x86::_mm_movemask_epi8(self.0) as u16)
-        }
-    }
-
-    /// Returns a `BitMask` indicating all bytes in the group which are full.
-    #[inline]
-    pub fn match_full(&self) -> BitMask {
-        self.match_empty_or_deleted().invert()
-    }
-
-    /// Performs the following transformation on all bytes in the group:
-    /// - `EMPTY => EMPTY`
-    /// - `DELETED => EMPTY`
-    /// - `FULL => DELETED`
-    #[inline]
-    pub fn convert_special_to_empty_and_full_to_deleted(self) -> Self {
-        // Map high_bit = 1 (EMPTY or DELETED) to 1111_1111
-        // and high_bit = 0 (FULL) to 1000_0000
-        //
-        // Here's this logic expanded to concrete values:
-        //   let special = 0 > byte = 1111_1111 (true) or 0000_0000 (false)
-        //   1111_1111 | 1000_0000 = 1111_1111
-        //   0000_0000 | 1000_0000 = 1000_0000
-        #[allow(
-            clippy::cast_possible_wrap, // byte: 0x80_u8 as i8
-        )]
-        unsafe {
-            let zero = x86::_mm_setzero_si128();
-            let special = x86::_mm_cmpgt_epi8(zero, self.0);
-            Group(x86::_mm_or_si128(special, x86::_mm_set1_epi8(0x80_u8 as i8)))
-        }
-    }
-}
diff --git a/third_party/rust_crates/vendor/hashbrown/src/rustc_entry.rs b/third_party/rust_crates/vendor/hashbrown/src/rustc_entry.rs
deleted file mode 100644
index 5cc3bd5..0000000
--- a/third_party/rust_crates/vendor/hashbrown/src/rustc_entry.rs
+++ /dev/null
@@ -1,573 +0,0 @@
-use self::RustcEntry::*;
-use crate::map::{make_hash, Drain, HashMap, IntoIter, Iter, IterMut};
-use crate::raw::{Bucket, RawTable};
-use core::fmt::{self, Debug};
-use core::hash::{BuildHasher, Hash};
-use core::mem;
-
-impl<K, V, S> HashMap<K, V, S>
-where
-    K: Eq + Hash,
-    S: BuildHasher,
-{
-    /// Gets the given key's corresponding entry in the map for in-place manipulation.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut letters = HashMap::new();
-    ///
-    /// for ch in "a short treatise on fungi".chars() {
-    ///     let counter = letters.rustc_entry(ch).or_insert(0);
-    ///     *counter += 1;
-    /// }
-    ///
-    /// assert_eq!(letters[&'s'], 2);
-    /// assert_eq!(letters[&'t'], 3);
-    /// assert_eq!(letters[&'u'], 1);
-    /// assert_eq!(letters.get(&'y'), None);
-    /// ```
-    #[inline]
-    pub fn rustc_entry(&mut self, key: K) -> RustcEntry<'_, K, V> {
-        let hash = make_hash(&self.hash_builder, &key);
-        if let Some(elem) = self.table.find(hash, |q| q.0.eq(&key)) {
-            RustcEntry::Occupied(RustcOccupiedEntry {
-                key: Some(key),
-                elem,
-                table: &mut self.table,
-            })
-        } else {
-            // Ideally we would put this in VacantEntry::insert, but Entry is not
-            // generic over the BuildHasher and adding a generic parameter would be
-            // a breaking change.
-            self.reserve(1);
-
-            RustcEntry::Vacant(RustcVacantEntry {
-                hash,
-                key,
-                table: &mut self.table,
-            })
-        }
-    }
-}
-
-/// A view into a single entry in a map, which may either be vacant or occupied.
-///
-/// This `enum` is constructed from the [`entry`] method on [`HashMap`].
-///
-/// [`HashMap`]: struct.HashMap.html
-/// [`entry`]: struct.HashMap.html#method.rustc_entry
-pub enum RustcEntry<'a, K: 'a, V: 'a> {
-    /// An occupied entry.
-    Occupied(RustcOccupiedEntry<'a, K, V>),
-
-    /// A vacant entry.
-    Vacant(RustcVacantEntry<'a, K, V>),
-}
-
-impl<K: Debug, V: Debug> Debug for RustcEntry<'_, K, V> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match *self {
-            Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(),
-            Occupied(ref o) => f.debug_tuple("Entry").field(o).finish(),
-        }
-    }
-}
-
-/// A view into an occupied entry in a `HashMap`.
-/// It is part of the [`RustcEntry`] enum.
-///
-/// [`RustcEntry`]: enum.RustcEntry.html
-pub struct RustcOccupiedEntry<'a, K, V> {
-    key: Option<K>,
-    elem: Bucket<(K, V)>,
-    table: &'a mut RawTable<(K, V)>,
-}
-
-unsafe impl<K, V> Send for RustcOccupiedEntry<'_, K, V>
-where
-    K: Send,
-    V: Send,
-{
-}
-unsafe impl<K, V> Sync for RustcOccupiedEntry<'_, K, V>
-where
-    K: Sync,
-    V: Sync,
-{
-}
-
-impl<K: Debug, V: Debug> Debug for RustcOccupiedEntry<'_, K, V> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("OccupiedEntry")
-            .field("key", self.key())
-            .field("value", self.get())
-            .finish()
-    }
-}
-
-/// A view into a vacant entry in a `HashMap`.
-/// It is part of the [`RustcEntry`] enum.
-///
-/// [`RustcEntry`]: enum.RustcEntry.html
-pub struct RustcVacantEntry<'a, K, V> {
-    hash: u64,
-    key: K,
-    table: &'a mut RawTable<(K, V)>,
-}
-
-impl<K: Debug, V> Debug for RustcVacantEntry<'_, K, V> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_tuple("VacantEntry").field(self.key()).finish()
-    }
-}
-
-impl<'a, K, V> RustcEntry<'a, K, V> {
-    /// Ensures a value is in the entry by inserting the default if empty, and returns
-    /// a mutable reference to the value in the entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    ///
-    /// map.rustc_entry("poneyland").or_insert(3);
-    /// assert_eq!(map["poneyland"], 3);
-    ///
-    /// *map.rustc_entry("poneyland").or_insert(10) *= 2;
-    /// assert_eq!(map["poneyland"], 6);
-    /// ```
-    #[inline]
-    pub fn or_insert(self, default: V) -> &'a mut V
-    where
-        K: Hash,
-    {
-        match self {
-            Occupied(entry) => entry.into_mut(),
-            Vacant(entry) => entry.insert(default),
-        }
-    }
-
-    /// Ensures a value is in the entry by inserting the result of the default function if empty,
-    /// and returns a mutable reference to the value in the entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, String> = HashMap::new();
-    /// let s = "hoho".to_string();
-    ///
-    /// map.rustc_entry("poneyland").or_insert_with(|| s);
-    ///
-    /// assert_eq!(map["poneyland"], "hoho".to_string());
-    /// ```
-    #[inline]
-    pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V
-    where
-        K: Hash,
-    {
-        match self {
-            Occupied(entry) => entry.into_mut(),
-            Vacant(entry) => entry.insert(default()),
-        }
-    }
-
-    /// Returns a reference to this entry's key.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// assert_eq!(map.rustc_entry("poneyland").key(), &"poneyland");
-    /// ```
-    #[inline]
-    pub fn key(&self) -> &K {
-        match *self {
-            Occupied(ref entry) => entry.key(),
-            Vacant(ref entry) => entry.key(),
-        }
-    }
-
-    /// Provides in-place mutable access to an occupied entry before any
-    /// potential inserts into the map.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    ///
-    /// map.rustc_entry("poneyland")
-    ///    .and_modify(|e| { *e += 1 })
-    ///    .or_insert(42);
-    /// assert_eq!(map["poneyland"], 42);
-    ///
-    /// map.rustc_entry("poneyland")
-    ///    .and_modify(|e| { *e += 1 })
-    ///    .or_insert(42);
-    /// assert_eq!(map["poneyland"], 43);
-    /// ```
-    #[inline]
-    pub fn and_modify<F>(self, f: F) -> Self
-    where
-        F: FnOnce(&mut V),
-    {
-        match self {
-            Occupied(mut entry) => {
-                f(entry.get_mut());
-                Occupied(entry)
-            }
-            Vacant(entry) => Vacant(entry),
-        }
-    }
-}
-
-impl<'a, K, V: Default> RustcEntry<'a, K, V> {
-    /// Ensures a value is in the entry by inserting the default value if empty,
-    /// and returns a mutable reference to the value in the entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # fn main() {
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, Option<u32>> = HashMap::new();
-    /// map.rustc_entry("poneyland").or_default();
-    ///
-    /// assert_eq!(map["poneyland"], None);
-    /// # }
-    /// ```
-    #[inline]
-    pub fn or_default(self) -> &'a mut V
-    where
-        K: Hash,
-    {
-        match self {
-            Occupied(entry) => entry.into_mut(),
-            Vacant(entry) => entry.insert(Default::default()),
-        }
-    }
-}
-
-impl<'a, K, V> RustcOccupiedEntry<'a, K, V> {
-    /// Gets a reference to the key in the entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.rustc_entry("poneyland").or_insert(12);
-    /// assert_eq!(map.rustc_entry("poneyland").key(), &"poneyland");
-    /// ```
-    #[inline]
-    pub fn key(&self) -> &K {
-        unsafe { &self.elem.as_ref().0 }
-    }
-
-    /// Take the ownership of the key and value from the map.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::RustcEntry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.rustc_entry("poneyland").or_insert(12);
-    ///
-    /// if let RustcEntry::Occupied(o) = map.rustc_entry("poneyland") {
-    ///     // We delete the entry from the map.
-    ///     o.remove_entry();
-    /// }
-    ///
-    /// assert_eq!(map.contains_key("poneyland"), false);
-    /// ```
-    #[inline]
-    pub fn remove_entry(self) -> (K, V) {
-        unsafe {
-            self.table.erase_no_drop(&self.elem);
-            self.elem.read()
-        }
-    }
-
-    /// Gets a reference to the value in the entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::RustcEntry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.rustc_entry("poneyland").or_insert(12);
-    ///
-    /// if let RustcEntry::Occupied(o) = map.rustc_entry("poneyland") {
-    ///     assert_eq!(o.get(), &12);
-    /// }
-    /// ```
-    #[inline]
-    pub fn get(&self) -> &V {
-        unsafe { &self.elem.as_ref().1 }
-    }
-
-    /// Gets a mutable reference to the value in the entry.
-    ///
-    /// If you need a reference to the `RustcOccupiedEntry` which may outlive the
-    /// destruction of the `RustcEntry` value, see [`into_mut`].
-    ///
-    /// [`into_mut`]: #method.into_mut
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::RustcEntry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.rustc_entry("poneyland").or_insert(12);
-    ///
-    /// assert_eq!(map["poneyland"], 12);
-    /// if let RustcEntry::Occupied(mut o) = map.rustc_entry("poneyland") {
-    ///     *o.get_mut() += 10;
-    ///     assert_eq!(*o.get(), 22);
-    ///
-    ///     // We can use the same RustcEntry multiple times.
-    ///     *o.get_mut() += 2;
-    /// }
-    ///
-    /// assert_eq!(map["poneyland"], 24);
-    /// ```
-    #[inline]
-    pub fn get_mut(&mut self) -> &mut V {
-        unsafe { &mut self.elem.as_mut().1 }
-    }
-
-    /// Converts the RustcOccupiedEntry into a mutable reference to the value in the entry
-    /// with a lifetime bound to the map itself.
-    ///
-    /// If you need multiple references to the `RustcOccupiedEntry`, see [`get_mut`].
-    ///
-    /// [`get_mut`]: #method.get_mut
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::RustcEntry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.rustc_entry("poneyland").or_insert(12);
-    ///
-    /// assert_eq!(map["poneyland"], 12);
-    /// if let RustcEntry::Occupied(o) = map.rustc_entry("poneyland") {
-    ///     *o.into_mut() += 10;
-    /// }
-    ///
-    /// assert_eq!(map["poneyland"], 22);
-    /// ```
-    #[inline]
-    pub fn into_mut(self) -> &'a mut V {
-        unsafe { &mut self.elem.as_mut().1 }
-    }
-
-    /// Sets the value of the entry, and returns the entry's old value.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::RustcEntry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.rustc_entry("poneyland").or_insert(12);
-    ///
-    /// if let RustcEntry::Occupied(mut o) = map.rustc_entry("poneyland") {
-    ///     assert_eq!(o.insert(15), 12);
-    /// }
-    ///
-    /// assert_eq!(map["poneyland"], 15);
-    /// ```
-    #[inline]
-    pub fn insert(&mut self, mut value: V) -> V {
-        let old_value = self.get_mut();
-        mem::swap(&mut value, old_value);
-        value
-    }
-
-    /// Takes the value out of the entry, and returns it.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::RustcEntry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// map.rustc_entry("poneyland").or_insert(12);
-    ///
-    /// if let RustcEntry::Occupied(o) = map.rustc_entry("poneyland") {
-    ///     assert_eq!(o.remove(), 12);
-    /// }
-    ///
-    /// assert_eq!(map.contains_key("poneyland"), false);
-    /// ```
-    #[inline]
-    pub fn remove(self) -> V {
-        self.remove_entry().1
-    }
-
-    /// Replaces the entry, returning the old key and value. The new key in the hash map will be
-    /// the key used to create this entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::hash_map::{RustcEntry, HashMap};
-    /// use std::rc::Rc;
-    ///
-    /// let mut map: HashMap<Rc<String>, u32> = HashMap::new();
-    /// map.insert(Rc::new("Stringthing".to_string()), 15);
-    ///
-    /// let my_key = Rc::new("Stringthing".to_string());
-    ///
-    /// if let RustcEntry::Occupied(entry) = map.rustc_entry(my_key) {
-    ///     // Also replace the key with a handle to our other key.
-    ///     let (old_key, old_value): (Rc<String>, u32) = entry.replace_entry(16);
-    /// }
-    ///
-    /// ```
-    #[inline]
-    pub fn replace_entry(self, value: V) -> (K, V) {
-        let entry = unsafe { self.elem.as_mut() };
-
-        let old_key = mem::replace(&mut entry.0, self.key.unwrap());
-        let old_value = mem::replace(&mut entry.1, value);
-
-        (old_key, old_value)
-    }
-
-    /// Replaces the key in the hash map with the key used to create this entry.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::hash_map::{RustcEntry, HashMap};
-    /// use std::rc::Rc;
-    ///
-    /// let mut map: HashMap<Rc<String>, u32> = HashMap::new();
-    /// let mut known_strings: Vec<Rc<String>> = Vec::new();
-    ///
-    /// // Initialise known strings, run program, etc.
-    ///
-    /// reclaim_memory(&mut map, &known_strings);
-    ///
-    /// fn reclaim_memory(map: &mut HashMap<Rc<String>, u32>, known_strings: &[Rc<String>] ) {
-    ///     for s in known_strings {
-    ///         if let RustcEntry::Occupied(entry) = map.rustc_entry(s.clone()) {
-    ///             // Replaces the entry's key with our version of it in `known_strings`.
-    ///             entry.replace_key();
-    ///         }
-    ///     }
-    /// }
-    /// ```
-    #[inline]
-    pub fn replace_key(self) -> K {
-        let entry = unsafe { self.elem.as_mut() };
-        mem::replace(&mut entry.0, self.key.unwrap())
-    }
-}
-
-impl<'a, K, V> RustcVacantEntry<'a, K, V> {
-    /// Gets a reference to the key that would be used when inserting a value
-    /// through the `RustcVacantEntry`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    /// assert_eq!(map.rustc_entry("poneyland").key(), &"poneyland");
-    /// ```
-    #[inline]
-    pub fn key(&self) -> &K {
-        &self.key
-    }
-
-    /// Take ownership of the key.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::RustcEntry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    ///
-    /// if let RustcEntry::Vacant(v) = map.rustc_entry("poneyland") {
-    ///     v.into_key();
-    /// }
-    /// ```
-    #[inline]
-    pub fn into_key(self) -> K {
-        self.key
-    }
-
-    /// Sets the value of the entry with the RustcVacantEntry's key,
-    /// and returns a mutable reference to it.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashMap;
-    /// use hashbrown::hash_map::RustcEntry;
-    ///
-    /// let mut map: HashMap<&str, u32> = HashMap::new();
-    ///
-    /// if let RustcEntry::Vacant(o) = map.rustc_entry("poneyland") {
-    ///     o.insert(37);
-    /// }
-    /// assert_eq!(map["poneyland"], 37);
-    /// ```
-    #[inline]
-    pub fn insert(self, value: V) -> &'a mut V {
-        let bucket = self.table.insert_no_grow(self.hash, (self.key, value));
-        unsafe { &mut bucket.as_mut().1 }
-    }
-}
-
-impl<K, V> IterMut<'_, K, V> {
-    /// Returns a iterator of references over the remaining items.
-    #[inline]
-    pub fn rustc_iter(&self) -> Iter<'_, K, V> {
-        self.iter()
-    }
-}
-
-impl<K, V> IntoIter<K, V> {
-    /// Returns a iterator of references over the remaining items.
-    #[inline]
-    pub fn rustc_iter(&self) -> Iter<'_, K, V> {
-        self.iter()
-    }
-}
-
-impl<K, V> Drain<'_, K, V> {
-    /// Returns a iterator of references over the remaining items.
-    #[inline]
-    pub fn rustc_iter(&self) -> Iter<'_, K, V> {
-        self.iter()
-    }
-}
diff --git a/third_party/rust_crates/vendor/hashbrown/src/scopeguard.rs b/third_party/rust_crates/vendor/hashbrown/src/scopeguard.rs
deleted file mode 100644
index 4e9bf04..0000000
--- a/third_party/rust_crates/vendor/hashbrown/src/scopeguard.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-// Extracted from the scopeguard crate
-use core::ops::{Deref, DerefMut};
-
-pub struct ScopeGuard<T, F>
-where
-    F: FnMut(&mut T),
-{
-    dropfn: F,
-    value: T,
-}
-
-#[inline]
-pub fn guard<T, F>(value: T, dropfn: F) -> ScopeGuard<T, F>
-where
-    F: FnMut(&mut T),
-{
-    ScopeGuard { dropfn, value }
-}
-
-impl<T, F> Deref for ScopeGuard<T, F>
-where
-    F: FnMut(&mut T),
-{
-    type Target = T;
-    #[inline]
-    fn deref(&self) -> &T {
-        &self.value
-    }
-}
-
-impl<T, F> DerefMut for ScopeGuard<T, F>
-where
-    F: FnMut(&mut T),
-{
-    #[inline]
-    fn deref_mut(&mut self) -> &mut T {
-        &mut self.value
-    }
-}
-
-impl<T, F> Drop for ScopeGuard<T, F>
-where
-    F: FnMut(&mut T),
-{
-    #[inline]
-    fn drop(&mut self) {
-        (self.dropfn)(&mut self.value)
-    }
-}
diff --git a/third_party/rust_crates/vendor/hashbrown/src/set.rs b/third_party/rust_crates/vendor/hashbrown/src/set.rs
deleted file mode 100644
index ade7726..0000000
--- a/third_party/rust_crates/vendor/hashbrown/src/set.rs
+++ /dev/null
@@ -1,1829 +0,0 @@
-use crate::CollectionAllocErr;
-use core::borrow::Borrow;
-use core::fmt;
-use core::hash::{BuildHasher, Hash};
-use core::iter::{Chain, FromIterator, FusedIterator};
-use core::ops::{BitAnd, BitOr, BitXor, Sub};
-
-use super::map::{self, DefaultHashBuilder, HashMap, Keys};
-
-// Future Optimization (FIXME!)
-// =============================
-//
-// Iteration over zero sized values is a noop. There is no need
-// for `bucket.val` in the case of HashSet. I suppose we would need HKT
-// to get rid of it properly.
-
-/// A hash set implemented as a `HashMap` where the value is `()`.
-///
-/// As with the [`HashMap`] type, a `HashSet` requires that the elements
-/// implement the [`Eq`] and [`Hash`] traits. This can frequently be achieved by
-/// using `#[derive(PartialEq, Eq, Hash)]`. If you implement these yourself,
-/// it is important that the following property holds:
-///
-/// ```text
-/// k1 == k2 -> hash(k1) == hash(k2)
-/// ```
-///
-/// In other words, if two keys are equal, their hashes must be equal.
-///
-///
-/// It is a logic error for an item to be modified in such a way that the
-/// item's hash, as determined by the [`Hash`] trait, or its equality, as
-/// determined by the [`Eq`] trait, changes while it is in the set. This is
-/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or
-/// unsafe code.
-///
-/// It is also a logic error for the [`Hash`] implementation of a key to panic.
-/// This is generally only possible if the trait is implemented manually. If a
-/// panic does occur then the contents of the `HashSet` may become corrupted and
-/// some items may be dropped from the table.
-///
-/// # Examples
-///
-/// ```
-/// use hashbrown::HashSet;
-/// // Type inference lets us omit an explicit type signature (which
-/// // would be `HashSet<String>` in this example).
-/// let mut books = HashSet::new();
-///
-/// // Add some books.
-/// books.insert("A Dance With Dragons".to_string());
-/// books.insert("To Kill a Mockingbird".to_string());
-/// books.insert("The Odyssey".to_string());
-/// books.insert("The Great Gatsby".to_string());
-///
-/// // Check for a specific one.
-/// if !books.contains("The Winds of Winter") {
-///     println!("We have {} books, but The Winds of Winter ain't one.",
-///              books.len());
-/// }
-///
-/// // Remove a book.
-/// books.remove("The Odyssey");
-///
-/// // Iterate over everything.
-/// for book in &books {
-///     println!("{}", book);
-/// }
-/// ```
-///
-/// The easiest way to use `HashSet` with a custom type is to derive
-/// [`Eq`] and [`Hash`]. We must also derive [`PartialEq`], this will in the
-/// future be implied by [`Eq`].
-///
-/// ```
-/// use hashbrown::HashSet;
-/// #[derive(Hash, Eq, PartialEq, Debug)]
-/// struct Viking {
-///     name: String,
-///     power: usize,
-/// }
-///
-/// let mut vikings = HashSet::new();
-///
-/// vikings.insert(Viking { name: "Einar".to_string(), power: 9 });
-/// vikings.insert(Viking { name: "Einar".to_string(), power: 9 });
-/// vikings.insert(Viking { name: "Olaf".to_string(), power: 4 });
-/// vikings.insert(Viking { name: "Harald".to_string(), power: 8 });
-///
-/// // Use derived implementation to print the vikings.
-/// for x in &vikings {
-///     println!("{:?}", x);
-/// }
-/// ```
-///
-/// A `HashSet` with fixed list of elements can be initialized from an array:
-///
-/// ```
-/// use hashbrown::HashSet;
-///
-/// fn main() {
-///     let viking_names: HashSet<&'static str> =
-///         [ "Einar", "Olaf", "Harald" ].iter().cloned().collect();
-///     // use the values stored in the set
-/// }
-/// ```
-///
-/// [`Cell`]: https://doc.rust-lang.org/std/cell/struct.Cell.html
-/// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
-/// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
-/// [`HashMap`]: struct.HashMap.html
-/// [`PartialEq`]: https://doc.rust-lang.org/std/cmp/trait.PartialEq.html
-/// [`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html
-#[derive(Clone)]
-pub struct HashSet<T, S = DefaultHashBuilder> {
-    pub(crate) map: HashMap<T, (), S>,
-}
-
-impl<T: Hash + Eq> HashSet<T, DefaultHashBuilder> {
-    /// Creates an empty `HashSet`.
-    ///
-    /// The hash set is initially created with a capacity of 0, so it will not allocate until it
-    /// is first inserted into.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// let set: HashSet<i32> = HashSet::new();
-    /// ```
-    #[inline]
-    pub fn new() -> Self {
-        Self {
-            map: HashMap::new(),
-        }
-    }
-
-    /// Creates an empty `HashSet` with the specified capacity.
-    ///
-    /// The hash set will be able to hold at least `capacity` elements without
-    /// reallocating. If `capacity` is 0, the hash set will not allocate.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// let set: HashSet<i32> = HashSet::with_capacity(10);
-    /// assert!(set.capacity() >= 10);
-    /// ```
-    #[inline]
-    pub fn with_capacity(capacity: usize) -> Self {
-        Self {
-            map: HashMap::with_capacity(capacity),
-        }
-    }
-}
-
-impl<T, S> HashSet<T, S> {
-    /// Returns the number of elements the set can hold without reallocating.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// let set: HashSet<i32> = HashSet::with_capacity(100);
-    /// assert!(set.capacity() >= 100);
-    /// ```
-    #[inline]
-    pub fn capacity(&self) -> usize {
-        self.map.capacity()
-    }
-
-    /// An iterator visiting all elements in arbitrary order.
-    /// The iterator element type is `&'a T`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// let mut set = HashSet::new();
-    /// set.insert("a");
-    /// set.insert("b");
-    ///
-    /// // Will print in an arbitrary order.
-    /// for x in set.iter() {
-    ///     println!("{}", x);
-    /// }
-    /// ```
-    #[inline]
-    pub fn iter(&self) -> Iter<'_, T> {
-        Iter {
-            iter: self.map.keys(),
-        }
-    }
-
-    /// Returns the number of elements in the set.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let mut v = HashSet::new();
-    /// assert_eq!(v.len(), 0);
-    /// v.insert(1);
-    /// assert_eq!(v.len(), 1);
-    /// ```
-    #[inline]
-    pub fn len(&self) -> usize {
-        self.map.len()
-    }
-
-    /// Returns `true` if the set contains no elements.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let mut v = HashSet::new();
-    /// assert!(v.is_empty());
-    /// v.insert(1);
-    /// assert!(!v.is_empty());
-    /// ```
-    #[inline]
-    pub fn is_empty(&self) -> bool {
-        self.map.is_empty()
-    }
-
-    /// Clears the set, returning all elements in an iterator.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
-    /// assert!(!set.is_empty());
-    ///
-    /// // print 1, 2, 3 in an arbitrary order
-    /// for i in set.drain() {
-    ///     println!("{}", i);
-    /// }
-    ///
-    /// assert!(set.is_empty());
-    /// ```
-    #[inline]
-    pub fn drain(&mut self) -> Drain<'_, T> {
-        Drain {
-            iter: self.map.drain(),
-        }
-    }
-
-    /// Clears the set, removing all values.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let mut v = HashSet::new();
-    /// v.insert(1);
-    /// v.clear();
-    /// assert!(v.is_empty());
-    /// ```
-    #[inline]
-    pub fn clear(&mut self) {
-        self.map.clear()
-    }
-}
-
-impl<T, S> HashSet<T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher,
-{
-    /// Creates a new empty hash set which will use the given hasher to hash
-    /// keys.
-    ///
-    /// The hash set is also created with the default initial capacity.
-    ///
-    /// Warning: `hasher` is normally randomly generated, and
-    /// is designed to allow `HashSet`s to be resistant to attacks that
-    /// cause many collisions and very poor performance. Setting it
-    /// manually using this function can expose a DoS attack vector.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// use hashbrown::hash_map::DefaultHashBuilder;
-    ///
-    /// let s = DefaultHashBuilder::default();
-    /// let mut set = HashSet::with_hasher(s);
-    /// set.insert(2);
-    /// ```
-    #[inline]
-    pub fn with_hasher(hasher: S) -> Self {
-        Self {
-            map: HashMap::with_hasher(hasher),
-        }
-    }
-
-    /// Creates an empty `HashSet` with the specified capacity, using
-    /// `hasher` to hash the keys.
-    ///
-    /// The hash set will be able to hold at least `capacity` elements without
-    /// reallocating. If `capacity` is 0, the hash set will not allocate.
-    ///
-    /// Warning: `hasher` is normally randomly generated, and
-    /// is designed to allow `HashSet`s to be resistant to attacks that
-    /// cause many collisions and very poor performance. Setting it
-    /// manually using this function can expose a DoS attack vector.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// use hashbrown::hash_map::DefaultHashBuilder;
-    ///
-    /// let s = DefaultHashBuilder::default();
-    /// let mut set = HashSet::with_capacity_and_hasher(10, s);
-    /// set.insert(1);
-    /// ```
-    #[inline]
-    pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self {
-        Self {
-            map: HashMap::with_capacity_and_hasher(capacity, hasher),
-        }
-    }
-
-    /// Returns a reference to the set's [`BuildHasher`].
-    ///
-    /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// use hashbrown::hash_map::DefaultHashBuilder;
-    ///
-    /// let hasher = DefaultHashBuilder::default();
-    /// let set: HashSet<i32> = HashSet::with_hasher(hasher);
-    /// let hasher: &DefaultHashBuilder = set.hasher();
-    /// ```
-    #[inline]
-    pub fn hasher(&self) -> &S {
-        self.map.hasher()
-    }
-
-    /// Reserves capacity for at least `additional` more elements to be inserted
-    /// in the `HashSet`. The collection may reserve more space to avoid
-    /// frequent reallocations.
-    ///
-    /// # Panics
-    ///
-    /// Panics if the new allocation size overflows `usize`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// let mut set: HashSet<i32> = HashSet::new();
-    /// set.reserve(10);
-    /// assert!(set.capacity() >= 10);
-    /// ```
-    #[inline]
-    pub fn reserve(&mut self, additional: usize) {
-        self.map.reserve(additional)
-    }
-
-    /// Tries to reserve capacity for at least `additional` more elements to be inserted
-    /// in the given `HashSet<K,V>`. The collection may reserve more space to avoid
-    /// frequent reallocations.
-    ///
-    /// # Errors
-    ///
-    /// If the capacity overflows, or the allocator reports a failure, then an error
-    /// is returned.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// let mut set: HashSet<i32> = HashSet::new();
-    /// set.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?");
-    /// ```
-    #[inline]
-    pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
-        self.map.try_reserve(additional)
-    }
-
-    /// Shrinks the capacity of the set as much as possible. It will drop
-    /// down as much as possible while maintaining the internal rules
-    /// and possibly leaving some space in accordance with the resize policy.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let mut set = HashSet::with_capacity(100);
-    /// set.insert(1);
-    /// set.insert(2);
-    /// assert!(set.capacity() >= 100);
-    /// set.shrink_to_fit();
-    /// assert!(set.capacity() >= 2);
-    /// ```
-    #[inline]
-    pub fn shrink_to_fit(&mut self) {
-        self.map.shrink_to_fit()
-    }
-
-    /// Shrinks the capacity of the set with a lower limit. It will drop
-    /// down no lower than the supplied limit while maintaining the internal rules
-    /// and possibly leaving some space in accordance with the resize policy.
-    ///
-    /// Panics if the current capacity is smaller than the supplied
-    /// minimum capacity.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let mut set = HashSet::with_capacity(100);
-    /// set.insert(1);
-    /// set.insert(2);
-    /// assert!(set.capacity() >= 100);
-    /// set.shrink_to(10);
-    /// assert!(set.capacity() >= 10);
-    /// set.shrink_to(0);
-    /// assert!(set.capacity() >= 2);
-    /// ```
-    #[inline]
-    pub fn shrink_to(&mut self, min_capacity: usize) {
-        self.map.shrink_to(min_capacity)
-    }
-
-    /// Visits the values representing the difference,
-    /// i.e., the values that are in `self` but not in `other`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect();
-    /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect();
-    ///
-    /// // Can be seen as `a - b`.
-    /// for x in a.difference(&b) {
-    ///     println!("{}", x); // Print 1
-    /// }
-    ///
-    /// let diff: HashSet<_> = a.difference(&b).collect();
-    /// assert_eq!(diff, [1].iter().collect());
-    ///
-    /// // Note that difference is not symmetric,
-    /// // and `b - a` means something else:
-    /// let diff: HashSet<_> = b.difference(&a).collect();
-    /// assert_eq!(diff, [4].iter().collect());
-    /// ```
-    #[inline]
-    pub fn difference<'a>(&'a self, other: &'a Self) -> Difference<'a, T, S> {
-        Difference {
-            iter: self.iter(),
-            other,
-        }
-    }
-
-    /// Visits the values representing the symmetric difference,
-    /// i.e., the values that are in `self` or in `other` but not in both.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect();
-    /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect();
-    ///
-    /// // Print 1, 4 in arbitrary order.
-    /// for x in a.symmetric_difference(&b) {
-    ///     println!("{}", x);
-    /// }
-    ///
-    /// let diff1: HashSet<_> = a.symmetric_difference(&b).collect();
-    /// let diff2: HashSet<_> = b.symmetric_difference(&a).collect();
-    ///
-    /// assert_eq!(diff1, diff2);
-    /// assert_eq!(diff1, [1, 4].iter().collect());
-    /// ```
-    #[inline]
-    pub fn symmetric_difference<'a>(&'a self, other: &'a Self) -> SymmetricDifference<'a, T, S> {
-        SymmetricDifference {
-            iter: self.difference(other).chain(other.difference(self)),
-        }
-    }
-
-    /// Visits the values representing the intersection,
-    /// i.e., the values that are both in `self` and `other`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect();
-    /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect();
-    ///
-    /// // Print 2, 3 in arbitrary order.
-    /// for x in a.intersection(&b) {
-    ///     println!("{}", x);
-    /// }
-    ///
-    /// let intersection: HashSet<_> = a.intersection(&b).collect();
-    /// assert_eq!(intersection, [2, 3].iter().collect());
-    /// ```
-    #[inline]
-    pub fn intersection<'a>(&'a self, other: &'a Self) -> Intersection<'a, T, S> {
-        Intersection {
-            iter: self.iter(),
-            other,
-        }
-    }
-
-    /// Visits the values representing the union,
-    /// i.e., all the values in `self` or `other`, without duplicates.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect();
-    /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect();
-    ///
-    /// // Print 1, 2, 3, 4 in arbitrary order.
-    /// for x in a.union(&b) {
-    ///     println!("{}", x);
-    /// }
-    ///
-    /// let union: HashSet<_> = a.union(&b).collect();
-    /// assert_eq!(union, [1, 2, 3, 4].iter().collect());
-    /// ```
-    #[inline]
-    pub fn union<'a>(&'a self, other: &'a Self) -> Union<'a, T, S> {
-        Union {
-            iter: self.iter().chain(other.difference(self)),
-        }
-    }
-
-    /// Returns `true` if the set contains a value.
-    ///
-    /// The value may be any borrowed form of the set's value type, but
-    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
-    /// the value type.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
-    /// assert_eq!(set.contains(&1), true);
-    /// assert_eq!(set.contains(&4), false);
-    /// ```
-    ///
-    /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
-    /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
-    #[inline]
-    pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool
-    where
-        T: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        self.map.contains_key(value)
-    }
-
-    /// Returns a reference to the value in the set, if any, that is equal to the given value.
-    ///
-    /// The value may be any borrowed form of the set's value type, but
-    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
-    /// the value type.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
-    /// assert_eq!(set.get(&2), Some(&2));
-    /// assert_eq!(set.get(&4), None);
-    /// ```
-    ///
-    /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
-    /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
-    #[inline]
-    pub fn get<Q: ?Sized>(&self, value: &Q) -> Option<&T>
-    where
-        T: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        self.map.get_key_value(value).map(|(k, _)| k)
-    }
-
-    /// Returns `true` if `self` has no elements in common with `other`.
-    /// This is equivalent to checking for an empty intersection.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect();
-    /// let mut b = HashSet::new();
-    ///
-    /// assert_eq!(a.is_disjoint(&b), true);
-    /// b.insert(4);
-    /// assert_eq!(a.is_disjoint(&b), true);
-    /// b.insert(1);
-    /// assert_eq!(a.is_disjoint(&b), false);
-    /// ```
-    pub fn is_disjoint(&self, other: &Self) -> bool {
-        self.iter().all(|v| !other.contains(v))
-    }
-
-    /// Returns `true` if the set is a subset of another,
-    /// i.e., `other` contains at least all the values in `self`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let sup: HashSet<_> = [1, 2, 3].iter().cloned().collect();
-    /// let mut set = HashSet::new();
-    ///
-    /// assert_eq!(set.is_subset(&sup), true);
-    /// set.insert(2);
-    /// assert_eq!(set.is_subset(&sup), true);
-    /// set.insert(4);
-    /// assert_eq!(set.is_subset(&sup), false);
-    /// ```
-    pub fn is_subset(&self, other: &Self) -> bool {
-        if self.len() <= other.len() {
-            self.iter().all(|v| other.contains(v))
-        } else {
-            false
-        }
-    }
-
-    /// Returns `true` if the set is a superset of another,
-    /// i.e., `self` contains at least all the values in `other`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let sub: HashSet<_> = [1, 2].iter().cloned().collect();
-    /// let mut set = HashSet::new();
-    ///
-    /// assert_eq!(set.is_superset(&sub), false);
-    ///
-    /// set.insert(0);
-    /// set.insert(1);
-    /// assert_eq!(set.is_superset(&sub), false);
-    ///
-    /// set.insert(2);
-    /// assert_eq!(set.is_superset(&sub), true);
-    /// ```
-    #[inline]
-    pub fn is_superset(&self, other: &Self) -> bool {
-        other.is_subset(self)
-    }
-
-    /// Adds a value to the set.
-    ///
-    /// If the set did not have this value present, `true` is returned.
-    ///
-    /// If the set did have this value present, `false` is returned.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let mut set = HashSet::new();
-    ///
-    /// assert_eq!(set.insert(2), true);
-    /// assert_eq!(set.insert(2), false);
-    /// assert_eq!(set.len(), 1);
-    /// ```
-    #[inline]
-    pub fn insert(&mut self, value: T) -> bool {
-        self.map.insert(value, ()).is_none()
-    }
-
-    /// Adds a value to the set, replacing the existing value, if any, that is equal to the given
-    /// one. Returns the replaced value.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let mut set = HashSet::new();
-    /// set.insert(Vec::<i32>::new());
-    ///
-    /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 0);
-    /// set.replace(Vec::with_capacity(10));
-    /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 10);
-    /// ```
-    #[inline]
-    pub fn replace(&mut self, value: T) -> Option<T> {
-        match self.map.entry(value) {
-            map::Entry::Occupied(occupied) => Some(occupied.replace_key()),
-            map::Entry::Vacant(vacant) => {
-                vacant.insert(());
-                None
-            }
-        }
-    }
-
-    /// Removes a value from the set. Returns whether the value was
-    /// present in the set.
-    ///
-    /// The value may be any borrowed form of the set's value type, but
-    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
-    /// the value type.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let mut set = HashSet::new();
-    ///
-    /// set.insert(2);
-    /// assert_eq!(set.remove(&2), true);
-    /// assert_eq!(set.remove(&2), false);
-    /// ```
-    ///
-    /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
-    /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
-    #[inline]
-    pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool
-    where
-        T: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        self.map.remove(value).is_some()
-    }
-
-    /// Removes and returns the value in the set, if any, that is equal to the given one.
-    ///
-    /// The value may be any borrowed form of the set's value type, but
-    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
-    /// the value type.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
-    /// assert_eq!(set.take(&2), Some(2));
-    /// assert_eq!(set.take(&2), None);
-    /// ```
-    ///
-    /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
-    /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
-    #[inline]
-    pub fn take<Q: ?Sized>(&mut self, value: &Q) -> Option<T>
-    where
-        T: Borrow<Q>,
-        Q: Hash + Eq,
-    {
-        self.map.remove_entry(value).map(|(k, _)| k)
-    }
-
-    /// Retains only the elements specified by the predicate.
-    ///
-    /// In other words, remove all elements `e` such that `f(&e)` returns `false`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let xs = [1,2,3,4,5,6];
-    /// let mut set: HashSet<i32> = xs.iter().cloned().collect();
-    /// set.retain(|&k| k % 2 == 0);
-    /// assert_eq!(set.len(), 3);
-    /// ```
-    pub fn retain<F>(&mut self, mut f: F)
-    where
-        F: FnMut(&T) -> bool,
-    {
-        self.map.retain(|k, _| f(k));
-    }
-}
-
-impl<T, S> PartialEq for HashSet<T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher,
-{
-    fn eq(&self, other: &Self) -> bool {
-        if self.len() != other.len() {
-            return false;
-        }
-
-        self.iter().all(|key| other.contains(key))
-    }
-}
-
-impl<T, S> Eq for HashSet<T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher,
-{
-}
-
-impl<T, S> fmt::Debug for HashSet<T, S>
-where
-    T: Eq + Hash + fmt::Debug,
-    S: BuildHasher,
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_set().entries(self.iter()).finish()
-    }
-}
-
-impl<T, S> FromIterator<T> for HashSet<T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher + Default,
-{
-    #[inline]
-    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
-        let mut set = Self::with_hasher(Default::default());
-        set.extend(iter);
-        set
-    }
-}
-
-impl<T, S> Extend<T> for HashSet<T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher,
-{
-    #[inline]
-    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
-        self.map.extend(iter.into_iter().map(|k| (k, ())));
-    }
-}
-
-impl<'a, T, S> Extend<&'a T> for HashSet<T, S>
-where
-    T: 'a + Eq + Hash + Copy,
-    S: BuildHasher,
-{
-    #[inline]
-    fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
-        self.extend(iter.into_iter().cloned());
-    }
-}
-
-impl<T, S> Default for HashSet<T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher + Default,
-{
-    /// Creates an empty `HashSet<T, S>` with the `Default` value for the hasher.
-    #[inline]
-    fn default() -> Self {
-        Self {
-            map: HashMap::default(),
-        }
-    }
-}
-
-impl<T, S> BitOr<&HashSet<T, S>> for &HashSet<T, S>
-where
-    T: Eq + Hash + Clone,
-    S: BuildHasher + Default,
-{
-    type Output = HashSet<T, S>;
-
-    /// Returns the union of `self` and `rhs` as a new `HashSet<T, S>`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect();
-    /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect();
-    ///
-    /// let set = &a | &b;
-    ///
-    /// let mut i = 0;
-    /// let expected = [1, 2, 3, 4, 5];
-    /// for x in &set {
-    ///     assert!(expected.contains(x));
-    ///     i += 1;
-    /// }
-    /// assert_eq!(i, expected.len());
-    /// ```
-    fn bitor(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
-        self.union(rhs).cloned().collect()
-    }
-}
-
-impl<T, S> BitAnd<&HashSet<T, S>> for &HashSet<T, S>
-where
-    T: Eq + Hash + Clone,
-    S: BuildHasher + Default,
-{
-    type Output = HashSet<T, S>;
-
-    /// Returns the intersection of `self` and `rhs` as a new `HashSet<T, S>`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect();
-    /// let b: HashSet<_> = vec![2, 3, 4].into_iter().collect();
-    ///
-    /// let set = &a & &b;
-    ///
-    /// let mut i = 0;
-    /// let expected = [2, 3];
-    /// for x in &set {
-    ///     assert!(expected.contains(x));
-    ///     i += 1;
-    /// }
-    /// assert_eq!(i, expected.len());
-    /// ```
-    fn bitand(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
-        self.intersection(rhs).cloned().collect()
-    }
-}
-
-impl<T, S> BitXor<&HashSet<T, S>> for &HashSet<T, S>
-where
-    T: Eq + Hash + Clone,
-    S: BuildHasher + Default,
-{
-    type Output = HashSet<T, S>;
-
-    /// Returns the symmetric difference of `self` and `rhs` as a new `HashSet<T, S>`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect();
-    /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect();
-    ///
-    /// let set = &a ^ &b;
-    ///
-    /// let mut i = 0;
-    /// let expected = [1, 2, 4, 5];
-    /// for x in &set {
-    ///     assert!(expected.contains(x));
-    ///     i += 1;
-    /// }
-    /// assert_eq!(i, expected.len());
-    /// ```
-    fn bitxor(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
-        self.symmetric_difference(rhs).cloned().collect()
-    }
-}
-
-impl<T, S> Sub<&HashSet<T, S>> for &HashSet<T, S>
-where
-    T: Eq + Hash + Clone,
-    S: BuildHasher + Default,
-{
-    type Output = HashSet<T, S>;
-
-    /// Returns the difference of `self` and `rhs` as a new `HashSet<T, S>`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    ///
-    /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect();
-    /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect();
-    ///
-    /// let set = &a - &b;
-    ///
-    /// let mut i = 0;
-    /// let expected = [1, 2];
-    /// for x in &set {
-    ///     assert!(expected.contains(x));
-    ///     i += 1;
-    /// }
-    /// assert_eq!(i, expected.len());
-    /// ```
-    fn sub(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
-        self.difference(rhs).cloned().collect()
-    }
-}
-
-/// An iterator over the items of a `HashSet`.
-///
-/// This `struct` is created by the [`iter`] method on [`HashSet`].
-/// See its documentation for more.
-///
-/// [`HashSet`]: struct.HashSet.html
-/// [`iter`]: struct.HashSet.html#method.iter
-pub struct Iter<'a, K> {
-    iter: Keys<'a, K, ()>,
-}
-
-/// An owning iterator over the items of a `HashSet`.
-///
-/// This `struct` is created by the [`into_iter`] method on [`HashSet`][`HashSet`]
-/// (provided by the `IntoIterator` trait). See its documentation for more.
-///
-/// [`HashSet`]: struct.HashSet.html
-/// [`into_iter`]: struct.HashSet.html#method.into_iter
-pub struct IntoIter<K> {
-    iter: map::IntoIter<K, ()>,
-}
-
-/// A draining iterator over the items of a `HashSet`.
-///
-/// This `struct` is created by the [`drain`] method on [`HashSet`].
-/// See its documentation for more.
-///
-/// [`HashSet`]: struct.HashSet.html
-/// [`drain`]: struct.HashSet.html#method.drain
-pub struct Drain<'a, K> {
-    iter: map::Drain<'a, K, ()>,
-}
-
-/// A lazy iterator producing elements in the intersection of `HashSet`s.
-///
-/// This `struct` is created by the [`intersection`] method on [`HashSet`].
-/// See its documentation for more.
-///
-/// [`HashSet`]: struct.HashSet.html
-/// [`intersection`]: struct.HashSet.html#method.intersection
-pub struct Intersection<'a, T, S> {
-    // iterator of the first set
-    iter: Iter<'a, T>,
-    // the second set
-    other: &'a HashSet<T, S>,
-}
-
-/// A lazy iterator producing elements in the difference of `HashSet`s.
-///
-/// This `struct` is created by the [`difference`] method on [`HashSet`].
-/// See its documentation for more.
-///
-/// [`HashSet`]: struct.HashSet.html
-/// [`difference`]: struct.HashSet.html#method.difference
-pub struct Difference<'a, T, S> {
-    // iterator of the first set
-    iter: Iter<'a, T>,
-    // the second set
-    other: &'a HashSet<T, S>,
-}
-
-/// A lazy iterator producing elements in the symmetric difference of `HashSet`s.
-///
-/// This `struct` is created by the [`symmetric_difference`] method on
-/// [`HashSet`]. See its documentation for more.
-///
-/// [`HashSet`]: struct.HashSet.html
-/// [`symmetric_difference`]: struct.HashSet.html#method.symmetric_difference
-pub struct SymmetricDifference<'a, T, S> {
-    iter: Chain<Difference<'a, T, S>, Difference<'a, T, S>>,
-}
-
-/// A lazy iterator producing elements in the union of `HashSet`s.
-///
-/// This `struct` is created by the [`union`] method on [`HashSet`].
-/// See its documentation for more.
-///
-/// [`HashSet`]: struct.HashSet.html
-/// [`union`]: struct.HashSet.html#method.union
-pub struct Union<'a, T, S> {
-    iter: Chain<Iter<'a, T>, Difference<'a, T, S>>,
-}
-
-impl<'a, T, S> IntoIterator for &'a HashSet<T, S> {
-    type Item = &'a T;
-    type IntoIter = Iter<'a, T>;
-
-    #[inline]
-    fn into_iter(self) -> Iter<'a, T> {
-        self.iter()
-    }
-}
-
-impl<T, S> IntoIterator for HashSet<T, S> {
-    type Item = T;
-    type IntoIter = IntoIter<T>;
-
-    /// Creates a consuming iterator, that is, one that moves each value out
-    /// of the set in arbitrary order. The set cannot be used after calling
-    /// this.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use hashbrown::HashSet;
-    /// let mut set = HashSet::new();
-    /// set.insert("a".to_string());
-    /// set.insert("b".to_string());
-    ///
-    /// // Not possible to collect to a Vec<String> with a regular `.iter()`.
-    /// let v: Vec<String> = set.into_iter().collect();
-    ///
-    /// // Will print in an arbitrary order.
-    /// for x in &v {
-    ///     println!("{}", x);
-    /// }
-    /// ```
-    #[inline]
-    fn into_iter(self) -> IntoIter<T> {
-        IntoIter {
-            iter: self.map.into_iter(),
-        }
-    }
-}
-
-impl<K> Clone for Iter<'_, K> {
-    #[inline]
-    fn clone(&self) -> Self {
-        Iter {
-            iter: self.iter.clone(),
-        }
-    }
-}
-impl<'a, K> Iterator for Iter<'a, K> {
-    type Item = &'a K;
-
-    #[inline]
-    fn next(&mut self) -> Option<&'a K> {
-        self.iter.next()
-    }
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-impl<'a, K> ExactSizeIterator for Iter<'a, K> {
-    #[inline]
-    fn len(&self) -> usize {
-        self.iter.len()
-    }
-}
-impl<K> FusedIterator for Iter<'_, K> {}
-
-impl<K: fmt::Debug> fmt::Debug for Iter<'_, K> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().entries(self.clone()).finish()
-    }
-}
-
-impl<K> Iterator for IntoIter<K> {
-    type Item = K;
-
-    #[inline]
-    fn next(&mut self) -> Option<K> {
-        self.iter.next().map(|(k, _)| k)
-    }
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-impl<K> ExactSizeIterator for IntoIter<K> {
-    #[inline]
-    fn len(&self) -> usize {
-        self.iter.len()
-    }
-}
-impl<K> FusedIterator for IntoIter<K> {}
-
-impl<K: fmt::Debug> fmt::Debug for IntoIter<K> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let entries_iter = self.iter.iter().map(|(k, _)| k);
-        f.debug_list().entries(entries_iter).finish()
-    }
-}
-
-impl<K> Iterator for Drain<'_, K> {
-    type Item = K;
-
-    #[inline]
-    fn next(&mut self) -> Option<K> {
-        self.iter.next().map(|(k, _)| k)
-    }
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-impl<K> ExactSizeIterator for Drain<'_, K> {
-    #[inline]
-    fn len(&self) -> usize {
-        self.iter.len()
-    }
-}
-impl<K> FusedIterator for Drain<'_, K> {}
-
-impl<K: fmt::Debug> fmt::Debug for Drain<'_, K> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let entries_iter = self.iter.iter().map(|(k, _)| k);
-        f.debug_list().entries(entries_iter).finish()
-    }
-}
-
-impl<T, S> Clone for Intersection<'_, T, S> {
-    #[inline]
-    fn clone(&self) -> Self {
-        Intersection {
-            iter: self.iter.clone(),
-            ..*self
-        }
-    }
-}
-
-impl<'a, T, S> Iterator for Intersection<'a, T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher,
-{
-    type Item = &'a T;
-
-    #[inline]
-    fn next(&mut self) -> Option<&'a T> {
-        loop {
-            let elt = self.iter.next()?;
-            if self.other.contains(elt) {
-                return Some(elt);
-            }
-        }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let (_, upper) = self.iter.size_hint();
-        (0, upper)
-    }
-}
-
-impl<T, S> fmt::Debug for Intersection<'_, T, S>
-where
-    T: fmt::Debug + Eq + Hash,
-    S: BuildHasher,
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().entries(self.clone()).finish()
-    }
-}
-
-impl<T, S> FusedIterator for Intersection<'_, T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher,
-{
-}
-
-impl<T, S> Clone for Difference<'_, T, S> {
-    #[inline]
-    fn clone(&self) -> Self {
-        Difference {
-            iter: self.iter.clone(),
-            ..*self
-        }
-    }
-}
-
-impl<'a, T, S> Iterator for Difference<'a, T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher,
-{
-    type Item = &'a T;
-
-    #[inline]
-    fn next(&mut self) -> Option<&'a T> {
-        loop {
-            let elt = self.iter.next()?;
-            if !self.other.contains(elt) {
-                return Some(elt);
-            }
-        }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let (_, upper) = self.iter.size_hint();
-        (0, upper)
-    }
-}
-
-impl<T, S> FusedIterator for Difference<'_, T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher,
-{
-}
-
-impl<T, S> fmt::Debug for Difference<'_, T, S>
-where
-    T: fmt::Debug + Eq + Hash,
-    S: BuildHasher,
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().entries(self.clone()).finish()
-    }
-}
-
-impl<T, S> Clone for SymmetricDifference<'_, T, S> {
-    #[inline]
-    fn clone(&self) -> Self {
-        SymmetricDifference {
-            iter: self.iter.clone(),
-        }
-    }
-}
-
-impl<'a, T, S> Iterator for SymmetricDifference<'a, T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher,
-{
-    type Item = &'a T;
-
-    #[inline]
-    fn next(&mut self) -> Option<&'a T> {
-        self.iter.next()
-    }
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-
-impl<T, S> FusedIterator for SymmetricDifference<'_, T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher,
-{
-}
-
-impl<T, S> fmt::Debug for SymmetricDifference<'_, T, S>
-where
-    T: fmt::Debug + Eq + Hash,
-    S: BuildHasher,
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().entries(self.clone()).finish()
-    }
-}
-
-impl<T, S> Clone for Union<'_, T, S> {
-    #[inline]
-    fn clone(&self) -> Self {
-        Union {
-            iter: self.iter.clone(),
-        }
-    }
-}
-
-impl<T, S> FusedIterator for Union<'_, T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher,
-{
-}
-
-impl<T, S> fmt::Debug for Union<'_, T, S>
-where
-    T: fmt::Debug + Eq + Hash,
-    S: BuildHasher,
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().entries(self.clone()).finish()
-    }
-}
-
-impl<'a, T, S> Iterator for Union<'a, T, S>
-where
-    T: Eq + Hash,
-    S: BuildHasher,
-{
-    type Item = &'a T;
-
-    #[inline]
-    fn next(&mut self) -> Option<&'a T> {
-        self.iter.next()
-    }
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
-    }
-}
-
-#[allow(dead_code)]
-fn assert_covariance() {
-    fn set<'new>(v: HashSet<&'static str>) -> HashSet<&'new str> {
-        v
-    }
-    fn iter<'a, 'new>(v: Iter<'a, &'static str>) -> Iter<'a, &'new str> {
-        v
-    }
-    fn into_iter<'new>(v: IntoIter<&'static str>) -> IntoIter<&'new str> {
-        v
-    }
-    fn difference<'a, 'new>(
-        v: Difference<'a, &'static str, DefaultHashBuilder>,
-    ) -> Difference<'a, &'new str, DefaultHashBuilder> {
-        v
-    }
-    fn symmetric_difference<'a, 'new>(
-        v: SymmetricDifference<'a, &'static str, DefaultHashBuilder>,
-    ) -> SymmetricDifference<'a, &'new str, DefaultHashBuilder> {
-        v
-    }
-    fn intersection<'a, 'new>(
-        v: Intersection<'a, &'static str, DefaultHashBuilder>,
-    ) -> Intersection<'a, &'new str, DefaultHashBuilder> {
-        v
-    }
-    fn union<'a, 'new>(
-        v: Union<'a, &'static str, DefaultHashBuilder>,
-    ) -> Union<'a, &'new str, DefaultHashBuilder> {
-        v
-    }
-    fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> {
-        d
-    }
-}
-
-#[cfg(test)]
-mod test_set {
-    use super::super::map::DefaultHashBuilder;
-    use super::HashSet;
-    use std::vec::Vec;
-
-    #[test]
-    fn test_zero_capacities() {
-        type HS = HashSet<i32>;
-
-        let s = HS::new();
-        assert_eq!(s.capacity(), 0);
-
-        let s = HS::default();
-        assert_eq!(s.capacity(), 0);
-
-        let s = HS::with_hasher(DefaultHashBuilder::default());
-        assert_eq!(s.capacity(), 0);
-
-        let s = HS::with_capacity(0);
-        assert_eq!(s.capacity(), 0);
-
-        let s = HS::with_capacity_and_hasher(0, DefaultHashBuilder::default());
-        assert_eq!(s.capacity(), 0);
-
-        let mut s = HS::new();
-        s.insert(1);
-        s.insert(2);
-        s.remove(&1);
-        s.remove(&2);
-        s.shrink_to_fit();
-        assert_eq!(s.capacity(), 0);
-
-        let mut s = HS::new();
-        s.reserve(0);
-        assert_eq!(s.capacity(), 0);
-    }
-
-    #[test]
-    fn test_disjoint() {
-        let mut xs = HashSet::new();
-        let mut ys = HashSet::new();
-        assert!(xs.is_disjoint(&ys));
-        assert!(ys.is_disjoint(&xs));
-        assert!(xs.insert(5));
-        assert!(ys.insert(11));
-        assert!(xs.is_disjoint(&ys));
-        assert!(ys.is_disjoint(&xs));
-        assert!(xs.insert(7));
-        assert!(xs.insert(19));
-        assert!(xs.insert(4));
-        assert!(ys.insert(2));
-        assert!(ys.insert(-11));
-        assert!(xs.is_disjoint(&ys));
-        assert!(ys.is_disjoint(&xs));
-        assert!(ys.insert(7));
-        assert!(!xs.is_disjoint(&ys));
-        assert!(!ys.is_disjoint(&xs));
-    }
-
-    #[test]
-    fn test_subset_and_superset() {
-        let mut a = HashSet::new();
-        assert!(a.insert(0));
-        assert!(a.insert(5));
-        assert!(a.insert(11));
-        assert!(a.insert(7));
-
-        let mut b = HashSet::new();
-        assert!(b.insert(0));
-        assert!(b.insert(7));
-        assert!(b.insert(19));
-        assert!(b.insert(250));
-        assert!(b.insert(11));
-        assert!(b.insert(200));
-
-        assert!(!a.is_subset(&b));
-        assert!(!a.is_superset(&b));
-        assert!(!b.is_subset(&a));
-        assert!(!b.is_superset(&a));
-
-        assert!(b.insert(5));
-
-        assert!(a.is_subset(&b));
-        assert!(!a.is_superset(&b));
-        assert!(!b.is_subset(&a));
-        assert!(b.is_superset(&a));
-    }
-
-    #[test]
-    fn test_iterate() {
-        let mut a = HashSet::new();
-        for i in 0..32 {
-            assert!(a.insert(i));
-        }
-        let mut observed: u32 = 0;
-        for k in &a {
-            observed |= 1 << *k;
-        }
-        assert_eq!(observed, 0xFFFF_FFFF);
-    }
-
-    #[test]
-    fn test_intersection() {
-        let mut a = HashSet::new();
-        let mut b = HashSet::new();
-
-        assert!(a.insert(11));
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(77));
-        assert!(a.insert(103));
-        assert!(a.insert(5));
-        assert!(a.insert(-5));
-
-        assert!(b.insert(2));
-        assert!(b.insert(11));
-        assert!(b.insert(77));
-        assert!(b.insert(-9));
-        assert!(b.insert(-42));
-        assert!(b.insert(5));
-        assert!(b.insert(3));
-
-        let mut i = 0;
-        let expected = [3, 5, 11, 77];
-        for x in a.intersection(&b) {
-            assert!(expected.contains(x));
-            i += 1
-        }
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_difference() {
-        let mut a = HashSet::new();
-        let mut b = HashSet::new();
-
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(5));
-        assert!(a.insert(9));
-        assert!(a.insert(11));
-
-        assert!(b.insert(3));
-        assert!(b.insert(9));
-
-        let mut i = 0;
-        let expected = [1, 5, 11];
-        for x in a.difference(&b) {
-            assert!(expected.contains(x));
-            i += 1
-        }
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_symmetric_difference() {
-        let mut a = HashSet::new();
-        let mut b = HashSet::new();
-
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(5));
-        assert!(a.insert(9));
-        assert!(a.insert(11));
-
-        assert!(b.insert(-2));
-        assert!(b.insert(3));
-        assert!(b.insert(9));
-        assert!(b.insert(14));
-        assert!(b.insert(22));
-
-        let mut i = 0;
-        let expected = [-2, 1, 5, 11, 14, 22];
-        for x in a.symmetric_difference(&b) {
-            assert!(expected.contains(x));
-            i += 1
-        }
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_union() {
-        let mut a = HashSet::new();
-        let mut b = HashSet::new();
-
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(5));
-        assert!(a.insert(9));
-        assert!(a.insert(11));
-        assert!(a.insert(16));
-        assert!(a.insert(19));
-        assert!(a.insert(24));
-
-        assert!(b.insert(-2));
-        assert!(b.insert(1));
-        assert!(b.insert(5));
-        assert!(b.insert(9));
-        assert!(b.insert(13));
-        assert!(b.insert(19));
-
-        let mut i = 0;
-        let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24];
-        for x in a.union(&b) {
-            assert!(expected.contains(x));
-            i += 1
-        }
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_from_iter() {
-        let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9];
-
-        let set: HashSet<_> = xs.iter().cloned().collect();
-
-        for x in &xs {
-            assert!(set.contains(x));
-        }
-    }
-
-    #[test]
-    fn test_move_iter() {
-        let hs = {
-            let mut hs = HashSet::new();
-
-            hs.insert('a');
-            hs.insert('b');
-
-            hs
-        };
-
-        let v = hs.into_iter().collect::<Vec<char>>();
-        assert!(v == ['a', 'b'] || v == ['b', 'a']);
-    }
-
-    #[test]
-    fn test_eq() {
-        // These constants once happened to expose a bug in insert().
-        // I'm keeping them around to prevent a regression.
-        let mut s1 = HashSet::new();
-
-        s1.insert(1);
-        s1.insert(2);
-        s1.insert(3);
-
-        let mut s2 = HashSet::new();
-
-        s2.insert(1);
-        s2.insert(2);
-
-        assert!(s1 != s2);
-
-        s2.insert(3);
-
-        assert_eq!(s1, s2);
-    }
-
-    #[test]
-    fn test_show() {
-        let mut set = HashSet::new();
-        let empty = HashSet::<i32>::new();
-
-        set.insert(1);
-        set.insert(2);
-
-        let set_str = format!("{:?}", set);
-
-        assert!(set_str == "{1, 2}" || set_str == "{2, 1}");
-        assert_eq!(format!("{:?}", empty), "{}");
-    }
-
-    #[test]
-    fn test_trivial_drain() {
-        let mut s = HashSet::<i32>::new();
-        for _ in s.drain() {}
-        assert!(s.is_empty());
-        drop(s);
-
-        let mut s = HashSet::<i32>::new();
-        drop(s.drain());
-        assert!(s.is_empty());
-    }
-
-    #[test]
-    fn test_drain() {
-        let mut s: HashSet<_> = (1..100).collect();
-
-        // try this a bunch of times to make sure we don't screw up internal state.
-        for _ in 0..20 {
-            assert_eq!(s.len(), 99);
-
-            {
-                let mut last_i = 0;
-                let mut d = s.drain();
-                for (i, x) in d.by_ref().take(50).enumerate() {
-                    last_i = i;
-                    assert!(x != 0);
-                }
-                assert_eq!(last_i, 49);
-            }
-
-            for _ in &s {
-                panic!("s should be empty!");
-            }
-
-            // reset to try again.
-            s.extend(1..100);
-        }
-    }
-
-    #[test]
-    fn test_replace() {
-        use core::hash;
-
-        #[derive(Debug)]
-        struct Foo(&'static str, i32);
-
-        impl PartialEq for Foo {
-            fn eq(&self, other: &Self) -> bool {
-                self.0 == other.0
-            }
-        }
-
-        impl Eq for Foo {}
-
-        impl hash::Hash for Foo {
-            fn hash<H: hash::Hasher>(&self, h: &mut H) {
-                self.0.hash(h);
-            }
-        }
-
-        let mut s = HashSet::new();
-        assert_eq!(s.replace(Foo("a", 1)), None);
-        assert_eq!(s.len(), 1);
-        assert_eq!(s.replace(Foo("a", 2)), Some(Foo("a", 1)));
-        assert_eq!(s.len(), 1);
-
-        let mut it = s.iter();
-        assert_eq!(it.next(), Some(&Foo("a", 2)));
-        assert_eq!(it.next(), None);
-    }
-
-    #[test]
-    fn test_extend_ref() {
-        let mut a = HashSet::new();
-        a.insert(1);
-
-        a.extend(&[2, 3, 4]);
-
-        assert_eq!(a.len(), 4);
-        assert!(a.contains(&1));
-        assert!(a.contains(&2));
-        assert!(a.contains(&3));
-        assert!(a.contains(&4));
-
-        let mut b = HashSet::new();
-        b.insert(5);
-        b.insert(6);
-
-        a.extend(&b);
-
-        assert_eq!(a.len(), 6);
-        assert!(a.contains(&1));
-        assert!(a.contains(&2));
-        assert!(a.contains(&3));
-        assert!(a.contains(&4));
-        assert!(a.contains(&5));
-        assert!(a.contains(&6));
-    }
-
-    #[test]
-    fn test_retain() {
-        let xs = [1, 2, 3, 4, 5, 6];
-        let mut set: HashSet<i32> = xs.iter().cloned().collect();
-        set.retain(|&k| k % 2 == 0);
-        assert_eq!(set.len(), 3);
-        assert!(set.contains(&2));
-        assert!(set.contains(&4));
-        assert!(set.contains(&6));
-    }
-}
diff --git a/third_party/rust_crates/vendor/hashbrown/tests/hasher.rs b/third_party/rust_crates/vendor/hashbrown/tests/hasher.rs
deleted file mode 100644
index e455e3d3..0000000
--- a/third_party/rust_crates/vendor/hashbrown/tests/hasher.rs
+++ /dev/null
@@ -1,65 +0,0 @@
-//! Sanity check that alternate hashers work correctly.
-
-#![cfg(not(miri))] // FIXME: takes too long
-
-use hashbrown::HashSet;
-use std::hash::{BuildHasher, BuildHasherDefault, Hasher};
-
-fn check<S: BuildHasher + Default>() {
-    let range = 0..1_000;
-
-    let mut set = HashSet::<i32, S>::default();
-    set.extend(range.clone());
-
-    assert!(!set.contains(&i32::min_value()));
-    assert!(!set.contains(&(range.start - 1)));
-    for i in range.clone() {
-        assert!(set.contains(&i));
-    }
-    assert!(!set.contains(&range.end));
-    assert!(!set.contains(&i32::max_value()));
-}
-
-/// Use hashbrown's default hasher.
-#[test]
-fn default() {
-    check::<hashbrown::hash_map::DefaultHashBuilder>();
-}
-
-/// Use std's default hasher.
-#[test]
-fn random_state() {
-    check::<std::collections::hash_map::RandomState>();
-}
-
-/// Use a constant 0 hash.
-#[test]
-fn zero() {
-    #[derive(Default)]
-    struct ZeroHasher;
-
-    impl Hasher for ZeroHasher {
-        fn finish(&self) -> u64 {
-            0
-        }
-        fn write(&mut self, _: &[u8]) {}
-    }
-
-    check::<BuildHasherDefault<ZeroHasher>>();
-}
-
-/// Use a constant maximum hash.
-#[test]
-fn max() {
-    #[derive(Default)]
-    struct MaxHasher;
-
-    impl Hasher for MaxHasher {
-        fn finish(&self) -> u64 {
-            u64::max_value()
-        }
-        fn write(&mut self, _: &[u8]) {}
-    }
-
-    check::<BuildHasherDefault<MaxHasher>>();
-}
diff --git a/third_party/rust_crates/vendor/hashbrown/tests/rayon.rs b/third_party/rust_crates/vendor/hashbrown/tests/rayon.rs
deleted file mode 100644
index 39b4770..0000000
--- a/third_party/rust_crates/vendor/hashbrown/tests/rayon.rs
+++ /dev/null
@@ -1,533 +0,0 @@
-#![cfg(feature = "rayon")]
-
-#[macro_use]
-extern crate lazy_static;
-
-use hashbrown::{HashMap, HashSet};
-use rayon::iter::{
-    IntoParallelIterator, IntoParallelRefIterator, IntoParallelRefMutIterator, ParallelExtend,
-    ParallelIterator,
-};
-
-macro_rules! assert_eq3 {
-    ($e1:expr, $e2:expr, $e3:expr) => {{
-        assert_eq!($e1, $e2);
-        assert_eq!($e1, $e3);
-        assert_eq!($e2, $e3);
-    }};
-}
-
-lazy_static! {
-    static ref MAP_EMPTY: HashMap<char, u32> = HashMap::new();
-    static ref MAP: HashMap<char, u32> = {
-        let mut m = HashMap::new();
-        m.insert('b', 20);
-        m.insert('a', 10);
-        m.insert('c', 30);
-        m.insert('e', 50);
-        m.insert('f', 60);
-        m.insert('d', 40);
-        m
-    };
-}
-
-#[test]
-fn map_seq_par_equivalence_iter_empty() {
-    let vec_seq = MAP_EMPTY.iter().collect::<Vec<_>>();
-    let vec_par = MAP_EMPTY.par_iter().collect::<Vec<_>>();
-
-    assert_eq3!(vec_seq, vec_par, []);
-}
-
-#[test]
-fn map_seq_par_equivalence_iter() {
-    let mut vec_seq = MAP.iter().collect::<Vec<_>>();
-    let mut vec_par = MAP.par_iter().collect::<Vec<_>>();
-
-    assert_eq!(vec_seq, vec_par);
-
-    // Do not depend on the exact order of values
-    let expected_sorted = [
-        (&'a', &10),
-        (&'b', &20),
-        (&'c', &30),
-        (&'d', &40),
-        (&'e', &50),
-        (&'f', &60),
-    ];
-
-    vec_seq.sort_unstable();
-    vec_par.sort_unstable();
-
-    assert_eq3!(vec_seq, vec_par, expected_sorted);
-}
-
-#[test]
-fn map_seq_par_equivalence_keys_empty() {
-    let vec_seq = MAP_EMPTY.keys().collect::<Vec<&char>>();
-    let vec_par = MAP_EMPTY.par_keys().collect::<Vec<&char>>();
-
-    let expected: [&char; 0] = [];
-
-    assert_eq3!(vec_seq, vec_par, expected);
-}
-
-#[test]
-fn map_seq_par_equivalence_keys() {
-    let mut vec_seq = MAP.keys().collect::<Vec<_>>();
-    let mut vec_par = MAP.par_keys().collect::<Vec<_>>();
-
-    assert_eq!(vec_seq, vec_par);
-
-    // Do not depend on the exact order of values
-    let expected_sorted = [&'a', &'b', &'c', &'d', &'e', &'f'];
-
-    vec_seq.sort_unstable();
-    vec_par.sort_unstable();
-
-    assert_eq3!(vec_seq, vec_par, expected_sorted);
-}
-
-#[test]
-fn map_seq_par_equivalence_values_empty() {
-    let vec_seq = MAP_EMPTY.values().collect::<Vec<_>>();
-    let vec_par = MAP_EMPTY.par_values().collect::<Vec<_>>();
-
-    let expected: [&u32; 0] = [];
-
-    assert_eq3!(vec_seq, vec_par, expected);
-}
-
-#[test]
-fn map_seq_par_equivalence_values() {
-    let mut vec_seq = MAP.values().collect::<Vec<_>>();
-    let mut vec_par = MAP.par_values().collect::<Vec<_>>();
-
-    assert_eq!(vec_seq, vec_par);
-
-    // Do not depend on the exact order of values
-    let expected_sorted = [&10, &20, &30, &40, &50, &60];
-
-    vec_seq.sort_unstable();
-    vec_par.sort_unstable();
-
-    assert_eq3!(vec_seq, vec_par, expected_sorted);
-}
-
-#[test]
-fn map_seq_par_equivalence_iter_mut_empty() {
-    let mut map1 = MAP_EMPTY.clone();
-    let mut map2 = MAP_EMPTY.clone();
-
-    let vec_seq = map1.iter_mut().collect::<Vec<_>>();
-    let vec_par = map2.par_iter_mut().collect::<Vec<_>>();
-
-    assert_eq3!(vec_seq, vec_par, []);
-}
-
-#[test]
-fn map_seq_par_equivalence_iter_mut() {
-    let mut map1 = MAP.clone();
-    let mut map2 = MAP.clone();
-
-    let mut vec_seq = map1.iter_mut().collect::<Vec<_>>();
-    let mut vec_par = map2.par_iter_mut().collect::<Vec<_>>();
-
-    assert_eq!(vec_seq, vec_par);
-
-    // Do not depend on the exact order of values
-    let expected_sorted = [
-        (&'a', &mut 10),
-        (&'b', &mut 20),
-        (&'c', &mut 30),
-        (&'d', &mut 40),
-        (&'e', &mut 50),
-        (&'f', &mut 60),
-    ];
-
-    vec_seq.sort_unstable();
-    vec_par.sort_unstable();
-
-    assert_eq3!(vec_seq, vec_par, expected_sorted);
-}
-
-#[test]
-fn map_seq_par_equivalence_values_mut_empty() {
-    let mut map1 = MAP_EMPTY.clone();
-    let mut map2 = MAP_EMPTY.clone();
-
-    let vec_seq = map1.values_mut().collect::<Vec<_>>();
-    let vec_par = map2.par_values_mut().collect::<Vec<_>>();
-
-    let expected: [&u32; 0] = [];
-
-    assert_eq3!(vec_seq, vec_par, expected);
-}
-
-#[test]
-fn map_seq_par_equivalence_values_mut() {
-    let mut map1 = MAP.clone();
-    let mut map2 = MAP.clone();
-
-    let mut vec_seq = map1.values_mut().collect::<Vec<_>>();
-    let mut vec_par = map2.par_values_mut().collect::<Vec<_>>();
-
-    assert_eq!(vec_seq, vec_par);
-
-    // Do not depend on the exact order of values
-    let expected_sorted = [&mut 10, &mut 20, &mut 30, &mut 40, &mut 50, &mut 60];
-
-    vec_seq.sort_unstable();
-    vec_par.sort_unstable();
-
-    assert_eq3!(vec_seq, vec_par, expected_sorted);
-}
-
-#[test]
-fn map_seq_par_equivalence_into_iter_empty() {
-    let vec_seq = MAP_EMPTY.clone().into_iter().collect::<Vec<_>>();
-    let vec_par = MAP_EMPTY.clone().into_par_iter().collect::<Vec<_>>();
-
-    assert_eq3!(vec_seq, vec_par, []);
-}
-
-#[test]
-fn map_seq_par_equivalence_into_iter() {
-    let mut vec_seq = MAP.clone().into_iter().collect::<Vec<_>>();
-    let mut vec_par = MAP.clone().into_par_iter().collect::<Vec<_>>();
-
-    assert_eq!(vec_seq, vec_par);
-
-    // Do not depend on the exact order of values
-    let expected_sorted = [
-        ('a', 10),
-        ('b', 20),
-        ('c', 30),
-        ('d', 40),
-        ('e', 50),
-        ('f', 60),
-    ];
-
-    vec_seq.sort_unstable();
-    vec_par.sort_unstable();
-
-    assert_eq3!(vec_seq, vec_par, expected_sorted);
-}
-
-lazy_static! {
-    static ref MAP_VEC_EMPTY: Vec<(char, u32)> = vec![];
-    static ref MAP_VEC: Vec<(char, u32)> = vec![
-        ('b', 20),
-        ('a', 10),
-        ('c', 30),
-        ('e', 50),
-        ('f', 60),
-        ('d', 40),
-    ];
-}
-
-#[test]
-fn map_seq_par_equivalence_collect_empty() {
-    let map_expected = MAP_EMPTY.clone();
-    let map_seq = MAP_VEC_EMPTY.clone().into_iter().collect::<HashMap<_, _>>();
-    let map_par = MAP_VEC_EMPTY
-        .clone()
-        .into_par_iter()
-        .collect::<HashMap<_, _>>();
-
-    assert_eq!(map_seq, map_par);
-    assert_eq!(map_seq, map_expected);
-    assert_eq!(map_par, map_expected);
-}
-
-#[test]
-fn map_seq_par_equivalence_collect() {
-    let map_expected = MAP.clone();
-    let map_seq = MAP_VEC.clone().into_iter().collect::<HashMap<_, _>>();
-    let map_par = MAP_VEC.clone().into_par_iter().collect::<HashMap<_, _>>();
-
-    assert_eq!(map_seq, map_par);
-    assert_eq!(map_seq, map_expected);
-    assert_eq!(map_par, map_expected);
-}
-
-lazy_static! {
-    static ref MAP_EXISTING_EMPTY: HashMap<char, u32> = HashMap::new();
-    static ref MAP_EXISTING: HashMap<char, u32> = {
-        let mut m = HashMap::new();
-        m.insert('b', 20);
-        m.insert('a', 10);
-        m
-    };
-    static ref MAP_EXTENSION_EMPTY: Vec<(char, u32)> = vec![];
-    static ref MAP_EXTENSION: Vec<(char, u32)> = vec![('c', 30), ('e', 50), ('f', 60), ('d', 40),];
-}
-
-#[test]
-fn map_seq_par_equivalence_existing_empty_extend_empty() {
-    let expected = HashMap::new();
-    let mut map_seq = MAP_EXISTING_EMPTY.clone();
-    let mut map_par = MAP_EXISTING_EMPTY.clone();
-
-    map_seq.extend(MAP_EXTENSION_EMPTY.iter().cloned());
-    map_par.par_extend(MAP_EXTENSION_EMPTY.par_iter().cloned());
-
-    assert_eq3!(map_seq, map_par, expected);
-}
-
-#[test]
-fn map_seq_par_equivalence_existing_empty_extend() {
-    let expected = MAP_EXTENSION.iter().cloned().collect::<HashMap<_, _>>();
-    let mut map_seq = MAP_EXISTING_EMPTY.clone();
-    let mut map_par = MAP_EXISTING_EMPTY.clone();
-
-    map_seq.extend(MAP_EXTENSION.iter().cloned());
-    map_par.par_extend(MAP_EXTENSION.par_iter().cloned());
-
-    assert_eq3!(map_seq, map_par, expected);
-}
-
-#[test]
-fn map_seq_par_equivalence_existing_extend_empty() {
-    let expected = MAP_EXISTING.clone();
-    let mut map_seq = MAP_EXISTING.clone();
-    let mut map_par = MAP_EXISTING.clone();
-
-    map_seq.extend(MAP_EXTENSION_EMPTY.iter().cloned());
-    map_par.par_extend(MAP_EXTENSION_EMPTY.par_iter().cloned());
-
-    assert_eq3!(map_seq, map_par, expected);
-}
-
-#[test]
-fn map_seq_par_equivalence_existing_extend() {
-    let expected = MAP.clone();
-    let mut map_seq = MAP_EXISTING.clone();
-    let mut map_par = MAP_EXISTING.clone();
-
-    map_seq.extend(MAP_EXTENSION.iter().cloned());
-    map_par.par_extend(MAP_EXTENSION.par_iter().cloned());
-
-    assert_eq3!(map_seq, map_par, expected);
-}
-
-lazy_static! {
-    static ref SET_EMPTY: HashSet<char> = HashSet::new();
-    static ref SET: HashSet<char> = {
-        let mut s = HashSet::new();
-        s.insert('b');
-        s.insert('a');
-        s.insert('c');
-        s.insert('e');
-        s.insert('f');
-        s.insert('d');
-        s
-    };
-}
-
-#[test]
-fn set_seq_par_equivalence_iter_empty() {
-    let vec_seq = SET_EMPTY.iter().collect::<Vec<_>>();
-    let vec_par = SET_EMPTY.par_iter().collect::<Vec<_>>();
-
-    let expected: [&char; 0] = [];
-
-    assert_eq3!(vec_seq, vec_par, expected);
-}
-
-#[test]
-fn set_seq_par_equivalence_iter() {
-    let mut vec_seq = SET.iter().collect::<Vec<_>>();
-    let mut vec_par = SET.par_iter().collect::<Vec<_>>();
-
-    assert_eq!(vec_seq, vec_par);
-
-    // Do not depend on the exact order of values
-    let expected_sorted = [&'a', &'b', &'c', &'d', &'e', &'f'];
-
-    vec_seq.sort_unstable();
-    vec_par.sort_unstable();
-
-    assert_eq3!(vec_seq, vec_par, expected_sorted);
-}
-
-#[test]
-fn set_seq_par_equivalence_into_iter_empty() {
-    let vec_seq = SET_EMPTY.clone().into_iter().collect::<Vec<_>>();
-    let vec_par = SET_EMPTY.clone().into_par_iter().collect::<Vec<_>>();
-
-    assert_eq3!(vec_seq, vec_par, []);
-}
-
-#[test]
-fn set_seq_par_equivalence_into_iter() {
-    let mut vec_seq = SET.clone().into_iter().collect::<Vec<_>>();
-    let mut vec_par = SET.clone().into_par_iter().collect::<Vec<_>>();
-
-    assert_eq!(vec_seq, vec_par);
-
-    // Do not depend on the exact order of values
-    let expected_sorted = ['a', 'b', 'c', 'd', 'e', 'f'];
-
-    vec_seq.sort_unstable();
-    vec_par.sort_unstable();
-
-    assert_eq3!(vec_seq, vec_par, expected_sorted);
-}
-
-lazy_static! {
-    static ref SET_VEC_EMPTY: Vec<char> = vec![];
-    static ref SET_VEC: Vec<char> = vec!['b', 'a', 'c', 'e', 'f', 'd',];
-}
-
-#[test]
-fn set_seq_par_equivalence_collect_empty() {
-    let set_expected = SET_EMPTY.clone();
-    let set_seq = SET_VEC_EMPTY.clone().into_iter().collect::<HashSet<_>>();
-    let set_par = SET_VEC_EMPTY
-        .clone()
-        .into_par_iter()
-        .collect::<HashSet<_>>();
-
-    assert_eq!(set_seq, set_par);
-    assert_eq!(set_seq, set_expected);
-    assert_eq!(set_par, set_expected);
-}
-
-#[test]
-fn set_seq_par_equivalence_collect() {
-    let set_expected = SET.clone();
-    let set_seq = SET_VEC.clone().into_iter().collect::<HashSet<_>>();
-    let set_par = SET_VEC.clone().into_par_iter().collect::<HashSet<_>>();
-
-    assert_eq!(set_seq, set_par);
-    assert_eq!(set_seq, set_expected);
-    assert_eq!(set_par, set_expected);
-}
-
-lazy_static! {
-    static ref SET_EXISTING_EMPTY: HashSet<char> = HashSet::new();
-    static ref SET_EXISTING: HashSet<char> = {
-        let mut s = HashSet::new();
-        s.insert('b');
-        s.insert('a');
-        s
-    };
-    static ref SET_EXTENSION_EMPTY: Vec<char> = vec![];
-    static ref SET_EXTENSION: Vec<char> = vec!['c', 'e', 'f', 'd',];
-}
-
-#[test]
-fn set_seq_par_equivalence_existing_empty_extend_empty() {
-    let expected = HashSet::new();
-    let mut set_seq = SET_EXISTING_EMPTY.clone();
-    let mut set_par = SET_EXISTING_EMPTY.clone();
-
-    set_seq.extend(SET_EXTENSION_EMPTY.iter().cloned());
-    set_par.par_extend(SET_EXTENSION_EMPTY.par_iter().cloned());
-
-    assert_eq3!(set_seq, set_par, expected);
-}
-
-#[test]
-fn set_seq_par_equivalence_existing_empty_extend() {
-    let expected = SET_EXTENSION.iter().cloned().collect::<HashSet<_>>();
-    let mut set_seq = SET_EXISTING_EMPTY.clone();
-    let mut set_par = SET_EXISTING_EMPTY.clone();
-
-    set_seq.extend(SET_EXTENSION.iter().cloned());
-    set_par.par_extend(SET_EXTENSION.par_iter().cloned());
-
-    assert_eq3!(set_seq, set_par, expected);
-}
-
-#[test]
-fn set_seq_par_equivalence_existing_extend_empty() {
-    let expected = SET_EXISTING.clone();
-    let mut set_seq = SET_EXISTING.clone();
-    let mut set_par = SET_EXISTING.clone();
-
-    set_seq.extend(SET_EXTENSION_EMPTY.iter().cloned());
-    set_par.par_extend(SET_EXTENSION_EMPTY.par_iter().cloned());
-
-    assert_eq3!(set_seq, set_par, expected);
-}
-
-#[test]
-fn set_seq_par_equivalence_existing_extend() {
-    let expected = SET.clone();
-    let mut set_seq = SET_EXISTING.clone();
-    let mut set_par = SET_EXISTING.clone();
-
-    set_seq.extend(SET_EXTENSION.iter().cloned());
-    set_par.par_extend(SET_EXTENSION.par_iter().cloned());
-
-    assert_eq3!(set_seq, set_par, expected);
-}
-
-lazy_static! {
-    static ref SET_A: HashSet<char> = ['a', 'b', 'c', 'd'].iter().cloned().collect();
-    static ref SET_B: HashSet<char> = ['a', 'b', 'e', 'f'].iter().cloned().collect();
-    static ref SET_DIFF_AB: HashSet<char> = ['c', 'd'].iter().cloned().collect();
-    static ref SET_DIFF_BA: HashSet<char> = ['e', 'f'].iter().cloned().collect();
-    static ref SET_SYMM_DIFF_AB: HashSet<char> = ['c', 'd', 'e', 'f'].iter().cloned().collect();
-    static ref SET_INTERSECTION_AB: HashSet<char> = ['a', 'b'].iter().cloned().collect();
-    static ref SET_UNION_AB: HashSet<char> =
-        ['a', 'b', 'c', 'd', 'e', 'f'].iter().cloned().collect();
-}
-
-#[test]
-fn set_seq_par_equivalence_difference() {
-    let diff_ab_seq = SET_A.difference(&*SET_B).cloned().collect::<HashSet<_>>();
-    let diff_ab_par = SET_A
-        .par_difference(&*SET_B)
-        .cloned()
-        .collect::<HashSet<_>>();
-
-    assert_eq3!(diff_ab_seq, diff_ab_par, *SET_DIFF_AB);
-
-    let diff_ba_seq = SET_B.difference(&*SET_A).cloned().collect::<HashSet<_>>();
-    let diff_ba_par = SET_B
-        .par_difference(&*SET_A)
-        .cloned()
-        .collect::<HashSet<_>>();
-
-    assert_eq3!(diff_ba_seq, diff_ba_par, *SET_DIFF_BA);
-}
-
-#[test]
-fn set_seq_par_equivalence_symmetric_difference() {
-    let symm_diff_ab_seq = SET_A
-        .symmetric_difference(&*SET_B)
-        .cloned()
-        .collect::<HashSet<_>>();
-    let symm_diff_ab_par = SET_A
-        .par_symmetric_difference(&*SET_B)
-        .cloned()
-        .collect::<HashSet<_>>();
-
-    assert_eq3!(symm_diff_ab_seq, symm_diff_ab_par, *SET_SYMM_DIFF_AB);
-}
-
-#[test]
-fn set_seq_par_equivalence_intersection() {
-    let intersection_ab_seq = SET_A.intersection(&*SET_B).cloned().collect::<HashSet<_>>();
-    let intersection_ab_par = SET_A
-        .par_intersection(&*SET_B)
-        .cloned()
-        .collect::<HashSet<_>>();
-
-    assert_eq3!(
-        intersection_ab_seq,
-        intersection_ab_par,
-        *SET_INTERSECTION_AB
-    );
-}
-
-#[test]
-fn set_seq_par_equivalence_union() {
-    let union_ab_seq = SET_A.union(&*SET_B).cloned().collect::<HashSet<_>>();
-    let union_ab_par = SET_A.par_union(&*SET_B).cloned().collect::<HashSet<_>>();
-
-    assert_eq3!(union_ab_seq, union_ab_par, *SET_UNION_AB);
-}
diff --git a/third_party/rust_crates/vendor/hashbrown/tests/serde.rs b/third_party/rust_crates/vendor/hashbrown/tests/serde.rs
deleted file mode 100644
index f32cd98..0000000
--- a/third_party/rust_crates/vendor/hashbrown/tests/serde.rs
+++ /dev/null
@@ -1,59 +0,0 @@
-#![cfg(feature = "serde")]
-
-use hashbrown::{HashMap, HashSet};
-use serde_test::{assert_tokens, Token};
-
-#[test]
-fn map_serde_tokens_empty() {
-    let map = HashMap::<char, u32>::new();
-
-    assert_tokens(&map, &[Token::Map { len: Some(0) }, Token::MapEnd]);
-}
-
-#[test]
-fn map_serde_tokens() {
-    let mut map = HashMap::new();
-    map.insert('b', 20);
-    map.insert('a', 10);
-    map.insert('c', 30);
-
-    assert_tokens(
-        &map,
-        &[
-            Token::Map { len: Some(3) },
-            Token::Char('a'),
-            Token::I32(10),
-            Token::Char('b'),
-            Token::I32(20),
-            Token::Char('c'),
-            Token::I32(30),
-            Token::MapEnd,
-        ],
-    );
-}
-
-#[test]
-fn set_serde_tokens_empty() {
-    let set = HashSet::<u32>::new();
-
-    assert_tokens(&set, &[Token::Seq { len: Some(0) }, Token::SeqEnd]);
-}
-
-#[test]
-fn set_serde_tokens() {
-    let mut set = HashSet::new();
-    set.insert(20);
-    set.insert(10);
-    set.insert(30);
-
-    assert_tokens(
-        &set,
-        &[
-            Token::Seq { len: Some(3) },
-            Token::I32(20),
-            Token::I32(10),
-            Token::I32(30),
-            Token::SeqEnd,
-        ],
-    );
-}
diff --git a/third_party/rust_crates/vendor/hashbrown/tests/set.rs b/third_party/rust_crates/vendor/hashbrown/tests/set.rs
deleted file mode 100644
index 332f3f6..0000000
--- a/third_party/rust_crates/vendor/hashbrown/tests/set.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-#![cfg(not(miri))] // FIXME: takes too long
-
-use hashbrown::HashSet;
-use rand::{distributions::Alphanumeric, Rng, SeedableRng, XorShiftRng};
-
-#[test]
-fn test_hashset_insert_remove() {
-    let mut m: HashSet<Vec<char>> = HashSet::new();
-    //let num: u32 = 4096;
-    //let tx: Vec<Vec<u8>> = (0..num).map(|i| (i..(16 + i)).collect()).collect();
-    let seed: [u8; 16] = [
-        130, 220, 246, 217, 111, 124, 221, 189, 190, 234, 121, 93, 67, 95, 100, 43,
-    ];
-
-    let mut rng: XorShiftRng = SeedableRng::from_seed(seed);
-    //let mut rng: XorShiftRng = XorShiftRng::new_unseeded();
-    let tx: Vec<Vec<char>> = (0..4096)
-        .map(|_| (rng.sample_iter(&Alphanumeric).take(32).collect()))
-        .collect();
-
-    for _ in 0..32 {
-        for i in 0..4096 {
-            assert_eq!(m.contains(&tx[i].clone()), false);
-            assert_eq!(m.insert(tx[i].clone()), true);
-        }
-        for i in 0..4096 {
-            println!("removing {} {:?}", i, tx[i]);
-            assert_eq!(m.remove(&tx[i]), true);
-        }
-    }
-}
diff --git a/third_party/rust_crates/vendor/quick-error-1.2.2/.cargo-checksum.json b/third_party/rust_crates/vendor/quick-error-1.2.2/.cargo-checksum.json
new file mode 100644
index 0000000..fbbd2b9
--- /dev/null
+++ b/third_party/rust_crates/vendor/quick-error-1.2.2/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"4c012206d297a8e8b0d2a92046a1135191ec67d561120b4e58de148ccafb1efe","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"058f01fe181608d027fcde7e528fc03ea3cf90f30903c407644b0a9bbc54f500","README.rst":"15120e9c7ef1ff5d794b3ce3bd301c0304c5bad5da974b7030622f31efc6e6f8","bulk.yaml":"17c2548388e0cd3a63473021a2f1e4ddedee082d79d9167cb31ad06a1890d3fc","examples/context.rs":"b9be9a4ca021a1f0ba659932bfc0cf891728bfaea49d48a8be183644c492515b","src/lib.rs":"92f3a2cb0351ffe7680cd54aee9cce26cf6d2623ac74725615bbccd099875964","vagga.yaml":"b01ad1fd3aa25de2439c0f7a437c6517808ba3a7eeeb0363eb209f08e326cc8e"},"package":"9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"}
\ No newline at end of file
diff --git a/third_party/rust_crates/vendor/quick-error-1.2.2/Cargo.toml b/third_party/rust_crates/vendor/quick-error-1.2.2/Cargo.toml
new file mode 100644
index 0000000..19bc242
--- /dev/null
+++ b/third_party/rust_crates/vendor/quick-error-1.2.2/Cargo.toml
@@ -0,0 +1,23 @@
+# 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 = "quick-error"
+version = "1.2.2"
+authors = ["Paul Colomiets <paul@colomiets.name>", "Colin Kiegel <kiegel@gmx.de>"]
+description = "    A macro which makes error types pleasant to write.\n"
+homepage = "http://github.com/tailhook/quick-error"
+documentation = "http://docs.rs/quick-error"
+keywords = ["macro", "error", "type", "enum"]
+categories = ["rust-patterns"]
+license = "MIT/Apache-2.0"
+repository = "http://github.com/tailhook/quick-error"
diff --git a/third_party/rust_crates/vendor/quick-error-1.2.2/LICENSE-APACHE b/third_party/rust_crates/vendor/quick-error-1.2.2/LICENSE-APACHE
new file mode 100644
index 0000000..8f71f43
--- /dev/null
+++ b/third_party/rust_crates/vendor/quick-error-1.2.2/LICENSE-APACHE
@@ -0,0 +1,202 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright {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_crates/vendor/quick-error-1.2.2/LICENSE-MIT b/third_party/rust_crates/vendor/quick-error-1.2.2/LICENSE-MIT
new file mode 100644
index 0000000..14f715b
--- /dev/null
+++ b/third_party/rust_crates/vendor/quick-error-1.2.2/LICENSE-MIT
@@ -0,0 +1,19 @@
+Copyright (c) 2015 The quick-error 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_crates/vendor/quick-error-1.2.2/README.rst b/third_party/rust_crates/vendor/quick-error-1.2.2/README.rst
new file mode 100644
index 0000000..9b934a9
--- /dev/null
+++ b/third_party/rust_crates/vendor/quick-error-1.2.2/README.rst
@@ -0,0 +1,69 @@
+===========
+Quick Error
+===========
+
+:Status: production-ready
+:Documentation: http://tailhook.github.io/quick-error/
+
+A macro which makes error types pleasant to write.
+
+Features:
+
+* Define enum type with arbitrary parameters
+* Concise notation of ``Display`` and ``Error`` traits
+* Full control of ``Display`` and ``Error`` trait implementation
+* Any number of ``From`` traits
+* Support for all enum-variants ``Unit``, ``Tuple`` and ``Struct``
+
+Here is the comprehensive example:
+
+.. code-block:: rust
+
+    quick_error! {
+        #[derive(Debug)]
+        pub enum IoWrapper {
+            Io(err: io::Error) {
+                from()
+                description("io error")
+                display("I/O error: {}", err)
+                cause(err)
+            }
+            Other(descr: &'static str) {
+                description(descr)
+                display("Error {}", descr)
+            }
+            IoAt { place: &'static str, err: io::Error } {
+                cause(err)
+                display(me) -> ("{} {}: {}", me.description(), place, err)
+                description("io error at")
+                from(s: String) -> {
+                    place: "some string",
+                    err: io::Error::new(io::ErrorKind::Other, s)
+                }
+            }
+            Discard {
+                from(&'static str)
+            }
+        }
+    }
+
+=======
+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_crates/vendor/quick-error-1.2.2/bulk.yaml b/third_party/rust_crates/vendor/quick-error-1.2.2/bulk.yaml
new file mode 100644
index 0000000..cdb9763
--- /dev/null
+++ b/third_party/rust_crates/vendor/quick-error-1.2.2/bulk.yaml
@@ -0,0 +1,8 @@
+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_crates/vendor/quick-error-1.2.2/examples/context.rs b/third_party/rust_crates/vendor/quick-error-1.2.2/examples/context.rs
new file mode 100644
index 0000000..334700a
--- /dev/null
+++ b/third_party/rust_crates/vendor/quick-error-1.2.2/examples/context.rs
@@ -0,0 +1,48 @@
+#[macro_use(quick_error)] extern crate quick_error;
+
+use std::io::{self, stderr, Read, Write};
+use std::fs::File;
+use std::env;
+use std::num::ParseIntError;
+use std::path::{Path, PathBuf};
+
+use quick_error::ResultExt;
+
+quick_error! {
+    #[derive(Debug)]
+    pub enum Error {
+        NoFileName {
+            description("no file name specified")
+        }
+        Io(err: io::Error, path: PathBuf) {
+            display("could not read file {:?}: {}", path, err)
+            context(path: &'a Path, err: io::Error)
+                -> (err, path.to_path_buf())
+        }
+        Parse(err: ParseIntError, path: PathBuf) {
+            display("could not parse file {:?}: {}", path, err)
+            context(path: &'a Path, err: ParseIntError)
+                -> (err, path.to_path_buf())
+        }
+    }
+}
+
+fn parse_file() -> Result<u64, Error> {
+    let fname = try!(env::args().skip(1).next().ok_or(Error::NoFileName));
+    let fname = Path::new(&fname);
+    let mut file = try!(File::open(fname).context(fname));
+    let mut buf = String::new();
+    try!(file.read_to_string(&mut buf).context(fname));
+    Ok(try!(buf.parse().context(fname)))
+}
+
+fn main() {
+    match parse_file() {
+        Ok(val) => {
+            println!("Read: {}", val);
+        }
+        Err(e) => {
+            writeln!(&mut stderr(), "Error: {}", e).ok();
+        }
+    }
+}
diff --git a/third_party/rust_crates/vendor/quick-error-1.2.2/src/lib.rs b/third_party/rust_crates/vendor/quick-error-1.2.2/src/lib.rs
new file mode 100644
index 0000000..fd95fe13
--- /dev/null
+++ b/third_party/rust_crates/vendor/quick-error-1.2.2/src/lib.rs
@@ -0,0 +1,1309 @@
+#![warn(missing_docs)]
+//! A macro which makes errors easy to write
+//!
+//! Minimum type is like this:
+//!
+//! ```rust
+//! #[macro_use] extern crate quick_error;
+//! # fn main() {}
+//!
+//! quick_error! {
+//!     #[derive(Debug)]
+//!     pub enum SomeError {
+//!         Variant1 {}
+//!     }
+//! }
+//! ```
+//! Both ``pub`` and non-public types may be declared, and all meta attributes
+//! (such as ``#[derive(Debug)]``) are forwarded as is. The `Debug` must be
+//! implemented (but you may do that yourself if you like). The documentation
+//! comments ``/// something`` (as well as other meta attrbiutes) on variants
+//! are allowed.
+//!
+//! # Allowed Syntax
+//!
+//! You may add arbitrary parameters to any struct variant:
+//!
+//! ```rust
+//! # #[macro_use] extern crate quick_error;
+//! # fn main() {}
+//! #
+//! quick_error! {
+//!     #[derive(Debug)]
+//!     pub enum SomeError {
+//!         /// IO Error
+//!         Io(err: std::io::Error) {}
+//!         /// Utf8 Error
+//!         Utf8(err: std::str::Utf8Error) {}
+//!     }
+//! }
+//! ```
+//!
+//! Note unlike in normal Enum declarations you declare names of fields (which
+//! are omitted from type). How they can be used is outlined below.
+//!
+//! Now you might have noticed trailing braces `{}`. They are used to define
+//! implementations. By default:
+//!
+//! * `Error::description()` returns variant name as static string
+//! * `Error::cause()` returns None (even if type wraps some value)
+//! * `Display` outputs `description()`
+//! * No `From` implementations are defined
+//!
+//! To define description simply add `description(value)` inside braces:
+//!
+//! ```rust
+//! # #[macro_use] extern crate quick_error;
+//! # fn main() {}
+//! #
+//! quick_error! {
+//!     #[derive(Debug)]
+//!     pub enum SomeError {
+//!         Io(err: std::io::Error) {
+//!             description(err.description())
+//!         }
+//!         Utf8(err: std::str::Utf8Error) {
+//!             description("utf8 error")
+//!         }
+//!     }
+//! }
+//! ```
+//!
+//! Normal rules for borrowing apply. So most of the time description either
+//! returns constant string or forwards description from enclosed type.
+//!
+//! To change `cause` method to return some error, add `cause(value)`, for
+//! example:
+//!
+//! ```rust
+//! # #[macro_use] extern crate quick_error;
+//! # fn main() {}
+//! #
+//! quick_error! {
+//!     #[derive(Debug)]
+//!     pub enum SomeError {
+//!         Io(err: std::io::Error) {
+//!             cause(err)
+//!             description(err.description())
+//!         }
+//!         Utf8(err: std::str::Utf8Error) {
+//!             description("utf8 error")
+//!         }
+//!         Other(err: Box<std::error::Error>) {
+//!             cause(&**err)
+//!             description(err.description())
+//!         }
+//!     }
+//! }
+//! ```
+//! Note you don't need to wrap value in `Some`, its implicit. In case you want
+//! `None` returned just omit the `cause`. You can't return `None`
+//! conditionally.
+//!
+//! To change how each clause is `Display`ed add `display(pattern,..args)`,
+//! for example:
+//!
+//! ```rust
+//! # #[macro_use] extern crate quick_error;
+//! # fn main() {}
+//! #
+//! quick_error! {
+//!     #[derive(Debug)]
+//!     pub enum SomeError {
+//!         Io(err: std::io::Error) {
+//!             display("I/O error: {}", err)
+//!         }
+//!         Utf8(err: std::str::Utf8Error) {
+//!             display("Utf8 error, valid up to {}", err.valid_up_to())
+//!         }
+//!     }
+//! }
+//! ```
+//!
+//! If you need a reference to the error when `Display`ing, you can instead use
+//! `display(x) -> (pattern, ..args)`, where `x` sets the name of the reference.
+//!
+//! ```rust
+//! # #[macro_use] extern crate quick_error;
+//! # fn main() {}
+//! #
+//! use std::error::Error; // put methods like `description()` of this trait into scope
+//!
+//! quick_error! {
+//!     #[derive(Debug)]
+//!     pub enum SomeError {
+//!         Io(err: std::io::Error) {
+//!             display(x) -> ("{}: {}", x.description(), err)
+//!         }
+//!         Utf8(err: std::str::Utf8Error) {
+//!             display(self_) -> ("{}, valid up to {}", self_.description(), err.valid_up_to())
+//!         }
+//!     }
+//! }
+//! ```
+//!
+//! To convert to the type from any other, use one of the three forms of
+//! `from` clause.
+//!
+//! For example, to convert simple wrapper use bare `from()`:
+//!
+//! ```rust
+//! # #[macro_use] extern crate quick_error;
+//! # fn main() {}
+//! #
+//! quick_error! {
+//!     #[derive(Debug)]
+//!     pub enum SomeError {
+//!         Io(err: std::io::Error) {
+//!             from()
+//!         }
+//!     }
+//! }
+//! ```
+//!
+//! This implements ``From<io::Error>``.
+//!
+//! To convert to singleton enumeration type (discarding the value), use
+//! the `from(type)` form:
+//!
+//! ```rust
+//! # #[macro_use] extern crate quick_error;
+//! # fn main() {}
+//! #
+//! quick_error! {
+//!     #[derive(Debug)]
+//!     pub enum SomeError {
+//!         FormatError {
+//!             from(std::fmt::Error)
+//!         }
+//!     }
+//! }
+//! ```
+//!
+//! And the most powerful form is `from(var: type) -> (arguments...)`. It
+//! might be used to convert to type with multiple arguments or for arbitrary
+//! value conversions:
+//!
+//! ```rust
+//! # #[macro_use] extern crate quick_error;
+//! # fn main() {}
+//! #
+//! quick_error! {
+//!     #[derive(Debug)]
+//!     pub enum SomeError {
+//!         FailedOperation(s: &'static str, errno: i32) {
+//!             from(errno: i32) -> ("os error", errno)
+//!             from(e: std::io::Error) -> ("io error", e.raw_os_error().unwrap())
+//!         }
+//!         /// Converts from both kinds of utf8 errors
+//!         Utf8(err: std::str::Utf8Error) {
+//!             from()
+//!             from(err: std::string::FromUtf8Error) -> (err.utf8_error())
+//!         }
+//!     }
+//! }
+//! ```
+//! # Context
+//!
+//! Since quick-error 1.1 we also have a `context` declaration, which is
+//! similar to (the longest form of) `from`, but allows adding some context to
+//! the error. We need a longer example to demonstrate this:
+//!
+//! ```rust
+//! # #[macro_use] extern crate quick_error;
+//! # use std::io;
+//! # use std::fs::File;
+//! # use std::path::{Path, PathBuf};
+//! #
+//! use quick_error::ResultExt;
+//!
+//! quick_error! {
+//!     #[derive(Debug)]
+//!     pub enum Error {
+//!         File(filename: PathBuf, err: io::Error) {
+//!             context(path: &'a Path, err: io::Error)
+//!                 -> (path.to_path_buf(), err)
+//!         }
+//!     }
+//! }
+//!
+//! fn openfile(path: &Path) -> Result<(), Error> {
+//!     try!(File::open(path).context(path));
+//!
+//!     // If we didn't have context, the line above would be written as;
+//!     //
+//!     // try!(File::open(path)
+//!     //     .map_err(|err| Error::File(path.to_path_buf(), err)));
+//!
+//!     Ok(())
+//! }
+//!
+//! # fn main() {
+//! #     openfile(Path::new("/etc/somefile")).ok();
+//! # }
+//! ```
+//!
+//! Each `context(a: A, b: B)` clause implements
+//! `From<Context<A, B>> for Error`. Which means multiple `context` clauses
+//! are a subject to the normal coherence rules. Unfortunately, we can't
+//! provide full support of generics for the context, but you may either use a
+//! lifetime `'a` for references or `AsRef<Type>` (the latter means `A:
+//! AsRef<Type>`, and `Type` must be concrete). It's also occasionally useful
+//! to use a tuple as a type of the first argument.
+//!
+//! You also need to `use quick_error::ResultExt` extension trait to get
+//! working `.context()` method.
+//!
+//! More info on context in [this article](http://bit.ly/1PsuxDt).
+//!
+//! All forms of `from`, `display`, `description`, `cause`, and `context`
+//! clauses can be combined and put in arbitrary order. Only `from` and
+//! `context` can be used multiple times in single variant of enumeration.
+//! Docstrings are also okay.  Empty braces can be omitted as of quick_error
+//! 0.1.3.
+//!
+//! # Private Enums
+//!
+//! Since quick-error 1.2.0 we  have a way to make a private enum that is
+//! wrapped by public structure:
+//!
+//! ```rust
+//! #[macro_use] extern crate quick_error;
+//! # fn main() {}
+//!
+//! quick_error! {
+//!     #[derive(Debug)]
+//!     pub enum PubError wraps ErrorEnum {
+//!         Variant1 {}
+//!     }
+//! }
+//! ```
+//!
+//! This generates data structures like this
+//!
+//! ```rust
+//!
+//! pub struct PubError(ErrorEnum);
+//!
+//! enum ErrorEnum {
+//!     Variant1,
+//! }
+//!
+//! ```
+//!
+//! Which in turn allows you to export just `PubError` in your crate and keep
+//! actual enumeration private to the crate. This is useful to keep backwards
+//! compatibility for error types. Currently there is no shorcuts to define
+//! error constructors for the inner type, but we consider adding some in
+//! future versions.
+//!
+//! It's possible to declare internal enum as public too.
+//!
+//!
+
+
+/// Main macro that does all the work
+#[macro_export]
+macro_rules! quick_error {
+
+    (   $(#[$meta:meta])*
+        pub enum $name:ident { $($chunks:tt)* }
+    ) => {
+        quick_error!(SORT [pub enum $name $(#[$meta])* ]
+            items [] buf []
+            queue [ $($chunks)* ]);
+    };
+    (   $(#[$meta:meta])*
+        enum $name:ident { $($chunks:tt)* }
+    ) => {
+        quick_error!(SORT [enum $name $(#[$meta])* ]
+            items [] buf []
+            queue [ $($chunks)* ]);
+    };
+
+    (   $(#[$meta:meta])*
+        pub enum $name:ident wraps $enum_name:ident { $($chunks:tt)* }
+    ) => {
+        quick_error!(WRAPPER $enum_name [ pub struct ] $name $(#[$meta])*);
+        quick_error!(SORT [enum $enum_name $(#[$meta])* ]
+            items [] buf []
+            queue [ $($chunks)* ]);
+    };
+
+    (   $(#[$meta:meta])*
+        pub enum $name:ident wraps pub $enum_name:ident { $($chunks:tt)* }
+    ) => {
+        quick_error!(WRAPPER $enum_name [ pub struct ] $name $(#[$meta])*);
+        quick_error!(SORT [pub enum $enum_name $(#[$meta])* ]
+            items [] buf []
+            queue [ $($chunks)* ]);
+    };
+    (   $(#[$meta:meta])*
+        enum $name:ident wraps $enum_name:ident { $($chunks:tt)* }
+    ) => {
+        quick_error!(WRAPPER $enum_name [ struct ] $name $(#[$meta])*);
+        quick_error!(SORT [enum $enum_name $(#[$meta])* ]
+            items [] buf []
+            queue [ $($chunks)* ]);
+    };
+
+    (   $(#[$meta:meta])*
+        enum $name:ident wraps pub $enum_name:ident { $($chunks:tt)* }
+    ) => {
+        quick_error!(WRAPPER $enum_name [ struct ] $name $(#[$meta])*);
+        quick_error!(SORT [pub enum $enum_name $(#[$meta])* ]
+            items [] buf []
+            queue [ $($chunks)* ]);
+    };
+
+
+    (
+        WRAPPER $internal:ident [ $($strdef:tt)* ] $strname:ident
+        $(#[$meta:meta])*
+    ) => {
+        $(#[$meta])*
+        $($strdef)* $strname ( $internal );
+
+        impl ::std::fmt::Display for $strname {
+            fn fmt(&self, f: &mut ::std::fmt::Formatter)
+                -> ::std::fmt::Result
+            {
+                ::std::fmt::Display::fmt(&self.0, f)
+            }
+        }
+
+        impl From<$internal> for $strname {
+            fn from(err: $internal) -> Self {
+                $strname(err)
+            }
+        }
+
+        impl ::std::error::Error for $strname {
+            fn description(&self) -> &str {
+                self.0.description()
+            }
+            fn cause(&self) -> Option<&::std::error::Error> {
+                self.0.cause()
+            }
+        }
+    };
+
+    // Queue is empty, can do the work
+    (SORT [enum $name:ident $( #[$meta:meta] )*]
+        items [$($( #[$imeta:meta] )*
+                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
+                                {$( $ifuncs:tt )*} )* ]
+        buf [ ]
+        queue [ ]
+    ) => {
+        quick_error!(ENUM_DEFINITION [enum $name $( #[$meta] )*]
+            body []
+            queue [$($( #[$imeta] )*
+                      => $iitem: $imode [$( $ivar: $ityp ),*] )*]
+        );
+        quick_error!(IMPLEMENTATIONS $name {$(
+           $iitem: $imode [$(#[$imeta])*] [$( $ivar: $ityp ),*] {$( $ifuncs )*}
+           )*});
+        $(
+            quick_error!(ERROR_CHECK $imode $($ifuncs)*);
+        )*
+    };
+    (SORT [pub enum $name:ident $( #[$meta:meta] )*]
+        items [$($( #[$imeta:meta] )*
+                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
+                                {$( $ifuncs:tt )*} )* ]
+        buf [ ]
+        queue [ ]
+    ) => {
+        quick_error!(ENUM_DEFINITION [pub enum $name $( #[$meta] )*]
+            body []
+            queue [$($( #[$imeta] )*
+                      => $iitem: $imode [$( $ivar: $ityp ),*] )*]
+        );
+        quick_error!(IMPLEMENTATIONS $name {$(
+           $iitem: $imode [$(#[$imeta])*] [$( $ivar: $ityp ),*] {$( $ifuncs )*}
+           )*});
+        $(
+            quick_error!(ERROR_CHECK $imode $($ifuncs)*);
+        )*
+    };
+    // Add meta to buffer
+    (SORT [$( $def:tt )*]
+        items [$($( #[$imeta:meta] )*
+                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
+                                {$( $ifuncs:tt )*} )* ]
+        buf [$( #[$bmeta:meta] )*]
+        queue [ #[$qmeta:meta] $( $tail:tt )*]
+    ) => {
+        quick_error!(SORT [$( $def )*]
+            items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
+            buf [$( #[$bmeta] )* #[$qmeta] ]
+            queue [$( $tail )*]);
+    };
+    // Add ident to buffer
+    (SORT [$( $def:tt )*]
+        items [$($( #[$imeta:meta] )*
+                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
+                                {$( $ifuncs:tt )*} )* ]
+        buf [$( #[$bmeta:meta] )*]
+        queue [ $qitem:ident $( $tail:tt )*]
+    ) => {
+        quick_error!(SORT [$( $def )*]
+            items [$( $(#[$imeta])*
+                      => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
+            buf [$(#[$bmeta])* => $qitem : UNIT [ ] ]
+            queue [$( $tail )*]);
+    };
+    // Flush buffer on meta after ident
+    (SORT [$( $def:tt )*]
+        items [$($( #[$imeta:meta] )*
+                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
+                                {$( $ifuncs:tt )*} )* ]
+        buf [$( #[$bmeta:meta] )*
+            => $bitem:ident: $bmode:tt [$( $bvar:ident: $btyp:ty ),*] ]
+        queue [ #[$qmeta:meta] $( $tail:tt )*]
+    ) => {
+        quick_error!(SORT [$( $def )*]
+            enum [$( $(#[$emeta])* => $eitem $(( $($etyp),* ))* )*
+                     $(#[$bmeta])* => $bitem: $bmode $(( $($btyp),* ))*]
+            items [$($( #[$imeta:meta] )*
+                      => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*
+                     $bitem: $bmode [$( $bvar:$btyp ),*] {} ]
+            buf [ #[$qmeta] ]
+            queue [$( $tail )*]);
+    };
+    // Add tuple enum-variant
+    (SORT [$( $def:tt )*]
+        items [$($( #[$imeta:meta] )*
+                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
+                                {$( $ifuncs:tt )*} )* ]
+        buf [$( #[$bmeta:meta] )* => $bitem:ident: UNIT [ ] ]
+        queue [($( $qvar:ident: $qtyp:ty ),+) $( $tail:tt )*]
+    ) => {
+        quick_error!(SORT [$( $def )*]
+            items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
+            buf [$( #[$bmeta] )* => $bitem: TUPLE [$( $qvar:$qtyp ),*] ]
+            queue [$( $tail )*]
+        );
+    };
+    // Add struct enum-variant - e.g. { descr: &'static str }
+    (SORT [$( $def:tt )*]
+        items [$($( #[$imeta:meta] )*
+                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
+                                {$( $ifuncs:tt )*} )* ]
+        buf [$( #[$bmeta:meta] )* => $bitem:ident: UNIT [ ] ]
+        queue [{ $( $qvar:ident: $qtyp:ty ),+} $( $tail:tt )*]
+    ) => {
+        quick_error!(SORT [$( $def )*]
+            items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
+            buf [$( #[$bmeta] )* => $bitem: STRUCT [$( $qvar:$qtyp ),*] ]
+            queue [$( $tail )*]);
+    };
+    // Add struct enum-variant, with excess comma - e.g. { descr: &'static str, }
+    (SORT [$( $def:tt )*]
+        items [$($( #[$imeta:meta] )*
+                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
+                                {$( $ifuncs:tt )*} )* ]
+        buf [$( #[$bmeta:meta] )* => $bitem:ident: UNIT [ ] ]
+        queue [{$( $qvar:ident: $qtyp:ty ),+ ,} $( $tail:tt )*]
+    ) => {
+        quick_error!(SORT [$( $def )*]
+            items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
+            buf [$( #[$bmeta] )* => $bitem: STRUCT [$( $qvar:$qtyp ),*] ]
+            queue [$( $tail )*]);
+    };
+    // Add braces and flush always on braces
+    (SORT [$( $def:tt )*]
+        items [$($( #[$imeta:meta] )*
+                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
+                                {$( $ifuncs:tt )*} )* ]
+        buf [$( #[$bmeta:meta] )*
+                 => $bitem:ident: $bmode:tt [$( $bvar:ident: $btyp:ty ),*] ]
+        queue [ {$( $qfuncs:tt )*} $( $tail:tt )*]
+    ) => {
+        quick_error!(SORT [$( $def )*]
+            items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*
+                      $(#[$bmeta])* => $bitem: $bmode [$( $bvar:$btyp ),*] {$( $qfuncs )*} ]
+            buf [ ]
+            queue [$( $tail )*]);
+    };
+    // Flush buffer on double ident
+    (SORT [$( $def:tt )*]
+        items [$($( #[$imeta:meta] )*
+                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
+                                {$( $ifuncs:tt )*} )* ]
+        buf [$( #[$bmeta:meta] )*
+                 => $bitem:ident: $bmode:tt [$( $bvar:ident: $btyp:ty ),*] ]
+        queue [ $qitem:ident $( $tail:tt )*]
+    ) => {
+        quick_error!(SORT [$( $def )*]
+            items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*
+                     $(#[$bmeta])* => $bitem: $bmode [$( $bvar:$btyp ),*] {} ]
+            buf [ => $qitem : UNIT [ ] ]
+            queue [$( $tail )*]);
+    };
+    // Flush buffer on end
+    (SORT [$( $def:tt )*]
+        items [$($( #[$imeta:meta] )*
+                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
+                                {$( $ifuncs:tt )*} )* ]
+        buf [$( #[$bmeta:meta] )*
+            => $bitem:ident: $bmode:tt [$( $bvar:ident: $btyp:ty ),*] ]
+        queue [ ]
+    ) => {
+        quick_error!(SORT [$( $def )*]
+            items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*
+                     $(#[$bmeta])* => $bitem: $bmode [$( $bvar:$btyp ),*] {} ]
+            buf [ ]
+            queue [ ]);
+    };
+    // Public enum (Queue Empty)
+    (ENUM_DEFINITION [pub enum $name:ident $( #[$meta:meta] )*]
+        body [$($( #[$imeta:meta] )*
+            => $iitem:ident ($(($( $ttyp:ty ),+))*) {$({$( $svar:ident: $styp:ty ),*})*} )* ]
+        queue [ ]
+    ) => {
+        #[allow(unknown_lints)]  // no unused_doc_comments in older rust
+        #[allow(renamed_and_removed_lints)]
+        #[allow(unused_doc_comment)]
+        #[allow(unused_doc_comments)]
+        $(#[$meta])*
+        pub enum $name {
+            $(
+                $(#[$imeta])*
+                $iitem $(($( $ttyp ),*))* $({$( $svar: $styp ),*})*,
+            )*
+        }
+    };
+    // Private enum (Queue Empty)
+    (ENUM_DEFINITION [enum $name:ident $( #[$meta:meta] )*]
+        body [$($( #[$imeta:meta] )*
+            => $iitem:ident ($(($( $ttyp:ty ),+))*) {$({$( $svar:ident: $styp:ty ),*})*} )* ]
+        queue [ ]
+    ) => {
+        #[allow(unknown_lints)]  // no unused_doc_comments in older rust
+        #[allow(renamed_and_removed_lints)]
+        #[allow(unused_doc_comment)]
+        #[allow(unused_doc_comments)]
+        $(#[$meta])*
+        enum $name {
+            $(
+                $(#[$imeta])*
+                $iitem $(($( $ttyp ),*))* $({$( $svar: $styp ),*})*,
+            )*
+        }
+    };
+    // Unit variant
+    (ENUM_DEFINITION [$( $def:tt )*]
+        body [$($( #[$imeta:meta] )*
+            => $iitem:ident ($(($( $ttyp:ty ),+))*) {$({$( $svar:ident: $styp:ty ),*})*} )* ]
+        queue [$( #[$qmeta:meta] )*
+            => $qitem:ident: UNIT [ ] $( $queue:tt )*]
+    ) => {
+        quick_error!(ENUM_DEFINITION [ $($def)* ]
+            body [$($( #[$imeta] )* => $iitem ($(($( $ttyp ),+))*) {$({$( $svar: $styp ),*})*} )*
+                    $( #[$qmeta] )* => $qitem () {} ]
+            queue [ $($queue)* ]
+        );
+    };
+    // Tuple variant
+    (ENUM_DEFINITION [$( $def:tt )*]
+        body [$($( #[$imeta:meta] )*
+            => $iitem:ident ($(($( $ttyp:ty ),+))*) {$({$( $svar:ident: $styp:ty ),*})*} )* ]
+        queue [$( #[$qmeta:meta] )*
+            => $qitem:ident: TUPLE [$( $qvar:ident: $qtyp:ty ),+] $( $queue:tt )*]
+    ) => {
+        quick_error!(ENUM_DEFINITION [ $($def)* ]
+            body [$($( #[$imeta] )* => $iitem ($(($( $ttyp ),+))*) {$({$( $svar: $styp ),*})*} )*
+                    $( #[$qmeta] )* => $qitem (($( $qtyp ),*)) {} ]
+            queue [ $($queue)* ]
+        );
+    };
+    // Struct variant
+    (ENUM_DEFINITION [$( $def:tt )*]
+        body [$($( #[$imeta:meta] )*
+            => $iitem:ident ($(($( $ttyp:ty ),+))*) {$({$( $svar:ident: $styp:ty ),*})*} )* ]
+        queue [$( #[$qmeta:meta] )*
+            => $qitem:ident: STRUCT [$( $qvar:ident: $qtyp:ty ),*] $( $queue:tt )*]
+    ) => {
+        quick_error!(ENUM_DEFINITION [ $($def)* ]
+            body [$($( #[$imeta] )* => $iitem ($(($( $ttyp ),+))*) {$({$( $svar: $styp ),*})*} )*
+                    $( #[$qmeta] )* => $qitem () {{$( $qvar: $qtyp ),*}} ]
+            queue [ $($queue)* ]
+        );
+    };
+    (IMPLEMENTATIONS
+        $name:ident {$(
+            $item:ident: $imode:tt [$(#[$imeta:meta])*] [$( $var:ident: $typ:ty ),*] {$( $funcs:tt )*}
+        )*}
+    ) => {
+        #[allow(unused)]
+        #[allow(unknown_lints)]  // no unused_doc_comments in older rust
+        #[allow(renamed_and_removed_lints)]
+        #[allow(unused_doc_comment)]
+        #[allow(unused_doc_comments)]
+        impl ::std::fmt::Display for $name {
+            fn fmt(&self, fmt: &mut ::std::fmt::Formatter)
+                -> ::std::fmt::Result
+            {
+                match *self {
+                    $(
+                        $(#[$imeta])*
+                        quick_error!(ITEM_PATTERN
+                            $name $item: $imode [$( ref $var ),*]
+                        ) => {
+                            let display_fn = quick_error!(FIND_DISPLAY_IMPL
+                                $name $item: $imode
+                                {$( $funcs )*});
+
+                            display_fn(self, fmt)
+                        }
+                    )*
+                }
+            }
+        }
+        #[allow(unused)]
+        #[allow(unknown_lints)]  // no unused_doc_comments in older rust
+        #[allow(renamed_and_removed_lints)]
+        #[allow(unused_doc_comment)]
+        #[allow(unused_doc_comments)]
+        impl ::std::error::Error for $name {
+            fn description(&self) -> &str {
+                match *self {
+                    $(
+                        $(#[$imeta])*
+                        quick_error!(ITEM_PATTERN
+                            $name $item: $imode [$( ref $var ),*]
+                        ) => {
+                            quick_error!(FIND_DESCRIPTION_IMPL
+                                $item: $imode self fmt [$( $var ),*]
+                                {$( $funcs )*})
+                        }
+                    )*
+                }
+            }
+            fn cause(&self) -> Option<&::std::error::Error> {
+                match *self {
+                    $(
+                        $(#[$imeta])*
+                        quick_error!(ITEM_PATTERN
+                            $name $item: $imode [$( ref $var ),*]
+                        ) => {
+                            quick_error!(FIND_CAUSE_IMPL
+                                $item: $imode [$( $var ),*]
+                                {$( $funcs )*})
+                        }
+                    )*
+                }
+            }
+        }
+        $(
+            quick_error!(FIND_FROM_IMPL
+                $name $item: $imode [$( $var:$typ ),*]
+                {$( $funcs )*});
+        )*
+        $(
+            quick_error!(FIND_CONTEXT_IMPL
+                $name $item: $imode [$( $var:$typ ),*]
+                {$( $funcs )*});
+        )*
+    };
+    (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt
+        { display($self_:tt) -> ($( $exprs:tt )*) $( $tail:tt )*}
+    ) => {
+        |quick_error!(IDENT $self_): &$name, f: &mut ::std::fmt::Formatter| { write!(f, $( $exprs )*) }
+    };
+    (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt
+        { display($pattern:expr) $( $tail:tt )*}
+    ) => {
+        |_, f: &mut ::std::fmt::Formatter| { write!(f, $pattern) }
+    };
+    (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt
+        { display($pattern:expr, $( $exprs:tt )*) $( $tail:tt )*}
+    ) => {
+        |_, f: &mut ::std::fmt::Formatter| { write!(f, $pattern, $( $exprs )*) }
+    };
+    (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt
+        { $t:tt $( $tail:tt )*}
+    ) => {
+        quick_error!(FIND_DISPLAY_IMPL
+            $name $item: $imode
+            {$( $tail )*})
+    };
+    (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt
+        { }
+    ) => {
+        |self_: &$name, f: &mut ::std::fmt::Formatter| {
+            write!(f, "{}", ::std::error::Error::description(self_))
+        }
+    };
+    (FIND_DESCRIPTION_IMPL $item:ident: $imode:tt $me:ident $fmt:ident
+        [$( $var:ident ),*]
+        { description($expr:expr) $( $tail:tt )*}
+    ) => {
+        $expr
+    };
+    (FIND_DESCRIPTION_IMPL $item:ident: $imode:tt $me:ident $fmt:ident
+        [$( $var:ident ),*]
+        { $t:tt $( $tail:tt )*}
+    ) => {
+        quick_error!(FIND_DESCRIPTION_IMPL
+            $item: $imode $me $fmt [$( $var ),*]
+            {$( $tail )*})
+    };
+    (FIND_DESCRIPTION_IMPL $item:ident: $imode:tt $me:ident $fmt:ident
+        [$( $var:ident ),*]
+        { }
+    ) => {
+        stringify!($item)
+    };
+    (FIND_CAUSE_IMPL $item:ident: $imode:tt
+        [$( $var:ident ),*]
+        { cause($expr:expr) $( $tail:tt )*}
+    ) => {
+        Some($expr)
+    };
+    (FIND_CAUSE_IMPL $item:ident: $imode:tt
+        [$( $var:ident ),*]
+        { $t:tt $( $tail:tt )*}
+    ) => {
+        quick_error!(FIND_CAUSE_IMPL
+            $item: $imode [$( $var ),*]
+            { $($tail)* })
+    };
+    (FIND_CAUSE_IMPL $item:ident: $imode:tt
+        [$( $var:ident ),*]
+        { }
+    ) => {
+        None
+    };
+    // ----------------------------- FROM IMPL --------------------------
+    (FIND_FROM_IMPL $name:ident $item:ident: $imode:tt
+        [$( $var:ident: $typ:ty ),*]
+        { from() $( $tail:tt )*}
+    ) => {
+        $(
+            impl From<$typ> for $name {
+                fn from($var: $typ) -> $name {
+                    $name::$item($var)
+                }
+            }
+        )*
+        quick_error!(FIND_FROM_IMPL
+            $name $item: $imode [$( $var:$typ ),*]
+            {$( $tail )*});
+    };
+    (FIND_FROM_IMPL $name:ident $item:ident: UNIT
+        [ ]
+        { from($ftyp:ty) $( $tail:tt )*}
+    ) => {
+        impl From<$ftyp> for $name {
+            fn from(_discarded_error: $ftyp) -> $name {
+                $name::$item
+            }
+        }
+        quick_error!(FIND_FROM_IMPL
+            $name $item: UNIT [  ]
+            {$( $tail )*});
+    };
+    (FIND_FROM_IMPL $name:ident $item:ident: TUPLE
+        [$( $var:ident: $typ:ty ),*]
+        { from($fvar:ident: $ftyp:ty) -> ($( $texpr:expr ),*) $( $tail:tt )*}
+    ) => {
+        impl From<$ftyp> for $name {
+            fn from($fvar: $ftyp) -> $name {
+                $name::$item($( $texpr ),*)
+            }
+        }
+        quick_error!(FIND_FROM_IMPL
+            $name $item: TUPLE [$( $var:$typ ),*]
+            { $($tail)* });
+    };
+    (FIND_FROM_IMPL $name:ident $item:ident: STRUCT
+        [$( $var:ident: $typ:ty ),*]
+        { from($fvar:ident: $ftyp:ty) -> {$( $tvar:ident: $texpr:expr ),*} $( $tail:tt )*}
+    ) => {
+        impl From<$ftyp> for $name {
+            fn from($fvar: $ftyp) -> $name {
+                $name::$item {
+                    $( $tvar: $texpr ),*
+                }
+            }
+        }
+        quick_error!(FIND_FROM_IMPL
+            $name $item: STRUCT [$( $var:$typ ),*]
+            { $($tail)* });
+    };
+    (FIND_FROM_IMPL $name:ident $item:ident: $imode:tt
+        [$( $var:ident: $typ:ty ),*]
+        { $t:tt $( $tail:tt )*}
+    ) => {
+        quick_error!(FIND_FROM_IMPL
+            $name $item: $imode [$( $var:$typ ),*]
+            {$( $tail )*}
+        );
+    };
+    (FIND_FROM_IMPL $name:ident $item:ident: $imode:tt
+        [$( $var:ident: $typ:ty ),*]
+        { }
+    ) => {
+    };
+    // ----------------------------- CONTEXT IMPL --------------------------
+    (FIND_CONTEXT_IMPL $name:ident $item:ident: TUPLE
+        [$( $var:ident: $typ:ty ),*]
+        { context($cvar:ident: AsRef<$ctyp:ty>, $fvar:ident: $ftyp:ty)
+            -> ($( $texpr:expr ),*) $( $tail:tt )* }
+    ) => {
+        impl<T: AsRef<$ctyp>> From<$crate::Context<T, $ftyp>> for $name {
+            fn from(
+                $crate::Context($cvar, $fvar): $crate::Context<T, $ftyp>)
+                -> $name
+            {
+                $name::$item($( $texpr ),*)
+            }
+        }
+        quick_error!(FIND_CONTEXT_IMPL
+            $name $item: TUPLE [$( $var:$typ ),*]
+            { $($tail)* });
+    };
+    (FIND_CONTEXT_IMPL $name:ident $item:ident: TUPLE
+        [$( $var:ident: $typ:ty ),*]
+        { context($cvar:ident: $ctyp:ty, $fvar:ident: $ftyp:ty)
+            -> ($( $texpr:expr ),*) $( $tail:tt )* }
+    ) => {
+        impl<'a> From<$crate::Context<$ctyp, $ftyp>> for $name {
+            fn from(
+                $crate::Context($cvar, $fvar): $crate::Context<$ctyp, $ftyp>)
+                -> $name
+            {
+                $name::$item($( $texpr ),*)
+            }
+        }
+        quick_error!(FIND_CONTEXT_IMPL
+            $name $item: TUPLE [$( $var:$typ ),*]
+            { $($tail)* });
+    };
+    (FIND_CONTEXT_IMPL $name:ident $item:ident: STRUCT
+        [$( $var:ident: $typ:ty ),*]
+        { context($cvar:ident: AsRef<$ctyp:ty>, $fvar:ident: $ftyp:ty)
+            -> {$( $tvar:ident: $texpr:expr ),*} $( $tail:tt )* }
+    ) => {
+        impl<T: AsRef<$ctyp>> From<$crate::Context<T, $ftyp>> for $name {
+            fn from(
+                $crate::Context($cvar, $fvar): $crate::Context<$ctyp, $ftyp>)
+                -> $name
+            {
+                $name::$item {
+                    $( $tvar: $texpr ),*
+                }
+            }
+        }
+        quick_error!(FIND_CONTEXT_IMPL
+            $name $item: STRUCT [$( $var:$typ ),*]
+            { $($tail)* });
+    };
+    (FIND_CONTEXT_IMPL $name:ident $item:ident: STRUCT
+        [$( $var:ident: $typ:ty ),*]
+        { context($cvar:ident: $ctyp:ty, $fvar:ident: $ftyp:ty)
+            -> {$( $tvar:ident: $texpr:expr ),*} $( $tail:tt )* }
+    ) => {
+        impl<'a> From<$crate::Context<$ctyp, $ftyp>> for $name {
+            fn from(
+                $crate::Context($cvar, $fvar): $crate::Context<$ctyp, $ftyp>)
+                -> $name
+            {
+                $name::$item {
+                    $( $tvar: $texpr ),*
+                }
+            }
+        }
+        quick_error!(FIND_CONTEXT_IMPL
+            $name $item: STRUCT [$( $var:$typ ),*]
+            { $($tail)* });
+    };
+    (FIND_CONTEXT_IMPL $name:ident $item:ident: $imode:tt
+        [$( $var:ident: $typ:ty ),*]
+        { $t:tt $( $tail:tt )*}
+    ) => {
+        quick_error!(FIND_CONTEXT_IMPL
+            $name $item: $imode [$( $var:$typ ),*]
+            {$( $tail )*}
+        );
+    };
+    (FIND_CONTEXT_IMPL $name:ident $item:ident: $imode:tt
+        [$( $var:ident: $typ:ty ),*]
+        { }
+    ) => {
+    };
+    // ----------------------------- ITEM IMPL --------------------------
+    (ITEM_BODY $(#[$imeta:meta])* $item:ident: UNIT
+    ) => { };
+    (ITEM_BODY $(#[$imeta:meta])* $item:ident: TUPLE
+        [$( $typ:ty ),*]
+    ) => {
+        ($( $typ ),*)
+    };
+    (ITEM_BODY $(#[$imeta:meta])* $item:ident: STRUCT
+        [$( $var:ident: $typ:ty ),*]
+    ) => {
+        {$( $var:$typ ),*}
+    };
+    (ITEM_PATTERN $name:ident $item:ident: UNIT []
+    ) => {
+        $name::$item
+    };
+    (ITEM_PATTERN $name:ident $item:ident: TUPLE
+        [$( ref $var:ident ),*]
+    ) => {
+        $name::$item ($( ref $var ),*)
+    };
+    (ITEM_PATTERN $name:ident $item:ident: STRUCT
+        [$( ref $var:ident ),*]
+    ) => {
+        $name::$item {$( ref $var ),*}
+    };
+    // This one should match all allowed sequences in "funcs" but not match
+    // anything else.
+    // This is to contrast FIND_* clauses which just find stuff they need and
+    // skip everything else completely
+    (ERROR_CHECK $imode:tt display($self_:tt) -> ($( $exprs:tt )*) $( $tail:tt )*)
+    => { quick_error!(ERROR_CHECK $imode $($tail)*); };
+    (ERROR_CHECK $imode:tt display($pattern: expr) $( $tail:tt )*)
+    => { quick_error!(ERROR_CHECK $imode $($tail)*); };
+    (ERROR_CHECK $imode:tt display($pattern: expr, $( $exprs:tt )*) $( $tail:tt )*)
+    => { quick_error!(ERROR_CHECK $imode $($tail)*); };
+    (ERROR_CHECK $imode:tt description($expr:expr) $( $tail:tt )*)
+    => { quick_error!(ERROR_CHECK $imode $($tail)*); };
+    (ERROR_CHECK $imode:tt cause($expr:expr) $($tail:tt)*)
+    => { quick_error!(ERROR_CHECK $imode $($tail)*); };
+    (ERROR_CHECK $imode:tt from() $($tail:tt)*)
+    => { quick_error!(ERROR_CHECK $imode $($tail)*); };
+    (ERROR_CHECK $imode:tt from($ftyp:ty) $($tail:tt)*)
+    => { quick_error!(ERROR_CHECK $imode $($tail)*); };
+    (ERROR_CHECK TUPLE from($fvar:ident: $ftyp:ty) -> ($( $e:expr ),*) $( $tail:tt )*)
+    => { quick_error!(ERROR_CHECK TUPLE $($tail)*); };
+    (ERROR_CHECK STRUCT from($fvar:ident: $ftyp:ty) -> {$( $v:ident: $e:expr ),*} $( $tail:tt )*)
+    => { quick_error!(ERROR_CHECK STRUCT $($tail)*); };
+
+    (ERROR_CHECK TUPLE context($cvar:ident: $ctyp:ty, $fvar:ident: $ftyp:ty)
+        -> ($( $e:expr ),*) $( $tail:tt )*)
+    => { quick_error!(ERROR_CHECK TUPLE $($tail)*); };
+    (ERROR_CHECK STRUCT context($cvar:ident: $ctyp:ty, $fvar:ident: $ftyp:ty)
+        -> {$( $v:ident: $e:expr ),*} $( $tail:tt )*)
+    => { quick_error!(ERROR_CHECK STRUCT $($tail)*); };
+
+    (ERROR_CHECK $imode:tt ) => {};
+    // Utility functions
+    (IDENT $ident:ident) => { $ident }
+}
+
+
+/// Generic context type
+///
+/// Used mostly as a transport for `ResultExt::context` method
+#[derive(Debug)]
+pub struct Context<X, E>(pub X, pub E);
+
+/// Result extension trait adding a `context` method
+pub trait ResultExt<T, E> {
+    /// The method is use to add context information to current operation
+    ///
+    /// The context data is then used in error constructor to store additional
+    /// information within error. For example, you may add a filename as a
+    /// context for file operation. See crate documentation for the actual
+    /// example.
+    fn context<X>(self, x: X) -> Result<T, Context<X, E>>;
+}
+
+impl<T, E> ResultExt<T, E> for Result<T, E> {
+    fn context<X>(self, x: X) -> Result<T, Context<X, E>> {
+        self.map_err(|e| Context(x, e))
+    }
+}
+
+
+
+#[cfg(test)]
+mod test {
+    use std::num::{ParseFloatError, ParseIntError};
+    use std::str::Utf8Error;
+    use std::string::FromUtf8Error;
+    use std::error::Error;
+    use std::path::{Path, PathBuf};
+
+    use super::ResultExt;
+
+    quick_error! {
+        #[derive(Debug)]
+        pub enum Bare {
+            One
+            Two
+        }
+    }
+
+    #[test]
+    fn bare_item_direct() {
+        assert_eq!(format!("{}", Bare::One), "One".to_string());
+        assert_eq!(format!("{:?}", Bare::One), "One".to_string());
+        assert_eq!(Bare::One.description(), "One".to_string());
+        assert!(Bare::One.cause().is_none());
+    }
+    #[test]
+    fn bare_item_trait() {
+        let err: &Error = &Bare::Two;
+        assert_eq!(format!("{}", err), "Two".to_string());
+        assert_eq!(format!("{:?}", err), "Two".to_string());
+        assert_eq!(err.description(), "Two".to_string());
+        assert!(err.cause().is_none());
+    }
+
+    quick_error! {
+        #[derive(Debug)]
+        pub enum Wrapper wraps Wrapped {
+            One
+            Two(s: String) {
+                display("two: {}", s)
+                from()
+            }
+        }
+    }
+
+    #[test]
+    fn wrapper() {
+        assert_eq!(format!("{}", Wrapper::from(Wrapped::One)),
+            "One".to_string());
+        assert_eq!(format!("{}",
+            Wrapper::from(Wrapped::from(String::from("hello")))),
+            "two: hello".to_string());
+        assert_eq!(format!("{:?}", Wrapper::from(Wrapped::One)),
+            "Wrapper(One)".to_string());
+        assert_eq!(Wrapper::from(Wrapped::One).description(),
+            "One".to_string());
+    }
+
+    quick_error! {
+        #[derive(Debug, PartialEq)]
+        pub enum TupleWrapper {
+            /// ParseFloat Error
+            ParseFloatError(err: ParseFloatError) {
+                from()
+                description(err.description())
+                display("parse float error: {err}", err=err)
+                cause(err)
+            }
+            Other(descr: &'static str) {
+                description(descr)
+                display("Error: {}", descr)
+            }
+            /// FromUtf8 Error
+            FromUtf8Error(err: Utf8Error, source: Vec<u8>) {
+                cause(err)
+                display(me) -> ("{desc} at index {pos}: {err}", desc=me.description(), pos=err.valid_up_to(), err=err)
+                description("utf8 error")
+                from(err: FromUtf8Error) -> (err.utf8_error().clone(), err.into_bytes())
+            }
+            Discard {
+                from(&'static str)
+            }
+            Singleton {
+                display("Just a string")
+            }
+        }
+    }
+
+    #[test]
+    fn tuple_wrapper_err() {
+        let cause = "one and a half times pi".parse::<f32>().unwrap_err();
+        let err = TupleWrapper::ParseFloatError(cause.clone());
+        assert_eq!(format!("{}", err), format!("parse float error: {}", cause));
+        assert_eq!(format!("{:?}", err), format!("ParseFloatError({:?})", cause));
+        assert_eq!(err.description(), cause.description());
+        assert_eq!(format!("{:?}", err.cause().unwrap()), format!("{:?}", cause));
+    }
+
+    #[test]
+    fn tuple_wrapper_trait_str() {
+        let desc = "hello";
+        let err: &Error = &TupleWrapper::Other(desc);
+        assert_eq!(format!("{}", err), format!("Error: {}", desc));
+        assert_eq!(format!("{:?}", err), format!("Other({:?})", desc));
+        assert_eq!(err.description(), desc);
+        assert!(err.cause().is_none());
+    }
+
+    #[test]
+    fn tuple_wrapper_trait_two_fields() {
+        let invalid_utf8: Vec<u8> = vec![0, 159, 146, 150];
+        let cause = String::from_utf8(invalid_utf8.clone()).unwrap_err().utf8_error();
+        let err: &Error = &TupleWrapper::FromUtf8Error(cause.clone(), invalid_utf8.clone());
+        assert_eq!(format!("{}", err), format!("{desc} at index {pos}: {cause}", desc=err.description(), pos=cause.valid_up_to(), cause=cause));
+        assert_eq!(format!("{:?}", err), format!("FromUtf8Error({:?}, {:?})", cause, invalid_utf8));
+        assert_eq!(err.description(), "utf8 error");
+        assert_eq!(format!("{:?}", err.cause().unwrap()), format!("{:?}", cause));
+    }
+
+    #[test]
+    fn tuple_wrapper_from() {
+        let cause = "one and a half times pi".parse::<f32>().unwrap_err();
+        let err = TupleWrapper::ParseFloatError(cause.clone());
+        let err_from: TupleWrapper = From::from(cause);
+        assert_eq!(err_from, err);
+    }
+
+    #[test]
+    fn tuple_wrapper_custom_from() {
+        let invalid_utf8: Vec<u8> = vec![0, 159, 146, 150];
+        let cause = String::from_utf8(invalid_utf8.clone()).unwrap_err();
+        let err = TupleWrapper::FromUtf8Error(cause.utf8_error().clone(), invalid_utf8);
+        let err_from: TupleWrapper = From::from(cause);
+        assert_eq!(err_from, err);
+    }
+
+    #[test]
+    fn tuple_wrapper_discard() {
+        let err: TupleWrapper = From::from("hello");
+        assert_eq!(format!("{}", err), format!("Discard"));
+        assert_eq!(format!("{:?}", err), format!("Discard"));
+        assert_eq!(err.description(), "Discard");
+        assert!(err.cause().is_none());
+    }
+
+    #[test]
+    fn tuple_wrapper_singleton() {
+        let err: TupleWrapper = TupleWrapper::Singleton;
+        assert_eq!(format!("{}", err), format!("Just a string"));
+        assert_eq!(format!("{:?}", err), format!("Singleton"));
+        assert_eq!(err.description(), "Singleton");
+        assert!(err.cause().is_none());
+    }
+
+    quick_error! {
+        #[derive(Debug, PartialEq)]
+        pub enum StructWrapper {
+            // Utf8 Error
+            Utf8Error{ err: Utf8Error, hint: Option<&'static str> } {
+                cause(err)
+                display(me) -> ("{desc} at index {pos}: {err}", desc=me.description(), pos=err.valid_up_to(), err=err)
+                description("utf8 error")
+                from(err: Utf8Error) -> { err: err, hint: None }
+            }
+            // Utf8 Error
+            ExcessComma { descr: &'static str, } {
+                description(descr)
+                display("Error: {}", descr)
+            }
+        }
+    }
+
+    #[test]
+    fn struct_wrapper_err() {
+        let invalid_utf8: Vec<u8> = vec![0, 159, 146, 150];
+        let cause = String::from_utf8(invalid_utf8.clone()).unwrap_err().utf8_error();
+        let err: &Error = &StructWrapper::Utf8Error{ err: cause.clone(), hint: Some("nonsense") };
+        assert_eq!(format!("{}", err), format!("{desc} at index {pos}: {cause}", desc=err.description(), pos=cause.valid_up_to(), cause=cause));
+        assert_eq!(format!("{:?}", err), format!("Utf8Error {{ err: {:?}, hint: {:?} }}", cause, Some("nonsense")));
+        assert_eq!(err.description(), "utf8 error");
+        assert_eq!(format!("{:?}", err.cause().unwrap()), format!("{:?}", cause));
+    }
+
+    #[test]
+    fn struct_wrapper_struct_from() {
+        let invalid_utf8: Vec<u8> = vec![0, 159, 146, 150];
+        let cause = String::from_utf8(invalid_utf8.clone()).unwrap_err().utf8_error();
+        let err = StructWrapper::Utf8Error{ err: cause.clone(), hint: None };
+        let err_from: StructWrapper = From::from(cause);
+        assert_eq!(err_from, err);
+    }
+
+    #[test]
+    fn struct_wrapper_excess_comma() {
+        let descr = "hello";
+        let err = StructWrapper::ExcessComma { descr: descr };
+        assert_eq!(format!("{}", err), format!("Error: {}", descr));
+        assert_eq!(format!("{:?}", err), format!("ExcessComma {{ descr: {:?} }}", descr));
+        assert_eq!(err.description(), descr);
+        assert!(err.cause().is_none());
+    }
+
+    quick_error! {
+        #[derive(Debug)]
+        pub enum ContextErr {
+            Float(src: String, err: ParseFloatError) {
+                context(s: &'a str, e: ParseFloatError) -> (s.to_string(), e)
+                display("Float error {:?}: {}", src, err)
+            }
+            Int { src: String, err: ParseIntError } {
+                context(s: &'a str, e: ParseIntError)
+                    -> {src: s.to_string(), err: e}
+                display("Int error {:?}: {}", src, err)
+            }
+            Utf8(path: PathBuf, err: Utf8Error) {
+                context(p: AsRef<Path>, e: Utf8Error)
+                    -> (p.as_ref().to_path_buf(), e)
+                display("Path error at {:?}: {}", path, err)
+            }
+            Utf8Str(s: String, err: ::std::io::Error) {
+                context(s: AsRef<str>, e: ::std::io::Error)
+                    -> (s.as_ref().to_string(), e)
+                display("Str error {:?}: {}", s, err)
+            }
+        }
+    }
+
+    #[test]
+    fn parse_float_error() {
+        fn parse_float(s: &str) -> Result<f32, ContextErr> {
+            Ok(try!(s.parse().context(s)))
+        }
+        assert_eq!(format!("{}", parse_float("12ab").unwrap_err()),
+            r#"Float error "12ab": invalid float literal"#);
+    }
+
+    #[test]
+    fn parse_int_error() {
+        fn parse_int(s: &str) -> Result<i32, ContextErr> {
+            Ok(try!(s.parse().context(s)))
+        }
+        assert_eq!(format!("{}", parse_int("12.5").unwrap_err()),
+            r#"Int error "12.5": invalid digit found in string"#);
+    }
+
+    #[test]
+    fn debug_context() {
+        fn parse_int(s: &str) -> i32 {
+            s.parse().context(s).unwrap()
+        }
+        assert_eq!(parse_int("12"), 12);
+        assert_eq!(format!("{:?}", "x".parse::<i32>().context("x")),
+            r#"Err(Context("x", ParseIntError { kind: InvalidDigit }))"#);
+    }
+
+    #[test]
+    fn path_context() {
+        fn parse_utf<P: AsRef<Path>>(s: &[u8], p: P)
+            -> Result<(), ContextErr>
+        {
+            try!(::std::str::from_utf8(s).context(p));
+            Ok(())
+        }
+        let etext = parse_utf(b"a\x80\x80", "/etc").unwrap_err().to_string();
+        assert!(etext.starts_with(
+            "Path error at \"/etc\": invalid utf-8"));
+        let etext = parse_utf(b"\x80\x80", PathBuf::from("/tmp")).unwrap_err()
+            .to_string();
+        assert!(etext.starts_with(
+            "Path error at \"/tmp\": invalid utf-8"));
+    }
+
+    #[test]
+    fn conditional_compilation() {
+        quick_error! {
+            #[allow(dead_code)]
+            #[derive(Debug)]
+            pub enum Test {
+                #[cfg(feature = "foo")]
+                Variant
+            }
+        }
+    }
+}
diff --git a/third_party/rust_crates/vendor/quick-error-1.2.2/vagga.yaml b/third_party/rust_crates/vendor/quick-error-1.2.2/vagga.yaml
new file mode 100644
index 0000000..71b9be4
--- /dev/null
+++ b/third_party/rust_crates/vendor/quick-error-1.2.2/vagga.yaml
@@ -0,0 +1,36 @@
+commands:
+
+  cargo: !Command
+    description: Run any cargo command
+    container: ubuntu
+    run: [cargo]
+
+  test: !Command
+    description: Run unit tests
+    container: ubuntu
+    run: [cargo, test]
+
+  _bulk: !Command
+    description: Run `bulk` command (for version bookkeeping)
+    container: ubuntu
+    run: [bulk]
+
+containers:
+
+  ubuntu:
+    setup:
+    - !Ubuntu xenial
+    - !Install [ca-certificates, build-essential, vim]
+
+    - !TarInstall
+      url: "https://static.rust-lang.org/dist/rust-1.16.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.9/bulk-v0.4.9.tar.gz"
+      sha256: 23471a9986274bb4b7098c03e2eb7e1204171869b72c45385fcee1c64db2d111
+      path: /
+
+    environ:
+      HOME: /work/target
+      USER: pc
diff --git a/third_party/rust_crates/vendor/quick-error/.cargo-checksum.json b/third_party/rust_crates/vendor/quick-error/.cargo-checksum.json
index fbbd2b9..869218b 100644
--- a/third_party/rust_crates/vendor/quick-error/.cargo-checksum.json
+++ b/third_party/rust_crates/vendor/quick-error/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"4c012206d297a8e8b0d2a92046a1135191ec67d561120b4e58de148ccafb1efe","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"058f01fe181608d027fcde7e528fc03ea3cf90f30903c407644b0a9bbc54f500","README.rst":"15120e9c7ef1ff5d794b3ce3bd301c0304c5bad5da974b7030622f31efc6e6f8","bulk.yaml":"17c2548388e0cd3a63473021a2f1e4ddedee082d79d9167cb31ad06a1890d3fc","examples/context.rs":"b9be9a4ca021a1f0ba659932bfc0cf891728bfaea49d48a8be183644c492515b","src/lib.rs":"92f3a2cb0351ffe7680cd54aee9cce26cf6d2623ac74725615bbccd099875964","vagga.yaml":"b01ad1fd3aa25de2439c0f7a437c6517808ba3a7eeeb0363eb209f08e326cc8e"},"package":"9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"}
\ No newline at end of file
+{"files":{"Cargo.lock":"d586689373f57572b86215aba1457e8486665e3a598e00b8f3f352b129e8aab5","Cargo.toml":"65148316f0d5161bbc86cd08f3feedf44936284c0665603baacf503d933a256e","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"058f01fe181608d027fcde7e528fc03ea3cf90f30903c407644b0a9bbc54f500","README.rst":"97f715a3a68ede33bca81c98ad791375b2bb7ad0d814377b0651f5c4de8f7d4a","bulk.yaml":"17c2548388e0cd3a63473021a2f1e4ddedee082d79d9167cb31ad06a1890d3fc","examples/context.rs":"5045319e03fa5214c7b2f9ef28d6012ffd34f7095d2103b5579a4c8567ddab68","src/lib.rs":"c94106502d7afb9ffb18b57ba9b42075b28017c765529e30db75a0e612152ec0","vagga.yaml":"280ac771f03284bb3f7e1b5b50c0b8046e79cc5c54f40b7c738f7a8ebaa586f2"},"package":"3ac73b1112776fc109b2e61909bc46c7e1bf0d7f690ffb1676553acce16d5cda"}
\ No newline at end of file
diff --git a/third_party/rust_crates/vendor/quick-error/Cargo.lock b/third_party/rust_crates/vendor/quick-error/Cargo.lock
new file mode 100644
index 0000000..4e9e64e
--- /dev/null
+++ b/third_party/rust_crates/vendor/quick-error/Cargo.lock
@@ -0,0 +1,5 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "quick-error"
+version = "2.0.0"
diff --git a/third_party/rust_crates/vendor/quick-error/Cargo.toml b/third_party/rust_crates/vendor/quick-error/Cargo.toml
index 19bc242..f5f9292 100644
--- a/third_party/rust_crates/vendor/quick-error/Cargo.toml
+++ b/third_party/rust_crates/vendor/quick-error/Cargo.toml
@@ -3,7 +3,7 @@
 # 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
+# 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
@@ -11,8 +11,9 @@
 # will likely look very different (and much more reasonable)
 
 [package]
+edition = "2018"
 name = "quick-error"
-version = "1.2.2"
+version = "2.0.0"
 authors = ["Paul Colomiets <paul@colomiets.name>", "Colin Kiegel <kiegel@gmx.de>"]
 description = "    A macro which makes error types pleasant to write.\n"
 homepage = "http://github.com/tailhook/quick-error"
diff --git a/third_party/rust_crates/vendor/quick-error/README.rst b/third_party/rust_crates/vendor/quick-error/README.rst
index 9b934a9..67773e8 100644
--- a/third_party/rust_crates/vendor/quick-error/README.rst
+++ b/third_party/rust_crates/vendor/quick-error/README.rst
@@ -3,7 +3,7 @@
 ===========
 
 :Status: production-ready
-:Documentation: http://tailhook.github.io/quick-error/
+:Documentation: https://docs.rs/quick-error/
 
 A macro which makes error types pleasant to write.
 
@@ -24,18 +24,15 @@
         pub enum IoWrapper {
             Io(err: io::Error) {
                 from()
-                description("io error")
                 display("I/O error: {}", err)
-                cause(err)
+                source(err)
             }
             Other(descr: &'static str) {
-                description(descr)
                 display("Error {}", descr)
             }
             IoAt { place: &'static str, err: io::Error } {
-                cause(err)
-                display(me) -> ("{} {}: {}", me.description(), place, err)
-                description("io error at")
+                source(err)
+                display(me) -> ("io error at {}: {}", place, err)
                 from(s: String) -> {
                     place: "some string",
                     err: io::Error::new(io::ErrorKind::Other, s)
diff --git a/third_party/rust_crates/vendor/quick-error/examples/context.rs b/third_party/rust_crates/vendor/quick-error/examples/context.rs
index 334700a..1d40661 100644
--- a/third_party/rust_crates/vendor/quick-error/examples/context.rs
+++ b/third_party/rust_crates/vendor/quick-error/examples/context.rs
@@ -1,19 +1,14 @@
-#[macro_use(quick_error)] extern crate quick_error;
-
-use std::io::{self, stderr, Read, Write};
-use std::fs::File;
+use quick_error::{quick_error, ResultExt};
 use std::env;
+use std::fs::File;
+use std::io::{self, stderr, Read, Write};
 use std::num::ParseIntError;
 use std::path::{Path, PathBuf};
 
-use quick_error::ResultExt;
-
 quick_error! {
     #[derive(Debug)]
     pub enum Error {
-        NoFileName {
-            description("no file name specified")
-        }
+        NoFileName {}
         Io(err: io::Error, path: PathBuf) {
             display("could not read file {:?}: {}", path, err)
             context(path: &'a Path, err: io::Error)
@@ -28,12 +23,12 @@
 }
 
 fn parse_file() -> Result<u64, Error> {
-    let fname = try!(env::args().skip(1).next().ok_or(Error::NoFileName));
+    let fname = env::args().skip(1).next().ok_or(Error::NoFileName)?;
     let fname = Path::new(&fname);
-    let mut file = try!(File::open(fname).context(fname));
+    let mut file = File::open(fname).context(fname)?;
     let mut buf = String::new();
-    try!(file.read_to_string(&mut buf).context(fname));
-    Ok(try!(buf.parse().context(fname)))
+    file.read_to_string(&mut buf).context(fname)?;
+    Ok(buf.parse().context(fname)?)
 }
 
 fn main() {
diff --git a/third_party/rust_crates/vendor/quick-error/src/lib.rs b/third_party/rust_crates/vendor/quick-error/src/lib.rs
index fd95fe13..e5eb62e4 100644
--- a/third_party/rust_crates/vendor/quick-error/src/lib.rs
+++ b/third_party/rust_crates/vendor/quick-error/src/lib.rs
@@ -45,13 +45,10 @@
 //! Now you might have noticed trailing braces `{}`. They are used to define
 //! implementations. By default:
 //!
-//! * `Error::description()` returns variant name as static string
-//! * `Error::cause()` returns None (even if type wraps some value)
-//! * `Display` outputs `description()`
+//! * `Error::source()` returns None (even if type wraps some value)
+//! * `Display` outputs debug representation
 //! * No `From` implementations are defined
 //!
-//! To define description simply add `description(value)` inside braces:
-//!
 //! ```rust
 //! # #[macro_use] extern crate quick_error;
 //! # fn main() {}
@@ -60,19 +57,16 @@
 //!     #[derive(Debug)]
 //!     pub enum SomeError {
 //!         Io(err: std::io::Error) {
-//!             description(err.description())
+//!             display("{}", err)
 //!         }
 //!         Utf8(err: std::str::Utf8Error) {
-//!             description("utf8 error")
+//!             display("utf8 error")
 //!         }
 //!     }
 //! }
 //! ```
 //!
-//! Normal rules for borrowing apply. So most of the time description either
-//! returns constant string or forwards description from enclosed type.
-//!
-//! To change `cause` method to return some error, add `cause(value)`, for
+//! To change `source` method to return some error, add `source(value)`, for
 //! example:
 //!
 //! ```rust
@@ -83,21 +77,19 @@
 //!     #[derive(Debug)]
 //!     pub enum SomeError {
 //!         Io(err: std::io::Error) {
-//!             cause(err)
-//!             description(err.description())
+//!             source(err)
 //!         }
 //!         Utf8(err: std::str::Utf8Error) {
-//!             description("utf8 error")
+//!             display("utf8 error")
 //!         }
 //!         Other(err: Box<std::error::Error>) {
-//!             cause(&**err)
-//!             description(err.description())
+//!             source(&**err)
 //!         }
 //!     }
 //! }
 //! ```
 //! Note you don't need to wrap value in `Some`, its implicit. In case you want
-//! `None` returned just omit the `cause`. You can't return `None`
+//! `None` returned just omit the `source`. You can't return `None`
 //! conditionally.
 //!
 //! To change how each clause is `Display`ed add `display(pattern,..args)`,
@@ -127,16 +119,16 @@
 //! # #[macro_use] extern crate quick_error;
 //! # fn main() {}
 //! #
-//! use std::error::Error; // put methods like `description()` of this trait into scope
+//! use std::error::Error; // put methods like `source()` of this trait into scope
 //!
 //! quick_error! {
 //!     #[derive(Debug)]
 //!     pub enum SomeError {
 //!         Io(err: std::io::Error) {
-//!             display(x) -> ("{}: {}", x.description(), err)
+//!             display(x) -> ("I/O: {}", err)
 //!         }
 //!         Utf8(err: std::str::Utf8Error) {
-//!             display(self_) -> ("{}, valid up to {}", self_.description(), err.valid_up_to())
+//!             display(self_) -> ("UTF-8 error. Valid up to {}", err.valid_up_to())
 //!         }
 //!     }
 //! }
@@ -228,12 +220,12 @@
 //! }
 //!
 //! fn openfile(path: &Path) -> Result<(), Error> {
-//!     try!(File::open(path).context(path));
+//!     File::open(path).context(path)?;
 //!
 //!     // If we didn't have context, the line above would be written as;
 //!     //
-//!     // try!(File::open(path)
-//!     //     .map_err(|err| Error::File(path.to_path_buf(), err)));
+//!     // File::open(path)
+//!     //     .map_err(|err| Error::File(path.to_path_buf(), err))?;
 //!
 //!     Ok(())
 //! }
@@ -256,7 +248,7 @@
 //!
 //! More info on context in [this article](http://bit.ly/1PsuxDt).
 //!
-//! All forms of `from`, `display`, `description`, `cause`, and `context`
+//! All forms of `from`, `display`, `source`, and `context`
 //! clauses can be combined and put in arbitrary order. Only `from` and
 //! `context` can be used multiple times in single variant of enumeration.
 //! Docstrings are also okay.  Empty braces can be omitted as of quick_error
@@ -301,7 +293,6 @@
 //!
 //!
 
-
 /// Main macro that does all the work
 #[macro_export]
 macro_rules! quick_error {
@@ -379,11 +370,8 @@
         }
 
         impl ::std::error::Error for $strname {
-            fn description(&self) -> &str {
-                self.0.description()
-            }
-            fn cause(&self) -> Option<&::std::error::Error> {
-                self.0.cause()
+            fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
+                self.0.source()
             }
         }
     };
@@ -464,8 +452,6 @@
         queue [ #[$qmeta:meta] $( $tail:tt )*]
     ) => {
         quick_error!(SORT [$( $def )*]
-            enum [$( $(#[$emeta])* => $eitem $(( $($etyp),* ))* )*
-                     $(#[$bmeta])* => $bitem: $bmode $(( $($btyp),* ))*]
             items [$($( #[$imeta:meta] )*
                       => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*
                      $bitem: $bmode [$( $bvar:$btyp ),*] {} ]
@@ -482,7 +468,7 @@
     ) => {
         quick_error!(SORT [$( $def )*]
             items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
-            buf [$( #[$bmeta] )* => $bitem: TUPLE [$( $qvar:$qtyp ),*] ]
+            buf [$( #[$bmeta] )* => $bitem: TUPLE [$( $qvar:$qtyp ),+] ]
             queue [$( $tail )*]
         );
     };
@@ -496,7 +482,7 @@
     ) => {
         quick_error!(SORT [$( $def )*]
             items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
-            buf [$( #[$bmeta] )* => $bitem: STRUCT [$( $qvar:$qtyp ),*] ]
+            buf [$( #[$bmeta] )* => $bitem: STRUCT [$( $qvar:$qtyp ),+] ]
             queue [$( $tail )*]);
     };
     // Add struct enum-variant, with excess comma - e.g. { descr: &'static str, }
@@ -509,7 +495,7 @@
     ) => {
         quick_error!(SORT [$( $def )*]
             items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
-            buf [$( #[$bmeta] )* => $bitem: STRUCT [$( $qvar:$qtyp ),*] ]
+            buf [$( #[$bmeta] )* => $bitem: STRUCT [$( $qvar:$qtyp ),+] ]
             queue [$( $tail )*]);
     };
     // Add braces and flush always on braces
@@ -571,7 +557,7 @@
         pub enum $name {
             $(
                 $(#[$imeta])*
-                $iitem $(($( $ttyp ),*))* $({$( $svar: $styp ),*})*,
+                $iitem $(($( $ttyp ),+))* $({$( $svar: $styp ),*})*,
             )*
         }
     };
@@ -589,7 +575,7 @@
         enum $name {
             $(
                 $(#[$imeta])*
-                $iitem $(($( $ttyp ),*))* $({$( $svar: $styp ),*})*,
+                $iitem $(($( $ttyp ),+))* $({$( $svar: $styp ),*})*,
             )*
         }
     };
@@ -615,7 +601,7 @@
     ) => {
         quick_error!(ENUM_DEFINITION [ $($def)* ]
             body [$($( #[$imeta] )* => $iitem ($(($( $ttyp ),+))*) {$({$( $svar: $styp ),*})*} )*
-                    $( #[$qmeta] )* => $qitem (($( $qtyp ),*)) {} ]
+                    $( #[$qmeta] )* => $qitem (($( $qtyp ),+)) {} ]
             queue [ $($queue)* ]
         );
     };
@@ -668,28 +654,14 @@
         #[allow(unused_doc_comment)]
         #[allow(unused_doc_comments)]
         impl ::std::error::Error for $name {
-            fn description(&self) -> &str {
+            fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
                 match *self {
                     $(
                         $(#[$imeta])*
                         quick_error!(ITEM_PATTERN
                             $name $item: $imode [$( ref $var ),*]
                         ) => {
-                            quick_error!(FIND_DESCRIPTION_IMPL
-                                $item: $imode self fmt [$( $var ),*]
-                                {$( $funcs )*})
-                        }
-                    )*
-                }
-            }
-            fn cause(&self) -> Option<&::std::error::Error> {
-                match *self {
-                    $(
-                        $(#[$imeta])*
-                        quick_error!(ITEM_PATTERN
-                            $name $item: $imode [$( ref $var ),*]
-                        ) => {
-                            quick_error!(FIND_CAUSE_IMPL
+                            quick_error!(FIND_SOURCE_IMPL
                                 $item: $imode [$( $var ),*]
                                 {$( $funcs )*})
                         }
@@ -734,44 +706,24 @@
         { }
     ) => {
         |self_: &$name, f: &mut ::std::fmt::Formatter| {
-            write!(f, "{}", ::std::error::Error::description(self_))
+            write!(f, "{:?}", self_)
         }
     };
-    (FIND_DESCRIPTION_IMPL $item:ident: $imode:tt $me:ident $fmt:ident
+    (FIND_SOURCE_IMPL $item:ident: $imode:tt
         [$( $var:ident ),*]
-        { description($expr:expr) $( $tail:tt )*}
-    ) => {
-        $expr
-    };
-    (FIND_DESCRIPTION_IMPL $item:ident: $imode:tt $me:ident $fmt:ident
-        [$( $var:ident ),*]
-        { $t:tt $( $tail:tt )*}
-    ) => {
-        quick_error!(FIND_DESCRIPTION_IMPL
-            $item: $imode $me $fmt [$( $var ),*]
-            {$( $tail )*})
-    };
-    (FIND_DESCRIPTION_IMPL $item:ident: $imode:tt $me:ident $fmt:ident
-        [$( $var:ident ),*]
-        { }
-    ) => {
-        stringify!($item)
-    };
-    (FIND_CAUSE_IMPL $item:ident: $imode:tt
-        [$( $var:ident ),*]
-        { cause($expr:expr) $( $tail:tt )*}
+        { source($expr:expr) $( $tail:tt )*}
     ) => {
         Some($expr)
     };
-    (FIND_CAUSE_IMPL $item:ident: $imode:tt
+    (FIND_SOURCE_IMPL $item:ident: $imode:tt
         [$( $var:ident ),*]
         { $t:tt $( $tail:tt )*}
     ) => {
-        quick_error!(FIND_CAUSE_IMPL
+        quick_error!(FIND_SOURCE_IMPL
             $item: $imode [$( $var ),*]
             { $($tail)* })
     };
-    (FIND_CAUSE_IMPL $item:ident: $imode:tt
+    (FIND_SOURCE_IMPL $item:ident: $imode:tt
         [$( $var:ident ),*]
         { }
     ) => {
@@ -972,9 +924,7 @@
     => { quick_error!(ERROR_CHECK $imode $($tail)*); };
     (ERROR_CHECK $imode:tt display($pattern: expr, $( $exprs:tt )*) $( $tail:tt )*)
     => { quick_error!(ERROR_CHECK $imode $($tail)*); };
-    (ERROR_CHECK $imode:tt description($expr:expr) $( $tail:tt )*)
-    => { quick_error!(ERROR_CHECK $imode $($tail)*); };
-    (ERROR_CHECK $imode:tt cause($expr:expr) $($tail:tt)*)
+    (ERROR_CHECK $imode:tt source($expr:expr) $($tail:tt)*)
     => { quick_error!(ERROR_CHECK $imode $($tail)*); };
     (ERROR_CHECK $imode:tt from() $($tail:tt)*)
     => { quick_error!(ERROR_CHECK $imode $($tail)*); };
@@ -997,7 +947,6 @@
     (IDENT $ident:ident) => { $ident }
 }
 
-
 /// Generic context type
 ///
 /// Used mostly as a transport for `ResultExt::context` method
@@ -1021,15 +970,13 @@
     }
 }
 
-
-
 #[cfg(test)]
 mod test {
+    use std::error::Error;
     use std::num::{ParseFloatError, ParseIntError};
+    use std::path::{Path, PathBuf};
     use std::str::Utf8Error;
     use std::string::FromUtf8Error;
-    use std::error::Error;
-    use std::path::{Path, PathBuf};
 
     use super::ResultExt;
 
@@ -1045,16 +992,15 @@
     fn bare_item_direct() {
         assert_eq!(format!("{}", Bare::One), "One".to_string());
         assert_eq!(format!("{:?}", Bare::One), "One".to_string());
-        assert_eq!(Bare::One.description(), "One".to_string());
-        assert!(Bare::One.cause().is_none());
+        assert!(Bare::One.source().is_none());
     }
+
     #[test]
     fn bare_item_trait() {
-        let err: &Error = &Bare::Two;
+        let err: &dyn Error = &Bare::Two;
         assert_eq!(format!("{}", err), "Two".to_string());
         assert_eq!(format!("{:?}", err), "Two".to_string());
-        assert_eq!(err.description(), "Two".to_string());
-        assert!(err.cause().is_none());
+        assert!(err.source().is_none());
     }
 
     quick_error! {
@@ -1070,15 +1016,18 @@
 
     #[test]
     fn wrapper() {
-        assert_eq!(format!("{}", Wrapper::from(Wrapped::One)),
-            "One".to_string());
-        assert_eq!(format!("{}",
-            Wrapper::from(Wrapped::from(String::from("hello")))),
-            "two: hello".to_string());
-        assert_eq!(format!("{:?}", Wrapper::from(Wrapped::One)),
-            "Wrapper(One)".to_string());
-        assert_eq!(Wrapper::from(Wrapped::One).description(),
-            "One".to_string());
+        assert_eq!(
+            format!("{}", Wrapper::from(Wrapped::One)),
+            "One".to_string()
+        );
+        assert_eq!(
+            format!("{}", Wrapper::from(Wrapped::from(String::from("hello")))),
+            "two: hello".to_string()
+        );
+        assert_eq!(
+            format!("{:?}", Wrapper::from(Wrapped::One)),
+            "Wrapper(One)".to_string()
+        );
     }
 
     quick_error! {
@@ -1087,19 +1036,16 @@
             /// ParseFloat Error
             ParseFloatError(err: ParseFloatError) {
                 from()
-                description(err.description())
                 display("parse float error: {err}", err=err)
-                cause(err)
+                source(err)
             }
             Other(descr: &'static str) {
-                description(descr)
                 display("Error: {}", descr)
             }
             /// FromUtf8 Error
             FromUtf8Error(err: Utf8Error, source: Vec<u8>) {
-                cause(err)
-                display(me) -> ("{desc} at index {pos}: {err}", desc=me.description(), pos=err.valid_up_to(), err=err)
-                description("utf8 error")
+                source(err)
+                display(me) -> ("{desc} at index {pos}: {err}", desc="utf8 error", pos=err.valid_up_to(), err=err)
                 from(err: FromUtf8Error) -> (err.utf8_error().clone(), err.into_bytes())
             }
             Discard {
@@ -1113,49 +1059,68 @@
 
     #[test]
     fn tuple_wrapper_err() {
-        let cause = "one and a half times pi".parse::<f32>().unwrap_err();
-        let err = TupleWrapper::ParseFloatError(cause.clone());
-        assert_eq!(format!("{}", err), format!("parse float error: {}", cause));
-        assert_eq!(format!("{:?}", err), format!("ParseFloatError({:?})", cause));
-        assert_eq!(err.description(), cause.description());
-        assert_eq!(format!("{:?}", err.cause().unwrap()), format!("{:?}", cause));
+        let source = "one and a half times pi".parse::<f32>().unwrap_err();
+        let err = TupleWrapper::ParseFloatError(source.clone());
+        assert_eq!(format!("{}", err), format!("parse float error: {}", source));
+        assert_eq!(
+            format!("{:?}", err),
+            format!("ParseFloatError({:?})", source)
+        );
+        assert_eq!(
+            format!("{:?}", err.source().unwrap()),
+            format!("{:?}", source)
+        );
     }
 
     #[test]
     fn tuple_wrapper_trait_str() {
         let desc = "hello";
-        let err: &Error = &TupleWrapper::Other(desc);
+        let err: &dyn Error = &TupleWrapper::Other(desc);
         assert_eq!(format!("{}", err), format!("Error: {}", desc));
         assert_eq!(format!("{:?}", err), format!("Other({:?})", desc));
-        assert_eq!(err.description(), desc);
-        assert!(err.cause().is_none());
+        assert!(err.source().is_none());
     }
 
     #[test]
     fn tuple_wrapper_trait_two_fields() {
         let invalid_utf8: Vec<u8> = vec![0, 159, 146, 150];
-        let cause = String::from_utf8(invalid_utf8.clone()).unwrap_err().utf8_error();
-        let err: &Error = &TupleWrapper::FromUtf8Error(cause.clone(), invalid_utf8.clone());
-        assert_eq!(format!("{}", err), format!("{desc} at index {pos}: {cause}", desc=err.description(), pos=cause.valid_up_to(), cause=cause));
-        assert_eq!(format!("{:?}", err), format!("FromUtf8Error({:?}, {:?})", cause, invalid_utf8));
-        assert_eq!(err.description(), "utf8 error");
-        assert_eq!(format!("{:?}", err.cause().unwrap()), format!("{:?}", cause));
+        let source = String::from_utf8(invalid_utf8.clone())
+            .unwrap_err()
+            .utf8_error();
+        let err: &dyn Error = &TupleWrapper::FromUtf8Error(source.clone(), invalid_utf8.clone());
+        assert_eq!(
+            format!("{}", err),
+            format!(
+                "{desc} at index {pos}: {source}",
+                desc = "utf8 error",
+                pos = source.valid_up_to(),
+                source = source
+            )
+        );
+        assert_eq!(
+            format!("{:?}", err),
+            format!("FromUtf8Error({:?}, {:?})", source, invalid_utf8)
+        );
+        assert_eq!(
+            format!("{:?}", err.source().unwrap()),
+            format!("{:?}", source)
+        );
     }
 
     #[test]
     fn tuple_wrapper_from() {
-        let cause = "one and a half times pi".parse::<f32>().unwrap_err();
-        let err = TupleWrapper::ParseFloatError(cause.clone());
-        let err_from: TupleWrapper = From::from(cause);
+        let source = "one and a half times pi".parse::<f32>().unwrap_err();
+        let err = TupleWrapper::ParseFloatError(source.clone());
+        let err_from: TupleWrapper = From::from(source);
         assert_eq!(err_from, err);
     }
 
     #[test]
     fn tuple_wrapper_custom_from() {
         let invalid_utf8: Vec<u8> = vec![0, 159, 146, 150];
-        let cause = String::from_utf8(invalid_utf8.clone()).unwrap_err();
-        let err = TupleWrapper::FromUtf8Error(cause.utf8_error().clone(), invalid_utf8);
-        let err_from: TupleWrapper = From::from(cause);
+        let source = String::from_utf8(invalid_utf8.clone()).unwrap_err();
+        let err = TupleWrapper::FromUtf8Error(source.utf8_error().clone(), invalid_utf8);
+        let err_from: TupleWrapper = From::from(source);
         assert_eq!(err_from, err);
     }
 
@@ -1164,8 +1129,7 @@
         let err: TupleWrapper = From::from("hello");
         assert_eq!(format!("{}", err), format!("Discard"));
         assert_eq!(format!("{:?}", err), format!("Discard"));
-        assert_eq!(err.description(), "Discard");
-        assert!(err.cause().is_none());
+        assert!(err.source().is_none());
     }
 
     #[test]
@@ -1173,8 +1137,7 @@
         let err: TupleWrapper = TupleWrapper::Singleton;
         assert_eq!(format!("{}", err), format!("Just a string"));
         assert_eq!(format!("{:?}", err), format!("Singleton"));
-        assert_eq!(err.description(), "Singleton");
-        assert!(err.cause().is_none());
+        assert!(err.source().is_none());
     }
 
     quick_error! {
@@ -1182,14 +1145,12 @@
         pub enum StructWrapper {
             // Utf8 Error
             Utf8Error{ err: Utf8Error, hint: Option<&'static str> } {
-                cause(err)
-                display(me) -> ("{desc} at index {pos}: {err}", desc=me.description(), pos=err.valid_up_to(), err=err)
-                description("utf8 error")
+                source(err)
+                display(me) -> ("{desc} at index {pos}: {err}", desc="utf8 error", pos=err.valid_up_to(), err=err)
                 from(err: Utf8Error) -> { err: err, hint: None }
             }
             // Utf8 Error
             ExcessComma { descr: &'static str, } {
-                description(descr)
                 display("Error: {}", descr)
             }
         }
@@ -1198,20 +1159,47 @@
     #[test]
     fn struct_wrapper_err() {
         let invalid_utf8: Vec<u8> = vec![0, 159, 146, 150];
-        let cause = String::from_utf8(invalid_utf8.clone()).unwrap_err().utf8_error();
-        let err: &Error = &StructWrapper::Utf8Error{ err: cause.clone(), hint: Some("nonsense") };
-        assert_eq!(format!("{}", err), format!("{desc} at index {pos}: {cause}", desc=err.description(), pos=cause.valid_up_to(), cause=cause));
-        assert_eq!(format!("{:?}", err), format!("Utf8Error {{ err: {:?}, hint: {:?} }}", cause, Some("nonsense")));
-        assert_eq!(err.description(), "utf8 error");
-        assert_eq!(format!("{:?}", err.cause().unwrap()), format!("{:?}", cause));
+        let source = String::from_utf8(invalid_utf8.clone())
+            .unwrap_err()
+            .utf8_error();
+        let err: &dyn Error = &StructWrapper::Utf8Error {
+            err: source.clone(),
+            hint: Some("nonsense"),
+        };
+        assert_eq!(
+            format!("{}", err),
+            format!(
+                "{desc} at index {pos}: {source}",
+                desc = "utf8 error",
+                pos = source.valid_up_to(),
+                source = source
+            )
+        );
+        assert_eq!(
+            format!("{:?}", err),
+            format!(
+                "Utf8Error {{ err: {:?}, hint: {:?} }}",
+                source,
+                Some("nonsense")
+            )
+        );
+        assert_eq!(
+            format!("{:?}", err.source().unwrap()),
+            format!("{:?}", source)
+        );
     }
 
     #[test]
     fn struct_wrapper_struct_from() {
         let invalid_utf8: Vec<u8> = vec![0, 159, 146, 150];
-        let cause = String::from_utf8(invalid_utf8.clone()).unwrap_err().utf8_error();
-        let err = StructWrapper::Utf8Error{ err: cause.clone(), hint: None };
-        let err_from: StructWrapper = From::from(cause);
+        let source = String::from_utf8(invalid_utf8.clone())
+            .unwrap_err()
+            .utf8_error();
+        let err = StructWrapper::Utf8Error {
+            err: source.clone(),
+            hint: None,
+        };
+        let err_from: StructWrapper = From::from(source);
         assert_eq!(err_from, err);
     }
 
@@ -1220,9 +1208,11 @@
         let descr = "hello";
         let err = StructWrapper::ExcessComma { descr: descr };
         assert_eq!(format!("{}", err), format!("Error: {}", descr));
-        assert_eq!(format!("{:?}", err), format!("ExcessComma {{ descr: {:?} }}", descr));
-        assert_eq!(err.description(), descr);
-        assert!(err.cause().is_none());
+        assert_eq!(
+            format!("{:?}", err),
+            format!("ExcessComma {{ descr: {:?} }}", descr)
+        );
+        assert!(err.source().is_none());
     }
 
     quick_error! {
@@ -1253,19 +1243,23 @@
     #[test]
     fn parse_float_error() {
         fn parse_float(s: &str) -> Result<f32, ContextErr> {
-            Ok(try!(s.parse().context(s)))
+            Ok(s.parse().context(s)?)
         }
-        assert_eq!(format!("{}", parse_float("12ab").unwrap_err()),
-            r#"Float error "12ab": invalid float literal"#);
+        assert_eq!(
+            format!("{}", parse_float("12ab").unwrap_err()),
+            r#"Float error "12ab": invalid float literal"#
+        );
     }
 
     #[test]
     fn parse_int_error() {
         fn parse_int(s: &str) -> Result<i32, ContextErr> {
-            Ok(try!(s.parse().context(s)))
+            Ok(s.parse().context(s)?)
         }
-        assert_eq!(format!("{}", parse_int("12.5").unwrap_err()),
-            r#"Int error "12.5": invalid digit found in string"#);
+        assert_eq!(
+            format!("{}", parse_int("12.5").unwrap_err()),
+            r#"Int error "12.5": invalid digit found in string"#
+        );
     }
 
     #[test]
@@ -1274,25 +1268,24 @@
             s.parse().context(s).unwrap()
         }
         assert_eq!(parse_int("12"), 12);
-        assert_eq!(format!("{:?}", "x".parse::<i32>().context("x")),
-            r#"Err(Context("x", ParseIntError { kind: InvalidDigit }))"#);
+        assert_eq!(
+            format!("{:?}", "x".parse::<i32>().context("x")),
+            r#"Err(Context("x", ParseIntError { kind: InvalidDigit }))"#
+        );
     }
 
     #[test]
     fn path_context() {
-        fn parse_utf<P: AsRef<Path>>(s: &[u8], p: P)
-            -> Result<(), ContextErr>
-        {
-            try!(::std::str::from_utf8(s).context(p));
+        fn parse_utf<P: AsRef<Path>>(s: &[u8], p: P) -> Result<(), ContextErr> {
+            ::std::str::from_utf8(s).context(p)?;
             Ok(())
         }
         let etext = parse_utf(b"a\x80\x80", "/etc").unwrap_err().to_string();
-        assert!(etext.starts_with(
-            "Path error at \"/etc\": invalid utf-8"));
-        let etext = parse_utf(b"\x80\x80", PathBuf::from("/tmp")).unwrap_err()
+        assert!(etext.starts_with("Path error at \"/etc\": invalid utf-8"));
+        let etext = parse_utf(b"\x80\x80", PathBuf::from("/tmp"))
+            .unwrap_err()
             .to_string();
-        assert!(etext.starts_with(
-            "Path error at \"/tmp\": invalid utf-8"));
+        assert!(etext.starts_with("Path error at \"/tmp\": invalid utf-8"));
     }
 
     #[test]
@@ -1306,4 +1299,38 @@
             }
         }
     }
+
+    #[test]
+    #[allow(deprecated)]
+    fn cause_struct_wrapper_err() {
+        let invalid_utf8: Vec<u8> = vec![0, 159, 146, 150];
+        let cause = String::from_utf8(invalid_utf8.clone())
+            .unwrap_err()
+            .utf8_error();
+        let err: &dyn Error = &StructWrapper::Utf8Error {
+            err: cause.clone(),
+            hint: Some("nonsense"),
+        };
+        assert_eq!(
+            format!("{}", err),
+            format!(
+                "{desc} at index {pos}: {cause}",
+                desc = "utf8 error",
+                pos = cause.valid_up_to(),
+                cause = cause
+            )
+        );
+        assert_eq!(
+            format!("{:?}", err),
+            format!(
+                "Utf8Error {{ err: {:?}, hint: {:?} }}",
+                cause,
+                Some("nonsense")
+            )
+        );
+        assert_eq!(
+            format!("{:?}", err.cause().unwrap()),
+            format!("{:?}", cause)
+        );
+    }
 }
diff --git a/third_party/rust_crates/vendor/quick-error/vagga.yaml b/third_party/rust_crates/vendor/quick-error/vagga.yaml
index 71b9be4..35eb296 100644
--- a/third_party/rust_crates/vendor/quick-error/vagga.yaml
+++ b/third_party/rust_crates/vendor/quick-error/vagga.yaml
@@ -23,12 +23,12 @@
     - !Install [ca-certificates, build-essential, vim]
 
     - !TarInstall
-      url: "https://static.rust-lang.org/dist/rust-1.16.0-x86_64-unknown-linux-gnu.tar.gz"
+      url: "https://static.rust-lang.org/dist/rust-1.31.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.9/bulk-v0.4.9.tar.gz"
-      sha256: 23471a9986274bb4b7098c03e2eb7e1204171869b72c45385fcee1c64db2d111
+      url: "https://github.com/tailhook/bulk/releases/download/v0.4.10/bulk-v0.4.10.tar.gz"
+      sha256: 481513f8a0306a9857d045497fb5b50b50a51e9ff748909ecf7d2bda1de275ab
       path: /
 
     environ:
diff --git a/tools/create/src/main.rs b/tools/create/src/main.rs
index a72370e..dec82ac 100644
--- a/tools/create/src/main.rs
+++ b/tools/create/src/main.rs
@@ -292,7 +292,7 @@
 /// Registers any partial templates (templates whose file names begin with `_`) with the templating
 /// engine.
 fn register_partial_templates<FR>(
-    handlebars: &mut Handlebars,
+    handlebars: &mut Handlebars<'_>,
     templates_dir: &Path,
     template_files: &Vec<PathBuf>,
     file_reader: &FR,
@@ -462,7 +462,7 @@
     // accessible to the templates.
     fn render(
         &self,
-        handlebars: &mut Handlebars,
+        handlebars: &mut Handlebars<'_>,
         args: &TemplateArgs,
     ) -> Result<RenderedTree, handlebars::TemplateRenderError> {
         Ok(match self {
diff --git a/tools/create/src/template_helpers.rs b/tools/create/src/template_helpers.rs
index b706fdb..c4ff03a 100644
--- a/tools/create/src/template_helpers.rs
+++ b/tools/create/src/template_helpers.rs
@@ -13,7 +13,7 @@
 handlebars_helper!(screaming_snake_case: |arg: str| arg.to_shouty_snake_case());
 
 /// Register all applicable helper template methods.
-pub fn register_helpers(handlebars: &mut Handlebars) {
+pub fn register_helpers(handlebars: &mut Handlebars<'_>) {
     // `{{pascal_case arg}}` converts `arg` to PascalCase.
     handlebars.register_helper("pascal_case", Box::new(pascal_case));
 
diff --git a/tools/fidl/fidldoc/src/main.rs b/tools/fidl/fidldoc/src/main.rs
index cbef16a..b691831 100644
--- a/tools/fidl/fidldoc/src/main.rs
+++ b/tools/fidl/fidldoc/src/main.rs
@@ -428,10 +428,10 @@
     Ok(())
 }
 
-fn select_template(
+fn select_template<'a>(
     template_type: &TemplateType,
-    output_path: &PathBuf,
-) -> Result<Box<dyn FidldocTemplate>, Error> {
+    output_path: &'a PathBuf,
+) -> Result<Box<dyn FidldocTemplate + 'a>, Error> {
     // Instantiate the template selected by the user
     let template: Box<dyn FidldocTemplate> = match template_type {
         TemplateType::HTML => {
diff --git a/tools/fidl/fidldoc/src/templates/html/mod.rs b/tools/fidl/fidldoc/src/templates/html/mod.rs
index 3f452a5..f0f7f90 100644
--- a/tools/fidl/fidldoc/src/templates/html/mod.rs
+++ b/tools/fidl/fidldoc/src/templates/html/mod.rs
@@ -14,13 +14,13 @@
 
 use crate::templates::{FidldocTemplate, HandlebarsHelper};
 
-pub struct HtmlTemplate {
-    handlebars: Handlebars,
+pub struct HtmlTemplate<'a> {
+    handlebars: Handlebars<'a>,
     output_path: PathBuf,
 }
 
-impl HtmlTemplate {
-    pub fn new(output_path: &PathBuf) -> Result<HtmlTemplate, Error> {
+impl HtmlTemplate<'_> {
+    pub fn new(output_path: &PathBuf) -> Result<HtmlTemplate<'_>, Error> {
         info!("The HTML template is not ready, please use Markdown");
 
         // Handlebars
@@ -50,7 +50,7 @@
     }
 }
 
-impl FidldocTemplate for HtmlTemplate {
+impl FidldocTemplate for HtmlTemplate<'_> {
     fn render_main_page(&self, main_fidl_json: &Value) -> Result<(), Error> {
         // Render main page
         let main_page_path = self.output_path.join("index.html");
@@ -94,9 +94,9 @@
 
 fn package_hash(
     h: &Helper<'_, '_>,
-    _: &Handlebars,
+    _: &Handlebars<'_>,
     _: &Context,
-    _: &mut RenderContext<'_>,
+    _: &mut RenderContext<'_, '_>,
     out: &mut dyn Output,
 ) -> Result<(), RenderError> {
     // get parameter from helper or throw an error
diff --git a/tools/fidl/fidldoc/src/templates/markdown/mod.rs b/tools/fidl/fidldoc/src/templates/markdown/mod.rs
index 37753d4..ae37611 100644
--- a/tools/fidl/fidldoc/src/templates/markdown/mod.rs
+++ b/tools/fidl/fidldoc/src/templates/markdown/mod.rs
@@ -13,13 +13,13 @@
 
 use crate::templates::{FidldocTemplate, HandlebarsHelper};
 
-pub struct MarkdownTemplate {
-    handlebars: Handlebars,
+pub struct MarkdownTemplate<'a> {
+    handlebars: Handlebars<'a>,
     output_path: PathBuf,
 }
 
-impl MarkdownTemplate {
-    pub fn new(output_path: &PathBuf) -> MarkdownTemplate {
+impl MarkdownTemplate<'_> {
+    pub fn new(output_path: &PathBuf) -> MarkdownTemplate<'_> {
         // Handlebars
         let mut handlebars = Handlebars::new();
 
@@ -110,7 +110,7 @@
     }
 }
 
-impl FidldocTemplate for MarkdownTemplate {
+impl FidldocTemplate for MarkdownTemplate<'_> {
     fn render_main_page(&self, main_fidl_json: &Value) -> Result<(), Error> {
         // Render main page
         let main_page_path = self.output_path.join("README.md");
@@ -165,7 +165,7 @@
 }
 
 fn render_template(
-    handlebars: &Handlebars,
+    handlebars: &Handlebars<'_>,
     template_name: String,
     fidl_json: &Value,
 ) -> Result<String, Error> {
@@ -206,7 +206,8 @@
             "url_path": "/",
         });
 
-        let template = MarkdownTemplate::new(&PathBuf::new());
+        let pb = PathBuf::new();
+        let template = MarkdownTemplate::new(&pb);
 
         let result = render_template(&template.handlebars, "main".to_string(), &main_fidl_doc)
             .expect("Unable to render main template");
@@ -240,7 +241,8 @@
             "url_path": "/",
         });
 
-        let template = MarkdownTemplate::new(&PathBuf::new());
+        let pb = PathBuf::new();
+        let template = MarkdownTemplate::new(&pb);
 
         let result = render_template(&template.handlebars, "toc".to_string(), &main_fidl_doc)
             .expect("Unable to render toc template");
diff --git a/tools/fidl/fidldoc/src/templates/markdown/partials/declarations/constants.hbs b/tools/fidl/fidldoc/src/templates/markdown/partials/declarations/constants.hbs
index bc69a27..7d5608a 100644
--- a/tools/fidl/fidldoc/src/templates/markdown/partials/declarations/constants.hbs
+++ b/tools/fidl/fidldoc/src/templates/markdown/partials/declarations/constants.hbs
@@ -5,7 +5,7 @@
     <tr><th>Name</th><th>Value</th><th>Type</th><th>Description</th></tr>
     {{~ #each const_declarations ~}}
         <tr id="{{rpn name}}">
-            <td><a href="{{sl @root location}}">{{rpn name}}</a></td>
+            <td><a href="{{sl @root.config @root.tag location}}">{{rpn name}}</a></td>
             {{#if (eq type.kind "primitive") ~}}
                 <td>
                     <code>
diff --git a/tools/fidl/fidldoc/src/templates/markdown/partials/declarations/type_aliases.hbs b/tools/fidl/fidldoc/src/templates/markdown/partials/declarations/type_aliases.hbs
index f291ded..7e0ee17 100644
--- a/tools/fidl/fidldoc/src/templates/markdown/partials/declarations/type_aliases.hbs
+++ b/tools/fidl/fidldoc/src/templates/markdown/partials/declarations/type_aliases.hbs
@@ -5,7 +5,7 @@
     <tr><th>Name</th><th>Value</th><th>Description</th></tr>
     {{~ #each type_alias_declarations ~}}
         <tr id="{{rpn name}}">
-            <td><a href="{{sl @root location}}">{{rpn name}}</a></td>
+            <td><a href="{{sl @root.config @root.tag location}}">{{rpn name}}</a></td>
             <td>
                 <code>{{~ partial_type_ctor.name ~}}</code>
                 {{~ #if partial_type_ctor.maybe_size.identifier ~}}
diff --git a/tools/fidl/fidldoc/src/templates/markdown/partials/types/filename.hbs b/tools/fidl/fidldoc/src/templates/markdown/partials/types/filename.hbs
index b1109c6..e2aab8c 100644
--- a/tools/fidl/fidldoc/src/templates/markdown/partials/types/filename.hbs
+++ b/tools/fidl/fidldoc/src/templates/markdown/partials/types/filename.hbs
@@ -1,5 +1,5 @@
 {{~ #if (eq location.filename "generated") ~}}
     *generated*
 {{~ else ~}}
-    *Defined in [{{@root.name}}{{@root.config.source.package}}{{rpn location.filename}}]({{sl @root location}})*
+    *Defined in [{{@root.name}}{{@root.config.source.package}}{{rpn location.filename}}]({{sl @root.config @root.tag location}})*
 {{~ /if}}
\ No newline at end of file
diff --git a/tools/fidl/fidldoc/src/templates/mod.rs b/tools/fidl/fidldoc/src/templates/mod.rs
index 93ea583..150dfc4 100644
--- a/tools/fidl/fidldoc/src/templates/mod.rs
+++ b/tools/fidl/fidldoc/src/templates/mod.rs
@@ -21,17 +21,17 @@
 
 pub type HandlebarsHelper = fn(
     h: &Helper<'_, '_>,
-    _: &Handlebars,
+    _: &Handlebars<'_>,
     _: &Context,
-    _: &mut RenderContext<'_>,
+    _: &mut RenderContext<'_, '_>,
     out: &mut dyn Output,
 ) -> Result<(), RenderError>;
 
 pub fn get_link_helper(
     h: &Helper<'_, '_>,
-    _: &Handlebars,
+    _: &Handlebars<'_>,
     _: &Context,
-    _: &mut RenderContext<'_>,
+    _: &mut RenderContext<'_, '_>,
     out: &mut dyn Output,
 ) -> Result<(), RenderError> {
     // get parameter from helper or throw an error
@@ -48,9 +48,9 @@
 
 pub fn remove_package_name(
     h: &Helper<'_, '_>,
-    _: &Handlebars,
+    _: &Handlebars<'_>,
     _: &Context,
-    _: &mut RenderContext<'_>,
+    _: &mut RenderContext<'_, '_>,
     out: &mut dyn Output,
 ) -> Result<(), RenderError> {
     // get parameter from helper or throw an error
@@ -69,9 +69,9 @@
 
 pub fn eq(
     h: &Helper<'_, '_>,
-    _: &Handlebars,
+    _: &Handlebars<'_>,
     _: &Context,
-    _: &mut RenderContext<'_>,
+    _: &mut RenderContext<'_, '_>,
     out: &mut dyn Output,
 ) -> Result<(), RenderError> {
     // get parameter from helper or throw an error
@@ -94,9 +94,9 @@
 
 fn package_link(
     h: &Helper<'_, '_>,
-    _: &Handlebars,
+    _: &Handlebars<'_>,
     _: &Context,
-    _: &mut RenderContext<'_>,
+    _: &mut RenderContext<'_, '_>,
     out: &mut dyn Output,
 ) -> Result<(), RenderError> {
     // get parameter from helper or throw an error
@@ -136,9 +136,9 @@
 
 fn doc_link(
     h: &Helper<'_, '_>,
-    _: &Handlebars,
+    _: &Handlebars<'_>,
     _: &Context,
-    _: &mut RenderContext<'_>,
+    _: &mut RenderContext<'_, '_>,
     out: &mut dyn Output,
 ) -> Result<(), RenderError> {
     // get parameter from helper or throw an error
@@ -166,9 +166,9 @@
 
 pub fn remove_parent_folders(
     h: &Helper<'_, '_>,
-    _: &Handlebars,
+    _: &Handlebars<'_>,
     _: &Context,
-    _: &mut RenderContext<'_>,
+    _: &mut RenderContext<'_, '_>,
     out: &mut dyn Output,
 ) -> Result<(), RenderError> {
     // get parameter from helper or throw an error
@@ -187,43 +187,44 @@
 
 fn source_link(
     h: &Helper<'_, '_>,
-    _: &Handlebars,
+    _: &Handlebars<'_>,
     _: &Context,
-    _: &mut RenderContext<'_>,
+    _: &mut RenderContext<'_, '_>,
     out: &mut dyn Output,
 ) -> Result<(), RenderError> {
-    let fidl_json =
-        h.param(0).ok_or_else(|| RenderError::new("Param 0 is required for sl helper"))?;
+    let config = h.param(0).ok_or_else(|| RenderError::new("Param 0 is required for sl helper"))?;
+    let tag = h.param(1).ok_or_else(|| RenderError::new("Param 1 is required for sl helper"))?;
     let location =
-        h.param(1).ok_or_else(|| RenderError::new("Param 1 is required for sl helper"))?;
+        h.param(2).ok_or_else(|| RenderError::new("Param 2 is required for sl helper"))?;
     debug!(
-        "source_link called on {} and {}",
-        fidl_json.value().to_string(),
+        "source_link called on {}, {} and {}",
+        config.value().to_string(),
+        tag.value().to_string(),
         location.value().to_string()
     );
-    out.write(&sl(&fidl_json.value(), &location.value()))?;
+    out.write(&sl(&config.value(), &tag.value(), &location.value()))?;
     Ok(())
 }
 
-fn sl(fidl_json: &Value, location: &Value) -> String {
+fn sl(config: &Value, tag: &Value, location: &Value) -> String {
     if location.get("line").is_some() {
         // Output source link with line number
         format!(
             "{baseUrl}{tag}{filenamePrefix}{filename}{linePrefix}{lineNo}",
-            baseUrl = fidl_json["config"]["source"]["baseUrl"].as_str().unwrap(),
-            tag = fidl_json["tag"].as_str().unwrap(),
-            filenamePrefix = fidl_json["config"]["source"]["filenamePrefix"].as_str().unwrap(),
+            baseUrl = config["source"]["baseUrl"].as_str().unwrap(),
+            tag = tag.as_str().unwrap(),
+            filenamePrefix = config["source"]["filenamePrefix"].as_str().unwrap(),
             filename = rpf(location["filename"].as_str().unwrap()),
-            linePrefix = fidl_json["config"]["source"]["line"].as_str().unwrap(),
+            linePrefix = config["source"]["line"].as_str().unwrap(),
             lineNo = location["line"]
         )
     } else {
         // Output general source link, without line number
         format!(
             "{baseUrl}{tag}{filenamePrefix}{filename}",
-            baseUrl = fidl_json["config"]["source"]["baseUrl"].as_str().unwrap(),
-            tag = fidl_json["tag"].as_str().unwrap(),
-            filenamePrefix = fidl_json["config"]["source"]["filenamePrefix"].as_str().unwrap(),
+            baseUrl = config["source"]["baseUrl"].as_str().unwrap(),
+            tag = tag.as_str().unwrap(),
+            filenamePrefix = config["source"]["filenamePrefix"].as_str().unwrap(),
             filename = rpf(location["filename"].as_str().unwrap())
         )
     }
@@ -231,9 +232,9 @@
 
 pub fn one_line(
     h: &Helper<'_, '_>,
-    _: &Handlebars,
+    _: &Handlebars<'_>,
     _: &Context,
-    _: &mut RenderContext<'_>,
+    _: &mut RenderContext<'_, '_>,
     out: &mut dyn Output,
 ) -> Result<(), RenderError> {
     // get parameter from helper or throw an error
@@ -252,9 +253,9 @@
 
 pub fn pulldown(
     h: &Helper<'_, '_>,
-    _: &Handlebars,
+    _: &Handlebars<'_>,
     _: &Context,
-    _: &mut RenderContext<'_>,
+    _: &mut RenderContext<'_, '_>,
     out: &mut dyn Output,
 ) -> Result<(), RenderError> {
     // get parameter from helper or throw an error
@@ -274,9 +275,9 @@
 
 pub fn method_id(
     h: &Helper<'_, '_>,
-    _: &Handlebars,
+    _: &Handlebars<'_>,
     _: &Context,
-    _: &mut RenderContext<'_>,
+    _: &mut RenderContext<'_, '_>,
     out: &mut dyn Output,
 ) -> Result<(), RenderError> {
     let method_name =
@@ -374,20 +375,26 @@
             "line": 42
         });
 
-        assert_eq!(sl(&fidl_json, &location_line), "https://example.com/HEAD:sample.fidl#42");
+        assert_eq!(
+            sl(&fidl_json["config"], &fidl_json["tag"], &location_line),
+            "https://example.com/HEAD:sample.fidl#42"
+        );
 
         let location_no_line = json!({
             "filename": "foobar.fidl"
         });
 
-        assert_eq!(sl(&fidl_json, &location_no_line), "https://example.com/HEAD:foobar.fidl");
+        assert_eq!(
+            sl(&fidl_json["config"], &fidl_json["tag"], &location_no_line),
+            "https://example.com/HEAD:foobar.fidl"
+        );
 
         let location_with_folders = json!({
             "filename": "../../sdk/fidl/fuchsia.bluetooth/address.fidl"
         });
 
         assert_eq!(
-            sl(&fidl_json, &location_with_folders),
+            sl(&fidl_json["config"], &fidl_json["tag"], &location_with_folders),
             "https://example.com/HEAD:sdk/fidl/fuchsia.bluetooth/address.fidl"
         );
 
@@ -397,7 +404,7 @@
         });
 
         assert_eq!(
-            sl(&fidl_json, &location_with_folders_and_line),
+            sl(&fidl_json["config"], &fidl_json["tag"], &location_with_folders_and_line),
             "https://example.com/HEAD:sdk/fidl/fuchsia.bluetooth/address.fidl#9"
         );
     }