Merge inbound to mozilla-central a=merge
authorarthur.iakab <aiakab@mozilla.com>
Tue, 25 Dec 2018 11:51:08 +0200
changeset 509011 47d3977ee67ef6e2dbdcc5ce83a159c1c8e886f5
parent 508999 f90034ef430e89e9413cfb59791d55175136d40c (diff)
parent 509010 0621040311260830908b35fbeebd42041911c531 (current diff)
child 509013 9f75719c6dcd06f391b61bdad888015512627bef
child 509015 8d911883cf66e594edc50f7f7e32c933d16df2d1
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone66.0a1
first release with
nightly linux32
47d3977ee67e / 66.0a1 / 20181225095124 / files
nightly linux64
47d3977ee67e / 66.0a1 / 20181225095124 / files
nightly mac
47d3977ee67e / 66.0a1 / 20181225095124 / files
nightly win32
47d3977ee67e / 66.0a1 / 20181225095124 / files
nightly win64
47d3977ee67e / 66.0a1 / 20181225095124 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central a=merge
dom/smil/nsSMILFloatType.cpp
dom/smil/nsSMILFloatType.h
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -278,31 +278,55 @@ name = "block-buffer"
 version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "arrayref 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "block-buffer"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "block-padding 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "block-padding"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "boxfnonce"
 version = "0.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "build_const"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "byte-tools"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "byte-tools"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "byteorder"
 version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "bytes"
 version = "0.4.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -724,16 +748,24 @@ source = "registry+https://github.com/ru
 name = "digest"
 version = "0.7.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "digest"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "dirs"
 version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_users 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
 ]
@@ -1008,16 +1040,24 @@ dependencies = [
 name = "generic-array"
 version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "generic-array"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "gkrust"
 version = "0.1.0"
 dependencies = [
  "gkrust-shared 0.1.0",
  "mozilla-central-workspace-hack 0.1.0",
  "stylo_tests 0.0.1",
 ]
 
@@ -1761,16 +1801,21 @@ version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "goblin 0.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "scroll 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "opaque-debug"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "ordered-float"
 version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2262,16 +2307,27 @@ source = "registry+https://github.com/ru
 dependencies = [
  "block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "sha2"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "opaque-debug 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "simd"
 version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "siphasher"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2939,17 +2995,17 @@ dependencies = [
  "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "plane-split 0.13.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
- "sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "webrender_api 0.57.2",
 ]
 
 [[package]]
 name = "webrender_api"
@@ -3125,19 +3181,22 @@ dependencies = [
 "checksum bindgen 0.43.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41df015ccbc22b038641bd84d0aeeff01e0a4c0714ed35ed0e9a3dd8ad8d732"
 "checksum binjs_meta 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "430239e4551e42b80fa5d92322ac80ea38c9dda56e5d5582e057e2288352b71a"
 "checksum bit-set 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6f1efcc46c18245a69c38fcc5cc650f16d3a59d034f3106e9ed63748f695730a"
 "checksum bit-vec 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4440d5cb623bb7390ae27fec0bb6c61111969860f8e3ae198bfa0663645e67cf"
 "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
 "checksum bitreader 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "80b13e2ab064ff3aa0bdbf1eff533f9822dc37899821f5f98c67f263eab51707"
 "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400"
 "checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab"
+"checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d"
+"checksum block-padding 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc4358306e344bf9775d0197fd00d2603e5afb0771bb353538630f022068ea3"
 "checksum boxfnonce 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8380105befe91099e6f69206164072c05bc92427ff6aa8a5171388317346dd75"
 "checksum build_const 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e90dc84f5e62d2ebe7676b83c22d33b6db8bd27340fb6ffbff0a364efa0cb9c9"
 "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40"
+"checksum byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "980479e6fde23246dfb54d47580d66b4e99202e7579c5eaa9fe10ecb5ebd2182"
 "checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
 "checksum bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e178b8e0e239e844b083d5a0d4a156b2654e67f9f80144d48398fcd736a24fb8"
 "checksum bzip2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3eafc42c44e0d827de6b1c131175098fe7fb53b8ce8a47e65cb3ea94688be24"
 "checksum bzip2-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2c5162604199bbb17690ede847eaa6120a3f33d5ab4dcc8e7c25b16d849ae79b"
 "checksum cc 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)" = "c37f0efaa4b9b001fa6f02d4b644dee4af97d3414df07c51e3e4f015f3a3e131"
 "checksum cexpr 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8fc0086be9ca82f7fc89fc873435531cb898b86e850005850de1f820e2db6e9b"
 "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
 "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878"
@@ -3174,16 +3233,17 @@ dependencies = [
 "checksum cubeb-core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37f7b20f757a4e4b6aa28863236551bff77682dc6db192eba15af615492b5445"
 "checksum cubeb-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "653b9e245d35dbe2a2da7c4586275cee75ff656ddeb02d4a73b4afdfa6d67502"
 "checksum darling 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f593353cad5af2df6d54810de2b61aa8acba5b5fbc70b0d75e7cc5bdd80aca73"
 "checksum darling_core 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "168c246e87e727d58575d9b4595491010627f0cdc910e3e6ea3b36db2b9a9d9a"
 "checksum darling_macro 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "99c4eff4bcbeaf6a22578012ff79c95910338668278d1901e528bd34a22f575d"
 "checksum devd-rs 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7c9ac481c38baf400d3b732e4a06850dfaa491d1b6379a249d9d40d14c2434c"
 "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
 "checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90"
+"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c"
 "checksum dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "88972de891f6118092b643d85a0b28e0678e0f948d7f879aa32f2d5aafe97d2a"
 "checksum docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d8acd393692c503b168471874953a2531df0e9ab77d0b6bbc582395743300a4a"
 "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
 "checksum dtoa-short 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "068d4026697c1a18f0b0bb8cfcad1b0c151b90d8edb9bf4c235ad68128920d1d"
 "checksum dwrote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f0beca78470f26189a662e72afe7a54c625b4feb06b2d36c207ac15319bd57c5"
 "checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a"
 "checksum ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "88dc8393b3c7352f94092497f6b52019643e493b6b890eb417cdb7c46117e621"
 "checksum encoding_c 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "769ecb8b33323998e482b218c0d13cd64c267609023b4b7ec3ee740714c318ee"
@@ -3201,16 +3261,17 @@ dependencies = [
 "checksum freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b659e75b7a7338fe75afd7f909fc2b71937845cffb6ebe54ba2e50f13d8e903d"
 "checksum fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
 "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
 "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
 "checksum futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)" = "884dbe32a6ae4cd7da5c6db9b78114449df9953b8d490c9d7e1b51720b922c62"
 "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4"
 "checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
 "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb"
+"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592"
 "checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d"
 "checksum gl_generator 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0ffaf173cf76c73a73e080366bf556b4776ece104b06961766ff11449f38604"
 "checksum gleam 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4b47f5b15742aee359c7895ab98cf2cceecc89bb4feb6f4e42f802d7899877da"
 "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
 "checksum goblin 0.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "5911d7df7b8f65ab676c5327b50acea29d3c6a1a4ad05e444cf5dce321b26db2"
 "checksum h2 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "a27e7ed946e8335bdf9a191bc1b9b14a03ba822d013d2f58437f4fabcbd7fc2c"
 "checksum http 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "dca621d0fa606a5ff2850b6e337b57ad6137ee4d67e940449643ff45af6874c6"
 "checksum httparse 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "af2f2dd97457e8fb1ae7c5a420db346af389926e36f43768b96f101546b04a07"
@@ -3260,16 +3321,17 @@ dependencies = [
 "checksum nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b"
 "checksum nom 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9c349f68f25f596b9f44cf0e7c69752a5c633b0550c3ff849518bfba0233774a"
 "checksum num-derive 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d2c31b75c36a993d30c7a13d70513cb93f02acafdd5b7ba250f9b0e18615de7"
 "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"
 "checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
 "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
 "checksum num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "514f0d73e64be53ff320680ca671b64fe3fb91da01e1ae2ddc99eb51d453b20d"
 "checksum object 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6cca6ad89d0801138cb4ef606908ae12d83edc4c790ef5178fc7b4c72d959e90"
+"checksum opaque-debug 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "51ecbcb821e1bd256d456fe858aaa7f380b63863eab2eb86eee1bd9f33dd6682"
 "checksum ordered-float 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2f0015e9e8e28ee20c581cfbfe47c650cedeb9ed0721090e0b7ebb10b9cdbcc2"
 "checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063"
 "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
 "checksum parking_lot 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "69376b761943787ebd5cc85a5bc95958651a22609c5c1c2b65de21786baec72b"
 "checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa"
 "checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
 "checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356"
 "checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f"
@@ -3315,16 +3377,17 @@ dependencies = [
 "checksum scroll_derive 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1aa96c45e7f5a91cb7fabe7b279f02fea7126239fc40b732316e8b6a2d0fcb"
 "checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537"
 "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
 "checksum serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "15c141fc7027dd265a47c090bf864cf62b42c4d228bbcf4e51a0c9e2b0d3f7ef"
 "checksum serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "adb6e51a6b3696b301bc221d785f898b4457c619b51d7ce195a6d20baecb37b3"
 "checksum serde_derive 1.0.80 (git+https://github.com/servo/serde?branch=deserialize_from_enums9)" = "<none>"
 "checksum serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "44dd2cfde475037451fa99b7e5df77aa3cfd1536575fa8e7a538ab36dcde49ae"
 "checksum sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0"
+"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d"
 "checksum simd 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0048b17eb9577ac545c61d85c3559b41dfb4cbea41c9bd9ca6a4f73ff05fda84"
 "checksum siphasher 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ffc669b726f2bc9a3bcff66e5e23b56ba6bf70e22a34c3d7b6d0b3450b65b84"
 "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23"
 "checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d"
 "checksum smallbitvec 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1764fe2b30ee783bfe3b9b37b2649d8d590b3148bb12e0079715d4d5c673562e"
 "checksum smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "622df2d454c29a4d89b30dc3b27b42d7d90d6b9e587dbf8f67652eb7514da484"
 "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
 "checksum string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00caf261d6f90f588f8450b8e1230fa0d5be49ee6140fdfbcb55335aff350970"
--- a/build/moz.configure/toolchain.configure
+++ b/build/moz.configure/toolchain.configure
@@ -752,66 +752,44 @@ def vc_compiler_path(host, target, vs_ma
         # Choose the newest version.
         data = all_versions[-1][1]
     paths = data.get(vc_target)
     if not paths:
         return
     return paths
 
 
-@dependable
-@imports(_from='os', _import='environ')
-def original_path():
-    return environ['PATH']
-
-
-@depends(vc_compiler_path, original_path)
+@depends(vc_compiler_path)
 @imports('os')
 @imports(_from='os', _import='environ')
-def toolchain_search_path(vc_compiler_path, original_path):
-    result = [original_path]
+def toolchain_search_path(vc_compiler_path):
+    result = [environ.get('PATH')]
 
     if vc_compiler_path:
-        # The second item, if there is one, is necessary to have in $PATH for
-        # Windows to load the required DLLs from there.
-        if len(vc_compiler_path) > 1:
-            environ['PATH'] = os.pathsep.join(result + vc_compiler_path[1:])
-
-        # The first item is where the programs are going to be
-        result.append(vc_compiler_path[0])
+        result.extend(vc_compiler_path)
 
     # Also add in the location to which `mach bootstrap` or
     # `mach artifact toolchain` installs clang.
     mozbuild_state_dir = environ.get('MOZBUILD_STATE_PATH',
                                      os.path.expanduser(os.path.join('~', '.mozbuild')))
     bootstrap_clang_path = os.path.join(mozbuild_state_dir, 'clang', 'bin')
     result.append(bootstrap_clang_path)
 
     bootstrap_cbindgen_path = os.path.join(mozbuild_state_dir, 'cbindgen')
     result.append(bootstrap_cbindgen_path)
 
+    if vc_compiler_path:
+        # We're going to alter PATH for good in windows.configure, but we also
+        # need to do it for the valid_compiler() check below. This is only needed
+        # on Windows, where MSVC needs PATH set to find dlls.
+        environ['PATH'] = os.pathsep.join(result)
+
     return result
 
 
-# If we modified the PATH environment variable for Windows DLLs, set the PATH
-# variable for the build.
-@depends(toolchain_search_path, original_path)
-@imports(_from='os', _import='environ')
-def altered_path(toolchain_search_path, original_path):
-    # Touch the dependency for the linter. We don't actually need the value,
-    # only its side effects.
-    toolchain_search_path
-
-    if environ['PATH'] != original_path:
-        return environ['PATH']
-
-
-set_config('PATH', altered_path)
-
-
 @template
 def default_c_compilers(host_or_target, other_c_compiler=None):
     '''Template defining the set of default C compilers for the host and
     target platforms.
     `host_or_target` is either `host` or `target` (the @depends functions
     from init.configure.
     `other_c_compiler` is the `target` C compiler when `host_or_target` is `host`.
     '''
@@ -1016,16 +994,36 @@ def compiler(language, host_or_target, c
             wrapper.extend(provided_wrapper)
             flags = provided_compiler.flags
         else:
             flags = []
 
         if not flags and macos_sdk and host_or_target.os == 'OSX':
             flags = ['-isysroot', macos_sdk]
 
+        # Ideally, we'd always use the absolute path, but unfortunately, on
+        # Windows, the compiler is very often in a directory containing spaces.
+        # Unfortunately, due to the way autoconf does its compiler tests with
+        # eval, that doesn't work out. So in that case, check that the
+        # compiler can still be found in $PATH, and use the file name instead
+        # of the full path.
+        if quote(compiler) != compiler:
+            full_path = os.path.abspath(compiler)
+            compiler = os.path.basename(compiler)
+            found_compiler = find_program(compiler)
+            if not found_compiler:
+                die('%s is not in your $PATH'
+                    % quote(os.path.dirname(full_path)))
+            if os.path.normcase(find_program(compiler)) != os.path.normcase(
+                    full_path):
+                die('Found `%s` before `%s` in your $PATH. '
+                    'Please reorder your $PATH.',
+                    quote(os.path.dirname(found_compiler)),
+                    quote(os.path.dirname(full_path)))
+
         info = check_compiler(wrapper + [compiler] + flags, language,
                               host_or_target)
 
         # Check that the additional flags we got are enough to not require any
         # more flags. If we get an exception, just ignore it; it's liable to be
         # invalid command-line flags, which means the compiler we're checking
         # doesn't support those command-line flags and will fail one or more of
         # the checks below.
@@ -1462,18 +1460,17 @@ def pgo_flags(compiler, build_env, targe
 
 
 set_config('PROFILE_GEN_CFLAGS', pgo_flags.gen_cflags)
 set_config('PROFILE_GEN_LDFLAGS', pgo_flags.gen_ldflags)
 set_config('PROFILE_USE_CFLAGS', pgo_flags.use_cflags)
 set_config('PROFILE_USE_LDFLAGS', pgo_flags.use_ldflags)
 
 llvm_profdata = check_prog('LLVM_PROFDATA', ['llvm-profdata'],
-                           allow_missing=True,
-                           paths=toolchain_search_path)
+                           allow_missing=True)
 
 add_old_configure_assignment('LLVM_PROFDATA', llvm_profdata)
 
 
 @depends(c_compiler)
 def preprocess_option(compiler):
     # The uses of PREPROCESS_OPTION depend on the spacing for -o/-Fi.
     if compiler.type in ('gcc', 'clang'):
@@ -1955,18 +1952,17 @@ def as_info(target, c_compiler):
 # One would expect the assembler to be specified merely as a program.  But in
 # cases where the assembler is passed down into js/, it can be specified in
 # the same way as CC: a program + a list of argument flags.  We might as well
 # permit the same behavior in general, even though it seems somewhat unusual.
 # So we have to do the same sort of dance as we did above with
 # `provided_compiler`.
 provided_assembler = provided_program('AS')
 assembler = check_prog('_AS', input=provided_assembler.program,
-                       what='the assembler', progs=as_info.names,
-                       paths=toolchain_search_path)
+                       what='the assembler', progs=as_info.names)
 
 @depends(as_info, assembler, provided_assembler, c_compiler)
 def as_with_flags(as_info, assembler, provided_assembler, c_compiler):
     if provided_assembler:
         return provided_assembler.wrapper + \
             [provided_assembler.program] + \
             provided_assembler.flags
 
--- a/build/moz.configure/windows.configure
+++ b/build/moz.configure/windows.configure
@@ -251,33 +251,37 @@ def valid_ucrt_sdk_dir(windows_sdk_dir, 
     return namespace(
         path=sdk.path,
         include=sdk.include,
         lib=sdk.lib,
         version=version,
     )
 
 
-@depends(c_compiler, toolchain_search_path)
+@depends(c_compiler)
 @imports('os')
-def vc_path(c_compiler, toolchain_search_path):
+def vc_path(c_compiler):
     vc_path_env = os.environ.get('VC_PATH')
     if vc_path_env:
         return os.path.normpath(vc_path_env)
 
     if c_compiler.type not in ('msvc', 'clang-cl'):
         return
 
+    # Normally, we'd start from c_compiler.compiler, but for now, it's not the
+    # ideal full path to the compiler. At least, we're guaranteed find_program
+    # will get us the one we found in toolchain.configure.
     vc_program = c_compiler.compiler
 
     # In clang-cl builds, we use the headers and libraries from an MSVC installation.
     if c_compiler.type == 'clang-cl':
-        vc_program = find_program('cl.exe', paths=toolchain_search_path)
+        vc_program = 'cl.exe'
 
-    result = os.path.dirname(vc_program)
+    cl = find_program(vc_program)
+    result = os.path.dirname(cl)
     while True:
         next, p = os.path.split(result)
         if next == result:
             die('Cannot determine the Visual C++ directory the compiler (%s) '
                 'is in' % cl)
         result = next
         if p.lower() == 'bin':
             break
@@ -459,16 +463,30 @@ link = check_prog('LINKER', ('lld-link.e
                   paths=toolchain_search_path)
 
 host_link = check_prog('HOST_LINKER', ('lld-link.exe', 'link.exe'),
                        paths=toolchain_search_path)
 
 add_old_configure_assignment('LINKER', link)
 
 
+# Normally, we'd just have CC, etc. set to absolute paths, but the build system
+# doesn't currently handle properly the case where the paths contain spaces.
+# Additionally, there's the issue described in toolchain.configure, in
+# valid_compiler().
+@depends(sdk_bin_path)
+@imports('os')
+def alter_path(sdk_bin_path):
+    path = os.pathsep.join(sdk_bin_path)
+    os.environ['PATH'] = path
+    return path
+
+
+set_config('PATH', alter_path)
+
 check_prog('MAKECAB', ('makecab.exe',))
 
 
 @depends(c_compiler, using_sccache)
 def need_showincludes_prefix(info, using_sccache):
     # sccache does its own -showIncludes prefix checking.
     # clang-cl uses a gcc-style dependency scheme, see toolchain.configure.
     if info.type == 'msvc' and not using_sccache:
--- a/build/win64-aarch64/mozconfig.vs2017
+++ b/build/win64-aarch64/mozconfig.vs2017
@@ -40,15 +40,8 @@ if [ -d "${VSPATH}" ]; then
     libs="${libs} -LIBPATH:${VSWINPATH}/SDK/Lib/${win_sdk_version}/ucrt/x64"
     export HOST_LDFLAGS="${libs}"
 
     export WIN64_LINK="${VSPATH}/VC/bin/Hostx64/x64/link.exe"
     export WIN64_LIB="${VSPATH}/VC/lib/x64:${VSPATH}/VC/atlmfc/lib/x64:${VSPATH}/SDK/Lib/${win_sdk_version}/ucrt/x64:${VSPATH}/SDK/Lib/${win_sdk_version}/um/x64:${VSPATH}/DIA SDK/lib/amd64"
 fi
 
 . $topsrcdir/build/mozconfig.vs-common
-
-mk_export_correct_style WINDOWSSDKDIR
-mk_export_correct_style WIN32_REDIST_DIR
-mk_export_correct_style WIN_DIA_SDK_BIN_DIR
-mk_export_correct_style PATH
-mk_export_correct_style INCLUDE
-mk_export_correct_style LIB
--- a/gfx/webrender_bindings/revision.txt
+++ b/gfx/webrender_bindings/revision.txt
@@ -1,1 +1,1 @@
-8b90bdd513419a06f2755b08713238e6ee52b1e9
+5da3e6bf916e84fc3ce72c6cf65c63df0cdd8eb5
--- a/gfx/wr/Cargo.lock
+++ b/gfx/wr/Cargo.lock
@@ -29,21 +29,16 @@ name = "app_units"
 version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
-name = "arrayref"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
 name = "arrayvec"
 version = "0.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -90,26 +85,36 @@ source = "registry+https://github.com/ru
 
 [[package]]
 name = "block"
 version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "block-buffer"
-version = "0.3.3"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "block-padding 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "block-padding"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "byte-tools"
-version = "0.2.0"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "byteorder"
 version = "1.2.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -318,20 +323,20 @@ version = "0.7.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "digest"
-version = "0.7.6"
+version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "direct-composition"
 version = "0.1.0"
 dependencies = [
  "euclid 0.19.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -480,17 +485,17 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "generic-array"
-version = "0.9.0"
+version = "0.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "gif"
 version = "0.10.0"
@@ -899,16 +904,21 @@ dependencies = [
 name = "objc"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "opaque-debug"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "osmesa-src"
 version = "0.1.1"
 source = "git+https://github.com/servo/osmesa-src#939207de2f4617cb958548490764f7380cf0c6e4"
 
 [[package]]
 name = "osmesa-sys"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1237,23 +1247,23 @@ dependencies = [
 
 [[package]]
 name = "sha1"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "sha2"
-version = "0.7.1"
+version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "opaque-debug 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "shared_library"
 version = "0.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1551,17 +1561,17 @@ dependencies = [
  "pathfinder_path_utils 0.2.0 (git+https://github.com/pcwalton/pathfinder?branch=webrender)",
  "plane-split 0.13.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "png 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "thread_profiler 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "webrender_api 0.57.2",
  "ws 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1751,27 +1761,27 @@ dependencies = [
 ]
 
 [metadata]
 "checksum adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6cbd0b9af8587c72beadc9f72d35b9fbb070982c9e6203e46e93f10df25f8f45"
 "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"
 "checksum android_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407"
 "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
 "checksum app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9dadc668390b373e73e4abbfc1f07238b09a25858f2f39c06cebc6d8e141d774"
-"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
 "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
 "checksum atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2fc4a1aa4c24c0718a250f0681885c1af91419d242f29eb8f2ab28502d80dbd1"
 "checksum base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "621fc7ecb8008f86d7fb9b95356cd692ce9514b80a86d85b397f32a22da7b9e2"
 "checksum binary-space-partition 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88ceb0d16c4fd0e42876e298d7d3ce3780dd9ebdcbe4199816a32c77e08597ff"
 "checksum bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bda13183df33055cbb84b847becce220d392df502ebe7a4a78d7021771ed94d0"
 "checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f"
 "checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789"
 "checksum block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
-"checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab"
-"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40"
+"checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d"
+"checksum block-padding 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc4358306e344bf9775d0197fd00d2603e5afb0771bb353538630f022068ea3"
+"checksum byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "980479e6fde23246dfb54d47580d66b4e99202e7579c5eaa9fe10ecb5ebd2182"
 "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"
 "checksum bytes 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "2f1d50c876fb7545f5f289cd8b2aee3f359d073ae819eed5d6373638e2c61e59"
 "checksum cc 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "0ebb87d1116151416c0cf66a0e3fb6430cccd120fd6300794b4dfaa050ac40ba"
 "checksum cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "405216fd8fe65f718daa7102ea808a946b6ce40c742998fbfd3463645552de18"
 "checksum cgl 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "55e7ec0b74fe5897894cbc207092c577e87c52f8a59e8ca8d97ef37551f60a49"
 "checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536"
 "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
 "checksum cmake 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "95470235c31c726d72bf2e1f421adc1e65b9d561bf5529612cbe1a72da1467b3"
@@ -1786,17 +1796,17 @@ dependencies = [
 "checksum crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bd66663db5a988098a89599d4857919b3acf7f61402e61365acfd3919857b9be"
 "checksum crossbeam-channel 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6c0a94250b0278d7fc5a894c3d276b11ea164edc8bf8feb10ca1ea517b44a649"
 "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
 "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
 "checksum crossbeam-epoch 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30fecfcac6abfef8771151f8be4abc9e4edc112c2bcb233314cafde2680536e9"
 "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
 "checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015"
 "checksum deflate 0.7.18 (registry+https://github.com/rust-lang/crates.io-index)" = "32c8120d981901a9970a3a1c97cf8b630e0fa8c3ca31e75b6fd6fd5f9f427b31"
-"checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90"
+"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c"
 "checksum dlib 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "77e51249a9d823a4cb79e3eca6dcd756153e8ed0157b6c04775d04bf1b13b76a"
 "checksum downcast-rs 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "18df8ce4470c189d18aa926022da57544f31e154631eb4cfe796aea97051fe6c"
 "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
 "checksum dwrote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f0beca78470f26189a662e72afe7a54c625b4feb06b2d36c207ac15319bd57c5"
 "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
 "checksum env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0e6e40ebb0e66918a37b38c7acab4e10d299e0463fe2af5d29b9cc86710cfd2a"
 "checksum euclid 0.19.4 (registry+https://github.com/rust-lang/crates.io-index)" = "dbbf962bb6f877239a34491f2e0a12c6b824f389bc789eb90f1d70d4780b0727"
 "checksum expat-sys 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c470ccb972f2088549b023db8029ed9da9426f5affbf9b62efff7009ab8ed5b1"
@@ -1805,17 +1815,17 @@ dependencies = [
 "checksum font-loader 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd330f40acb3016432cbfa4c54b3d6e6e893a538df79d8df8fd8c26e21c36aaa"
 "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
 "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
 "checksum freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b659e75b7a7338fe75afd7f909fc2b71937845cffb6ebe54ba2e50f13d8e903d"
 "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
 "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
 "checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
 "checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518"
-"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d"
+"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592"
 "checksum gif 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff3414b424657317e708489d2857d9575f4403698428b040b609b9d1c1a84a2c"
 "checksum gl_generator 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0ffaf173cf76c73a73e080366bf556b4776ece104b06961766ff11449f38604"
 "checksum gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a795170cbd85b5a7baa58d6d7525cae6a03e486859860c220f7ebbbdd379d0a"
 "checksum gleam 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4b47f5b15742aee359c7895ab98cf2cceecc89bb4feb6f4e42f802d7899877da"
 "checksum glutin 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a70c5fe78efbd5a3b243a804ea1032053c584510f8822819f94cfb29b2100317"
 "checksum half 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d5c5f71a723d10dfc58927cbed37c3071a50afc7f073d86fd7d3e5727db890f"
 "checksum httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2f407128745b78abc95c0ffbe4e5d37427fdc0d45470710cfef8c44522a2e37"
 "checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e"
@@ -1854,16 +1864,17 @@ dependencies = [
 "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
 "checksum num-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8af1847c907c2f04d7bfd572fb25bbb4385c637fe5be163cf2f8c5d778fe1e7d"
 "checksum num-integer 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac0ea58d64a89d9d6b7688031b3be9358d6c919badcf7fbb0527ccfd891ee45"
 "checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124"
 "checksum num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e96f040177bb3da242b5b1ecf3f54b5d5af3efbbfb18608977a5d2767b22f10"
 "checksum num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775393e285254d2f5004596d69bb8bc1149754570dcc08cf30cabeba67955e28"
 "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30"
 "checksum objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "877f30f37acef6749b1841cceab289707f211aecfc756553cd63976190e6cc2e"
+"checksum opaque-debug 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "51ecbcb821e1bd256d456fe858aaa7f380b63863eab2eb86eee1bd9f33dd6682"
 "checksum osmesa-src 0.1.1 (git+https://github.com/servo/osmesa-src)" = "<none>"
 "checksum osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88cfece6e95d2e717e0872a7f53a8684712ad13822a7979bc760b9c77ec0013b"
 "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
 "checksum parking_lot 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "69376b761943787ebd5cc85a5bc95958651a22609c5c1c2b65de21786baec72b"
 "checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa"
 "checksum pathfinder_font_renderer 0.5.0 (git+https://github.com/pcwalton/pathfinder?branch=webrender)" = "<none>"
 "checksum pathfinder_gfx_utils 0.2.0 (git+https://github.com/pcwalton/pathfinder?branch=webrender)" = "<none>"
 "checksum pathfinder_partitioner 0.2.0 (git+https://github.com/pcwalton/pathfinder?branch=webrender)" = "<none>"
@@ -1892,17 +1903,17 @@ dependencies = [
 "checksum serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "15c141fc7027dd265a47c090bf864cf62b42c4d228bbcf4e51a0c9e2b0d3f7ef"
 "checksum serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "adb6e51a6b3696b301bc221d785f898b4457c619b51d7ce195a6d20baecb37b3"
 "checksum serde_derive 1.0.80 (git+https://github.com/servo/serde?branch=deserialize_from_enums9)" = "<none>"
 "checksum serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "f3ad6d546e765177cf3dded3c2e424a8040f870083a0e64064746b958ece9cb1"
 "checksum servo-fontconfig 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a088f8d775a5c5314aae09bd77340bc9c67d72b9a45258be34c83548b4814cd9"
 "checksum servo-fontconfig-sys 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "38b494f03009ee81914b0e7d387ad7c145cafcd69747c2ec89b0e17bb94f303a"
 "checksum servo-freetype-sys 4.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4ccb6d0d32d277d3ef7dea86203d8210945eb7a45fba89dd445b3595dd0dfc"
 "checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c"
-"checksum sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0"
+"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d"
 "checksum shared_library 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8254bf098ce4d8d7cc7cc6de438c5488adc5297e5b7ffef88816c0a91bd289c1"
 "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23"
 "checksum smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "26df3bb03ca5eac2e64192b723d51f56c1b1e0860e7c766281f4598f181acdc8"
 "checksum smithay-client-toolkit 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "428d6c019bb92753be9670367e3f483e4fcef396180a9b59e813b69b20014881"
 "checksum stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffbc596e092fe5f598b12ef46cc03754085ac2f4d8c739ad61c4ae266cc3b3fa"
 "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
 "checksum syn 0.15.17 (registry+https://github.com/rust-lang/crates.io-index)" = "3391038ebc3e4ab24eb028cb0ef2f2dc4ba0cbf72ee895ed6a6fad730640b5bc"
 "checksum tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "47776f63b85777d984a50ce49d6b9e58826b6a3766a449fc95bc66cd5663c15b"
--- a/gfx/wr/webrender/Cargo.toml
+++ b/gfx/wr/webrender/Cargo.toml
@@ -32,17 +32,17 @@ lazy_static = "1"
 log = "0.4"
 num-traits = "0.2"
 plane-split = "0.13.3"
 png = { optional = true, version = "0.12" }
 rayon = "1"
 ron = { optional = true, version = "0.1.7" }
 serde = { optional = true, version = "1.0", features = ["serde_derive"] }
 serde_json = { optional = true, version = "1.0" }
-sha2 = "0.7"
+sha2 = "0.8"
 smallvec = "0.6"
 thread_profiler = "0.1.1"
 time = "0.1"
 webrender_api = { version = "0.57.2", path = "../webrender_api" }
 ws = { optional = true, version = "0.7.3" }
 
 [dependencies.pathfinder_font_renderer]
 git = "https://github.com/pcwalton/pathfinder"
--- a/gfx/wr/webrender/src/frame_builder.rs
+++ b/gfx/wr/webrender/src/frame_builder.rs
@@ -22,17 +22,16 @@ use render_backend::{FrameResources, Fra
 use render_task::{RenderTask, RenderTaskId, RenderTaskLocation, RenderTaskTree};
 use resource_cache::{ResourceCache};
 use scene::{ScenePipeline, SceneProperties};
 use segment::SegmentBuilder;
 use spatial_node::SpatialNode;
 use std::{f32, mem};
 use std::sync::Arc;
 use tiling::{Frame, RenderPass, RenderPassKind, RenderTargetContext};
-use tiling::{SpecialRenderPasses};
 
 
 #[derive(Clone, Copy, Debug, PartialEq)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub enum ChasePrimitive {
     Nothing,
     Id(PrimitiveDebugId),
@@ -81,17 +80,16 @@ pub struct FrameBuildingContext<'a> {
 }
 
 pub struct FrameBuildingState<'a> {
     pub render_tasks: &'a mut RenderTaskTree,
     pub profile_counters: &'a mut FrameProfileCounters,
     pub clip_store: &'a mut ClipStore,
     pub resource_cache: &'a mut ResourceCache,
     pub gpu_cache: &'a mut GpuCache,
-    pub special_render_passes: &'a mut SpecialRenderPasses,
     pub transforms: &'a mut TransformPalette,
     pub segment_builder: SegmentBuilder,
     pub surfaces: &'a mut Vec<SurfaceInfo>,
 }
 
 /// Immutable context of a picture when processing children.
 #[derive(Debug)]
 pub struct PictureContext {
@@ -205,17 +203,16 @@ impl FrameBuilder {
     /// primitives in screen space.
     fn build_layer_screen_rects_and_cull_layers(
         &mut self,
         clip_scroll_tree: &ClipScrollTree,
         pipelines: &FastHashMap<PipelineId, Arc<ScenePipeline>>,
         resource_cache: &mut ResourceCache,
         gpu_cache: &mut GpuCache,
         render_tasks: &mut RenderTaskTree,
-        special_render_passes: &mut SpecialRenderPasses,
         profile_counters: &mut FrameProfileCounters,
         device_pixel_scale: DevicePixelScale,
         scene_properties: &SceneProperties,
         transform_palette: &mut TransformPalette,
         resources: &mut FrameResources,
         surfaces: &mut Vec<SurfaceInfo>,
         scratch: &mut PrimitiveScratchBuffer,
     ) -> Option<RenderTaskId> {
@@ -303,17 +300,16 @@ impl FrameBuilder {
         }
 
         let mut frame_state = FrameBuildingState {
             render_tasks,
             profile_counters,
             clip_store: &mut self.clip_store,
             resource_cache,
             gpu_cache,
-            special_render_passes,
             transforms: transform_palette,
             segment_builder: SegmentBuilder::new(),
             surfaces: pic_update_state.surfaces,
         };
 
         let (pic_context, mut pic_state, mut prim_list) = self
             .prim_store
             .pictures[self.root_pic_index.0]
@@ -408,62 +404,65 @@ impl FrameBuilder {
             Some(&mut transform_palette),
         );
         self.clip_store.clear_old_instances();
 
         let mut render_tasks = RenderTaskTree::new(stamp.frame_id());
         let mut surfaces = Vec::new();
 
         let screen_size = self.screen_rect.size.to_i32();
-        let mut special_render_passes = SpecialRenderPasses::new(&screen_size);
 
         let main_render_task_id = self.build_layer_screen_rects_and_cull_layers(
             clip_scroll_tree,
             pipelines,
             resource_cache,
             gpu_cache,
             &mut render_tasks,
-            &mut special_render_passes,
             &mut profile_counters,
             device_pixel_scale,
             scene_properties,
             &mut transform_palette,
             resources,
             &mut surfaces,
             scratch,
         );
 
         resource_cache.block_until_all_resources_added(gpu_cache,
                                                        &mut render_tasks,
                                                        texture_cache_profile);
 
-        let mut passes = vec![
-            special_render_passes.alpha_glyph_pass,
-            special_render_passes.color_glyph_pass,
-        ];
+        let mut passes = vec![];
+
+        // Add passes as required for our cached render tasks.
+        if !render_tasks.cacheable_render_tasks.is_empty() {
+            passes.push(RenderPass::new_off_screen(screen_size));
+            for cacheable_render_task in &render_tasks.cacheable_render_tasks {
+                render_tasks.assign_to_passes(
+                    *cacheable_render_task,
+                    0,
+                    screen_size,
+                    &mut passes,
+                );
+            }
+            passes.reverse();
+        }
 
         if let Some(main_render_task_id) = main_render_task_id {
-            let mut required_pass_count = 0;
-            render_tasks.max_depth(main_render_task_id, 0, &mut required_pass_count);
-            assert_ne!(required_pass_count, 0);
-
-            // Do the allocations now, assigning each tile's tasks to a render
-            // pass and target as required.
-            for _ in 0 .. required_pass_count - 1 {
-                passes.push(RenderPass::new_off_screen(screen_size));
-            }
+            let passes_start = passes.len();
             passes.push(RenderPass::new_main_framebuffer(screen_size));
-
             render_tasks.assign_to_passes(
                 main_render_task_id,
-                required_pass_count - 1,
-                &mut passes[2..],
+                passes_start,
+                screen_size,
+                &mut passes,
             );
+            passes[passes_start..].reverse();
         }
 
+
         let mut deferred_resolves = vec![];
         let mut has_texture_cache_tasks = false;
         let mut prim_headers = PrimitiveHeaders::new();
         // Used to generated a unique z-buffer value per primitive.
         let mut z_generator = ZBufferIdGenerator::new();
         let use_dual_source_blending = self.config.dual_source_blending_is_enabled &&
                                        self.config.dual_source_blending_is_supported;
 
--- a/gfx/wr/webrender/src/glyph_rasterizer/mod.rs
+++ b/gfx/wr/webrender/src/glyph_rasterizer/mod.rs
@@ -705,18 +705,16 @@ mod test_glyph_rasterizer {
         // 50 glyphs each, deletes the font and waits for the result.
 
         use rayon::ThreadPoolBuilder;
         use std::fs::File;
         use std::io::Read;
         use texture_cache::TextureCache;
         use glyph_cache::GlyphCache;
         use gpu_cache::GpuCache;
-        use tiling::SpecialRenderPasses;
-        use api::DeviceIntSize;
         use render_task::{RenderTaskCache, RenderTaskTree};
         use profiler::TextureCacheProfileCounters;
         use api::{FontKey, FontTemplate, FontRenderMode,
                   IdNamespace, ColorF, ColorU, DevicePoint};
         use render_backend::FrameId;
         use app_units::Au;
         use thread_profiler::register_thread_with_profiler;
         use std::sync::Arc;
@@ -730,18 +728,16 @@ mod test_glyph_rasterizer {
             .build();
         let workers = Arc::new(worker.unwrap());
         let mut glyph_rasterizer = GlyphRasterizer::new(workers).unwrap();
         let mut glyph_cache = GlyphCache::new();
         let mut gpu_cache = GpuCache::new();
         let mut texture_cache = TextureCache::new_for_testing(2048, 1024);
         let mut render_task_cache = RenderTaskCache::new();
         let mut render_task_tree = RenderTaskTree::new(FrameId::INVALID);
-        let mut special_render_passes = SpecialRenderPasses::new(&DeviceIntSize::new(1366, 768));
-
         let mut font_file =
             File::open("../wrench/reftests/text/VeraBd.ttf").expect("Couldn't open font file");
         let mut font_data = vec![];
         font_file
             .read_to_end(&mut font_data)
             .expect("failed to read font file");
 
         let font_key = FontKey::new(IdNamespace(0), 0);
@@ -773,17 +769,16 @@ mod test_glyph_rasterizer {
             glyph_rasterizer.request_glyphs(
                 &mut glyph_cache,
                 font.clone(),
                 &glyph_keys[(50 * i) .. (50 * (i + 1))],
                 &mut texture_cache,
                 &mut gpu_cache,
                 &mut render_task_cache,
                 &mut render_task_tree,
-                &mut special_render_passes,
             );
         }
 
         glyph_rasterizer.delete_font(font_key);
 
         glyph_rasterizer.resolve_glyphs(
             &mut glyph_cache,
             &mut TextureCache::new_for_testing(4096, 1024),
--- a/gfx/wr/webrender/src/glyph_rasterizer/no_pathfinder.rs
+++ b/gfx/wr/webrender/src/glyph_rasterizer/no_pathfinder.rs
@@ -14,17 +14,16 @@ use std::sync::{Arc, MutexGuard};
 use platform::font::FontContext;
 use glyph_rasterizer::{FontInstance, FontContexts, GlyphKey};
 use glyph_rasterizer::{GlyphRasterizer, GlyphRasterJob, GlyphRasterJobs, GlyphRasterResult};
 use glyph_cache::{GlyphCache, CachedGlyphInfo, GlyphCacheEntry};
 use resource_cache::CachedImageData;
 use texture_cache::{TextureCache, TextureCacheHandle, Eviction};
 use gpu_cache::GpuCache;
 use render_task::{RenderTaskTree, RenderTaskCache};
-use tiling::SpecialRenderPasses;
 use profiler::TextureCacheProfileCounters;
 use std::collections::hash_map::Entry;
 
 impl FontContexts {
     /// Get access to the font context associated to the current thread.
     pub fn lock_current_context(&self) -> MutexGuard<FontContext> {
         let id = self.current_worker_id();
         self.lock_context(id)
@@ -41,17 +40,16 @@ impl GlyphRasterizer {
         &mut self,
         glyph_cache: &mut GlyphCache,
         font: FontInstance,
         glyph_keys: &[GlyphKey],
         texture_cache: &mut TextureCache,
         gpu_cache: &mut GpuCache,
         _: &mut RenderTaskCache,
         _: &mut RenderTaskTree,
-        _: &mut SpecialRenderPasses,
     ) {
         assert!(
             self.font_contexts
                 .lock_shared_context()
                 .has_font(&font.font_key)
         );
         let mut new_glyphs = Vec::new();
 
--- a/gfx/wr/webrender/src/glyph_rasterizer/pathfinder.rs
+++ b/gfx/wr/webrender/src/glyph_rasterizer/pathfinder.rs
@@ -1,25 +1,24 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! Module only available when pathfinder is activated
 
-use api::{DeviceIntPoint, DeviceIntSize, DevicePixel, FontRenderMode, FontKey, FontTemplate, NativeFontHandle};
+use api::{DeviceIntPoint, DeviceIntSize, DevicePixel, FontKey, FontTemplate, NativeFontHandle};
 use euclid::{TypedPoint2D, TypedSize2D, TypedVector2D};
 use pathfinder_font_renderer;
 use pathfinder_partitioner::mesh::Mesh as PathfinderMesh;
 use pathfinder_path_utils::cubic_to_quadratic::CubicToQuadraticTransformer;
 use render_task::{RenderTask, RenderTaskTree, RenderTaskCache, RenderTaskCacheKey, RenderTaskCacheEntryHandle,
                   RenderTaskCacheKeyKind, RenderTaskId, RenderTaskLocation};
 use resource_cache::CacheItem;
 use std::ops::Deref;
 use std::sync::{Arc, Mutex, MutexGuard};
-use tiling::{RenderTargetKind, SpecialRenderPasses};
 use glyph_rasterizer::AddFont;
 use internal_types::ResourceCacheError;
 use glyph_cache::{GlyphCache, GlyphCacheEntry, CachedGlyphInfo};
 use std::collections::hash_map::Entry;
 use std::f32;
 use glyph_rasterizer::{FontInstance, GlyphRasterizer, GlyphFormat, GlyphKey, FontContexts};
 use texture_cache::TextureCache;
 use gpu_cache::GpuCache;
@@ -117,54 +116,51 @@ impl GlyphRasterizer {
         glyph_key: &GlyphKey,
         font: &FontInstance,
         scale: f32,
         cached_glyph_info: CachedGlyphInfo,
         texture_cache: &mut TextureCache,
         gpu_cache: &mut GpuCache,
         render_task_cache: &mut RenderTaskCache,
         render_task_tree: &mut RenderTaskTree,
-        render_passes: &mut SpecialRenderPasses)
-    -> Result<(RenderTaskCacheEntryHandle,GlyphFormat), ()>
-    {
+    ) -> Result<(RenderTaskCacheEntryHandle,GlyphFormat), ()> {
         let mut pathfinder_font_context = self.font_contexts.lock_pathfinder_context();
         let render_task_cache_key = cached_glyph_info.render_task_cache_key;
         let (glyph_origin, glyph_size) = (cached_glyph_info.origin, render_task_cache_key.size);
         let user_data = [glyph_origin.x as f32, (glyph_origin.y - glyph_size.height) as f32, scale];
-        let handle = try!(render_task_cache.request_render_task(render_task_cache_key,
-                                                                texture_cache,
-                                                                gpu_cache,
-                                                                render_task_tree,
-                                                                Some(user_data),
-                                                                false,
-                                                                |render_tasks| {
+        let handle = render_task_cache.request_render_task(render_task_cache_key,
+                                                           texture_cache,
+                                                           gpu_cache,
+                                                           render_task_tree,
+                                                           Some(user_data),
+                                                           false,
+                                                           |render_tasks| {
             // TODO(pcwalton): Non-subpixel font render mode.
-            request_render_task_from_pathfinder(glyph_key,
-                                                font,
-                                                scale,
-                                                &glyph_origin,
-                                                &glyph_size,
-                                                &mut *pathfinder_font_context,
-                                                font.render_mode,
-                                                render_tasks,
-                                                render_passes)
-        }));
+            request_render_task_from_pathfinder(
+                glyph_key,
+                font,
+                scale,
+                &glyph_origin,
+                &glyph_size,
+                &mut *pathfinder_font_context,
+                render_tasks,
+            )
+        })?;
         Ok((handle, font.get_glyph_format()))
     }
 
     pub fn request_glyphs(
         &mut self,
         glyph_cache: &mut GlyphCache,
         font: FontInstance,
         glyph_keys: &[GlyphKey],
         texture_cache: &mut TextureCache,
         gpu_cache: &mut GpuCache,
         render_task_cache: &mut RenderTaskCache,
         render_task_tree: &mut RenderTaskTree,
-        render_passes: &mut SpecialRenderPasses,
     ) {
         debug_assert!(self.font_contexts.lock_shared_context().has_font(&font.font_key));
 
         let glyph_key_cache = glyph_cache.get_glyph_key_cache_for_font_mut(font.clone());
 
         let (x_scale, y_scale) = font.transform.compute_scale().unwrap_or((1.0, 1.0));
         let scale = font.oversized_scale_factor(x_scale, y_scale) as f32;
 
@@ -214,25 +210,26 @@ impl GlyphRasterizer {
                                                     -glyph_dimensions.origin.y as i32),
                     });
                     self.next_gpu_glyph_cache_key.0 += 1;
                 }
             }
 
             let handle = match cached_glyph_info {
                 Some(glyph_info) => {
-                    match self.request_glyph_from_pathfinder_if_necessary(glyph_key,
-                                                                          &font,
-                                                                          scale,
-                                                                          glyph_info.clone(),
-                                                                          texture_cache,
-                                                                          gpu_cache,
-                                                                          render_task_cache,
-                                                                          render_task_tree,
-                                                                          render_passes) {
+                    match self.request_glyph_from_pathfinder_if_necessary(
+                        glyph_key,
+                        &font,
+                        scale,
+                        glyph_info.clone(),
+                        texture_cache,
+                        gpu_cache,
+                        render_task_cache,
+                        render_task_tree,
+                    ) {
                         Ok(_) => GlyphCacheEntry::Cached(glyph_info),
                         Err(_) => GlyphCacheEntry::Blank,
                     }
                 }
                 None => GlyphCacheEntry::Blank,
             };
 
             glyph_key_cache.insert(glyph_key.clone(), handle);
@@ -258,26 +255,25 @@ impl FontContexts {
     }
 }
 
 fn compute_embolden_amount(ppem: f32) -> TypedVector2D<f32, DevicePixel> {
     TypedVector2D::new(f32::min(ppem * STEM_DARKENING_FACTOR_X, MAX_STEM_DARKENING_AMOUNT),
                        f32::min(ppem * STEM_DARKENING_FACTOR_Y, MAX_STEM_DARKENING_AMOUNT))
 }
 
-fn request_render_task_from_pathfinder(glyph_key: &GlyphKey,
-                                       font: &FontInstance,
-                                       scale: f32,
-                                       glyph_origin: &DeviceIntPoint,
-                                       glyph_size: &DeviceIntSize,
-                                       font_context: &mut PathfinderFontContext,
-                                       render_mode: FontRenderMode,
-                                       render_tasks: &mut RenderTaskTree,
-                                       render_passes: &mut SpecialRenderPasses)
-                                       -> Result<RenderTaskId, ()> {
+fn request_render_task_from_pathfinder(
+    glyph_key: &GlyphKey,
+    font: &FontInstance,
+    scale: f32,
+    glyph_origin: &DeviceIntPoint,
+    glyph_size: &DeviceIntSize,
+    font_context: &mut PathfinderFontContext,
+    render_tasks: &mut RenderTaskTree,
+) -> Result<RenderTaskId, ()> {
     let size = font.size.scale_by(scale.recip());
     let pathfinder_font_instance = pathfinder_font_renderer::FontInstance {
         font_key: font.font_key.clone(),
         size,
     };
 
     // TODO: pathfinder will need to support 2D subpixel offset
     let pathfinder_subpixel_offset =
@@ -297,26 +293,21 @@ fn request_render_task_from_pathfinder(g
     // FIXME(pcwalton): Support vertical subpixel offsets.
     // FIXME(pcwalton): Embolden amount should be 0 on macOS if "Use LCD font
     // smoothing" is unchecked in System Preferences.
 
     let subpixel_offset = TypedPoint2D::new(glyph_subpixel_offset as f32, 0.0);
     let embolden_amount = compute_embolden_amount(size.to_f32_px());
 
     let location = RenderTaskLocation::Dynamic(None, *glyph_size);
-    let glyph_render_task = RenderTask::new_glyph(location.clone(),
-                                                  mesh,
-                                                  &glyph_origin,
-                                                  &subpixel_offset,
-                                                  font.render_mode,
-                                                  &embolden_amount);
+    let glyph_render_task = RenderTask::new_glyph(
+        location.clone(),
+        mesh,
+        &glyph_origin,
+        &subpixel_offset,
+        font.render_mode,
+        &embolden_amount,
+    );
 
-    let root_task_id = render_tasks.add(glyph_render_task);
-    let render_pass = match render_mode {
-        FontRenderMode::Mono | FontRenderMode::Alpha => &mut render_passes.alpha_glyph_pass,
-        FontRenderMode::Subpixel => &mut render_passes.color_glyph_pass,
-    };
-    render_pass.add_render_task(root_task_id, *glyph_size, RenderTargetKind::Color, &location);
-
-    Ok(root_task_id)
+    Ok(render_tasks.add(glyph_render_task))
 }
 
 pub struct NativeFontHandleWrapper<'a>(pub &'a NativeFontHandle);
--- a/gfx/wr/webrender/src/prim_store/image.rs
+++ b/gfx/wr/webrender/src/prim_store/image.rs
@@ -7,17 +7,16 @@ use api::{
     DeviceIntSize, ImageRendering, LayoutRect, LayoutSize, LayoutPrimitiveInfo,
     PremultipliedColorF, Shadow, TileOffset, YuvColorSpace, YuvFormat
 };
 use api::ImageKey as ApiImageKey;
 use display_list_flattener::{AsInstanceKind, CreateShadow, IsVisible};
 use frame_builder::FrameBuildingState;
 use gpu_cache::{GpuCacheHandle, GpuDataRequest};
 use intern::{DataStore, Handle, Internable, Interner, InternDebug, UpdateList};
-use picture::SurfaceIndex;
 use prim_store::{
     EdgeAaSegmentMask, OpacityBindingIndex, PrimitiveInstanceKind,
     PrimitiveOpacity, PrimitiveSceneData, PrimKey, PrimKeyCommonData,
     PrimTemplate, PrimTemplateCommonData, PrimitiveStore, SegmentInstanceIndex,
     SizeKey
 };
 use render_task::{
     BlitSource, RenderTask, RenderTaskCacheEntryHandle, RenderTaskCacheKey,
@@ -170,22 +169,16 @@ impl From<Image> for ImageData {
 
 impl ImageData {
     /// Update the GPU cache for a given primitive template. This may be called multiple
     /// times per frame, by each primitive reference that refers to this interned
     /// template. The initial request call to the GPU cache ensures that work is only
     /// done if the cache entry is invalid (due to first use or eviction).
     pub fn update(
         &mut self,
-        // TODO(gw): Passing in surface_index here is not ideal. The primitive template
-        //           code shouldn't depend on current surface state. This is due to a
-        //           limitation in how render task caching works. We should fix this by
-        //           allowing render task caching to assign to surfaces implicitly
-        //           during pass allocation.
-        surface_index: SurfaceIndex,
         common: &mut PrimTemplateCommonData,
         frame_state: &mut FrameBuildingState,
     ) {
         if let Some(mut request) = frame_state.gpu_cache.request(&mut common.gpu_cache_handle) {
             self.write_prim_gpu_blocks(&mut request);
         }
 
         common.opacity = {
@@ -243,17 +236,16 @@ impl ImageData {
                             size.height += padding.vertical();
 
                             is_opaque &= padding == DeviceIntSideOffsets::zero();
 
                             let image_cache_key = ImageCacheKey {
                                 request,
                                 texel_rect: self.sub_rect,
                             };
-                            let surfaces = &mut frame_state.surfaces;
 
                             // Request a pre-rendered image task.
                             *handle = Some(frame_state.resource_cache.request_render_task(
                                 RenderTaskCacheKey {
                                     size: *size,
                                     kind: RenderTaskCacheKeyKind::Image(image_cache_key),
                                 },
                                 frame_state.gpu_cache,
@@ -279,24 +271,18 @@ impl ImageData {
                                     // task above back into the right spot in the persistent
                                         // render target cache.
                                     let target_to_cache_task = RenderTask::new_blit(
                                         *size,
                                         BlitSource::RenderTask {
                                             task_id: cache_to_target_task_id,
                                         },
                                     );
-                                    let target_to_cache_task_id = render_tasks.add(target_to_cache_task);
 
-                                    // Hook this into the render task tree at the right spot.
-                                    surfaces[surface_index.0].tasks.push(target_to_cache_task_id);
-
-                                    // Pass the image opacity, so that the cached render task
-                                    // item inherits the same opacity properties.
-                                    target_to_cache_task_id
+                                    render_tasks.add(target_to_cache_task)
                                 }
                             ));
                         }
                         ImageSource::Default => {
                             // Normal images just reference the source texture each frame.
                             request_source_image = true;
                         }
                     }
--- a/gfx/wr/webrender/src/prim_store/mod.rs
+++ b/gfx/wr/webrender/src/prim_store/mod.rs
@@ -2281,17 +2281,16 @@ impl PrimitiveStore {
 
                 // If we have a cache key, it's a wavy / dashed / dotted line. Otherwise, it's
                 // a simple solid line.
                 if let Some(cache_key) = line_dec_data.cache_key.as_ref() {
                     // TODO(gw): Do we ever need / want to support scales for text decorations
                     //           based on the current transform?
                     let scale_factor = TypedScale::new(1.0) * frame_context.device_pixel_scale;
                     let task_size = (LayoutSize::from_au(cache_key.size) * scale_factor).ceil().to_i32();
-                    let surfaces = &mut frame_state.surfaces;
 
                     // Request a pre-rendered image task.
                     // TODO(gw): This match is a bit untidy, but it should disappear completely
                     //           once the prepare_prims and batching are unified. When that
                     //           happens, we can use the cache handle immediately, and not need
                     //           to temporarily store it in the primitive instance.
                     *cache_handle = Some(frame_state.resource_cache.request_render_task(
                         RenderTaskCacheKey {
@@ -2305,19 +2304,17 @@ impl PrimitiveStore {
                         |render_tasks| {
                             let task = RenderTask::new_line_decoration(
                                 task_size,
                                 cache_key.style,
                                 cache_key.orientation,
                                 cache_key.wavy_line_thickness.to_f32_px(),
                                 LayoutSize::from_au(cache_key.size),
                             );
-                            let task_id = render_tasks.add(task);
-                            surfaces[pic_context.surface_index.0].tasks.push(task_id);
-                            task_id
+                            render_tasks.add(task)
                         }
                     ));
                 }
             }
             PrimitiveInstanceKind::TextRun { data_handle, run_index, .. } => {
                 let prim_data = &mut resources.text_run_data_store[*data_handle];
 
                 // Update the template this instane references, which may refresh the GPU
@@ -2338,17 +2335,16 @@ impl PrimitiveStore {
                     &prim_data.font,
                     &prim_data.glyphs,
                     frame_context.device_pixel_scale,
                     &transform,
                     pic_context,
                     frame_state.resource_cache,
                     frame_state.gpu_cache,
                     frame_state.render_tasks,
-                    frame_state.special_render_passes,
                     scratch,
                 );
             }
             PrimitiveInstanceKind::Clear { data_handle, .. } => {
                 let prim_data = &mut resources.prim_data_store[*data_handle];
 
                 // Update the template this instane references, which may refresh the GPU
                 // cache with any shared template data.
@@ -2371,17 +2367,16 @@ impl PrimitiveStore {
                 let max_scale = get_max_scale_for_border(&border_data.border.radius,
                                                          &border_data.widths);
                 scale.0 = scale.0.min(max_scale.0);
 
                 // For each edge and corner, request the render task by content key
                 // from the render task cache. This ensures that the render task for
                 // this segment will be available for batching later in the frame.
                 let mut handles: SmallVec<[RenderTaskCacheEntryHandle; 8]> = SmallVec::new();
-                let surfaces = &mut frame_state.surfaces;
 
                 for segment in &border_data.border_segments {
                     // Update the cache key device size based on requested scale.
                     let cache_size = to_cache_size(segment.local_task_size * scale);
                     let cache_key = RenderTaskCacheKey {
                         kind: RenderTaskCacheKeyKind::BorderSegment(segment.cache_key.clone()),
                         size: cache_size,
                     };
@@ -2398,21 +2393,17 @@ impl PrimitiveStore {
                                 build_border_instances(
                                     &segment.cache_key,
                                     cache_size,
                                     &border_data.border,
                                     scale,
                                 ),
                             );
 
-                            let task_id = render_tasks.add(task);
-
-                            surfaces[pic_context.surface_index.0].tasks.push(task_id);
-
-                            task_id
+                            render_tasks.add(task)
                         }
                     ));
                 }
 
                 *cache_handles = scratch
                     .border_cache_handles
                     .extend(handles);
             }
@@ -2455,21 +2446,17 @@ impl PrimitiveStore {
             }
             PrimitiveInstanceKind::Image { data_handle, image_instance_index, .. } => {
                 let prim_data = &mut resources.image_data_store[*data_handle];
                 let common_data = &mut prim_data.common;
                 let image_data = &mut prim_data.kind;
 
                 // Update the template this instane references, which may refresh the GPU
                 // cache with any shared template data.
-                image_data.update(
-                    pic_context.surface_index,
-                    common_data,
-                    frame_state,
-                );
+                image_data.update(common_data, frame_state);
 
                 let image_instance = &mut self.images[*image_instance_index];
 
                 update_opacity_binding(
                     &mut self.opacity_bindings,
                     image_instance.opacity_binding_index,
                     frame_context.scene_properties,
                 );
--- a/gfx/wr/webrender/src/prim_store/text_run.rs
+++ b/gfx/wr/webrender/src/prim_store/text_run.rs
@@ -10,17 +10,16 @@ use frame_builder::{FrameBuildingState, 
 use glyph_rasterizer::{FontInstance, FontTransform, GlyphKey, FONT_SIZE_LIMIT};
 use gpu_cache::GpuCache;
 use intern;
 use prim_store::{PrimitiveOpacity, PrimitiveSceneData,  PrimitiveScratchBuffer};
 use prim_store::{PrimitiveStore, PrimKeyCommonData, PrimTemplateCommonData, VectorKey};
 use render_task::{RenderTaskTree};
 use renderer::{MAX_VERTEX_TEXTURE_WIDTH};
 use resource_cache::{ResourceCache};
-use tiling::SpecialRenderPasses;
 use util::{MatrixHelpers};
 use prim_store::PrimitiveInstanceKind;
 use std::ops;
 use storage;
 
 /// A run of glyphs, with associated font information.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
@@ -293,17 +292,16 @@ impl TextRunPrimitive {
         specified_font: &FontInstance,
         glyphs: &[GlyphInstance],
         device_pixel_scale: DevicePixelScale,
         transform: &LayoutToWorldTransform,
         pic_context: &PictureContext,
         resource_cache: &mut ResourceCache,
         gpu_cache: &mut GpuCache,
         render_tasks: &mut RenderTaskTree,
-        special_render_passes: &mut SpecialRenderPasses,
         scratch: &mut PrimitiveScratchBuffer,
     ) {
         let cache_dirty = self.update_font_instance(
             specified_font,
             device_pixel_scale,
             transform,
             pic_context.allow_subpixel_aa,
             pic_context.raster_space,
@@ -321,17 +319,16 @@ impl TextRunPrimitive {
                 }));
         }
 
         resource_cache.request_glyphs(
             self.used_font.clone(),
             &scratch.glyph_keys[self.glyph_keys_range],
             gpu_cache,
             render_tasks,
-            special_render_passes,
         );
     }
 }
 
 #[test]
 #[cfg(target_os = "linux")]
 fn test_struct_sizes() {
     use std::mem;
--- a/gfx/wr/webrender/src/render_task.rs
+++ b/gfx/wr/webrender/src/render_task.rs
@@ -24,17 +24,17 @@ use pathfinder_partitioner::mesh::Mesh;
 use prim_store::PictureIndex;
 use prim_store::image::ImageCacheKey;
 use prim_store::line_dec::LineDecorationCacheKey;
 #[cfg(feature = "debugger")]
 use print_tree::{PrintTreePrinter};
 use render_backend::FrameId;
 use resource_cache::{CacheItem, ResourceCache};
 use surface::SurfaceCacheKey;
-use std::{cmp, ops, mem, usize, f32, i32, u32};
+use std::{ops, mem, usize, f32, i32, u32};
 use texture_cache::{TextureCache, TextureCacheHandle, Eviction};
 use tiling::{RenderPass, RenderTargetIndex};
 use tiling::{RenderTargetKind};
 #[cfg(feature = "pathfinder")]
 use webrender_api::DevicePixel;
 
 const RENDER_TASK_SIZE_SANITY_CHECK: i32 = 16000;
 const FLOATS_PER_RENDER_TASK_INFO: usize = 8;
@@ -75,82 +75,74 @@ impl RenderTaskId {
 pub struct RenderTaskAddress(pub u32);
 
 #[derive(Debug)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct RenderTaskTree {
     pub tasks: Vec<RenderTask>,
     pub task_data: Vec<RenderTaskData>,
+    /// Tasks that don't have dependencies, and that may be shared between
+    /// picture tasks.
+    ///
+    /// We render these unconditionally before-rendering the rest of the tree.
+    pub cacheable_render_tasks: Vec<RenderTaskId>,
     next_saved: SavedTargetIndex,
     frame_id: FrameId,
 }
 
 impl RenderTaskTree {
     pub fn new(frame_id: FrameId) -> Self {
         RenderTaskTree {
             tasks: Vec::new(),
             task_data: Vec::new(),
+            cacheable_render_tasks: Vec::new(),
             next_saved: SavedTargetIndex(0),
             frame_id,
         }
     }
 
     pub fn add(&mut self, task: RenderTask) -> RenderTaskId {
         let index = self.tasks.len() as _;
         self.tasks.push(task);
         RenderTaskId {
             index,
             #[cfg(debug_assertions)]
             frame_id: self.frame_id,
         }
     }
 
-    pub fn max_depth(&self, id: RenderTaskId, depth: usize, max_depth: &mut usize) {
-        #[cfg(debug_assertions)]
-        debug_assert_eq!(self.frame_id, id.frame_id);
-        let depth = depth + 1;
-        *max_depth = cmp::max(*max_depth, depth);
-        let task = &self.tasks[id.index as usize];
-        for child in &task.children {
-            self.max_depth(*child, depth, max_depth);
-        }
-    }
-
+    /// Assign the render tasks from the tree rooted at `id` to the `passes`
+    /// vector, so that the passes that we depend on end up _later_ in the pass
+    /// list.
+    ///
+    /// It is the caller's responsibility to reverse the list after calling into
+    /// us so that the passes end up in the right order.
     pub fn assign_to_passes(
         &self,
         id: RenderTaskId,
         pass_index: usize,
-        passes: &mut [RenderPass],
+        screen_size: DeviceIntSize,
+        passes: &mut Vec<RenderPass>,
     ) {
+        debug_assert!(pass_index < passes.len());
         #[cfg(debug_assertions)]
         debug_assert_eq!(self.frame_id, id.frame_id);
         let task = &self.tasks[id.index as usize];
 
-        for child in &task.children {
-            self.assign_to_passes(*child, pass_index - 1, passes);
-        }
-
-        // Sanity check - can be relaxed if needed
-        match task.location {
-            RenderTaskLocation::Fixed(..) => {
-                debug_assert!(pass_index == passes.len() - 1);
+        if !task.children.is_empty() {
+            let child_index = pass_index + 1;
+            if passes.len() == child_index {
+                passes.push(RenderPass::new_off_screen(screen_size));
             }
-            RenderTaskLocation::Dynamic(..) |
-            RenderTaskLocation::TextureCache { .. } => {
-                debug_assert!(pass_index < passes.len() - 1);
+            for child in &task.children {
+                self.assign_to_passes(*child, child_index, screen_size, passes);
             }
         }
 
-        let pass_index = if task.is_global_cached_task() {
-            0
-        } else {
-            pass_index
-        };
-
         passes[pass_index].add_render_task(
             id,
             task.get_dynamic_size(),
             task.target_kind(),
             &task.location,
         );
     }
 
@@ -546,18 +538,16 @@ impl RenderTask {
         clip_node_range: ClipNodeRange,
         root_spatial_node_index: SpatialNodeIndex,
         clip_store: &mut ClipStore,
         gpu_cache: &mut GpuCache,
         resource_cache: &mut ResourceCache,
         render_tasks: &mut RenderTaskTree,
         clip_data_store: &mut ClipDataStore,
     ) -> Self {
-        let mut children = Vec::new();
-
         // Step through the clip sources that make up this mask. If we find
         // any box-shadow clip sources, request that image from the render
         // task cache. This allows the blurred box-shadow rect to be cached
         // in the texture cache across frames.
         // TODO(gw): Consider moving this logic outside this function, especially
         //           as we add more clip sources that depend on render tasks.
         // TODO(gw): If this ever shows up in a profile, we could pre-calculate
         //           whether a ClipSources contains any box-shadows and skip
@@ -599,32 +589,29 @@ impl RenderTask {
                             let blur_render_task = RenderTask::new_blur(
                                 blur_radius_dp,
                                 mask_task_id,
                                 render_tasks,
                                 RenderTargetKind::Alpha,
                                 ClearMode::Zero,
                             );
 
-                            let root_task_id = render_tasks.add(blur_render_task);
-                            children.push(root_task_id);
-
-                            root_task_id
+                            render_tasks.add(blur_render_task)
                         }
                     ));
                 }
                 ClipItem::Rectangle(..) |
                 ClipItem::RoundedRectangle(..) |
                 ClipItem::Image { .. } => {}
             }
         }
 
         RenderTask::with_dynamic_location(
             outer_rect.size,
-            children,
+            vec![],
             RenderTaskKind::CacheMask(CacheMaskTask {
                 actual_rect: outer_rect,
                 clip_node_range,
                 root_spatial_node_index,
             }),
             ClearMode::One,
         )
     }
@@ -756,31 +743,32 @@ impl RenderTask {
             match target_kind {
                 RenderTargetKind::Color => ClearMode::Transparent,
                 RenderTargetKind::Alpha => ClearMode::One,
             },
         )
     }
 
     #[cfg(feature = "pathfinder")]
-    pub fn new_glyph(location: RenderTaskLocation,
-                     mesh: Mesh,
-                     origin: &DeviceIntPoint,
-                     subpixel_offset: &TypedPoint2D<f32, DevicePixel>,
-                     render_mode: FontRenderMode,
-                     embolden_amount: &TypedVector2D<f32, DevicePixel>)
-                     -> Self {
+    pub fn new_glyph(
+        location: RenderTaskLocation,
+        mesh: Mesh,
+        origin: &DeviceIntPoint,
+        subpixel_offset: &TypedPoint2D<f32, DevicePixel>,
+        render_mode: FontRenderMode,
+        embolden_amount: &TypedVector2D<f32, DevicePixel>,
+    ) -> Self {
         RenderTask {
             children: vec![],
-            location: location,
+            location,
             kind: RenderTaskKind::Glyph(GlyphTask {
                 mesh: Some(mesh),
                 origin: *origin,
                 subpixel_offset: *subpixel_offset,
-                render_mode: render_mode,
+                render_mode,
                 embolden_amount: *embolden_amount,
             }),
             clear_mode: ClearMode::Transparent,
             saved_index: None,
         }
     }
 
     fn uv_rect_kind(&self) -> UvRectKind {
@@ -972,40 +960,16 @@ impl RenderTask {
             }
 
             RenderTaskKind::Blit(..) => {
                 RenderTargetKind::Color
             }
         }
     }
 
-    /// If true, draw this task in the first pass. This is useful
-    /// for simple texture cached render tasks that we want to be made
-    /// available to all subsequent render passes.
-    pub fn is_global_cached_task(&self) -> bool {
-        match self.kind {
-            RenderTaskKind::LineDecoration(..) => {
-                true
-            }
-
-            RenderTaskKind::Readback(..) |
-            RenderTaskKind::ClipRegion(..) |
-            RenderTaskKind::CacheMask(..) |
-            RenderTaskKind::VerticalBlur(..) |
-            RenderTaskKind::HorizontalBlur(..) |
-            RenderTaskKind::Glyph(..) |
-            RenderTaskKind::Scaling(..) |
-            RenderTaskKind::Border(..) |
-            RenderTaskKind::Picture(..) |
-            RenderTaskKind::Blit(..) => {
-                false
-            }
-        }
-    }
-
     // Optionally, prepare the render task for drawing. This is executed
     // after all resource cache items (textures and glyphs) have been
     // resolved and can be queried. It also allows certain render tasks
     // to defer calculating an exact size until now, if desired.
     pub fn prepare_for_render(&mut self) {
     }
 
     pub fn write_gpu_blocks(
@@ -1292,39 +1256,40 @@ impl RenderTaskCache {
         key: RenderTaskCacheKey,
         texture_cache: &mut TextureCache,
         gpu_cache: &mut GpuCache,
         render_tasks: &mut RenderTaskTree,
         user_data: Option<[f32; 3]>,
         is_opaque: bool,
         f: F,
     ) -> Result<RenderTaskCacheEntryHandle, ()>
-         where F: FnOnce(&mut RenderTaskTree) -> Result<RenderTaskId, ()> {
+    where
+        F: FnOnce(&mut RenderTaskTree) -> Result<RenderTaskId, ()>,
+    {
         // Get the texture cache handle for this cache key,
         // or create one.
         let cache_entries = &mut self.cache_entries;
-        let entry_handle = self.map
-                               .entry(key)
-                               .or_insert_with(|| {
-                                    let entry = RenderTaskCacheEntry {
-                                        handle: TextureCacheHandle::invalid(),
-                                        pending_render_task_id: None,
-                                        user_data,
-                                        is_opaque,
-                                    };
-                                    cache_entries.insert(entry)
-                                });
+        let entry_handle = self.map.entry(key).or_insert_with(|| {
+            let entry = RenderTaskCacheEntry {
+                handle: TextureCacheHandle::invalid(),
+                pending_render_task_id: None,
+                user_data,
+                is_opaque,
+            };
+            cache_entries.insert(entry)
+        });
         let cache_entry = cache_entries.get_mut(entry_handle);
 
         if cache_entry.pending_render_task_id.is_none() {
             // Check if this texture cache handle is valid.
             if texture_cache.request(&cache_entry.handle, gpu_cache) {
                 // Invoke user closure to get render task chain
                 // to draw this into the texture cache.
-                let render_task_id = try!(f(render_tasks));
+                let render_task_id = f(render_tasks)?;
+                render_tasks.cacheable_render_tasks.push(render_task_id);
 
                 cache_entry.pending_render_task_id = Some(render_task_id);
                 cache_entry.user_data = user_data;
                 cache_entry.is_opaque = is_opaque;
             }
         }
 
         Ok(entry_handle.weak())
--- a/gfx/wr/webrender/src/resource_cache.rs
+++ b/gfx/wr/webrender/src/resource_cache.rs
@@ -40,17 +40,16 @@ use std::collections::VecDeque;
 use std::{cmp, mem};
 use std::fmt::Debug;
 use std::hash::Hash;
 use std::os::raw::c_void;
 #[cfg(any(feature = "capture", feature = "replay"))]
 use std::path::PathBuf;
 use std::sync::{Arc, RwLock};
 use texture_cache::{TextureCache, TextureCacheHandle, Eviction};
-use tiling::SpecialRenderPasses;
 use util::drain_filter;
 
 const DEFAULT_TILE_SIZE: TileSize = 512;
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct GlyphFetchResult {
     pub index_in_text_run: i32,
@@ -1291,30 +1290,28 @@ impl ResourceCache {
     }
 
     pub fn request_glyphs(
         &mut self,
         mut font: FontInstance,
         glyph_keys: &[GlyphKey],
         gpu_cache: &mut GpuCache,
         render_task_tree: &mut RenderTaskTree,
-        render_passes: &mut SpecialRenderPasses,
     ) {
         debug_assert_eq!(self.state, State::AddResources);
 
         self.glyph_rasterizer.prepare_font(&mut font);
         self.glyph_rasterizer.request_glyphs(
             &mut self.cached_glyphs,
             font,
             glyph_keys,
             &mut self.texture_cache,
             gpu_cache,
             &mut self.cached_render_tasks,
             render_task_tree,
-            render_passes,
         );
     }
 
     pub fn pending_updates(&mut self) -> TextureUpdateList {
         self.texture_cache.pending_updates()
     }
 
     #[cfg(feature = "pathfinder")]
--- a/gfx/wr/webrender/src/tiling.rs
+++ b/gfx/wr/webrender/src/tiling.rs
@@ -1154,22 +1154,8 @@ impl ScalingTask {
         let instance = ScalingInstance {
             task_address,
             src_task_address,
         };
 
         instances.push(instance);
     }
 }
-
-pub struct SpecialRenderPasses {
-    pub alpha_glyph_pass: RenderPass,
-    pub color_glyph_pass: RenderPass,
-}
-
-impl SpecialRenderPasses {
-    pub fn new(screen_size: &DeviceIntSize) -> SpecialRenderPasses {
-        SpecialRenderPasses {
-            alpha_glyph_pass: RenderPass::new_off_screen(*screen_size),
-            color_glyph_pass: RenderPass::new_off_screen(*screen_size),
-        }
-    }
-}
--- a/layout/style/StyleSheet.cpp
+++ b/layout/style/StyleSheet.cpp
@@ -194,29 +194,30 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(St
   tmp->UnlinkInner();
   tmp->DropRuleList();
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(StyleSheet)
 
 mozilla::dom::CSSStyleSheetParsingMode StyleSheet::ParsingModeDOM() {
-#define CHECK(X, Y)                                 \
+#define CHECK_MODE(X, Y)                            \
   static_assert(                                    \
       static_cast<int>(X) == static_cast<int>(Y),   \
       "mozilla::dom::CSSStyleSheetParsingMode and " \
       "mozilla::css::SheetParsingMode should have identical values");
 
-  CHECK(mozilla::dom::CSSStyleSheetParsingMode::Agent,
-        css::eAgentSheetFeatures);
-  CHECK(mozilla::dom::CSSStyleSheetParsingMode::User, css::eUserSheetFeatures);
-  CHECK(mozilla::dom::CSSStyleSheetParsingMode::Author,
-        css::eAuthorSheetFeatures);
+  CHECK_MODE(mozilla::dom::CSSStyleSheetParsingMode::Agent,
+             css::eAgentSheetFeatures);
+  CHECK_MODE(mozilla::dom::CSSStyleSheetParsingMode::User,
+             css::eUserSheetFeatures);
+  CHECK_MODE(mozilla::dom::CSSStyleSheetParsingMode::Author,
+             css::eAuthorSheetFeatures);
 
-#undef CHECK
+#undef CHECK_MODE
 
   return static_cast<mozilla::dom::CSSStyleSheetParsingMode>(mParsingMode);
 }
 
 void StyleSheet::SetComplete() {
   MOZ_ASSERT(!HasForcedUniqueInner(),
              "Can't complete a sheet that's already been forced unique.");
   MOZ_ASSERT(!IsComplete(), "Already complete?");
--- a/mozglue/build/WindowsDllBlocklist.cpp
+++ b/mozglue/build/WindowsDllBlocklist.cpp
@@ -25,16 +25,17 @@
 #pragma warning(pop)
 
 #include "Authenticode.h"
 #include "CrashAnnotations.h"
 #include "MozglueUtils.h"
 #include "UntrustedDllsHandler.h"
 #include "nsAutoPtr.h"
 #include "nsWindowsDllInterceptor.h"
+#include "mozilla/CmdLineAndEnvUtils.h"
 #include "mozilla/ScopeExit.h"
 #include "mozilla/Sprintf.h"
 #include "mozilla/StackWalk_windows.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/Vector.h"
 #include "mozilla/WindowsVersion.h"
 #include "nsWindowsHelpers.h"
 #include "WindowsDllBlocklist.h"
@@ -738,16 +739,49 @@ MFBT_API void DllBlocklist_Initialize(ui
   }
 
   sBlocklistInitAttempted = true;
 #if defined(NIGHTLY_BUILD)
   gStartAddressesToBlock = new mozilla::Vector<void*, 4>;
 #endif
 
   if (IsUntrustedDllsHandlerEnabled()) {
+#ifdef ENABLE_TESTS
+    // Check whether we are running as an xpcshell test.
+    if (mozilla::EnvHasValue("XPCSHELL_TEST_PROFILE_DIR")) {
+      // For xpcshell tests, load this untrusted DLL early enough that the
+      // untrusted module evaluator counts it as a startup module.
+      // It is located in the current directory; the full path must be specified
+      // or LoadLibrary() fails during xpcshell tests with ERROR_MOD_NOT_FOUND.
+
+      // This buffer will hold current directory + dll name
+      wchar_t dllFullPath[MAX_PATH] = {};
+      static const wchar_t kTestDllName[] = L"\\untrusted-startup-test-dll.dll";
+
+      // The amount of the buffer available to store the current directory,
+      // leaving room for the dll name.
+      static const DWORD kBufferDirLen =
+          ArrayLength(dllFullPath) - ArrayLength(kTestDllName);
+
+      DWORD ret = ::GetCurrentDirectoryW(kBufferDirLen, dllFullPath);
+      if ((ret > kBufferDirLen) || !ret) {
+        // Buffer too small or the call failed
+        printf_stderr("Unable to load %S; GetCurrentDirectoryW  failed: %lu",
+                      kTestDllName, GetLastError());
+      } else {
+        wcscat_s(dllFullPath, kTestDllName);
+        HMODULE hTestDll = ::LoadLibraryW(dllFullPath);
+        if (!hTestDll) {
+          printf_stderr("Unable to load %S; LoadLibraryW failed: %lu",
+                        kTestDllName, GetLastError());
+        }
+      }
+    }
+#endif
+
     glue::UntrustedDllsHandler::Init();
   }
 
   // In order to be effective against AppInit DLLs, the blocklist must be
   // initialized before user32.dll is loaded into the process (bug 932100).
   if (GetModuleHandleA("user32.dll")) {
     sUser32BeforeBlocklist = true;
 #ifdef DEBUG
--- a/taskcluster/ci/build/linux.yml
+++ b/taskcluster/ci/build/linux.yml
@@ -706,16 +706,17 @@ linux64-asan-reporter-nightly/opt:
         nightly: true
     index:
         product: firefox
         job-name: linux64-asan-reporter-opt
         type: nightly
     treeherder:
         platform: linux64-asan-reporter/opt
         symbol: BoR
+    run-on-projects: ['mozilla-central']
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         env:
             PERFHERDER_EXTRA_OPTIONS: asan-reporter
         max-run-time: 3600
     run:
         using: mozharness
         actions: [get-secrets, build, check-test]
--- a/taskcluster/ci/upload-generated-sources/kind.yml
+++ b/taskcluster/ci/upload-generated-sources/kind.yml
@@ -25,16 +25,10 @@ job-template:
         kind: build
     worker:
         docker-image: {in-tree: "lint"}
         max-run-time: 600
     run:
         using: mach
         mach: python build/upload_generated_sources.py ${ARTIFACT_URL}
         sparse-profile: upload-generated-sources
-    optimization:
-        only-if-dependencies-run: null
     scopes:
         - secrets:get:project/releng/gecko/build/level-{level}/gecko-generated-sources-upload
-    run-on-projects:
-        by-build-platform:
-            .*devedition.*: ['mozilla-beta', 'maple']
-            default: ['all']
--- a/taskcluster/ci/upload-symbols/kind.yml
+++ b/taskcluster/ci/upload-symbols/kind.yml
@@ -26,19 +26,10 @@ job-template:
         env:
             ARTIFACT_TASKID: {"task-reference": "<build>"}
             # {level} gets replaced in the upload_symbols transform
             SYMBOL_SECRET: "project/releng/gecko/build/level-{level}/gecko-symbol-upload"
     run:
         using: mach
         mach: python toolkit/crashreporter/tools/upload_symbols.py https://queue.taskcluster.net/v1/task/${ARTIFACT_TASKID}/artifacts/public/build/target.crashreporter-symbols-full.zip
         sparse-profile: upload-symbols
-    optimization:
-        only-if-dependencies-run: null
     scopes:
         - secrets:get:project/releng/gecko/build/level-{level}/gecko-symbol-upload
-    run-on-projects:
-        by-build-platform:
-            .*devedition.*: ['mozilla-beta', 'maple']
-            # Only upload symbols for nightlies on most branches.
-            .*(?<!-devedition)-nightly: ['all']
-            # Allow symbol upload for any build type on try.
-            default: ['try']
--- a/taskcluster/taskgraph/optimize.py
+++ b/taskcluster/taskgraph/optimize.py
@@ -72,17 +72,16 @@ def optimize_task_graph(target_task_grap
 def _make_default_strategies():
     return {
         'never': OptimizationStrategy(),  # "never" is the default behavior
         'index-search': IndexSearch(),
         'seta': SETA(),
         'skip-unless-changed': SkipUnlessChanged(),
         'skip-unless-schedules': SkipUnlessSchedules(),
         'skip-unless-schedules-or-seta': Either(SkipUnlessSchedules(), SETA()),
-        'only-if-dependencies-run': OnlyIfDependenciesRun(),
     }
 
 
 def _get_optimizations(target_task_graph, strategies):
     def optimizations(label):
         task = target_task_graph.tasks[label]
         if task.optimization:
             opt_by, arg = task.optimization.items()[0]
@@ -277,28 +276,16 @@ class Either(OptimizationStrategy):
             lambda sub, arg: sub.should_remove_task(task, params, arg))
 
     def should_replace_task(self, task, params, arg):
         return self._for_substrategies(
             arg,
             lambda sub, arg: sub.should_replace_task(task, params, arg))
 
 
-class OnlyIfDependenciesRun(OptimizationStrategy):
-    """Run this taks only if its dependencies run."""
-
-    # This takes advantage of the behavior of the second phase of optimization:
-    # a task can only be replaced if it has no un-optimized dependencies. So if
-    # should_replace_task is called, then a task has no un-optimized
-    # dependencies and can be removed (indicated by returning True)
-
-    def should_replace_task(self, task, params, arg):
-        return True
-
-
 class IndexSearch(OptimizationStrategy):
 
     # A task with no dependencies remaining after optimization will be replaced
     # if artifacts exist for the corresponding index_paths.
     # Otherwise, we're in one of the following cases:
     # - the task has un-optimized dependencies
     # - the artifacts have expired
     # - some changes altered the index_paths and new artifacts need to be
--- a/taskcluster/taskgraph/target_tasks.py
+++ b/taskcluster/taskgraph/target_tasks.py
@@ -55,19 +55,16 @@ def filter_on_platforms(task, platforms)
 
 
 def filter_release_tasks(task, parameters):
     platform = task.attributes.get('build_platform')
     if platform in (
             # On beta, Nightly builds are already PGOs
             'linux-pgo', 'linux64-pgo',
             'win32-pgo', 'win64-pgo',
-            # ASAN is central-only
-            'linux64-asan-reporter-nightly',
-            'win64-asan-reporter-nightly',
             ):
         return False
 
     if platform in (
             'linux', 'linux64',
             'macosx64',
             'win32', 'win64',
             ):
--- a/taskcluster/taskgraph/transforms/beetmover_repackage.py
+++ b/taskcluster/taskgraph/transforms/beetmover_repackage.py
@@ -26,23 +26,16 @@ import re
 
 logger = logging.getLogger(__name__)
 
 
 def _compile_regex_mapping(mapping):
     return {re.compile(regex): value for regex, value in mapping.iteritems()}
 
 
-_WINDOWS_BUILD_PLATFORMS = [
-    'win64-nightly',
-    'win32-nightly',
-    'win64-devedition-nightly',
-    'win32-devedition-nightly',
-]
-
 # Until bug 1331141 is fixed, if you are adding any new artifacts here that
 # need to be transfered to S3, please be aware you also need to follow-up
 # with a beetmover patch in https://github.com/mozilla-releng/beetmoverscript/.
 # See example in bug 1348286
 _DESKTOP_UPSTREAM_ARTIFACTS_UNSIGNED_EN_US = [
     "buildhub.json",
     "target.common.tests.tar.gz",
     "target.cppunittest.tests.tar.gz",
--- a/taskcluster/taskgraph/transforms/upload_generated_sources.py
+++ b/taskcluster/taskgraph/transforms/upload_generated_sources.py
@@ -33,10 +33,11 @@ def add_task_info(config, jobs):
         job['treeherder']['platform'] = plat
         job['treeherder']['tier'] = dep_th['tier']
         # Add an environment variable pointing at the artifact from the build.
         artifact_url = get_artifact_url('<build>',
                                         'public/build/target.generated-files.tar.gz')
         job['worker'].setdefault('env', {})['ARTIFACT_URL'] = {
             'task-reference': artifact_url
         }
+        job['run-on-projects'] = dep_task.attributes.get('run_on_projects')
 
         yield job
--- a/taskcluster/taskgraph/transforms/upload_symbols.py
+++ b/taskcluster/taskgraph/transforms/upload_symbols.py
@@ -74,12 +74,19 @@ def fill_template(config, tasks):
 
         # Disambiguate the treeherder symbol.
         sym = 'Sym' + (th_symbol[1:] if th_symbol.startswith('B') else th_symbol)
         treeherder.setdefault(
             'symbol', join_symbol(th_groupsymbol, sym)
         )
         task['treeherder'] = treeherder
 
+        if dep.attributes.get('nightly'):
+            # For nightly builds, we want to run these tasks if the build is run.
+            task['run-on-projects'] = dep.attributes.get('run_on_projects')
+        else:
+            # For non nightly builds, these can be requested to upload to the try symbol sever.
+            task['run-on-projects'] = ['try']
+
         # clear out the stuff that's not part of a task description
         del task['primary-dependency']
 
         yield task
--- a/taskcluster/taskgraph/util/schema.py
+++ b/taskcluster/taskgraph/util/schema.py
@@ -225,12 +225,9 @@ OptimizationSchema = voluptuous.Any(
     # consult SETA and skip this task if it is low-value
     {'seta': None},
     # skip this task if none of the given file patterns match
     {'skip-unless-changed': [basestring]},
     # skip this task if unless the change files' SCHEDULES contains any of these components
     {'skip-unless-schedules': list(schedules.ALL_COMPONENTS)},
     # skip if SETA or skip-unless-schedules says to
     {'skip-unless-schedules-or-seta': list(schedules.ALL_COMPONENTS)},
-    # only run this task if its dependencies will run (useful for follow-on tasks that
-    # are unnecessary if the parent tasks are not run)
-    {'only-if-dependencies-run': None}
 )
new file mode 100644
--- /dev/null
+++ b/third_party/rust/block-buffer-0.3.3/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{"Cargo.toml":"373908618d7bdf561f84ddc5add92f69dab295c97ab0908d3a4ec428fad23bad","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"9e0dfd2dd4173a530e238cb6adb37aa78c34c6bc7444e0e10c1ab5d8881f63ba","src/lib.rs":"bdf23c8a00fb4d51beabeb6600fe45ebf1be618632db885013b6f60a5666c124","src/paddings.rs":"7a18850dab9dca0a3e6cc49d6a94a9566ea2473628f42f726a69f8e07f95872a"},"package":"a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab"}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/block-buffer-0.3.3/Cargo.toml
@@ -0,0 +1,27 @@
+# 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 = "block-buffer"
+version = "0.3.3"
+authors = ["RustCrypto Developers"]
+description = "Fixed size buffer for block processing of data"
+documentation = "https://docs.rs/block-buffer"
+keywords = ["block", "padding", "pkcs7", "ansix923", "iso7816"]
+categories = ["cryptography", "no-std"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/RustCrypto/utils"
+[dependencies.arrayref]
+version = "0.3"
+
+[dependencies.byte-tools]
+version = "0.2"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/block-buffer-0.3.3/LICENSE-APACHE
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/block-buffer-0.3.3/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2017 Artyom Pavlov
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/block-buffer-0.3.3/src/lib.rs
@@ -0,0 +1,144 @@
+#![no_std]
+#[macro_use]
+extern crate arrayref;
+extern crate byte_tools;
+
+use byte_tools::{zero, write_u64_le};
+
+mod paddings;
+
+pub use paddings::*;
+
+macro_rules! impl_buffer {
+    ($name:ident, $len:expr) => {
+
+        pub struct $name {
+            buffer: [u8; $len],
+            pos: usize,
+        }
+
+        impl Copy for $name {}
+
+        impl Clone for $name {
+            fn clone(&self) -> Self {
+                *self
+            }
+        }
+
+        impl Default for $name {
+            fn default() -> Self {
+                $name {buffer: [0; $len], pos: 0}
+            }
+        }
+
+        impl $name {
+            #[inline]
+            pub fn input<F: FnMut(&[u8; $len])>(&mut self, mut input: &[u8], mut func: F) {
+                // If there is already data in the buffer, copy as much as we can
+                // into it and process the data if the buffer becomes full.
+                if self.pos != 0 {
+                    let rem = self.remaining();
+
+                    if input.len() >= rem {
+                        let (l, r) = input.split_at(rem);
+                        input = r;
+                        self.buffer[self.pos..].copy_from_slice(l);
+                        self.pos = 0;
+                        func(&self.buffer);
+                    } else {
+                        let end = self.pos + input.len();
+                        self.buffer[self.pos..end].copy_from_slice(input);
+                        self.pos = end;
+                        return;
+                    }
+                }
+
+                // While we have at least a full buffer size chunks's worth of data,
+                // process that data without copying it into the buffer
+                while input.len() >= self.size() {
+                    let (l, r) = input.split_at(self.size());
+                    input = r;
+                    func(array_ref!(l, 0, $len));
+                }
+
+                // Copy any input data into the buffer. At this point in the method,
+                // the ammount of data left in the input vector will be less than
+                // the buffer size and the buffer will be empty.
+                self.buffer[..input.len()].copy_from_slice(input);
+                self.pos = input.len();
+            }
+
+            #[inline]
+            fn digest_pad<F>(&mut self, up_to: usize, func: &mut F)
+                where F: FnMut(&[u8; $len])
+            {
+                self.buffer[self.pos] = 0x80;
+                self.pos += 1;
+
+                zero(&mut self.buffer[self.pos..]);
+
+                if self.remaining() < up_to {
+                    func(&self.buffer);
+                    zero(&mut self.buffer[..self.pos]);
+                }
+            }
+
+            #[inline]
+            /// Will pad message with message length in big-endian format
+            pub fn len_padding<F>(&mut self, data_len: u64, mut func: F)
+                where F: FnMut(&[u8; $len])
+            {
+                self.digest_pad(8, &mut func);
+                let s = self.size();
+                write_u64_le(&mut self.buffer[s-8..], data_len);
+                func(&self.buffer);
+                self.pos = 0;
+            }
+
+            #[inline]
+            pub fn len_padding_u128<F>(&mut self, hi: u64, lo: u64, mut func: F)
+                where F: FnMut(&[u8; $len])
+            {
+                self.digest_pad(16, &mut func);
+                let s = self.size();
+                write_u64_le(&mut self.buffer[s-16..s-8], hi);
+                write_u64_le(&mut self.buffer[s-8..], lo);
+                func(&self.buffer);
+                self.pos = 0;
+            }
+
+            #[inline]
+            pub fn pad_with<P: Padding>(&mut self) -> &mut [u8; $len] {
+                P::pad(&mut self.buffer[..], self.pos);
+                self.pos = 0;
+                &mut self.buffer
+            }
+
+            #[inline]
+            pub fn size(&self) -> usize {
+                $len
+            }
+
+            #[inline]
+            pub fn position(&self) -> usize {
+                self.pos
+            }
+
+            #[inline]
+            pub fn remaining(&self) -> usize {
+                self.size() - self.pos
+            }
+        }
+    }
+}
+
+impl_buffer!(BlockBuffer128, 16);
+impl_buffer!(BlockBuffer256, 32);
+impl_buffer!(BlockBuffer512, 64);
+impl_buffer!(BlockBuffer1024, 128);
+
+impl_buffer!(BlockBuffer576, 72);
+impl_buffer!(BlockBuffer832, 104);
+impl_buffer!(BlockBuffer1088, 136);
+impl_buffer!(BlockBuffer1152, 144);
+impl_buffer!(BlockBuffer1344, 168);
rename from third_party/rust/block-buffer/src/paddings.rs
rename to third_party/rust/block-buffer-0.3.3/src/paddings.rs
--- a/third_party/rust/block-buffer/.cargo-checksum.json
+++ b/third_party/rust/block-buffer/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"373908618d7bdf561f84ddc5add92f69dab295c97ab0908d3a4ec428fad23bad","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"9e0dfd2dd4173a530e238cb6adb37aa78c34c6bc7444e0e10c1ab5d8881f63ba","src/lib.rs":"bdf23c8a00fb4d51beabeb6600fe45ebf1be618632db885013b6f60a5666c124","src/paddings.rs":"7a18850dab9dca0a3e6cc49d6a94a9566ea2473628f42f726a69f8e07f95872a"},"package":"a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab"}
\ No newline at end of file
+{"files":{"Cargo.toml":"1f13fcd2c3ee3e1a47b5f1519a9840f6fc00a6c9b54ad29697e6120e3756f4b8","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"9e0dfd2dd4173a530e238cb6adb37aa78c34c6bc7444e0e10c1ab5d8881f63ba","src/lib.rs":"13262364125a588d9cd179e1bd24a3286f8778b8d3f11fc86cce605939ebe5b1"},"package":"49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d"}
\ No newline at end of file
--- a/third_party/rust/block-buffer/Cargo.toml
+++ b/third_party/rust/block-buffer/Cargo.toml
@@ -7,21 +7,30 @@
 #
 # 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 = "block-buffer"
-version = "0.3.3"
+version = "0.7.0"
 authors = ["RustCrypto Developers"]
 description = "Fixed size buffer for block processing of data"
 documentation = "https://docs.rs/block-buffer"
-keywords = ["block", "padding", "pkcs7", "ansix923", "iso7816"]
+keywords = ["block", "buffer"]
 categories = ["cryptography", "no-std"]
 license = "MIT/Apache-2.0"
 repository = "https://github.com/RustCrypto/utils"
-[dependencies.arrayref]
+[dependencies.block-padding]
+version = "0.1"
+
+[dependencies.byte-tools]
 version = "0.3"
 
-[dependencies.byte-tools]
-version = "0.2"
+[dependencies.byteorder]
+version = "1"
+default-features = false
+
+[dependencies.generic-array]
+version = "0.12"
+[badges.travis-ci]
+repository = "RustCrypto/utils"
--- a/third_party/rust/block-buffer/src/lib.rs
+++ b/third_party/rust/block-buffer/src/lib.rs
@@ -1,144 +1,170 @@
 #![no_std]
-#[macro_use]
-extern crate arrayref;
+pub extern crate byteorder;
+pub extern crate block_padding;
+pub extern crate generic_array;
 extern crate byte_tools;
 
-use byte_tools::{zero, write_u64_le};
+use byteorder::{ByteOrder, BE};
+use byte_tools::zero;
+use block_padding::{Padding, PadError};
+use generic_array::{GenericArray, ArrayLength};
 
-mod paddings;
-
-pub use paddings::*;
+/// Buffer for block processing of data
+#[derive(Clone, Default)]
+pub struct BlockBuffer<BlockSize: ArrayLength<u8>>  {
+    buffer: GenericArray<u8, BlockSize>,
+    pos: usize,
+}
 
-macro_rules! impl_buffer {
-    ($name:ident, $len:expr) => {
+#[inline(always)]
+unsafe fn cast<N: ArrayLength<u8>>(block: &[u8]) -> &GenericArray<u8, N> {
+    debug_assert_eq!(block.len(), N::to_usize());
+    &*(block.as_ptr() as *const GenericArray<u8, N>)
+}
 
-        pub struct $name {
-            buffer: [u8; $len],
-            pos: usize,
+impl<BlockSize: ArrayLength<u8>> BlockBuffer<BlockSize> {
+    /// Process data in `input` in blocks of size `BlockSize` using function `f`.
+    #[inline]
+    pub fn input<F>(&mut self, mut input: &[u8], mut f: F)
+        where F: FnMut(&GenericArray<u8, BlockSize>)
+    {
+        // If there is already data in the buffer, process it if we have
+        // enough to complete the chunk.
+        let rem = self.remaining();
+        if self.pos != 0 && input.len() >= rem {
+            let (l, r) = input.split_at(rem);
+            input = r;
+            self.buffer[self.pos..].copy_from_slice(l);
+            self.pos = 0;
+            f(&self.buffer);
         }
 
-        impl Copy for $name {}
-
-        impl Clone for $name {
-            fn clone(&self) -> Self {
-                *self
-            }
+        // While we have at least a full buffer size chunks's worth of data,
+        // process that data without copying it into the buffer
+        while input.len() >= self.size() {
+            let (block, r) = input.split_at(self.size());
+            input = r;
+            f(unsafe { cast(block) });
         }
 
-        impl Default for $name {
-            fn default() -> Self {
-                $name {buffer: [0; $len], pos: 0}
-            }
+        // Copy any remaining data into the buffer.
+        self.buffer[self.pos..self.pos+input.len()].copy_from_slice(input);
+        self.pos += input.len();
+    }
+
+    /// Variant that doesn't flush the buffer until there's additional
+    /// data to be processed. Suitable for tweakable block ciphers
+    /// like Threefish that need to know whether a block is the *last*
+    /// data block before processing it.
+    #[inline]
+    pub fn input_lazy<F>(&mut self, mut input: &[u8], mut f: F)
+        where F: FnMut(&GenericArray<u8, BlockSize>)
+    {
+        let rem = self.remaining();
+        if self.pos != 0 && input.len() > rem {
+            let (l, r) = input.split_at(rem);
+            input = r;
+            self.buffer[self.pos..].copy_from_slice(l);
+            self.pos = 0;
+            f(&self.buffer);
+        }
+
+        while input.len() > self.size() {
+            let (block, r) = input.split_at(self.size());
+            input = r;
+            f(unsafe { cast(block) });
         }
 
-        impl $name {
-            #[inline]
-            pub fn input<F: FnMut(&[u8; $len])>(&mut self, mut input: &[u8], mut func: F) {
-                // If there is already data in the buffer, copy as much as we can
-                // into it and process the data if the buffer becomes full.
-                if self.pos != 0 {
-                    let rem = self.remaining();
-
-                    if input.len() >= rem {
-                        let (l, r) = input.split_at(rem);
-                        input = r;
-                        self.buffer[self.pos..].copy_from_slice(l);
-                        self.pos = 0;
-                        func(&self.buffer);
-                    } else {
-                        let end = self.pos + input.len();
-                        self.buffer[self.pos..end].copy_from_slice(input);
-                        self.pos = end;
-                        return;
-                    }
-                }
-
-                // While we have at least a full buffer size chunks's worth of data,
-                // process that data without copying it into the buffer
-                while input.len() >= self.size() {
-                    let (l, r) = input.split_at(self.size());
-                    input = r;
-                    func(array_ref!(l, 0, $len));
-                }
-
-                // Copy any input data into the buffer. At this point in the method,
-                // the ammount of data left in the input vector will be less than
-                // the buffer size and the buffer will be empty.
-                self.buffer[..input.len()].copy_from_slice(input);
-                self.pos = input.len();
-            }
-
-            #[inline]
-            fn digest_pad<F>(&mut self, up_to: usize, func: &mut F)
-                where F: FnMut(&[u8; $len])
-            {
-                self.buffer[self.pos] = 0x80;
-                self.pos += 1;
-
-                zero(&mut self.buffer[self.pos..]);
+        self.buffer[self.pos..self.pos+input.len()].copy_from_slice(input);
+        self.pos += input.len();
+    }
 
-                if self.remaining() < up_to {
-                    func(&self.buffer);
-                    zero(&mut self.buffer[..self.pos]);
-                }
-            }
-
-            #[inline]
-            /// Will pad message with message length in big-endian format
-            pub fn len_padding<F>(&mut self, data_len: u64, mut func: F)
-                where F: FnMut(&[u8; $len])
-            {
-                self.digest_pad(8, &mut func);
-                let s = self.size();
-                write_u64_le(&mut self.buffer[s-8..], data_len);
-                func(&self.buffer);
-                self.pos = 0;
-            }
+    /// Pad buffer with `prefix` and make sure that internall buffer
+    /// has at least `up_to` free bytes. All remaining bytes get
+    /// zeroed-out.
+    #[inline]
+    fn digest_pad<F>(&mut self, up_to: usize, f: &mut F)
+        where F: FnMut(&GenericArray<u8, BlockSize>)
+    {
+        if self.pos == self.size() {
+            f(&self.buffer);
+            self.pos = 0;
+        }
+        self.buffer[self.pos] = 0x80;
+        self.pos += 1;
 
-            #[inline]
-            pub fn len_padding_u128<F>(&mut self, hi: u64, lo: u64, mut func: F)
-                where F: FnMut(&[u8; $len])
-            {
-                self.digest_pad(16, &mut func);
-                let s = self.size();
-                write_u64_le(&mut self.buffer[s-16..s-8], hi);
-                write_u64_le(&mut self.buffer[s-8..], lo);
-                func(&self.buffer);
-                self.pos = 0;
-            }
+        zero(&mut self.buffer[self.pos..]);
 
-            #[inline]
-            pub fn pad_with<P: Padding>(&mut self) -> &mut [u8; $len] {
-                P::pad(&mut self.buffer[..], self.pos);
-                self.pos = 0;
-                &mut self.buffer
-            }
-
-            #[inline]
-            pub fn size(&self) -> usize {
-                $len
-            }
-
-            #[inline]
-            pub fn position(&self) -> usize {
-                self.pos
-            }
-
-            #[inline]
-            pub fn remaining(&self) -> usize {
-                self.size() - self.pos
-            }
+        if self.remaining() < up_to {
+            f(&self.buffer);
+            zero(&mut self.buffer[..self.pos]);
         }
     }
-}
+
+    /// Pad message with 0x80, zeros and 64-bit message length
+    /// in a byte order specified by `B`
+    #[inline]
+    pub fn len64_padding<B, F>(&mut self, data_len: u64, mut f: F)
+        where B: ByteOrder, F: FnMut(&GenericArray<u8, BlockSize>)
+    {
+        // TODO: replace `F` with `impl Trait` on MSRV bump
+        self.digest_pad(8, &mut f);
+        let s = self.size();
+        B::write_u64(&mut self.buffer[s-8..], data_len);
+        f(&self.buffer);
+        self.pos = 0;
+    }
+
+
+    /// Pad message with 0x80, zeros and 128-bit message length
+    /// in the big-endian byte order
+    #[inline]
+    pub fn len128_padding_be<F>(&mut self, hi: u64, lo: u64, mut f: F)
+        where F: FnMut(&GenericArray<u8, BlockSize>)
+    {
+        // TODO: on MSRV bump replace `F` with `impl Trait`, use `u128`, add `B`
+        self.digest_pad(16, &mut f);
+        let s = self.size();
+        BE::write_u64(&mut self.buffer[s-16..s-8], hi);
+        BE::write_u64(&mut self.buffer[s-8..], lo);
+        f(&self.buffer);
+        self.pos = 0;
+    }
 
-impl_buffer!(BlockBuffer128, 16);
-impl_buffer!(BlockBuffer256, 32);
-impl_buffer!(BlockBuffer512, 64);
-impl_buffer!(BlockBuffer1024, 128);
+    /// Pad message with a given padding `P`
+    ///
+    /// Returns `PadError` if internall buffer is full, which can only happen if
+    /// `input_lazy` was used.
+    #[inline]
+    pub fn pad_with<P: Padding>(&mut self)
+        -> Result<&mut GenericArray<u8, BlockSize>, PadError>
+    {
+        P::pad_block(&mut self.buffer[..], self.pos)?;
+        self.pos = 0;
+        Ok(&mut self.buffer)
+    }
+
+    /// Return size of the internall buffer in bytes
+    #[inline]
+    pub fn size(&self) -> usize {
+        BlockSize::to_usize()
+    }
 
-impl_buffer!(BlockBuffer576, 72);
-impl_buffer!(BlockBuffer832, 104);
-impl_buffer!(BlockBuffer1088, 136);
-impl_buffer!(BlockBuffer1152, 144);
-impl_buffer!(BlockBuffer1344, 168);
+    /// Return current cursor position
+    #[inline]
+    pub fn position(&self) -> usize {
+        self.pos
+    }
+
+    /// Return number of remaining bytes in the internall buffer
+    #[inline]
+    pub fn remaining(&self) -> usize {
+        self.size() - self.pos
+    }
+
+    /// Reset buffer by setting cursor position to zero
+    #[inline]
+    pub fn reset(&mut self)  {
+        self.pos = 0
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/block-padding/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{"Cargo.toml":"31334ebd0923996ae8fb76ee87f9b2d75cc9e85c5126ef614e184af56dd96403","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"f7e8ab639afef15573680c97f796166835cbeb3865175882fea41c60d106b733","src/lib.rs":"812d9b3b472539aa4cc78745313d088879aafa8d1baa69872bc1ca8ee5bcfa41"},"package":"4fc4358306e344bf9775d0197fd00d2603e5afb0771bb353538630f022068ea3"}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/block-padding/Cargo.toml
@@ -0,0 +1,26 @@
+# 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 = "block-padding"
+version = "0.1.2"
+authors = ["RustCrypto Developers"]
+description = "Padding and unpadding of messages divided into blocks."
+documentation = "https://docs.rs/block-padding"
+keywords = ["padding", "pkcs7", "ansix923", "iso7816"]
+categories = ["cryptography", "no-std"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/RustCrypto/utils"
+[dependencies.byte-tools]
+version = "0.3"
+[badges.travis-ci]
+repository = "RustCrypto/utils"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/block-padding/LICENSE-APACHE
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/block-padding/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2018 Artyom Pavlov
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/block-padding/src/lib.rs
@@ -0,0 +1,276 @@
+//! Padding and unpadding of messages divided into blocks.
+//!
+//! This crate provides `Padding` trait which provides padding and unpadding
+//! operations. Additionally several common padding schemes are available out
+//! of the box.
+#![no_std]
+#![doc(html_logo_url =
+    "https://raw.githubusercontent.com/RustCrypto/meta/master/logo_small.png")]
+extern crate byte_tools;
+
+use byte_tools::{zero, set};
+
+/// Error for indicating failed padding operation
+#[derive(Clone, Copy, Debug)]
+pub struct PadError;
+
+/// Error for indicating failed unpadding operation
+#[derive(Clone, Copy, Debug)]
+pub struct UnpadError;
+
+/// Trait for padding messages divided into blocks
+pub trait Padding {
+    /// Pads `block` filled with data up to `pos`.
+    ///
+    /// `pos` should be inside of the block and block must not be full, i.e.
+    /// `pos < block.len()` must be true. Otherwise method will return
+    /// `PadError`. Some potentially irreversible padding schemes can allow
+    /// padding of the full block, in this case aforementioned condition is
+    /// relaxed to `pos <= block.len()`.
+    fn pad_block(block: &mut [u8], pos: usize) -> Result<(), PadError>;
+
+    /// Pads message with length `pos` in the provided buffer.
+    ///
+    /// `&buf[..pos]` is percieved as the message, buffer must contain at
+    /// least one block of leftover space, i.e. `buf.len() - pos >= block_size`
+    /// must be true. Otherwise method will return `PadError`.
+    fn pad(buf: &mut [u8], pos: usize, block_size: usize)
+        -> Result<&mut [u8], PadError>
+    {
+        if buf.len() - pos < block_size { Err(PadError)? }
+        if pos % block_size == 0 {
+            Self::pad_block(&mut buf[pos..pos + block_size], 0)?;
+            Ok(&mut buf[..pos+block_size])
+        } else {
+            let bs = block_size * (pos / block_size);
+            Self::pad_block(&mut buf[bs..bs+block_size], pos - bs)?;
+            Ok(&mut buf[..bs+block_size])
+        }
+    }
+
+    /// Unpad given `data` by truncating it according to the used padding.
+    /// In case of the malformed padding will return `UnpadError`
+    fn unpad(data: &[u8]) -> Result<&[u8], UnpadError>;
+}
+
+/// Pad block with zeros.
+///
+/// ```
+/// use block_padding::{ZeroPadding, Padding};
+///
+/// let msg = b"test";
+/// let n = msg.len();
+/// let mut buffer = [0xff; 16];
+/// buffer[..n].copy_from_slice(msg);
+/// let padded_msg = ZeroPadding::pad(&mut buffer, n, 8).unwrap();
+/// assert_eq!(padded_msg, b"test\x00\x00\x00\x00");
+/// assert_eq!(ZeroPadding::unpad(&padded_msg).unwrap(), msg);
+/// ```
+/// ```
+/// # use block_padding::{ZeroPadding, Padding};
+/// # let msg = b"test";
+/// # let n = msg.len();
+/// # let mut buffer = [0xff; 16];
+/// # buffer[..n].copy_from_slice(msg);
+/// let padded_msg = ZeroPadding::pad(&mut buffer, n, 2).unwrap();
+/// assert_eq!(padded_msg, b"test");
+/// assert_eq!(ZeroPadding::unpad(&padded_msg).unwrap(), msg);
+/// ```
+///
+/// Note that zero padding may not be reversible if the original message ends
+/// with one or more zero bytes.
+pub enum ZeroPadding{}
+
+impl Padding for ZeroPadding {
+    fn pad_block(block: &mut [u8], pos: usize) -> Result<(), PadError> {
+        if pos > block.len() { Err(PadError)? }
+        zero(&mut block[pos..]);
+        Ok(())
+    }
+
+    fn pad(buf: &mut [u8], pos: usize, block_size: usize)
+        -> Result<&mut [u8], PadError>
+    {
+        if pos % block_size == 0 {
+            Ok(&mut buf[..pos])
+        } else {
+            let bs = block_size * (pos / block_size);
+            let be = bs + block_size;
+            if buf.len() < be { Err(PadError)? }
+            Self::pad_block(&mut buf[bs..be], pos - bs)?;
+            Ok(&mut buf[..be])
+        }
+    }
+
+    fn unpad(data: &[u8]) -> Result<&[u8], UnpadError> {
+        let mut n = data.len() - 1;
+        while n != 0 {
+            if data[n] != 0 {
+                break;
+            }
+            n -= 1;
+        }
+        Ok(&data[..n+1])
+    }
+}
+
+/// Pad block with bytes with value equal to the number of bytes added.
+///
+/// PKCS#7 described in the [RFC 5652](https://tools.ietf.org/html/rfc5652#section-6.3).
+///
+/// ```
+/// use block_padding::{Pkcs7, Padding};
+///
+/// let msg = b"test";
+/// let n = msg.len();
+/// let mut buffer = [0xff; 16];
+/// buffer[..n].copy_from_slice(msg);
+/// let padded_msg = Pkcs7::pad(&mut buffer, n, 8).unwrap();
+/// assert_eq!(padded_msg, b"test\x04\x04\x04\x04");
+/// assert_eq!(Pkcs7::unpad(&padded_msg).unwrap(), msg);
+/// ```
+/// ```
+/// # use block_padding::{Pkcs7, Padding};
+/// # let msg = b"test";
+/// # let n = msg.len();
+/// # let mut buffer = [0xff; 16];
+/// # buffer[..n].copy_from_slice(msg);
+/// let padded_msg = Pkcs7::pad(&mut buffer, n, 2).unwrap();
+/// assert_eq!(padded_msg, b"test\x02\x02");
+/// assert_eq!(Pkcs7::unpad(&padded_msg).unwrap(), msg);
+/// ```
+/// ```
+/// # use block_padding::{Pkcs7, Padding};
+/// # let buffer = [0xff; 16];
+/// assert!(Pkcs7::unpad(&buffer).is_err());
+/// ```
+///
+/// In addition to conditions stated in the `Padding` trait documentation,
+/// `pad_block` will return `PadError` if `block.len() > 255`, and in case of
+/// `pad` if `block_size > 255`.
+pub enum Pkcs7{}
+
+impl Padding for Pkcs7 {
+    fn pad_block(block: &mut [u8], pos: usize) -> Result<(), PadError> {
+        if block.len() > 255 { Err(PadError)? }
+        if pos >= block.len() { Err(PadError)? }
+        let n = block.len() - pos;
+        set(&mut block[pos..], n as u8);
+        Ok(())
+    }
+
+    fn unpad(data: &[u8]) -> Result<&[u8], UnpadError> {
+        if data.is_empty() { Err(UnpadError)? }
+        let l = data.len();
+        let n = data[l-1];
+        if n == 0 || n as usize > l { Err(UnpadError)? }
+        for v in &data[l-n as usize..l-1] {
+            if *v != n { Err(UnpadError)? }
+        }
+        Ok(&data[..l - n as usize])
+    }
+}
+
+/// Pad block with zeros excpet the last byte which will be set to the number
+/// bytes.
+///
+/// ```
+/// use block_padding::{AnsiX923, Padding};
+///
+/// let msg = b"test";
+/// let n = msg.len();
+/// let mut buffer = [0xff; 16];
+/// buffer[..n].copy_from_slice(msg);
+/// let padded_msg = AnsiX923::pad(&mut buffer, n, 8).unwrap();
+/// assert_eq!(padded_msg, b"test\x00\x00\x00\x04");
+/// assert_eq!(AnsiX923::unpad(&padded_msg).unwrap(), msg);
+/// ```
+/// ```
+/// # use block_padding::{AnsiX923, Padding};
+/// # let msg = b"test";
+/// # let n = msg.len();
+/// # let mut buffer = [0xff; 16];
+/// # buffer[..n].copy_from_slice(msg);
+/// let padded_msg = AnsiX923::pad(&mut buffer, n, 2).unwrap();
+/// assert_eq!(padded_msg, b"test\x00\x02");
+/// assert_eq!(AnsiX923::unpad(&padded_msg).unwrap(), msg);
+/// ```
+/// ```
+/// # use block_padding::{AnsiX923, Padding};
+/// # let buffer = [0xff; 16];
+/// assert!(AnsiX923::unpad(&buffer).is_err());
+/// ```
+///
+/// In addition to conditions stated in the `Padding` trait documentation,
+/// `pad_block` will return `PadError` if `block.len() > 255`, and in case of
+/// `pad` if `block_size > 255`.
+pub enum AnsiX923{}
+
+impl Padding for AnsiX923 {
+    fn pad_block(block: &mut [u8], pos: usize) -> Result<(), PadError>{
+        if block.len() > 255 { Err(PadError)? }
+        if pos >= block.len() { Err(PadError)? }
+        let bs = block.len();
+        zero(&mut block[pos..bs-1]);
+        block[bs-1] = (bs - pos) as u8;
+        Ok(())
+    }
+
+    fn unpad(data: &[u8]) -> Result<&[u8], UnpadError> {
+        if data.is_empty() { Err(UnpadError)? }
+        let l = data.len();
+        let n = data[l-1] as usize;
+        if n == 0 || n > l {
+            return Err(UnpadError)
+        }
+        for v in &data[l-n..l-1] {
+            if *v != 0 { Err(UnpadError)? }
+        }
+        Ok(&data[..l-n])
+    }
+}
+
+/// Pad block with byte sequence `\x80 00...00 00`.
+///
+/// ```
+/// use block_padding::{Iso7816, Padding};
+///
+/// let msg = b"test";
+/// let n = msg.len();
+/// let mut buffer = [0xff; 16];
+/// buffer[..n].copy_from_slice(msg);
+/// let padded_msg = Iso7816::pad(&mut buffer, n, 8).unwrap();
+/// assert_eq!(padded_msg, b"test\x80\x00\x00\x00");
+/// assert_eq!(Iso7816::unpad(&padded_msg).unwrap(), msg);
+/// ```
+/// ```
+/// # use block_padding::{Iso7816, Padding};
+/// # let msg = b"test";
+/// # let n = msg.len();
+/// # let mut buffer = [0xff; 16];
+/// # buffer[..n].copy_from_slice(msg);
+/// let padded_msg = Iso7816::pad(&mut buffer, n, 2).unwrap();
+/// assert_eq!(padded_msg, b"test\x80\x00");
+/// assert_eq!(Iso7816::unpad(&padded_msg).unwrap(), msg);
+/// ```
+pub enum Iso7816{}
+
+impl Padding for Iso7816 {
+    fn pad_block(block: &mut [u8], pos: usize) -> Result<(), PadError> {
+        if pos >= block.len() { Err(PadError)? }
+        block[pos] = 0x80;
+        zero(&mut block[pos+1..]);
+        Ok(())
+    }
+
+    fn unpad(data: &[u8]) -> Result<&[u8], UnpadError> {
+        if data.is_empty() { Err(UnpadError)? }
+        let mut n = data.len() - 1;
+        while n != 0 {
+            if data[n] != 0 { break; }
+            n -= 1;
+        }
+        if data[n] != 0x80 { Err(UnpadError)? }
+        Ok(&data[..n])
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/byte-tools-0.2.0/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{"Cargo.toml":"af6af6ea1dfa296af5dc58986d1afb46952328588069ec0b08723db439e9972d","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"52232c2cee3bb7d8cabe47ef367f1bf8bb607c22bdfca0219d6156cb7f446e9d","src/lib.rs":"9c96cffef7458fc7bd9e4e61270b69d539ff3a9225a0319b7996155c25ff96ab","src/read_single.rs":"3ab78b15754c2a7848a1be871ff6ee2a31a099f8f4f89be44ad210cda0dbcc9a","src/read_slice.rs":"b3790f2fd080db97e239c05c63da123ea375fb9b354dc9cacb859ed9c44f552e","src/write_single.rs":"1cee4f2f5d8690e47840ea7017539ead417a26abc0717137442a6d9d2875afe4","src/write_slice.rs":"de90e6b9cfca67125871bee7cef55c63574b1871a6584e51fc00a97e5877fe69"},"package":"560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40"}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/byte-tools-0.2.0/Cargo.toml
@@ -0,0 +1,21 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "byte-tools"
+version = "0.2.0"
+authors = ["The Rust-Crypto Project Developers"]
+description = "Utility functions for working with bytes"
+documentation = "https://docs.rs/byte-tools"
+keywords = ["bytes"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/RustCrypto/utils"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/byte-tools-0.2.0/LICENSE-APACHE
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/byte-tools-0.2.0/LICENSE-MIT
@@ -0,0 +1,26 @@
+Copyright (c) 2006-2009 Graydon Hoare
+Copyright (c) 2009-2013 Mozilla Foundation
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/byte-tools-0.2.0/src/lib.rs
@@ -0,0 +1,37 @@
+#![no_std]
+use core::ptr;
+
+mod read_single;
+mod write_single;
+mod read_slice;
+mod write_slice;
+
+pub use read_single::*;
+pub use write_single::*;
+pub use read_slice::*;
+pub use write_slice::*;
+
+/// Copy bytes from src to dest
+#[inline]
+pub fn copy_memory(src: &[u8], dst: &mut [u8]) {
+    assert!(dst.len() >= src.len());
+    unsafe {
+        let srcp = src.as_ptr();
+        let dstp = dst.as_mut_ptr();
+        ptr::copy_nonoverlapping(srcp, dstp, src.len());
+    }
+}
+
+/// Zero all bytes in dst
+#[inline]
+pub fn zero(dst: &mut [u8]) {
+    set(dst, 0);
+}
+
+/// Sets all bytes in `dst` equal to `value`
+#[inline]
+pub fn set(dst: &mut [u8], value: u8) {
+    unsafe {
+        ptr::write_bytes(dst.as_mut_ptr(), value, dst.len());
+    }
+}
\ No newline at end of file
rename from third_party/rust/byte-tools/src/read_single.rs
rename to third_party/rust/byte-tools-0.2.0/src/read_single.rs
rename from third_party/rust/byte-tools/src/read_slice.rs
rename to third_party/rust/byte-tools-0.2.0/src/read_slice.rs
rename from third_party/rust/byte-tools/src/write_single.rs
rename to third_party/rust/byte-tools-0.2.0/src/write_single.rs
rename from third_party/rust/byte-tools/src/write_slice.rs
rename to third_party/rust/byte-tools-0.2.0/src/write_slice.rs
--- a/third_party/rust/byte-tools/.cargo-checksum.json
+++ b/third_party/rust/byte-tools/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"af6af6ea1dfa296af5dc58986d1afb46952328588069ec0b08723db439e9972d","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"52232c2cee3bb7d8cabe47ef367f1bf8bb607c22bdfca0219d6156cb7f446e9d","src/lib.rs":"9c96cffef7458fc7bd9e4e61270b69d539ff3a9225a0319b7996155c25ff96ab","src/read_single.rs":"3ab78b15754c2a7848a1be871ff6ee2a31a099f8f4f89be44ad210cda0dbcc9a","src/read_slice.rs":"b3790f2fd080db97e239c05c63da123ea375fb9b354dc9cacb859ed9c44f552e","src/write_single.rs":"1cee4f2f5d8690e47840ea7017539ead417a26abc0717137442a6d9d2875afe4","src/write_slice.rs":"de90e6b9cfca67125871bee7cef55c63574b1871a6584e51fc00a97e5877fe69"},"package":"560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40"}
\ No newline at end of file
+{"files":{"Cargo.toml":"365cb0aa728934d2d9be1c45f2e135c1dc4b2305b20c7f34210c0ab11cadc21c","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"52232c2cee3bb7d8cabe47ef367f1bf8bb607c22bdfca0219d6156cb7f446e9d","src/lib.rs":"c8fb45d44cae0b1094bf8cef5059827b28b490eb14a3865fa536b61241c2c8c4"},"package":"980479e6fde23246dfb54d47580d66b4e99202e7579c5eaa9fe10ecb5ebd2182"}
\ No newline at end of file
--- a/third_party/rust/byte-tools/Cargo.toml
+++ b/third_party/rust/byte-tools/Cargo.toml
@@ -7,15 +7,15 @@
 #
 # 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 = "byte-tools"
-version = "0.2.0"
-authors = ["The Rust-Crypto Project Developers"]
-description = "Utility functions for working with bytes"
+version = "0.3.0"
+authors = ["RustCrypto Developers"]
+description = "Bytes related utility functions"
 documentation = "https://docs.rs/byte-tools"
 keywords = ["bytes"]
 license = "MIT/Apache-2.0"
 repository = "https://github.com/RustCrypto/utils"
--- a/third_party/rust/byte-tools/src/lib.rs
+++ b/third_party/rust/byte-tools/src/lib.rs
@@ -1,37 +1,29 @@
 #![no_std]
 use core::ptr;
 
-mod read_single;
-mod write_single;
-mod read_slice;
-mod write_slice;
-
-pub use read_single::*;
-pub use write_single::*;
-pub use read_slice::*;
-pub use write_slice::*;
-
-/// Copy bytes from src to dest
-#[inline]
-pub fn copy_memory(src: &[u8], dst: &mut [u8]) {
+/// Copy bytes from `src` to `dst`
+///
+/// Panics if `src.len() < dst.len()`
+#[inline(always)]
+pub fn copy(src: &[u8], dst: &mut [u8]) {
     assert!(dst.len() >= src.len());
     unsafe {
-        let srcp = src.as_ptr();
-        let dstp = dst.as_mut_ptr();
-        ptr::copy_nonoverlapping(srcp, dstp, src.len());
+        ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), src.len());
     }
 }
 
-/// Zero all bytes in dst
-#[inline]
+/// Zero all bytes in `dst`
+#[inline(always)]
 pub fn zero(dst: &mut [u8]) {
-    set(dst, 0);
+    unsafe {
+        ptr::write_bytes(dst.as_mut_ptr(), 0, dst.len());
+    }
 }
 
 /// Sets all bytes in `dst` equal to `value`
-#[inline]
+#[inline(always)]
 pub fn set(dst: &mut [u8], value: u8) {
     unsafe {
         ptr::write_bytes(dst.as_mut_ptr(), value, dst.len());
     }
-}
\ No newline at end of file
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/digest-0.7.6/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{"Cargo.toml":"b3667b1e1a3985dd2c9e7873f6945c2d7163ed7da95569f40c2097285a325ec4","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"9e0dfd2dd4173a530e238cb6adb37aa78c34c6bc7444e0e10c1ab5d8881f63ba","src/dev.rs":"c824f834fa8b8c729024e4ec61138e89c26a56bfb6b50295600dddb5ff8fff62","src/digest.rs":"6710ac33c80e6159a2396839794fc76a61b94ab573516a69486457b3e291c793","src/errors.rs":"cff5bf2350bc109ad4f08caacf6780ff1e7016d9995f0847e84e96a8e31ab9d5","src/lib.rs":"bf4e93ebd066513001f3d6d77024ae8addf4df4fd89f76549fd1b73df386f3e4"},"package":"03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90"}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/digest-0.7.6/Cargo.toml
@@ -0,0 +1,32 @@
+# 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 = "digest"
+version = "0.7.6"
+authors = ["RustCrypto Developers"]
+description = "Traits for cryptographic hash functions"
+documentation = "https://docs.rs/digest"
+keywords = ["digest", "crypto", "hash"]
+categories = ["cryptography", "no-std"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/RustCrypto/traits"
+[package.metadata.docs.rs]
+features = ["std"]
+[dependencies.generic-array]
+version = "0.9"
+
+[features]
+dev = []
+std = []
+[badges.travis-ci]
+repository = "RustCrypto/traits"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/digest-0.7.6/LICENSE-APACHE
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/digest-0.7.6/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2017 Artyom Pavlov
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/digest-0.7.6/src/dev.rs
@@ -0,0 +1,171 @@
+use super::{Digest, Input, VariableOutput, ExtendableOutput, XofReader};
+use core::fmt::Debug;
+
+pub struct Test {
+    pub name: &'static str,
+    pub input: &'static [u8],
+    pub output: &'static [u8],
+}
+
+#[macro_export]
+macro_rules! new_tests {
+    ( $( $name:expr ),*  ) => {
+        [$(
+            Test {
+                name: $name,
+                input: include_bytes!(concat!("data/", $name, ".input.bin")),
+                output: include_bytes!(concat!("data/", $name, ".output.bin")),
+            },
+        )*]
+    };
+    ( $( $name:expr ),+, ) => (new_tests!($($name),+))
+}
+
+pub fn main_test<D: Digest + Debug + Clone>(tests: &[Test]) {
+    // Test that it works when accepting the message all at once
+    for t in tests.iter() {
+        let mut sh = D::default();
+        sh.input(t.input);
+
+        let out = sh.result();
+
+        assert_eq!(out[..], t.output[..]);
+    }
+
+    // Test that it works when accepting the message in pieces
+    for t in tests.iter() {
+        let mut sh = D::default();
+        let len = t.input.len();
+        let mut left = len;
+        while left > 0 {
+            let take = (left + 1) / 2;
+            sh.input(&t.input[len - left..take + len - left]);
+            left = left - take;
+        }
+
+        let out = sh.result();
+
+        assert_eq!(out[..], t.output[..]);
+    }
+}
+
+pub fn variable_test<D>(tests: &[Test])
+    where D: Input + VariableOutput + Clone + Debug
+{
+    let mut buf = [0u8; 1024];
+    // Test that it works when accepting the message all at once
+    for t in tests.iter() {
+        let mut sh = D::new(t.output.len()).unwrap();
+        sh.process(t.input);
+
+        let out = sh.variable_result(&mut buf[..t.output.len()]).unwrap();
+
+        assert_eq!(out[..], t.output[..]);
+    }
+
+    // Test that it works when accepting the message in pieces
+    for t in tests.iter() {
+        let mut sh = D::new(t.output.len()).unwrap();
+        let len = t.input.len();
+        let mut left = len;
+        while left > 0 {
+            let take = (left + 1) / 2;
+            sh.process(&t.input[len - left..take + len - left]);
+            left = left - take;
+        }
+
+        let out = sh.variable_result(&mut buf[..t.output.len()]).unwrap();
+
+        assert_eq!(out[..], t.output[..]);
+    }
+}
+
+
+pub fn xof_test<D>(tests: &[Test])
+    where D: Input + ExtendableOutput + Default + Debug + Clone
+{
+    let mut buf = [0u8; 1024];
+    // Test that it works when accepting the message all at once
+    for t in tests.iter() {
+        let mut sh = D::default();
+        sh.process(t.input);
+
+        let out = &mut buf[..t.output.len()];
+        sh.xof_result().read(out);
+
+        assert_eq!(out[..], t.output[..]);
+    }
+
+    // Test that it works when accepting the message in pieces
+    for t in tests.iter() {
+        let mut sh = D::default();
+        let len = t.input.len();
+        let mut left = len;
+        while left > 0 {
+            let take = (left + 1) / 2;
+            sh.process(&t.input[len - left..take + len - left]);
+            left = left - take;
+        }
+
+        let out = &mut buf[..t.output.len()];
+        sh.xof_result().read(out);
+
+        assert_eq!(out[..], t.output[..]);
+    }
+
+    // Test reeading from reader byte by byte
+    for t in tests.iter() {
+        let mut sh = D::default();
+        sh.process(t.input);
+
+        let mut reader = sh.xof_result();
+        let out = &mut buf[..t.output.len()];
+        for chunk in out.chunks_mut(1) {
+            reader.read(chunk);
+        }
+
+        assert_eq!(out[..], t.output[..]);
+    }
+}
+
+pub fn one_million_a<D: Digest + Default + Debug + Clone>(expected: &[u8]) {
+    let mut sh = D::default();
+    for _ in 0..50000 {
+        sh.input(&[b'a'; 10]);
+    }
+    sh.input(&[b'a'; 500000]);
+    let out = sh.result();
+    assert_eq!(out[..], expected[..]);
+}
+
+
+#[macro_export]
+macro_rules! bench_digest {
+    ($name:ident, $engine:path, $bs:expr) => {
+        #[bench]
+        fn $name(b: &mut Bencher) {
+            let mut d = <$engine>::default();
+            let data = [0; $bs];
+
+            b.iter(|| {
+                d.input(&data);
+            });
+
+            b.bytes = $bs;
+        }
+    };
+
+    ($engine:path) => {
+        extern crate test;
+
+        use test::Bencher;
+        use digest::Digest;
+
+        bench_digest!(bench1_16, $engine, 1<<4);
+        bench_digest!(bench2_64, $engine, 1<<6);
+        bench_digest!(bench3_256, $engine, 1<<8);
+        bench_digest!(bench4_1k, $engine, 1<<10);
+        bench_digest!(bench5_4k, $engine, 1<<12);
+        bench_digest!(bench6_16k, $engine, 1<<14);
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/digest-0.7.6/src/digest.rs
@@ -0,0 +1,86 @@
+use super::{Input, BlockInput, FixedOutput};
+use generic_array::GenericArray;
+#[cfg(feature = "std")]
+use std::io;
+
+type Output<N> = GenericArray<u8, N>;
+
+/// The `Digest` trait specifies an interface common for digest functions.
+///
+/// It's a convinience wrapper around `Input`, `FixedOutput`, `BlockInput` and
+/// `Default` traits. It also provides additional convenience methods.
+pub trait Digest: Input + BlockInput + FixedOutput + Default {
+    /// Create new hasher instance
+    fn new() -> Self {
+        Self::default()
+    }
+
+    /// Digest input data. This method can be called repeatedly
+    /// for use with streaming messages.
+    fn input(&mut self, input: &[u8]) {
+        self.process(input);
+    }
+
+    /// Retrieve the digest result. This method consumes digest instance.
+    fn result(self) -> Output<Self::OutputSize> {
+        self.fixed_result()
+    }
+
+    /// Convenience function to compute hash of the `data`. It will handle
+    /// hasher creation, data feeding and finalization.
+    ///
+    /// Example:
+    ///
+    /// ```rust,ignore
+    /// println!("{:x}", sha2::Sha256::digest(b"Hello world"));
+    /// ```
+    #[inline]
+    fn digest(data: &[u8]) -> Output<Self::OutputSize> {
+        let mut hasher = Self::default();
+        hasher.process(data);
+        hasher.fixed_result()
+    }
+
+    /// Convenience function to compute hash of the string. It's equivalent to
+    /// `digest(input_string.as_bytes())`.
+    #[inline]
+    fn digest_str(str: &str) -> Output<Self::OutputSize> {
+        Self::digest(str.as_bytes())
+    }
+
+    /// Convenience function which takes `std::io::Read` as a source and computes
+    /// value of digest function `D`, e.g. SHA-2, SHA-3, BLAKE2, etc. using 1 KB
+    /// blocks.
+    ///
+    /// Usage example:
+    ///
+    /// ```rust,ignore
+    /// use std::fs;
+    /// use sha2::{Sha256, Digest};
+    ///
+    /// let mut file = fs::File::open("Cargo.toml")?;
+    /// let result = Sha256::digest_reader(&mut file)?;
+    /// println!("{:x}", result);
+    /// ```
+    #[cfg(feature = "std")]
+    #[inline]
+    fn digest_reader(source: &mut io::Read)
+        -> io::Result<Output<Self::OutputSize>>
+    {
+        let mut hasher = Self::default();
+
+        let mut buf = [0u8; 8 * 1024];
+
+        loop {
+            let len = match source.read(&mut buf) {
+                Ok(0) => return Ok(hasher.result()),
+                Ok(len) => len,
+                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
+                Err(e) => Err(e)?,
+            };
+            hasher.process(&buf[..len]);
+        }
+    }
+}
+
+impl<D: Input + FixedOutput + BlockInput + Default> Digest for D {}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/digest-0.7.6/src/errors.rs
@@ -0,0 +1,37 @@
+use core::fmt;
+#[cfg(feature = "std")]
+use std::error;
+
+/// The error type for variable hasher initialization
+#[derive(Clone, Copy, Debug, Default)]
+pub struct InvalidOutputSize;
+
+/// The error type for variable hasher result
+#[derive(Clone, Copy, Debug, Default)]
+pub struct InvalidBufferLength;
+
+impl fmt::Display for InvalidOutputSize {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.write_str("invalid output size")
+    }
+}
+
+impl fmt::Display for InvalidBufferLength {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.write_str("invalid buffer length")
+    }
+}
+
+#[cfg(feature = "std")]
+impl error::Error for InvalidOutputSize {
+    fn description(&self) -> &str {
+        "invalid output size"
+    }
+}
+
+#[cfg(feature = "std")]
+impl error::Error for InvalidBufferLength {
+    fn description(&self) -> &str {
+        "invalid buffer size"
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/digest-0.7.6/src/lib.rs
@@ -0,0 +1,98 @@
+//! This crate provides traits for describing funcionality of cryptographic hash
+//! functions.
+//!
+//! By default std functionality in this crate disabled. (e.g. method for
+//! hashing `Read`ers) To enable it turn on `std` feature in your `Cargo.toml`
+//! for this crate.
+#![cfg_attr(not(feature = "std"), no_std)]
+pub extern crate generic_array;
+
+#[cfg(feature = "std")]
+use std as core;
+use generic_array::{GenericArray, ArrayLength};
+
+mod digest;
+mod errors;
+#[cfg(feature = "dev")]
+pub mod dev;
+
+pub use errors::{InvalidOutputSize, InvalidBufferLength};
+pub use digest::Digest;
+
+// `process` is choosen to not overlap with `input` method in the digest trait
+// change it on trait alias stabilization
+
+/// Trait for processing input data
+pub trait Input {
+    /// Digest input data. This method can be called repeatedly
+    /// for use with streaming messages.
+    fn process(&mut self, input: &[u8]);
+}
+
+/// Trait to indicate that digest function processes data in blocks of size
+/// `BlockSize`. Main usage of this trait is for implementing HMAC generically.
+pub trait BlockInput {
+    type BlockSize: ArrayLength<u8>;
+}
+
+/// Trait for returning digest result with the fixed size
+pub trait FixedOutput {
+    type OutputSize: ArrayLength<u8>;
+
+    /// Retrieve the digest result. This method consumes digest instance.
+    fn fixed_result(self) -> GenericArray<u8, Self::OutputSize>;
+}
+
+/// The error type for variable digest output
+#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
+pub struct InvalidLength;
+
+/// Trait for returning digest result with the varaible size
+pub trait VariableOutput: core::marker::Sized {
+    /// Create new hasher instance with given output size. Will return
+    /// `Err(InvalidLength)` in case if hasher can not work with the given
+    /// output size. Will always return an error if output size equals to zero.
+    fn new(output_size: usize) -> Result<Self, InvalidLength>;
+
+    /// Get output size of the hasher instance provided to the `new` method
+    fn output_size(&self) -> usize;
+
+    /// Retrieve the digest result into provided buffer. Length of the buffer
+    /// must be equal to output size provided to the `new` method, otherwise
+    /// `Err(InvalidLength)` will be returned
+    fn variable_result(self, buffer: &mut [u8]) -> Result<&[u8], InvalidLength>;
+}
+
+/// Trait for decribing readers which are used to extract extendable output
+/// from the resulting state of hash function.
+pub trait XofReader {
+    /// Read output into the `buffer`. Can be called unlimited number of times.
+    fn read(&mut self, buffer: &mut [u8]);
+}
+
+/// Trait which describes extendable output (XOF) of hash functions. Using this
+/// trait you first need to get structure which implements `XofReader`, using
+/// which you can read extendable output.
+pub trait ExtendableOutput {
+    type Reader: XofReader;
+
+    /// Finalize hash function and return XOF reader
+    fn xof_result(self) -> Self::Reader;
+}
+
+/// Macro for defining opaque `Debug` implementation. It will use the following
+/// format: "HasherName { ... }". While it's convinient to have it
+/// (e.g. for including in other structs), it could be undesirable to leak
+/// internall state, which can happen for example through uncareful logging.
+#[macro_export]
+macro_rules! impl_opaque_debug {
+    ($state:ty) => {
+        impl ::core::fmt::Debug for $state {
+            fn fmt(&self, f: &mut ::core::fmt::Formatter)
+                -> Result<(), ::core::fmt::Error>
+            {
+                write!(f, concat!(stringify!($state), " {{ ... }}"))
+            }
+        }
+    }
+}
--- a/third_party/rust/digest/.cargo-checksum.json
+++ b/third_party/rust/digest/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"b3667b1e1a3985dd2c9e7873f6945c2d7163ed7da95569f40c2097285a325ec4","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"9e0dfd2dd4173a530e238cb6adb37aa78c34c6bc7444e0e10c1ab5d8881f63ba","src/dev.rs":"c824f834fa8b8c729024e4ec61138e89c26a56bfb6b50295600dddb5ff8fff62","src/digest.rs":"6710ac33c80e6159a2396839794fc76a61b94ab573516a69486457b3e291c793","src/errors.rs":"cff5bf2350bc109ad4f08caacf6780ff1e7016d9995f0847e84e96a8e31ab9d5","src/lib.rs":"bf4e93ebd066513001f3d6d77024ae8addf4df4fd89f76549fd1b73df386f3e4"},"package":"03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90"}
\ No newline at end of file
+{"files":{"Cargo.toml":"fe0caba7c3959c31f8b7a53d6d077a074e399c7604a2b03dfddcce9c0e56a81e","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"9e0dfd2dd4173a530e238cb6adb37aa78c34c6bc7444e0e10c1ab5d8881f63ba","src/dev.rs":"5890305be2cd3d221d1c2ce295b911cc57017dc341966ba434def4a072f8bf1c","src/digest.rs":"73f564cb8084e61baf850948443bacdea81727dfbff5abeb520c0e5bb690da7a","src/dyn_digest.rs":"2b3151c46d09dae2b7b0d0788d7bcc3517fe638c6a3f6fe43e357494de538049","src/errors.rs":"2584007e98d691160313cc27e6237db9bd886e9774137b59a1289a20054e9375","src/lib.rs":"8b336814939efcb1c1157ccadd52d9e4d6c99a84a799af2fe70cc50d05c45a32"},"package":"05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c"}
\ No newline at end of file
--- a/third_party/rust/digest/Cargo.toml
+++ b/third_party/rust/digest/Cargo.toml
@@ -7,26 +7,30 @@
 #
 # 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 = "digest"
-version = "0.7.6"
+version = "0.8.0"
 authors = ["RustCrypto Developers"]
 description = "Traits for cryptographic hash functions"
 documentation = "https://docs.rs/digest"
 keywords = ["digest", "crypto", "hash"]
 categories = ["cryptography", "no-std"]
-license = "MIT/Apache-2.0"
+license = "MIT OR Apache-2.0"
 repository = "https://github.com/RustCrypto/traits"
 [package.metadata.docs.rs]
 features = ["std"]
+[dependencies.blobby]
+version = "0.1"
+optional = true
+
 [dependencies.generic-array]
-version = "0.9"
+version = "0.12"
 
 [features]
-dev = []
+dev = ["blobby"]
 std = []
 [badges.travis-ci]
 repository = "RustCrypto/traits"
--- a/third_party/rust/digest/src/dev.rs
+++ b/third_party/rust/digest/src/dev.rs
@@ -1,171 +1,218 @@
-use super::{Digest, Input, VariableOutput, ExtendableOutput, XofReader};
+use super::{Input, VariableOutput, ExtendableOutput, Reset, XofReader};
 use core::fmt::Debug;
 
-pub struct Test {
-    pub name: &'static str,
-    pub input: &'static [u8],
-    pub output: &'static [u8],
-}
-
 #[macro_export]
-macro_rules! new_tests {
-    ( $( $name:expr ),*  ) => {
-        [$(
-            Test {
-                name: $name,
-                input: include_bytes!(concat!("data/", $name, ".input.bin")),
-                output: include_bytes!(concat!("data/", $name, ".output.bin")),
-            },
-        )*]
-    };
-    ( $( $name:expr ),+, ) => (new_tests!($($name),+))
+macro_rules! new_test {
+    ($name:ident, $test_name:expr, $hasher:ty, $test_func:ident) => {
+        #[test]
+        fn $name() {
+            use digest::blobby::Blob2Iterator;
+            let data = include_bytes!(concat!("data/", $test_name, ".blb"));
+
+            for (i, row) in Blob2Iterator::new(data).unwrap().enumerate() {
+                let input = row[0];
+                let output = row[1];
+                if let Some(desc) = $test_func::<$hasher>(input, output) {
+                    panic!("\n\
+                        Failed test №{}: {}\n\
+                        input:\t{:?}\n\
+                        output:\t{:?}\n",
+                        i, desc, input, output,
+                    );
+                }
+            }
+        }
+    }
 }
 
-pub fn main_test<D: Digest + Debug + Clone>(tests: &[Test]) {
-    // Test that it works when accepting the message all at once
-    for t in tests.iter() {
-        let mut sh = D::default();
-        sh.input(t.input);
-
-        let out = sh.result();
+// module to separate Digest from other traits
+mod foo {
+    use super::super::Digest;
+    use core::fmt::Debug;
 
-        assert_eq!(out[..], t.output[..]);
-    }
+    pub fn digest_test<D>(input: &[u8], output: &[u8]) -> Option<&'static str>
+        where D: Digest + Debug + Clone
+    {
+        let mut hasher = D::new();
+        // Test that it works when accepting the message all at once
+        hasher.input(input);
+        let mut hasher2 = hasher.clone();
+        if hasher.result().as_slice() != output {
+            return Some("whole message");
+        }
 
-    // Test that it works when accepting the message in pieces
-    for t in tests.iter() {
-        let mut sh = D::default();
-        let len = t.input.len();
+        // Test if reset works correctly
+        hasher2.reset();
+        hasher2.input(input);
+        if hasher2.result().as_slice() != output {
+            return Some("whole message after reset");
+        }
+
+        // Test that it works when accepting the message in pieces
+        let mut hasher = D::new();
+        let len = input.len();
         let mut left = len;
         while left > 0 {
             let take = (left + 1) / 2;
-            sh.input(&t.input[len - left..take + len - left]);
+            hasher.input(&input[len - left..take + len - left]);
             left = left - take;
         }
+        if hasher.result().as_slice() != output {
+            return Some("message in pieces");
+        }
 
-        let out = sh.result();
+        // Test processing byte-by-byte
+        let mut hasher = D::new();
+        for chunk in input.chunks(1) {
+            hasher.input(chunk)
+        }
+        if hasher.result().as_slice() != output {
+            return Some("message byte-by-byte");
+        }
+        None
+    }
 
-        assert_eq!(out[..], t.output[..]);
+
+    pub fn one_million_a<D>(expected: &[u8])
+        where D: Digest + Debug + Clone
+    {
+        let mut sh = D::new();
+        for _ in 0..50_000 {
+            sh.input(&[b'a'; 10]);
+        }
+        sh.input(&[b'a'; 500_000][..]);
+        let out = sh.result();
+        assert_eq!(out[..], expected[..]);
     }
 }
 
-pub fn variable_test<D>(tests: &[Test])
-    where D: Input + VariableOutput + Clone + Debug
-{
-    let mut buf = [0u8; 1024];
-    // Test that it works when accepting the message all at once
-    for t in tests.iter() {
-        let mut sh = D::new(t.output.len()).unwrap();
-        sh.process(t.input);
-
-        let out = sh.variable_result(&mut buf[..t.output.len()]).unwrap();
-
-        assert_eq!(out[..], t.output[..]);
-    }
+pub use self::foo::{digest_test, one_million_a};
 
-    // Test that it works when accepting the message in pieces
-    for t in tests.iter() {
-        let mut sh = D::new(t.output.len()).unwrap();
-        let len = t.input.len();
-        let mut left = len;
-        while left > 0 {
-            let take = (left + 1) / 2;
-            sh.process(&t.input[len - left..take + len - left]);
-            left = left - take;
-        }
-
-        let out = sh.variable_result(&mut buf[..t.output.len()]).unwrap();
-
-        assert_eq!(out[..], t.output[..]);
-    }
-}
-
-
-pub fn xof_test<D>(tests: &[Test])
-    where D: Input + ExtendableOutput + Default + Debug + Clone
+pub fn xof_test<D>(input: &[u8], output: &[u8])
+    -> Option<&'static str>
+    where D: Input + ExtendableOutput + Default + Debug + Reset  + Clone
 {
+    let mut hasher = D::default();
     let mut buf = [0u8; 1024];
     // Test that it works when accepting the message all at once
-    for t in tests.iter() {
-        let mut sh = D::default();
-        sh.process(t.input);
+    hasher.input(input);
+
+    let mut hasher2 = hasher.clone();
+    {
+        let out = &mut buf[..output.len()];
+        hasher.xof_result().read(out);
+
+        if out != output { return Some("whole message"); }
+    }
+
+    // Test if hasher resets correctly
+    hasher2.reset();
+    hasher2.input(input);
+
+    {
+        let out = &mut buf[..output.len()];
+        hasher2.xof_result().read(out);
+
+        if out != output { return Some("whole message after reset"); }
+    }
+
+    // Test if hasher accepts message in pieces correctly
+    let mut hasher = D::default();
+    let len = input.len();
+    let mut left = len;
+    while left > 0 {
+        let take = (left + 1) / 2;
+        hasher.input(&input[len - left..take + len - left]);
+        left = left - take;
+    }
 
-        let out = &mut buf[..t.output.len()];
-        sh.xof_result().read(out);
+    {
+        let out = &mut buf[..output.len()];
+        hasher.xof_result().read(out);
+        if out != output { return Some("message in pieces"); }
+    }
+
+    // Test reading from reader byte by byte
+    let mut hasher = D::default();
+    hasher.input(input);
+
+    let mut reader = hasher.xof_result();
+    let out = &mut buf[..output.len()];
+    for chunk in out.chunks_mut(1) {
+        reader.read(chunk);
+    }
 
-        assert_eq!(out[..], t.output[..]);
-    }
+    if out != output { return Some("message in pieces"); }
+    None
+}
+
+pub fn variable_test<D>(input: &[u8], output: &[u8])
+    -> Option<&'static str>
+    where D: Input + VariableOutput  + Reset + Debug + Clone
+{
+    let mut hasher = D::new(output.len()).unwrap();
+    let mut buf = [0u8; 128];
+    let buf = &mut buf[..output.len()];
+    // Test that it works when accepting the message all at once
+    hasher.input(input);
+    let mut hasher2 = hasher.clone();
+    hasher.variable_result(|res| buf.copy_from_slice(res));
+    if buf != output { return Some("whole message"); }
+
+    // Test if reset works correctly
+    hasher2.reset();
+    hasher2.input(input);
+    hasher2.variable_result(|res| buf.copy_from_slice(res));
+    if buf != output { return Some("whole message after reset"); }
 
     // Test that it works when accepting the message in pieces
-    for t in tests.iter() {
-        let mut sh = D::default();
-        let len = t.input.len();
-        let mut left = len;
-        while left > 0 {
-            let take = (left + 1) / 2;
-            sh.process(&t.input[len - left..take + len - left]);
-            left = left - take;
-        }
-
-        let out = &mut buf[..t.output.len()];
-        sh.xof_result().read(out);
-
-        assert_eq!(out[..], t.output[..]);
+    let mut hasher = D::new(output.len()).unwrap();
+    let len = input.len();
+    let mut left = len;
+    while left > 0 {
+        let take = (left + 1) / 2;
+        hasher.input(&input[len - left..take + len - left]);
+        left = left - take;
     }
+    hasher.variable_result(|res| buf.copy_from_slice(res));
+    if buf != output { return Some("message in pieces"); }
 
-    // Test reeading from reader byte by byte
-    for t in tests.iter() {
-        let mut sh = D::default();
-        sh.process(t.input);
-
-        let mut reader = sh.xof_result();
-        let out = &mut buf[..t.output.len()];
-        for chunk in out.chunks_mut(1) {
-            reader.read(chunk);
-        }
-
-        assert_eq!(out[..], t.output[..]);
+    // Test processing byte-by-byte
+    let mut hasher = D::new(output.len()).unwrap();
+    for chunk in input.chunks(1) {
+        hasher.input(chunk)
     }
-}
-
-pub fn one_million_a<D: Digest + Default + Debug + Clone>(expected: &[u8]) {
-    let mut sh = D::default();
-    for _ in 0..50000 {
-        sh.input(&[b'a'; 10]);
-    }
-    sh.input(&[b'a'; 500000]);
-    let out = sh.result();
-    assert_eq!(out[..], expected[..]);
+    hasher.variable_result(|res| buf.copy_from_slice(res));
+    if buf != output { return Some("message byte-by-byte"); }
+    None
 }
 
 
 #[macro_export]
-macro_rules! bench_digest {
+macro_rules! bench {
     ($name:ident, $engine:path, $bs:expr) => {
         #[bench]
         fn $name(b: &mut Bencher) {
             let mut d = <$engine>::default();
             let data = [0; $bs];
 
             b.iter(|| {
-                d.input(&data);
+                d.input(&data[..]);
             });
 
             b.bytes = $bs;
         }
     };
 
     ($engine:path) => {
         extern crate test;
 
         use test::Bencher;
         use digest::Digest;
 
-        bench_digest!(bench1_16, $engine, 1<<4);
-        bench_digest!(bench2_64, $engine, 1<<6);
-        bench_digest!(bench3_256, $engine, 1<<8);
-        bench_digest!(bench4_1k, $engine, 1<<10);
-        bench_digest!(bench5_4k, $engine, 1<<12);
-        bench_digest!(bench6_16k, $engine, 1<<14);
+        bench!(bench1_10,    $engine, 10);
+        bench!(bench2_100,   $engine, 100);
+        bench!(bench3_1000,  $engine, 1000);
+        bench!(bench4_10000, $engine, 10000);
     }
 }
--- a/third_party/rust/digest/src/digest.rs
+++ b/third_party/rust/digest/src/digest.rs
@@ -1,86 +1,86 @@
-use super::{Input, BlockInput, FixedOutput};
-use generic_array::GenericArray;
-#[cfg(feature = "std")]
-use std::io;
-
-type Output<N> = GenericArray<u8, N>;
+use super::{Input, FixedOutput, Reset};
+use generic_array::{GenericArray, ArrayLength};
+use generic_array::typenum::Unsigned;
 
 /// The `Digest` trait specifies an interface common for digest functions.
 ///
-/// It's a convinience wrapper around `Input`, `FixedOutput`, `BlockInput` and
-/// `Default` traits. It also provides additional convenience methods.
-pub trait Digest: Input + BlockInput + FixedOutput + Default {
+/// It's a convenience wrapper around `Input`, `FixedOutput`, `Reset`, `Clone`,
+/// and `Default` traits. It also provides additional convenience methods.
+pub trait Digest {
+    type OutputSize: ArrayLength<u8>;
     /// Create new hasher instance
-    fn new() -> Self {
-        Self::default()
-    }
+    fn new() -> Self;
+
+    /// Digest input data.
+    ///
+    /// This method can be called repeatedly for use with streaming messages.
+    fn input<B: AsRef<[u8]>>(&mut self, data: B);
+
+    /// Digest input data in a chained manner.
+    fn chain<B: AsRef<[u8]>>(self, data: B) -> Self where Self: Sized;
 
-    /// Digest input data. This method can be called repeatedly
-    /// for use with streaming messages.
-    fn input(&mut self, input: &[u8]) {
-        self.process(input);
-    }
+    /// Retrieve result and consume hasher instance.
+    fn result(self) -> GenericArray<u8, Self::OutputSize>;
 
-    /// Retrieve the digest result. This method consumes digest instance.
-    fn result(self) -> Output<Self::OutputSize> {
-        self.fixed_result()
-    }
+    /// Retrieve result and reset hasher instance.
+    ///
+    /// This method sometimes can be more efficient compared to hasher
+    /// re-creation.
+    fn result_reset(&mut self) -> GenericArray<u8, Self::OutputSize>;
+
+    /// Reset hasher instance to its initial state.
+    fn reset(&mut self);
+
+    /// Get output size of the hasher
+    fn output_size() -> usize;
 
     /// Convenience function to compute hash of the `data`. It will handle
     /// hasher creation, data feeding and finalization.
     ///
     /// Example:
     ///
     /// ```rust,ignore
     /// println!("{:x}", sha2::Sha256::digest(b"Hello world"));
     /// ```
-    #[inline]
-    fn digest(data: &[u8]) -> Output<Self::OutputSize> {
-        let mut hasher = Self::default();
-        hasher.process(data);
-        hasher.fixed_result()
+    fn digest(data: &[u8]) -> GenericArray<u8, Self::OutputSize>;
+}
+
+impl<D: Input + FixedOutput + Reset + Clone + Default> Digest for D {
+    type OutputSize = <Self as FixedOutput>::OutputSize;
+
+    fn new() -> Self {
+        Self::default()
     }
 
-    /// Convenience function to compute hash of the string. It's equivalent to
-    /// `digest(input_string.as_bytes())`.
-    #[inline]
-    fn digest_str(str: &str) -> Output<Self::OutputSize> {
-        Self::digest(str.as_bytes())
+    fn input<B: AsRef<[u8]>>(&mut self, data: B) {
+        Input::input(self, data);
+    }
+
+    fn chain<B: AsRef<[u8]>>(self, data: B) -> Self where Self: Sized {
+        Input::chain(self, data)
     }
 
-    /// Convenience function which takes `std::io::Read` as a source and computes
-    /// value of digest function `D`, e.g. SHA-2, SHA-3, BLAKE2, etc. using 1 KB
-    /// blocks.
-    ///
-    /// Usage example:
-    ///
-    /// ```rust,ignore
-    /// use std::fs;
-    /// use sha2::{Sha256, Digest};
-    ///
-    /// let mut file = fs::File::open("Cargo.toml")?;
-    /// let result = Sha256::digest_reader(&mut file)?;
-    /// println!("{:x}", result);
-    /// ```
-    #[cfg(feature = "std")]
-    #[inline]
-    fn digest_reader(source: &mut io::Read)
-        -> io::Result<Output<Self::OutputSize>>
-    {
+    fn result(self) -> GenericArray<u8, Self::OutputSize> {
+        self.fixed_result()
+    }
+
+    fn result_reset(&mut self) -> GenericArray<u8, Self::OutputSize> {
+        let res = self.clone().fixed_result();
+        self.reset();
+        res
+    }
+
+    fn reset(&mut self) {
+        <Self as Reset>::reset(self)
+    }
+
+    fn output_size() -> usize {
+        Self::OutputSize::to_usize()
+    }
+
+    fn digest(data: &[u8]) -> GenericArray<u8, Self::OutputSize> {
         let mut hasher = Self::default();
-
-        let mut buf = [0u8; 8 * 1024];
-
-        loop {
-            let len = match source.read(&mut buf) {
-                Ok(0) => return Ok(hasher.result()),
-                Ok(len) => len,
-                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
-                Err(e) => Err(e)?,
-            };
-            hasher.process(&buf[..len]);
-        }
+        Input::input(&mut hasher, data);
+        hasher.fixed_result()
     }
 }
-
-impl<D: Input + FixedOutput + BlockInput + Default> Digest for D {}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/digest/src/dyn_digest.rs
@@ -0,0 +1,56 @@
+#![cfg(feature = "std")]
+use std::boxed::Box;
+
+use super::{Input, FixedOutput, Reset};
+use generic_array::typenum::Unsigned;
+
+/// The `DynDigest` trait is a modification of `Digest` trait suitable
+/// for trait objects.
+pub trait DynDigest {
+    /// Digest input data.
+    ///
+    /// This method can be called repeatedly for use with streaming messages.
+    fn input(&mut self, data: &[u8]);
+
+    /// Retrieve result and reset hasher instance
+    fn result_reset(&mut self) -> Box<[u8]>;
+
+    /// Retrieve result and consume boxed hasher instance
+    fn result(self: Box<Self>) -> Box<[u8]>;
+
+    /// Reset hasher instance to its initial state.
+    fn reset(&mut self);
+
+    /// Get output size of the hasher
+    fn output_size(&self) -> usize;
+}
+
+impl<D: Input + FixedOutput + Reset + Clone> DynDigest for D {
+    /// Digest input data.
+    ///
+    /// This method can be called repeatedly for use with streaming messages.
+    fn input(&mut self, data: &[u8]) {
+        Input::input(self, data);
+    }
+
+    /// Retrieve result and reset hasher instance
+    fn result_reset(&mut self) -> Box<[u8]> {
+        let res = self.clone().fixed_result().to_vec().into_boxed_slice();
+        Reset::reset(self);
+        res
+    }
+
+    /// Retrieve result and consume boxed hasher instance
+    fn result(self: Box<Self>) -> Box<[u8]> {
+        self.fixed_result().to_vec().into_boxed_slice()
+    }
+
+    fn reset(&mut self) {
+        Reset::reset(self);
+    }
+
+    /// Get output size of the hasher
+    fn output_size(&self) -> usize {
+        <Self as FixedOutput>::OutputSize::to_usize()
+    }
+}
--- a/third_party/rust/digest/src/errors.rs
+++ b/third_party/rust/digest/src/errors.rs
@@ -1,37 +1,20 @@
 use core::fmt;
 #[cfg(feature = "std")]
 use std::error;
 
 /// The error type for variable hasher initialization
 #[derive(Clone, Copy, Debug, Default)]
 pub struct InvalidOutputSize;
 
-/// The error type for variable hasher result
-#[derive(Clone, Copy, Debug, Default)]
-pub struct InvalidBufferLength;
-
 impl fmt::Display for InvalidOutputSize {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.write_str("invalid output size")
     }
 }
 
-impl fmt::Display for InvalidBufferLength {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.write_str("invalid buffer length")
-    }
-}
-
 #[cfg(feature = "std")]
 impl error::Error for InvalidOutputSize {
     fn description(&self) -> &str {
         "invalid output size"
     }
 }
-
-#[cfg(feature = "std")]
-impl error::Error for InvalidBufferLength {
-    fn description(&self) -> &str {
-        "invalid buffer size"
-    }
-}
--- a/third_party/rust/digest/src/lib.rs
+++ b/third_party/rust/digest/src/lib.rs
@@ -1,98 +1,141 @@
-//! This crate provides traits for describing funcionality of cryptographic hash
+//! This crate provides traits which describe funcionality of cryptographic hash
 //! functions.
 //!
-//! By default std functionality in this crate disabled. (e.g. method for
-//! hashing `Read`ers) To enable it turn on `std` feature in your `Cargo.toml`
-//! for this crate.
-#![cfg_attr(not(feature = "std"), no_std)]
+//! Traits in this repository can be separatedin two levels:
+//! - Low level traits: `Input`, `BlockInput`, `Reset`, `FixedOutput`,
+//! `VariableOutput`, `ExtendableOutput`. These traits atomically describe
+//! available functionality of hash function implementations.
+//! - Convinience trait: `Digest`, `DynDigest`. They are wrappers around
+//! low level traits for most common hash-function use-cases.
+//!
+//! Additionally hash functions implement traits from `std`: `Default`, `Clone`,
+//! `Write`. (the latter depends on enabled-by-default `std` crate feature)
+//!
+//! The `Digest` trait is the most commonly used trait.
+#![no_std]
+#![doc(html_logo_url =
+    "https://raw.githubusercontent.com/RustCrypto/meta/master/logo_small.png")]
 pub extern crate generic_array;
-
 #[cfg(feature = "std")]
-use std as core;
+#[macro_use] extern crate std;
+#[cfg(feature = "dev")]
+pub extern crate blobby;
 use generic_array::{GenericArray, ArrayLength};
+#[cfg(feature = "std")]
+use std::vec::Vec;
 
 mod digest;
+mod dyn_digest;
 mod errors;
 #[cfg(feature = "dev")]
 pub mod dev;
 
-pub use errors::{InvalidOutputSize, InvalidBufferLength};
+pub use errors::InvalidOutputSize;
 pub use digest::Digest;
-
-// `process` is choosen to not overlap with `input` method in the digest trait
-// change it on trait alias stabilization
+#[cfg(feature = "std")]
+pub use dyn_digest::DynDigest;
 
 /// Trait for processing input data
 pub trait Input {
-    /// Digest input data. This method can be called repeatedly
-    /// for use with streaming messages.
-    fn process(&mut self, input: &[u8]);
+    /// Digest input data.
+    ///
+    /// This method can be called repeatedly, e.g. for processing streaming
+    /// messages.
+    fn input<B: AsRef<[u8]>>(&mut self, data: B);
+
+    /// Digest input data in a chained manner.
+    fn chain<B: AsRef<[u8]>>(mut self, data: B) -> Self where Self: Sized {
+        self.input(data);
+        self
+    }
 }
 
 /// Trait to indicate that digest function processes data in blocks of size
-/// `BlockSize`. Main usage of this trait is for implementing HMAC generically.
+/// `BlockSize`.
+///
+/// The main usage of this trait is for implementing HMAC generically.
 pub trait BlockInput {
     type BlockSize: ArrayLength<u8>;
 }
 
 /// Trait for returning digest result with the fixed size
 pub trait FixedOutput {
     type OutputSize: ArrayLength<u8>;
 
-    /// Retrieve the digest result. This method consumes digest instance.
+    /// Retrieve result and consume hasher instance.
     fn fixed_result(self) -> GenericArray<u8, Self::OutputSize>;
 }
 
-/// The error type for variable digest output
-#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
-pub struct InvalidLength;
-
 /// Trait for returning digest result with the varaible size
 pub trait VariableOutput: core::marker::Sized {
-    /// Create new hasher instance with given output size. Will return
-    /// `Err(InvalidLength)` in case if hasher can not work with the given
-    /// output size. Will always return an error if output size equals to zero.
-    fn new(output_size: usize) -> Result<Self, InvalidLength>;
+    /// Create new hasher instance with the given output size.
+    ///
+    /// It will return `Err(InvalidOutputSize)` in case if hasher can not return
+    /// specified output size. It will always return an error if output size
+    /// equals to zero.
+    fn new(output_size: usize) -> Result<Self, InvalidOutputSize>;
 
     /// Get output size of the hasher instance provided to the `new` method
     fn output_size(&self) -> usize;
 
-    /// Retrieve the digest result into provided buffer. Length of the buffer
-    /// must be equal to output size provided to the `new` method, otherwise
-    /// `Err(InvalidLength)` will be returned
-    fn variable_result(self, buffer: &mut [u8]) -> Result<&[u8], InvalidLength>;
+    /// Retrieve result via closure and consume hasher.
+    ///
+    /// Closure is guaranteed to be called, length of the buffer passed to it
+    /// will be equal to `output_size`.
+    fn variable_result<F: FnOnce(&[u8])>(self, f: F);
+
+    /// Retrieve result into vector and consume hasher.
+    #[cfg(feature = "std")]
+    fn vec_result(self) -> Vec<u8> {
+        let mut buf = Vec::with_capacity(self.output_size());
+        self.variable_result(|res| buf.extend_from_slice(res));
+        buf
+    }
 }
 
 /// Trait for decribing readers which are used to extract extendable output
-/// from the resulting state of hash function.
+/// from XOF (extendable-output function) result.
 pub trait XofReader {
     /// Read output into the `buffer`. Can be called unlimited number of times.
     fn read(&mut self, buffer: &mut [u8]);
 }
 
-/// Trait which describes extendable output (XOF) of hash functions. Using this
-/// trait you first need to get structure which implements `XofReader`, using
-/// which you can read extendable output.
-pub trait ExtendableOutput {
+/// Trait which describes extendable-output functions (XOF).
+pub trait ExtendableOutput: core::marker::Sized {
     type Reader: XofReader;
 
-    /// Finalize hash function and return XOF reader
+    /// Retrieve XOF reader and consume hasher instance.
     fn xof_result(self) -> Self::Reader;
+
+    /// Retrieve result into vector of specified length.
+    #[cfg(feature = "std")]
+    fn vec_result(self, n: usize) -> Vec<u8> {
+        let mut buf = vec![0u8; n];
+        self.xof_result().read(&mut buf);
+        buf
+    }
 }
 
-/// Macro for defining opaque `Debug` implementation. It will use the following
-/// format: "HasherName { ... }". While it's convinient to have it
-/// (e.g. for including in other structs), it could be undesirable to leak
-/// internall state, which can happen for example through uncareful logging.
+/// Trait for resetting hash instances
+pub trait Reset {
+    /// Reset hasher instance to its initial state and return current state.
+    fn reset(&mut self);
+}
+
 #[macro_export]
-macro_rules! impl_opaque_debug {
-    ($state:ty) => {
-        impl ::core::fmt::Debug for $state {
-            fn fmt(&self, f: &mut ::core::fmt::Formatter)
-                -> Result<(), ::core::fmt::Error>
-            {
-                write!(f, concat!(stringify!($state), " {{ ... }}"))
+/// Implements `std::io::Write` trait for implementator of `Input`
+macro_rules! impl_write {
+    ($hasher:ident) => {
+        #[cfg(feature = "std")]
+        impl ::std::io::Write for $hasher {
+            fn write(&mut self, buf: &[u8]) -> ::std::io::Result<usize> {
+                Input::input(self, buf);
+                Ok(buf.len())
+            }
+
+            fn flush(&mut self) -> ::std::io::Result<()> {
+                Ok(())
             }
         }
     }
 }
new file mode 100644
--- /dev/null
+++ b/third_party/rust/generic-array-0.9.0/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{"Cargo.toml":"87ff65d640c137c26d338f96e21e769af1e1b2e7fa615b40a1bcc755448bb118","LICENSE":"ad4fcfaf8d5b12b97409c137a03d4a4e4b21024c65c54f976cc3b609c1bd5b0f","README.md":"9a1a45416eac57050036b13df6ec84d21d555e820726af3c782896bd9d37d94b","rustfmt.toml":"2a298b4ce1fe6e16b8f281a0035567b8eb15042ed3062729fd28224f29c2f75a","src/arr.rs":"cc1ea0a9ef6a524b90767cc8a89f6b939394a2948a645ed313c0bf5ce5a258a4","src/hex.rs":"bfbf304fb4dea6f7edc0569b38bf2ac7657ce089c5761891321722509e3b5076","src/impl_serde.rs":"805885478728b3c205b842d46deb377b7dd6dd4c4c50254064431f49f0981a2a","src/impls.rs":"8c54e294a82a2bf344bdcb9949b8a84903fb65698d6b1b1e0ab9f5e7847be64f","src/iter.rs":"e52217f04d0dc046f13ef2e3539b90eabd4d55bb85cf40f76ba0bf86d5e55ef0","src/lib.rs":"da93fa505eee94b40fce0fe98e26ed3bb4d2bc4d4869af01598b6e54fc9c0f8d","tests/hex.rs":"e909bc0564e7d52c5fcf172dfc0fac7085010c6a21d38581bf73a54ab2e256e1","tests/import_name.rs":"1235729ecbde47fc9a38b3bf35c750a53ed55e3cf967c9d2b24fd759dc9e9e0c","tests/mod.rs":"f4100c5338906c038636f98f4d2b3d272f59580662afa89d915eafb96d7bbcf9"},"package":"ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d"}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/generic-array-0.9.0/Cargo.toml
@@ -0,0 +1,32 @@
+# 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 = "generic-array"
+version = "0.9.0"
+authors = ["Bartłomiej Kamiński <fizyk20@gmail.com>"]
+description = "Generic types implementing functionality of arrays"
+documentation = "http://fizyk20.github.io/generic-array/generic_array/"
+license = "MIT"
+repository = "https://github.com/fizyk20/generic-array.git"
+
+[lib]
+name = "generic_array"
+[dependencies.typenum]
+version = "1.9"
+
+[dependencies.serde]
+version = "1.0"
+optional = true
+default-features = false
+[dev-dependencies.serde_json]
+version = "1.0"
new file mode 100644
--- /dev/null
+++ b/third_party/rust/generic-array-0.9.0/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Bartłomiej Kamiński
+
+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.
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/generic-array-0.9.0/README.md
@@ -0,0 +1,34 @@
+[![Crates.io](https://img.shields.io/crates/v/generic-array.svg)](https://crates.io/crates/generic-array)
+[![Build Status](https://travis-ci.org/fizyk20/generic-array.svg?branch=master)](https://travis-ci.org/fizyk20/generic-array)
+# generic-array
+
+This crate implements generic array types for Rust.
+
+[Documentation](http://fizyk20.github.io/generic-array/generic_array/)
+
+## Usage
+
+The Rust arrays `[T; N]` are problematic in that they can't be used generically with respect to `N`, so for example this won't work:
+
+```rust
+struct Foo<N> {
+	data: [i32; N]
+}
+```
+
+**generic-array** defines a new trait `ArrayLength<T>` and a struct `GenericArray<T, N: ArrayLength<T>>`, which let the above be implemented as:
+
+```rust
+struct Foo<N: ArrayLength<i32>> {
+	data: GenericArray<i32, N>
+}
+```
+
+To actually define a type implementing `ArrayLength`, you can use unsigned integer types defined in [typenum](https://github.com/paholg/typenum) crate - for example, `GenericArray<T, U5>` would work almost like `[T; 5]` :)
+
+In version 0.1.1 an `arr!` macro was introduced, allowing for creation of arrays as shown below:
+
+```rust
+let array = arr![u32; 1, 2, 3];
+assert_eq!(array[2], 3);
+```
new file mode 100644
--- /dev/null
+++ b/third_party/rust/generic-array-0.9.0/rustfmt.toml
@@ -0,0 +1,3 @@
+reorder_imports = true
+reorder_imported_names = true
+use_try_shorthand = true
new file mode 100644
--- /dev/null
+++ b/third_party/rust/generic-array-0.9.0/src/arr.rs
@@ -0,0 +1,57 @@
+//! Implementation for `arr!` macro.
+
+use super::ArrayLength;
+use core::ops::Add;
+use typenum::U1;
+
+/// Helper trait for `arr!` macro
+pub trait AddLength<T, N: ArrayLength<T>>: ArrayLength<T> {
+    /// Resulting length
+    type Output: ArrayLength<T>;
+}
+
+impl<T, N1, N2> AddLength<T, N2> for N1
+where
+    N1: ArrayLength<T> + Add<N2>,
+    N2: ArrayLength<T>,
+    <N1 as Add<N2>>::Output: ArrayLength<T>,
+{
+    type Output = <N1 as Add<N2>>::Output;
+}
+
+/// Helper type for `arr!` macro
+pub type Inc<T, U> = <U as AddLength<T, U1>>::Output;
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! arr_impl {
+    ($T:ty; $N:ty, [$($x:expr),*], []) => ({
+	unsafe { $crate::transmute::<_, $crate::GenericArray<$T, $N>>([$($x),*]) }
+    });
+    ($T:ty; $N:ty, [], [$x1:expr]) => (
+        arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1 as $T], [])
+    );
+    ($T:ty; $N:ty, [], [$x1:expr, $($x:expr),+]) => (
+        arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1 as $T], [$($x),*])
+    );
+    ($T:ty; $N:ty, [$($y:expr),+], [$x1:expr]) => (
+        arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),*, $x1 as $T], [])
+    );
+    ($T:ty; $N:ty, [$($y:expr),+], [$x1:expr, $($x:expr),+]) => (
+        arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),*, $x1 as $T], [$($x),*])
+    );
+}
+
+/// Macro allowing for easy generation of Generic Arrays.
+/// Example: `let test = arr![u32; 1, 2, 3];`
+#[macro_export]
+macro_rules! arr {
+    ($T:ty;) => ({
+        unsafe { $crate::transmute::<[$T; 0], $crate::GenericArray<$T, $crate::typenum::U0>>([]) }
+    });
+    ($T:ty; $($x:expr),*) => (
+        arr_impl!($T; $crate::typenum::U0, [], [$($x),*])
+    );
+    ($($x:expr,)+) => (arr![$($x),*]);
+    () => ("""Macro requires a type, e.g. `let array = arr![u32; 1, 2, 3];`")
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/generic-array-0.9.0/src/hex.rs
@@ -0,0 +1,101 @@
+//! Generic array are commonly used as a return value for hash digests, so
+//! it's a good idea to allow to hexlify them easily. This module implements
+//! `std::fmt::LowerHex` and `std::fmt::UpperHex` traits.
+//!
+//! Example:
+//!
+//! ```rust
+//! # #[macro_use]
+//! # extern crate generic_array;
+//! # extern crate typenum;
+//! # fn main() {
+//! let array = arr![u8; 10, 20, 30];
+//! assert_eq!(format!("{:x}", array), "0a141e");
+//! # }
+//! ```
+//!
+
+use {ArrayLength, GenericArray};
+use core::fmt;
+use core::ops::Add;
+use core::str;
+use typenum::*;
+
+static LOWER_CHARS: &'static [u8] = b"0123456789abcdef";
+static UPPER_CHARS: &'static [u8] = b"0123456789ABCDEF";
+
+impl<T: ArrayLength<u8>> fmt::LowerHex for GenericArray<u8, T>
+where
+    T: Add<T>,
+    <T as Add<T>>::Output: ArrayLength<u8>,
+{
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let max_digits = f.precision().unwrap_or_else(|| self.len());
+
+        if T::to_usize() < 1024 {
+            // For small arrays use a stack allocated
+            // buffer of 2x number of bytes
+            let mut res = GenericArray::<u8, Sum<T, T>>::default();
+
+            for (i, c) in self.iter().take(max_digits).enumerate() {
+                res[i * 2] = LOWER_CHARS[(c >> 4) as usize];
+                res[i * 2 + 1] = LOWER_CHARS[(c & 0xF) as usize];
+            }
+            f.write_str(
+                unsafe { str::from_utf8_unchecked(&res[..max_digits * 2]) },
+            )?;
+        } else {
+            // For large array use chunks of up to 1024 bytes (2048 hex chars)
+            let mut buf = [0u8; 2048];
+
+            for chunk in self[..max_digits].chunks(1024) {
+                for (i, c) in chunk.iter().enumerate() {
+                    buf[i * 2] = LOWER_CHARS[(c >> 4) as usize];
+                    buf[i * 2 + 1] = LOWER_CHARS[(c & 0xF) as usize];
+                }
+                f.write_str(unsafe {
+                    str::from_utf8_unchecked(&buf[..chunk.len() * 2])
+                })?;
+            }
+        }
+        Ok(())
+    }
+}
+
+impl<T: ArrayLength<u8>> fmt::UpperHex for GenericArray<u8, T>
+where
+    T: Add<T>,
+    <T as Add<T>>::Output: ArrayLength<u8>,
+{
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let max_digits = f.precision().unwrap_or_else(|| self.len());
+
+        if T::to_usize() < 1024 {
+            // For small arrays use a stack allocated
+            // buffer of 2x number of bytes
+            let mut res = GenericArray::<u8, Sum<T, T>>::default();
+
+            for (i, c) in self.iter().take(max_digits).enumerate() {
+                res[i * 2] = UPPER_CHARS[(c >> 4) as usize];
+                res[i * 2 + 1] = UPPER_CHARS[(c & 0xF) as usize];
+            }
+            f.write_str(
+                unsafe { str::from_utf8_unchecked(&res[..max_digits * 2]) },
+            )?;
+        } else {
+            // For large array use chunks of up to 1024 bytes (2048 hex chars)
+            let mut buf = [0u8; 2048];
+
+            for chunk in self[..max_digits].chunks(1024) {
+                for (i, c) in chunk.iter().enumerate() {
+                    buf[i * 2] = UPPER_CHARS[(c >> 4) as usize];
+                    buf[i * 2 + 1] = UPPER_CHARS[(c & 0xF) as usize];
+                }
+                f.write_str(unsafe {
+                    str::from_utf8_unchecked(&buf[..chunk.len() * 2])
+                })?;
+            }
+        }
+        Ok(())
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/generic-array-0.9.0/src/impl_serde.rs
@@ -0,0 +1,68 @@
+//! Serde serialization/deserialization implementation
+
+use {ArrayLength, GenericArray};
+use core::fmt;
+use core::marker::PhantomData;
+use serde::{Deserialize, Deserializer, Serialize, Serializer};
+use serde::de::{self, SeqAccess, Visitor};
+
+impl<T, N> Serialize for GenericArray<T, N>
+where
+    T: Serialize,
+    N: ArrayLength<T>,
+{
+    #[inline]
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        serializer.collect_seq(self.iter())
+    }
+}
+
+struct GAVisitor<T, N> {
+    _t: PhantomData<T>,
+    _n: PhantomData<N>,
+}
+
+impl<'de, T, N> Visitor<'de> for GAVisitor<T, N>
+where
+    T: Deserialize<'de> + Default,
+    N: ArrayLength<T>,
+{
+    type Value = GenericArray<T, N>;
+
+    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        formatter.write_str("struct GenericArray")
+    }
+
+    fn visit_seq<A>(self, mut seq: A) -> Result<GenericArray<T, N>, A::Error>
+    where
+        A: SeqAccess<'de>,
+    {
+        let mut result = GenericArray::default();
+        for i in 0..N::to_usize() {
+            result[i] = seq.next_element()?.ok_or_else(
+                || de::Error::invalid_length(i, &self),
+            )?;
+        }
+        Ok(result)
+    }
+}
+
+impl<'de, T, N> Deserialize<'de> for GenericArray<T, N>
+where
+    T: Deserialize<'de> + Default,
+    N: ArrayLength<T>,
+{
+    fn deserialize<D>(deserializer: D) -> Result<GenericArray<T, N>, D::Error>
+    where
+        D: Deserializer<'de>,
+    {
+        let visitor = GAVisitor {
+            _t: PhantomData,
+            _n: PhantomData,
+        };
+        deserializer.deserialize_seq(visitor)
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/generic-array-0.9.0/src/impls.rs
@@ -0,0 +1,171 @@
+use super::{ArrayLength, GenericArray};
+use core::borrow::{Borrow, BorrowMut};
+use core::cmp::Ordering;
+use core::fmt::{self, Debug};
+use core::hash::{Hash, Hasher};
+
+impl<T: Default, N> Default for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    #[inline]
+    fn default() -> Self {
+        Self::generate(|_| T::default())
+    }
+}
+
+impl<T: Clone, N> Clone for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn clone(&self) -> GenericArray<T, N> {
+        self.map_ref(|x| x.clone())
+    }
+}
+
+impl<T: Copy, N> Copy for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+    N::ArrayType: Copy,
+{
+}
+
+impl<T: PartialEq, N> PartialEq for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn eq(&self, other: &Self) -> bool {
+        **self == **other
+    }
+}
+impl<T: Eq, N> Eq for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+}
+
+impl<T: PartialOrd, N> PartialOrd for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn partial_cmp(&self, other: &GenericArray<T, N>) -> Option<Ordering> {
+        PartialOrd::partial_cmp(self.as_slice(), other.as_slice())
+    }
+}
+
+impl<T: Ord, N> Ord for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn cmp(&self, other: &GenericArray<T, N>) -> Ordering {
+        Ord::cmp(self.as_slice(), other.as_slice())
+    }
+}
+
+impl<T: Debug, N> Debug for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        self[..].fmt(fmt)
+    }
+}
+
+impl<T, N> Borrow<[T]> for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn borrow(&self) -> &[T] {
+        &self[..]
+    }
+}
+
+impl<T, N> BorrowMut<[T]> for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn borrow_mut(&mut self) -> &mut [T] {
+        &mut self[..]
+    }
+}
+
+impl<T, N> AsRef<[T]> for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn as_ref(&self) -> &[T] {
+        &self[..]
+    }
+}
+
+impl<T, N> AsMut<[T]> for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn as_mut(&mut self) -> &mut [T] {
+        &mut self[..]
+    }
+}
+
+impl<T: Hash, N> Hash for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn hash<H>(&self, state: &mut H)
+    where
+        H: Hasher,
+    {
+        Hash::hash(&self[..], state)
+    }
+}
+
+macro_rules! impl_from {
+    ($($n: expr => $ty: ty),*) => {
+        $(
+            impl<T> From<[T; $n]> for GenericArray<T, $ty> {
+                fn from(arr: [T; $n]) -> Self {
+                    use core::mem::{forget, transmute_copy};
+                    let x = unsafe { transmute_copy(&arr) };
+                    forget(arr);
+                    x
+                }
+            }
+        )*
+
+    }
+}
+
+impl_from! {
+    1  => ::typenum::U1,
+    2  => ::typenum::U2,
+    3  => ::typenum::U3,
+    4  => ::typenum::U4,
+    5  => ::typenum::U5,
+    6  => ::typenum::U6,
+    7  => ::typenum::U7,
+    8  => ::typenum::U8,
+    9  => ::typenum::U9,
+    10 => ::typenum::U10,
+    11 => ::typenum::U11,
+    12 => ::typenum::U12,
+    13 => ::typenum::U13,
+    14 => ::typenum::U14,
+    15 => ::typenum::U15,
+    16 => ::typenum::U16,
+    17 => ::typenum::U17,
+    18 => ::typenum::U18,
+    19 => ::typenum::U19,
+    20 => ::typenum::U20,
+    21 => ::typenum::U21,
+    22 => ::typenum::U22,
+    23 => ::typenum::U23,
+    24 => ::typenum::U24,
+    25 => ::typenum::U25,
+    26 => ::typenum::U26,
+    27 => ::typenum::U27,
+    28 => ::typenum::U28,
+    29 => ::typenum::U29,
+    30 => ::typenum::U30,
+    31 => ::typenum::U31,
+    32 => ::typenum::U32
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/generic-array-0.9.0/src/iter.rs
@@ -0,0 +1,117 @@
+//! `GenericArray` iterator implementation.
+
+use super::{ArrayLength, GenericArray};
+use core::{cmp, ptr};
+use core::mem::ManuallyDrop;
+
+/// An iterator that moves out of a `GenericArray`
+pub struct GenericArrayIter<T, N: ArrayLength<T>> {
+    // Invariants: index <= index_back <= N
+    // Only values in array[index..index_back] are alive at any given time.
+    // Values from array[..index] and array[index_back..] are already moved/dropped.
+    array: ManuallyDrop<GenericArray<T, N>>,
+    index: usize,
+    index_back: usize,
+}
+
+impl<T, N> IntoIterator for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    type Item = T;
+    type IntoIter = GenericArrayIter<T, N>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        GenericArrayIter {
+            array: ManuallyDrop::new(self),
+            index: 0,
+            index_back: N::to_usize(),
+        }
+    }
+}
+
+impl<T, N> Drop for GenericArrayIter<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn drop(&mut self) {
+        // Drop values that are still alive.
+        for p in &mut self.array[self.index..self.index_back] {
+            unsafe {
+                ptr::drop_in_place(p);
+            }
+        }
+    }
+}
+
+impl<T, N> Iterator for GenericArrayIter<T, N>
+where
+    N: ArrayLength<T>,
+{
+    type Item = T;
+
+    fn next(&mut self) -> Option<T> {
+        if self.len() > 0 {
+            unsafe {
+                let p = self.array.get_unchecked(self.index);
+                self.index += 1;
+                Some(ptr::read(p))
+            }
+        } else {
+            None
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let len = self.len();
+        (len, Some(len))
+    }
+
+    fn count(self) -> usize {
+        self.len()
+    }
+
+    fn nth(&mut self, n: usize) -> Option<T> {
+        // First consume values prior to the nth.
+        let ndrop = cmp::min(n, self.len());
+        for p in &mut self.array[self.index..self.index + ndrop] {
+            self.index += 1;
+            unsafe {
+                ptr::drop_in_place(p);
+            }
+        }
+
+        self.next()
+    }
+
+    fn last(mut self) -> Option<T> {
+        // Note, everything else will correctly drop first as `self` leaves scope.
+        self.next_back()
+    }
+}
+
+impl<T, N> DoubleEndedIterator for GenericArrayIter<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn next_back(&mut self) -> Option<T> {
+        if self.len() > 0 {
+            self.index_back -= 1;
+            unsafe {
+                let p = self.array.get_unchecked(self.index_back);
+                Some(ptr::read(p))
+            }
+        } else {
+            None
+        }
+    }
+}
+
+impl<T, N> ExactSizeIterator for GenericArrayIter<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn len(&self) -> usize {
+        self.index_back - self.index
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/generic-array-0.9.0/src/lib.rs
@@ -0,0 +1,464 @@
+//! This crate implements a structure that can be used as a generic array type.use
+//! Core Rust array types `[T; N]` can't be used generically with
+//! respect to `N`, so for example this:
+//!
+//! ```{should_fail}
+//! struct Foo<T, N> {
+//!     data: [T; N]
+//! }
+//! ```
+//!
+//! won't work.
+//!
+//! **generic-array** exports a `GenericArray<T,N>` type, which lets
+//! the above be implemented as:
+//!
+//! ```
+//! # use generic_array::{ArrayLength, GenericArray};
+//! struct Foo<T, N: ArrayLength<T>> {
+//!     data: GenericArray<T,N>
+//! }
+//! ```
+//!
+//! The `ArrayLength<T>` trait is implemented by default for
+//! [unsigned integer types](../typenum/uint/index.html) from
+//! [typenum](../typenum/index.html).
+//!
+//! For ease of use, an `arr!` macro is provided - example below:
+//!
+//! ```
+//! # #[macro_use]
+//! # extern crate generic_array;
+//! # extern crate typenum;
+//! # fn main() {
+//! let array = arr![u32; 1, 2, 3];
+//! assert_eq!(array[2], 3);
+//! # }
+//! ```
+
+//#![deny(missing_docs)]
+#![no_std]
+
+pub extern crate typenum;
+#[cfg(feature = "serde")]
+extern crate serde;
+
+mod hex;
+mod impls;
+
+#[cfg(feature = "serde")]
+pub mod impl_serde;
+
+use core::{mem, ptr, slice};
+
+use core::marker::PhantomData;
+use core::mem::ManuallyDrop;
+pub use core::mem::transmute;
+use core::ops::{Deref, DerefMut};
+
+use typenum::bit::{B0, B1};
+use typenum::uint::{UInt, UTerm, Unsigned};
+
+#[cfg_attr(test, macro_use)]
+pub mod arr;
+pub mod iter;
+pub use iter::GenericArrayIter;
+
+/// Trait making `GenericArray` work, marking types to be used as length of an array
+pub unsafe trait ArrayLength<T>: Unsigned {
+    /// Associated type representing the array type for the number
+    type ArrayType;
+}
+
+unsafe impl<T> ArrayLength<T> for UTerm {
+    #[doc(hidden)]
+    type ArrayType = ();
+}
+
+/// Internal type used to generate a struct of appropriate size
+#[allow(dead_code)]
+#[repr(C)]
+#[doc(hidden)]
+pub struct GenericArrayImplEven<T, U> {
+    parent1: U,
+    parent2: U,
+    _marker: PhantomData<T>,
+}
+
+impl<T: Clone, U: Clone> Clone for GenericArrayImplEven<T, U> {
+    fn clone(&self) -> GenericArrayImplEven<T, U> {
+        GenericArrayImplEven {
+            parent1: self.parent1.clone(),
+            parent2: self.parent2.clone(),
+            _marker: PhantomData,
+        }
+    }
+}
+
+impl<T: Copy, U: Copy> Copy for GenericArrayImplEven<T, U> {}
+
+/// Internal type used to generate a struct of appropriate size
+#[allow(dead_code)]
+#[repr(C)]
+#[doc(hidden)]
+pub struct GenericArrayImplOdd<T, U> {
+    parent1: U,
+    parent2: U,
+    data: T,
+}
+
+impl<T: Clone, U: Clone> Clone for GenericArrayImplOdd<T, U> {
+    fn clone(&self) -> GenericArrayImplOdd<T, U> {
+        GenericArrayImplOdd {
+            parent1: self.parent1.clone(),
+            parent2: self.parent2.clone(),
+            data: self.data.clone(),
+        }
+    }
+}
+
+impl<T: Copy, U: Copy> Copy for GenericArrayImplOdd<T, U> {}
+
+unsafe impl<T, N: ArrayLength<T>> ArrayLength<T> for UInt<N, B0> {
+    #[doc(hidden)]
+    type ArrayType = GenericArrayImplEven<T, N::ArrayType>;
+}
+
+unsafe impl<T, N: ArrayLength<T>> ArrayLength<T> for UInt<N, B1> {
+    #[doc(hidden)]
+    type ArrayType = GenericArrayImplOdd<T, N::ArrayType>;
+}
+
+/// Struct representing a generic array - `GenericArray<T, N>` works like [T; N]
+#[allow(dead_code)]
+pub struct GenericArray<T, U: ArrayLength<T>> {
+    data: U::ArrayType,
+}
+
+impl<T, N> Deref for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    type Target = [T];
+
+    fn deref(&self) -> &[T] {
+        unsafe { slice::from_raw_parts(self as *const Self as *const T, N::to_usize()) }
+    }
+}
+
+impl<T, N> DerefMut for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn deref_mut(&mut self) -> &mut [T] {
+        unsafe { slice::from_raw_parts_mut(self as *mut Self as *mut T, N::to_usize()) }
+    }
+}
+
+struct ArrayBuilder<T, N: ArrayLength<T>> {
+    array: ManuallyDrop<GenericArray<T, N>>,
+    position: usize,
+}
+
+impl<T, N: ArrayLength<T>> ArrayBuilder<T, N> {
+    fn new() -> ArrayBuilder<T, N> {
+        ArrayBuilder {
+            array: ManuallyDrop::new(unsafe { mem::uninitialized() }),
+            position: 0,
+        }
+    }
+
+    fn into_inner(self) -> GenericArray<T, N> {
+        let array = unsafe { ptr::read(&self.array) };
+
+        mem::forget(self);
+
+        ManuallyDrop::into_inner(array)
+    }
+}
+
+impl<T, N: ArrayLength<T>> Drop for ArrayBuilder<T, N> {
+    fn drop(&mut self) {
+        for value in self.array.iter_mut().take(self.position) {
+            unsafe {
+                ptr::drop_in_place(value);
+            }
+        }
+    }
+}
+
+struct ArrayConsumer<T, N: ArrayLength<T>> {
+    array: ManuallyDrop<GenericArray<T, N>>,
+    position: usize,
+}
+
+impl<T, N: ArrayLength<T>> ArrayConsumer<T, N> {
+    fn new(array: GenericArray<T, N>) -> ArrayConsumer<T, N> {
+        ArrayConsumer {
+            array: ManuallyDrop::new(array),
+            position: 0,
+        }
+    }
+}
+
+impl<T, N: ArrayLength<T>> Drop for ArrayConsumer<T, N> {
+    fn drop(&mut self) {
+        for i in self.position..N::to_usize() {
+            unsafe {
+                ptr::drop_in_place(self.array.get_unchecked_mut(i));
+            }
+        }
+    }
+}
+
+impl<T, N> GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    /// Initializes a new `GenericArray` instance using the given function.
+    ///
+    /// If the generator function panics while initializing the array,
+    /// any already initialized elements will be dropped.
+    pub fn generate<F>(f: F) -> GenericArray<T, N>
+    where
+        F: Fn(usize) -> T,
+    {
+        let mut destination = ArrayBuilder::new();
+
+        for (i, dst) in destination.array.iter_mut().enumerate() {
+            unsafe {
+                ptr::write(dst, f(i));
+            }
+
+            destination.position += 1;
+        }
+
+        destination.into_inner()
+    }
+
+    /// Map a function over a slice to a `GenericArray`.
+    ///
+    /// The length of the slice *must* be equal to the length of the array.
+    #[inline]
+    pub fn map_slice<S, F: Fn(&S) -> T>(s: &[S], f: F) -> GenericArray<T, N> {
+        assert_eq!(s.len(), N::to_usize());
+
+        Self::generate(|i| f(unsafe { s.get_unchecked(i) }))
+    }
+
+    /// Maps a `GenericArray` to another `GenericArray`.
+    ///
+    /// If the mapping function panics, any already initialized elements in the new array
+    /// will be dropped, AND any unused elements in the source array will also be dropped.
+    pub fn map<U, F>(self, f: F) -> GenericArray<U, N>
+    where
+        F: Fn(T) -> U,
+        N: ArrayLength<U>,
+    {
+        let mut source = ArrayConsumer::new(self);
+        let mut destination = ArrayBuilder::new();
+
+        for (dst, src) in destination.array.iter_mut().zip(source.array.iter()) {
+            unsafe {
+                ptr::write(dst, f(ptr::read(src)));
+            }
+
+            source.position += 1;
+            destination.position += 1;
+        }
+
+        destination.into_inner()
+    }
+
+    /// Maps a `GenericArray` to another `GenericArray` by reference.
+    ///
+    /// If the mapping function panics, any already initialized elements will be dropped.
+    #[inline]
+    pub fn map_ref<U, F>(&self, f: F) -> GenericArray<U, N>
+    where
+        F: Fn(&T) -> U,
+        N: ArrayLength<U>,
+    {
+        GenericArray::generate(|i| f(unsafe { self.get_unchecked(i) }))
+    }
+
+    /// Combines two `GenericArray` instances and iterates through both of them,
+    /// initializing a new `GenericArray` with the result of the zipped mapping function.
+    ///
+    /// If the mapping function panics, any already initialized elements in the new array
+    /// will be dropped, AND any unused elements in the source arrays will also be dropped.
+    pub fn zip<B, U, F>(self, rhs: GenericArray<B, N>, f: F) -> GenericArray<U, N>
+    where
+        F: Fn(T, B) -> U,
+        N: ArrayLength<B> + ArrayLength<U>,
+    {
+        let mut left = ArrayConsumer::new(self);
+        let mut right = ArrayConsumer::new(rhs);
+
+        let mut destination = ArrayBuilder::new();
+
+        for (dst, (lhs, rhs)) in
+            destination.array.iter_mut().zip(left.array.iter().zip(
+                right.array.iter(),
+            ))
+        {
+            unsafe {
+                ptr::write(dst, f(ptr::read(lhs), ptr::read(rhs)));
+            }
+
+            destination.position += 1;
+            left.position += 1;
+            right.position += 1;
+        }
+
+        destination.into_inner()
+    }
+
+    /// Combines two `GenericArray` instances and iterates through both of them by reference,
+    /// initializing a new `GenericArray` with the result of the zipped mapping function.
+    ///
+    /// If the mapping function panics, any already initialized elements will be dropped.
+    pub fn zip_ref<B, U, F>(&self, rhs: &GenericArray<B, N>, f: F) -> GenericArray<U, N>
+    where
+        F: Fn(&T, &B) -> U,
+        N: ArrayLength<B> + ArrayLength<U>,
+    {
+        GenericArray::generate(|i| unsafe {
+            f(self.get_unchecked(i), rhs.get_unchecked(i))
+        })
+    }
+
+    /// Extracts a slice containing the entire array.
+    #[inline]
+    pub fn as_slice(&self) -> &[T] {
+        self.deref()
+    }
+
+    /// Extracts a mutable slice containing the entire array.
+    #[inline]
+    pub fn as_mut_slice(&mut self) -> &mut [T] {
+        self.deref_mut()
+    }
+
+    /// Converts slice to a generic array reference with inferred length;
+    ///
+    /// Length of the slice must be equal to the length of the array.
+    #[inline]
+    pub fn from_slice(slice: &[T]) -> &GenericArray<T, N> {
+        assert_eq!(slice.len(), N::to_usize());
+
+        unsafe { &*(slice.as_ptr() as *const GenericArray<T, N>) }
+    }
+
+    /// Converts mutable slice to a mutable generic array reference
+    ///
+    /// Length of the slice must be equal to the length of the array.
+    #[inline]
+    pub fn from_mut_slice(slice: &mut [T]) -> &mut GenericArray<T, N> {
+        assert_eq!(slice.len(), N::to_usize());
+
+        unsafe { &mut *(slice.as_mut_ptr() as *mut GenericArray<T, N>) }
+    }
+}
+
+impl<T: Clone, N> GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    /// Construct a `GenericArray` from a slice by cloning its content
+    ///
+    /// Length of the slice must be equal to the length of the array
+    #[inline]
+    pub fn clone_from_slice(list: &[T]) -> GenericArray<T, N> {
+        Self::from_exact_iter(list.iter().cloned()).expect(
+            "Slice must be the same length as the array",
+        )
+    }
+}
+
+impl<T, N> GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    pub fn from_exact_iter<I>(iter: I) -> Option<Self>
+    where
+        I: IntoIterator<Item = T>,
+        <I as IntoIterator>::IntoIter: ExactSizeIterator,
+    {
+        let iter = iter.into_iter();
+
+        if iter.len() == N::to_usize() {
+            let mut destination = ArrayBuilder::new();
+
+            for (dst, src) in destination.array.iter_mut().zip(iter.into_iter()) {
+                unsafe {
+                    ptr::write(dst, src);
+                }
+
+                destination.position += 1;
+            }
+
+            let array = unsafe { ptr::read(&destination.array) };
+
+            mem::forget(destination);
+
+            Some(ManuallyDrop::into_inner(array))
+        } else {
+            None
+        }
+    }
+}
+
+impl<T, N> ::core::iter::FromIterator<T> for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+    T: Default,
+{
+    fn from_iter<I>(iter: I) -> GenericArray<T, N>
+    where
+        I: IntoIterator<Item = T>,
+    {
+        let mut destination = ArrayBuilder::new();
+
+        let defaults = ::core::iter::repeat(()).map(|_| T::default());
+
+        for (dst, src) in destination.array.iter_mut().zip(
+            iter.into_iter().chain(defaults),
+        )
+        {
+            unsafe {
+                ptr::write(dst, src);
+            }
+        }
+
+        destination.into_inner()
+    }
+}
+
+#[cfg(test)]
+mod test {
+    // Compile with:
+    // cargo rustc --lib --profile test --release --
+    //      -C target-cpu=native -C opt-level=3 --emit asm
+    // and view the assembly to make sure test_assembly generates
+    // SIMD instructions instead of a niave loop.
+
+    #[inline(never)]
+    pub fn black_box<T>(val: T) -> T {
+        use core::{mem, ptr};
+
+        let ret = unsafe { ptr::read_volatile(&val) };
+        mem::forget(val);
+        ret
+    }
+
+    #[test]
+    fn test_assembly() {
+        let a = black_box(arr![i32; 1, 3, 5, 7]);
+        let b = black_box(arr![i32; 2, 4, 6, 8]);
+
+        let c = a.zip_ref(&b, |l, r| l + r);
+
+        assert_eq!(c, arr![i32; 3, 7, 11, 15]);
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/generic-array-0.9.0/tests/hex.rs
@@ -0,0 +1,44 @@
+#[macro_use]
+extern crate generic_array;
+extern crate typenum;
+
+use generic_array::GenericArray;
+use std::str::from_utf8;
+use typenum::U2048;
+
+
+#[test]
+fn short_lower_hex() {
+    let ar = arr![u8; 10, 20, 30];
+    assert_eq!(format!("{:x}", ar), "0a141e");
+}
+
+#[test]
+fn short_upper_hex() {
+    let ar = arr![u8; 30, 20, 10];
+    assert_eq!(format!("{:X}", ar), "1E140A");
+}
+
+#[test]
+fn long_lower_hex() {
+    let ar = GenericArray::<u8, U2048>::default();
+    assert_eq!(format!("{:x}", ar), from_utf8(&[b'0'; 4096]).unwrap());
+}
+
+#[test]
+fn long_upper_hex() {
+    let ar = GenericArray::<u8, U2048>::default();
+    assert_eq!(format!("{:X}", ar), from_utf8(&[b'0'; 4096]).unwrap());
+}
+
+#[test]
+fn truncated_lower_hex() {
+    let ar = arr![u8; 10, 20, 30, 40, 50];
+    assert_eq!(format!("{:.2x}", ar), "0a14");
+}
+
+#[test]
+fn truncated_upper_hex() {
+    let ar = arr![u8; 30, 20, 10, 17, 0];
+    assert_eq!(format!("{:.4X}", ar), "1E140A11");
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/generic-array-0.9.0/tests/import_name.rs
@@ -0,0 +1,10 @@
+#[macro_use]
+extern crate generic_array as gen_arr;
+
+use gen_arr::typenum;
+
+#[test]
+fn test_different_crate_name() {
+    let _: gen_arr::GenericArray<u32, typenum::U4> = arr![u32; 0, 1, 2, 3];
+    let _: gen_arr::GenericArray<u32, typenum::U0> = arr![u32;];
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/generic-array-0.9.0/tests/mod.rs
@@ -0,0 +1,169 @@
+#![recursion_limit="128"]
+#![no_std]
+#[macro_use]
+extern crate generic_array;
+use core::cell::Cell;
+use core::ops::Drop;
+use generic_array::GenericArray;
+use generic_array::typenum::{U1, U3, U4, U97};
+
+#[test]
+fn test() {
+    let mut list97 = [0; 97];
+    for i in 0..97 {
+        list97[i] = i as i32;
+    }
+    let l: GenericArray<i32, U97> = GenericArray::clone_from_slice(&list97);
+    assert_eq!(l[0], 0);
+    assert_eq!(l[1], 1);
+    assert_eq!(l[32], 32);
+    assert_eq!(l[56], 56);
+}
+
+#[test]
+fn test_drop() {
+    #[derive(Clone)]
+    struct TestDrop<'a>(&'a Cell<u32>);
+
+    impl<'a> Drop for TestDrop<'a> {
+        fn drop(&mut self) {
+            self.0.set(self.0.get() + 1);
+        }
+    }
+
+    let drop_counter = Cell::new(0);
+    {
+        let _: GenericArray<TestDrop, U3> =
+            arr![TestDrop; TestDrop(&drop_counter),
+                           TestDrop(&drop_counter),
+                           TestDrop(&drop_counter)];
+    }
+    assert_eq!(drop_counter.get(), 3);
+}
+
+#[test]
+fn test_arr() {
+    let test: GenericArray<u32, U3> = arr![u32; 1, 2, 3];
+    assert_eq!(test[1], 2);
+}
+
+#[test]
+fn test_copy() {
+    let test = arr![u32; 1, 2, 3];
+    let test2 = test;
+    // if GenericArray is not copy, this should fail as a use of a moved value
+    assert_eq!(test[1], 2);
+    assert_eq!(test2[0], 1);
+}
+
+#[test]
+fn test_iter_flat_map() {
+    assert!((0..5).flat_map(|i| arr![i32; 2 * i, 2 * i + 1]).eq(0..10));
+}
+
+#[derive(Debug, PartialEq, Eq)]
+struct NoClone<T>(T);
+
+#[test]
+fn test_from_slice() {
+    let arr = [1, 2, 3, 4];
+    let gen_arr = GenericArray::<_, U3>::from_slice(&arr[..3]);
+    assert_eq!(&arr[..3], gen_arr.as_slice());
+    let arr = [NoClone(1u32), NoClone(2), NoClone(3), NoClone(4)];
+    let gen_arr = GenericArray::<_, U3>::from_slice(&arr[..3]);
+    assert_eq!(&arr[..3], gen_arr.as_slice());
+}
+
+#[test]
+fn test_from_mut_slice() {
+    let mut arr = [1, 2, 3, 4];
+    {
+        let gen_arr = GenericArray::<_, U3>::from_mut_slice(&mut arr[..3]);
+        gen_arr[2] = 10;
+    }
+    assert_eq!(arr, [1, 2, 10, 4]);
+    let mut arr = [NoClone(1u32), NoClone(2), NoClone(3), NoClone(4)];
+    {
+        let gen_arr = GenericArray::<_, U3>::from_mut_slice(&mut arr[..3]);
+        gen_arr[2] = NoClone(10);
+    }
+    assert_eq!(arr, [NoClone(1), NoClone(2), NoClone(10), NoClone(4)]);
+}
+
+#[test]
+fn test_default() {
+    let arr = GenericArray::<u8, U1>::default();
+    assert_eq!(arr[0], 0);
+}
+
+#[test]
+fn test_from() {
+    let data = [(1, 2, 3), (4, 5, 6), (7, 8, 9)];
+    let garray: GenericArray<(usize, usize, usize), U3> = data.into();
+    assert_eq!(&data, garray.as_slice());
+}
+
+#[test]
+fn test_unit_macro() {
+    let arr = arr![f32; 3.14];
+    assert_eq!(arr[0], 3.14);
+}
+
+#[test]
+fn test_empty_macro() {
+    let _arr = arr![f32;];
+}
+
+#[test]
+fn test_cmp() {
+    arr![u8; 0x00].cmp(&arr![u8; 0x00]);
+}
+
+/// This test should cause a helpful compile error if uncommented.
+// #[test]
+// fn test_empty_macro2(){
+//     let arr = arr![];
+// }
+#[cfg(feature = "serde")]
+mod impl_serde {
+    extern crate serde_json;
+
+    use generic_array::GenericArray;
+    use generic_array::typenum::U6;
+
+    #[test]
+    fn test_serde_implementation() {
+        let array: GenericArray<f64, U6> = arr![f64; 0.0, 5.0, 3.0, 7.07192, 76.0, -9.0];
+        let string = serde_json::to_string(&array).unwrap();
+        assert_eq!(string, "[0.0,5.0,3.0,7.07192,76.0,-9.0]");
+
+        let test_array: GenericArray<f64, U6> = serde_json::from_str(&string).unwrap();
+        assert_eq!(test_array, array);
+    }
+}
+
+#[test]
+fn test_map() {
+    let b: GenericArray<i32, U4> = GenericArray::generate(|i| i as i32 * 4).map(|x| x - 3);
+
+    assert_eq!(b, arr![i32; -3, 1, 5, 9]);
+}
+
+#[test]
+fn test_zip() {
+    let a: GenericArray<_, U4> = GenericArray::generate(|i| i + 1);
+    let b: GenericArray<_, U4> = GenericArray::generate(|i| i as i32 * 4);
+
+    let c = a.zip(b, |r, l| r as i32 + l);
+
+    assert_eq!(c, arr![i32; 1, 6, 11, 16]);
+}
+
+#[test]
+fn test_from_iter() {
+    use core::iter::repeat;
+
+    let a: GenericArray<_, U4> = repeat(11).take(3).collect();
+
+    assert_eq!(a, arr![i32; 11, 11, 11, 0]);
+}
--- a/third_party/rust/generic-array/.cargo-checksum.json
+++ b/third_party/rust/generic-array/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"87ff65d640c137c26d338f96e21e769af1e1b2e7fa615b40a1bcc755448bb118","LICENSE":"ad4fcfaf8d5b12b97409c137a03d4a4e4b21024c65c54f976cc3b609c1bd5b0f","README.md":"9a1a45416eac57050036b13df6ec84d21d555e820726af3c782896bd9d37d94b","rustfmt.toml":"2a298b4ce1fe6e16b8f281a0035567b8eb15042ed3062729fd28224f29c2f75a","src/arr.rs":"cc1ea0a9ef6a524b90767cc8a89f6b939394a2948a645ed313c0bf5ce5a258a4","src/hex.rs":"bfbf304fb4dea6f7edc0569b38bf2ac7657ce089c5761891321722509e3b5076","src/impl_serde.rs":"805885478728b3c205b842d46deb377b7dd6dd4c4c50254064431f49f0981a2a","src/impls.rs":"8c54e294a82a2bf344bdcb9949b8a84903fb65698d6b1b1e0ab9f5e7847be64f","src/iter.rs":"e52217f04d0dc046f13ef2e3539b90eabd4d55bb85cf40f76ba0bf86d5e55ef0","src/lib.rs":"da93fa505eee94b40fce0fe98e26ed3bb4d2bc4d4869af01598b6e54fc9c0f8d","tests/hex.rs":"e909bc0564e7d52c5fcf172dfc0fac7085010c6a21d38581bf73a54ab2e256e1","tests/import_name.rs":"1235729ecbde47fc9a38b3bf35c750a53ed55e3cf967c9d2b24fd759dc9e9e0c","tests/mod.rs":"f4100c5338906c038636f98f4d2b3d272f59580662afa89d915eafb96d7bbcf9"},"package":"ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d"}
\ No newline at end of file
+{"files":{"CHANGELOG.md":"aa938a1a7581e59cbb554b44cc2dcf628cc1af9ddee6dccd53f557ed8d62775e","Cargo.toml":"df66f4832231be648f616c6d5ef1bacf25b40ff5118c7075554a4b41ce1d8ab1","LICENSE":"c09aae9d3c77b531f56351a9947bc7446511d6b025b3255312d3e3442a9a7583","README.md":"aad2a8508f8ae6b009d04d388bffb751875d4cfdcc6f3398212c65cc3c390d03","rustfmt.toml":"13d771354ddee15d5aa5a168fd6965c3c0ee7aa7ce75cdd5e3b82852cdac5123","src/arr.rs":"5fee5550800b890383c1dd80e00a0a568475a8599e7678e143740c941e98099d","src/functional.rs":"2437c360c645d8a9816a3b13531f23b005d1aed3ef7b1d9bcc9b2859b1d56826","src/hex.rs":"438288cf41fad3fd40ce60eb893cd038e9a88e450bab0189fe4dba8ce833a686","src/impl_serde.rs":"2cab2f808ba000c214a3ded9f43b4d5363114fe57c2c7abf545345b8b749f0db","src/impls.rs":"a7fbfc134e2d716d3a816c4b7b8aa8376172fb7f2caf91bbb02a52595a45d253","src/iter.rs":"156f798c82bc0d5e2c9a0a7777acc156bfdda793b64295ad7495cc5daa5ecb97","src/lib.rs":"a6e6a869ed40ac944e7817d571b8357eab168b132ad0c2418ab4f3f5cdeede69","src/sequence.rs":"63813c9e305b6642ac29f0ba3dd70d7db86e27fc58b31e7508c68ea52c060e82","tests/arr.rs":"22d332fcb5e0314980ddc952af0265125cf53bb9cb8b546a9dcaec2e29bfc3b0","tests/generics.rs":"491c9351fd973ff2b7bc72e78d3069cf3ed3fcd2f9180558ab027099605fa147","tests/hex.rs":"fd428c2558da2f1e2cf229af2e40e5b35a2094b3306312ac41943d25a85b7de1","tests/import_name.rs":"c9439c7d7531ce79419b0d413d729ea4321887c091bd9be8b18e6c2413021ed0","tests/iter.rs":"edf27c43ed13bf8cba2cd01de2fd7b6451c1226c8ad8331880996248e7f14d12","tests/mod.rs":"fca2966183ccd1d1681f91a845773911ab61f618bd412470612fac240ecfe0db"},"package":"3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592"}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/generic-array/CHANGELOG.md
@@ -0,0 +1,48 @@
+* **`0.12.0`**
+    * Allow trailing commas in `arr!` macro.
+    * **BREAKING**: Serialize `GenericArray` using `serde` tuples, instead of variable-length sequences. This may not be compatible with old serialized data.
+
+* **`0.11.0`**
+    * **BREAKING** Redesign `GenericSequence` with an emphasis on use in generic type parameters.
+    * Add `MappedGenericSequence` and `FunctionalSequence`
+        * Implements optimized `map`, `zip` and `fold` for `GenericArray`, `&GenericArray` and `&mut GenericArray`
+    * **BREAKING** Remove `map_ref`, `zip_ref` and `map_slice`
+        * `map_slice` is now equivalent to `GenericArray::from_iter(slice.iter().map(...))`
+* **`0.10.0`**
+    * Add `GenericSequence`, `Lengthen`, `Shorten`, `Split` and `Concat` traits.
+    * Redefine `transmute` to avert errors.
+* **`0.9.0`**
+    * Rewrite construction methods to be well-defined in panic situations, correctly dropping elements.
+    * `NoDrop` crate replaced by `ManuallyDrop` as it became stable in Rust core.
+    * Add optimized `map`/`map_ref` and `zip`/`zip_ref` methods to `GenericArray`
+* **`0.8.0`**
+    * Implement `AsRef`, `AsMut`, `Borrow`, `BorrowMut`, `Hash` for `GenericArray`
+    * Update `serde` to `1.0`
+    * Update `typenum`
+    * Make macro `arr!` non-cloning
+    * Implement `From<[T; N]>` up to `N=32`
+    * Fix #45
+* **`0.7.0`**
+    * Upgrade `serde` to `0.9`
+    * Make `serde` with `no_std`
+    * Implement `PartialOrd`/`Ord` for `GenericArray`
+* **`0.6.0`**
+    * Fixed #30
+    * Implement `Default` for `GenericArray`
+    * Implement `LowerHex` and `UpperHex` for `GenericArray<u8, N>`
+    * Use `precision` formatting field in hex representation
+    * Add `as_slice`, `as_mut_slice`
+    * Remove `GenericArray::new` in favor of `Default` trait
+    * Add `from_slice` and `from_mut_slice`
+    * `no_std` and `core` for crate.
+* **`0.5.0`**
+    * Update `serde`
+    * remove `no_std` feature, fixed #19
+* **`0.4.0`**
+    * Re-export `typenum`
+* **`0.3.0`**
+    * Implement `IntoIter` for `GenericArray`
+    * Add `map` method
+    * Add optional `serde` (de)serialization support feature.
+* **`< 0.3.0`**
+    * Initial implementation in late 2015
--- a/third_party/rust/generic-array/Cargo.toml
+++ b/third_party/rust/generic-array/Cargo.toml
@@ -7,26 +7,34 @@
 #
 # 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 = "generic-array"
-version = "0.9.0"
-authors = ["Bartłomiej Kamiński <fizyk20@gmail.com>"]
+version = "0.12.0"
+authors = ["Bartłomiej Kamiński <fizyk20@gmail.com>", "Aaron Trent <novacrazy@gmail.com>"]
 description = "Generic types implementing functionality of arrays"
 documentation = "http://fizyk20.github.io/generic-array/generic_array/"
+readme = "README.md"
+keywords = ["generic", "array"]
+categories = ["data-structures", "no-std"]
 license = "MIT"
 repository = "https://github.com/fizyk20/generic-array.git"
 
 [lib]
 name = "generic_array"
-[dependencies.typenum]
-version = "1.9"
-
 [dependencies.serde]
 version = "1.0"
 optional = true
 default-features = false
+
+[dependencies.typenum]
+version = "1.10"
+[dev-dependencies.bincode]
+version = "1.0"
+
 [dev-dependencies.serde_json]
 version = "1.0"
+[badges.travis-ci]
+repository = "fizyk20/generic-array"
--- a/third_party/rust/generic-array/LICENSE
+++ b/third_party/rust/generic-array/LICENSE
@@ -1,21 +1,21 @@
-The MIT License (MIT)
-
-Copyright (c) 2015 Bartłomiej Kamiński
-
-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
+The MIT License (MIT)
+
+Copyright (c) 2015 Bartłomiej Kamiński
+
+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.
\ No newline at end of file
--- a/third_party/rust/generic-array/README.md
+++ b/third_party/rust/generic-array/README.md
@@ -1,34 +1,34 @@
-[![Crates.io](https://img.shields.io/crates/v/generic-array.svg)](https://crates.io/crates/generic-array)
-[![Build Status](https://travis-ci.org/fizyk20/generic-array.svg?branch=master)](https://travis-ci.org/fizyk20/generic-array)
-# generic-array
-
-This crate implements generic array types for Rust.
-
-[Documentation](http://fizyk20.github.io/generic-array/generic_array/)
-
-## Usage
-
-The Rust arrays `[T; N]` are problematic in that they can't be used generically with respect to `N`, so for example this won't work:
-
-```rust
-struct Foo<N> {
-	data: [i32; N]
-}
-```
-
-**generic-array** defines a new trait `ArrayLength<T>` and a struct `GenericArray<T, N: ArrayLength<T>>`, which let the above be implemented as:
-
-```rust
-struct Foo<N: ArrayLength<i32>> {
-	data: GenericArray<i32, N>
-}
-```
-
-To actually define a type implementing `ArrayLength`, you can use unsigned integer types defined in [typenum](https://github.com/paholg/typenum) crate - for example, `GenericArray<T, U5>` would work almost like `[T; 5]` :)
-
-In version 0.1.1 an `arr!` macro was introduced, allowing for creation of arrays as shown below:
-
-```rust
-let array = arr![u32; 1, 2, 3];
-assert_eq!(array[2], 3);
-```
+[![Crates.io](https://img.shields.io/crates/v/generic-array.svg)](https://crates.io/crates/generic-array)
+[![Build Status](https://travis-ci.org/fizyk20/generic-array.svg?branch=master)](https://travis-ci.org/fizyk20/generic-array)
+# generic-array
+
+This crate implements generic array types for Rust.
+
+[Documentation](http://fizyk20.github.io/generic-array/generic_array/)
+
+## Usage
+
+The Rust arrays `[T; N]` are problematic in that they can't be used generically with respect to `N`, so for example this won't work:
+
+```rust
+struct Foo<N> {
+	data: [i32; N]
+}
+```
+
+**generic-array** defines a new trait `ArrayLength<T>` and a struct `GenericArray<T, N: ArrayLength<T>>`, which let the above be implemented as:
+
+```rust
+struct Foo<N: ArrayLength<i32>> {
+	data: GenericArray<i32, N>
+}
+```
+
+To actually define a type implementing `ArrayLength`, you can use unsigned integer types defined in [typenum](https://github.com/paholg/typenum) crate - for example, `GenericArray<T, U5>` would work almost like `[T; 5]` :)
+
+In version 0.1.1 an `arr!` macro was introduced, allowing for creation of arrays as shown below:
+
+```rust
+let array = arr![u32; 1, 2, 3];
+assert_eq!(array[2], 3);
+```
--- a/third_party/rust/generic-array/rustfmt.toml
+++ b/third_party/rust/generic-array/rustfmt.toml
@@ -1,3 +1,3 @@
-reorder_imports = true
-reorder_imported_names = true
-use_try_shorthand = true
+reorder_imports = true
+reorder_imported_names = true
+use_try_shorthand = true
--- a/third_party/rust/generic-array/src/arr.rs
+++ b/third_party/rust/generic-array/src/arr.rs
@@ -1,57 +1,57 @@
-//! Implementation for `arr!` macro.
-
-use super::ArrayLength;
-use core::ops::Add;
-use typenum::U1;
-
-/// Helper trait for `arr!` macro
-pub trait AddLength<T, N: ArrayLength<T>>: ArrayLength<T> {
-    /// Resulting length
-    type Output: ArrayLength<T>;
-}
-
-impl<T, N1, N2> AddLength<T, N2> for N1
-where
-    N1: ArrayLength<T> + Add<N2>,
-    N2: ArrayLength<T>,
-    <N1 as Add<N2>>::Output: ArrayLength<T>,
-{
-    type Output = <N1 as Add<N2>>::Output;
-}
-
-/// Helper type for `arr!` macro
-pub type Inc<T, U> = <U as AddLength<T, U1>>::Output;
-
-#[doc(hidden)]
-#[macro_export]
-macro_rules! arr_impl {
-    ($T:ty; $N:ty, [$($x:expr),*], []) => ({
-	unsafe { $crate::transmute::<_, $crate::GenericArray<$T, $N>>([$($x),*]) }
-    });
-    ($T:ty; $N:ty, [], [$x1:expr]) => (
-        arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1 as $T], [])
-    );
-    ($T:ty; $N:ty, [], [$x1:expr, $($x:expr),+]) => (
-        arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1 as $T], [$($x),*])
-    );
-    ($T:ty; $N:ty, [$($y:expr),+], [$x1:expr]) => (
-        arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),*, $x1 as $T], [])
-    );
-    ($T:ty; $N:ty, [$($y:expr),+], [$x1:expr, $($x:expr),+]) => (
-        arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),*, $x1 as $T], [$($x),*])
-    );
-}
-
-/// Macro allowing for easy generation of Generic Arrays.
-/// Example: `let test = arr![u32; 1, 2, 3];`
-#[macro_export]
-macro_rules! arr {
-    ($T:ty;) => ({
-        unsafe { $crate::transmute::<[$T; 0], $crate::GenericArray<$T, $crate::typenum::U0>>([]) }
-    });
-    ($T:ty; $($x:expr),*) => (
-        arr_impl!($T; $crate::typenum::U0, [], [$($x),*])
-    );
-    ($($x:expr,)+) => (arr![$($x),*]);
-    () => ("""Macro requires a type, e.g. `let array = arr![u32; 1, 2, 3];`")
-}
+//! Implementation for `arr!` macro.
+
+use super::ArrayLength;
+use core::ops::Add;
+use typenum::U1;
+
+/// Helper trait for `arr!` macro
+pub trait AddLength<T, N: ArrayLength<T>>: ArrayLength<T> {
+    /// Resulting length
+    type Output: ArrayLength<T>;
+}
+
+impl<T, N1, N2> AddLength<T, N2> for N1
+where
+    N1: ArrayLength<T> + Add<N2>,
+    N2: ArrayLength<T>,
+    <N1 as Add<N2>>::Output: ArrayLength<T>,
+{
+    type Output = <N1 as Add<N2>>::Output;
+}
+
+/// Helper type for `arr!` macro
+pub type Inc<T, U> = <U as AddLength<T, U1>>::Output;
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! arr_impl {
+    ($T:ty; $N:ty, [$($x:expr),*], []) => ({
+        unsafe { $crate::transmute::<_, $crate::GenericArray<$T, $N>>([$($x),*]) }
+    });
+    ($T:ty; $N:ty, [], [$x1:expr]) => (
+        arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1 as $T], [])
+    );
+    ($T:ty; $N:ty, [], [$x1:expr, $($x:expr),+]) => (
+        arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1 as $T], [$($x),+])
+    );
+    ($T:ty; $N:ty, [$($y:expr),+], [$x1:expr]) => (
+        arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1 as $T], [])
+    );
+    ($T:ty; $N:ty, [$($y:expr),+], [$x1:expr, $($x:expr),+]) => (
+        arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1 as $T], [$($x),+])
+    );
+}
+
+/// Macro allowing for easy generation of Generic Arrays.
+/// Example: `let test = arr![u32; 1, 2, 3];`
+#[macro_export]
+macro_rules! arr {
+    ($T:ty; $(,)*) => ({
+        unsafe { $crate::transmute::<[$T; 0], $crate::GenericArray<$T, $crate::typenum::U0>>([]) }
+    });
+    ($T:ty; $($x:expr),* $(,)*) => (
+        arr_impl!($T; $crate::typenum::U0, [], [$($x),*])
+    );
+    ($($x:expr,)+) => (arr![$($x),*]);
+    () => ("""Macro requires a type, e.g. `let array = arr![u32; 1, 2, 3];`")
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/generic-array/src/functional.rs
@@ -0,0 +1,94 @@
+//! Functional programming with generic sequences
+//!
+//! Please see `tests/generics.rs` for examples of how to best use these in your generic functions.
+
+use super::ArrayLength;
+use core::iter::FromIterator;
+use sequence::*;
+
+/// Defines the relationship between one generic sequence and another,
+/// for operations such as `map` and `zip`.
+pub unsafe trait MappedGenericSequence<T, U>: GenericSequence<T>
+where
+    Self::Length: ArrayLength<U>,
+{
+    /// Mapped sequence type
+    type Mapped: GenericSequence<U, Length = Self::Length>;
+}
+
+unsafe impl<'a, T, U, S: MappedGenericSequence<T, U>> MappedGenericSequence<T, U> for &'a S
+where
+    &'a S: GenericSequence<T>,
+    S: GenericSequence<T, Length = <&'a S as GenericSequence<T>>::Length>,
+    <S as GenericSequence<T>>::Length: ArrayLength<U>,
+{
+    type Mapped = <S as MappedGenericSequence<T, U>>::Mapped;
+}
+
+unsafe impl<'a, T, U, S: MappedGenericSequence<T, U>> MappedGenericSequence<T, U> for &'a mut S
+where
+    &'a mut S: GenericSequence<T>,
+    S: GenericSequence<T, Length = <&'a mut S as GenericSequence<T>>::Length>,
+    <S as GenericSequence<T>>::Length: ArrayLength<U>,
+{
+    type Mapped = <S as MappedGenericSequence<T, U>>::Mapped;
+}
+
+/// Accessor type for a mapped generic sequence
+pub type MappedSequence<S, T, U> =
+    <<S as MappedGenericSequence<T, U>>::Mapped as GenericSequence<U>>::Sequence;
+
+/// Defines functional programming methods for generic sequences
+pub unsafe trait FunctionalSequence<T>: GenericSequence<T> {
+    /// Maps a `GenericSequence` to another `GenericSequence`.
+    ///
+    /// If the mapping function panics, any already initialized elements in the new sequence
+    /// will be dropped, AND any unused elements in the source sequence will also be dropped.
+    fn map<U, F>(self, f: F) -> MappedSequence<Self, T, U>
+    where
+        Self: MappedGenericSequence<T, U>,
+        Self::Length: ArrayLength<U>,
+        F: FnMut(Self::Item) -> U,
+    {
+        FromIterator::from_iter(self.into_iter().map(f))
+    }
+
+    /// Combines two `GenericSequence` instances and iterates through both of them,
+    /// initializing a new `GenericSequence` with the result of the zipped mapping function.
+    ///
+    /// If the mapping function panics, any already initialized elements in the new sequence
+    /// will be dropped, AND any unused elements in the source sequences will also be dropped.
+    #[inline]
+    fn zip<B, Rhs, U, F>(self, rhs: Rhs, f: F) -> MappedSequence<Self, T, U>
+    where
+        Self: MappedGenericSequence<T, U>,
+        Rhs: MappedGenericSequence<B, U, Mapped = MappedSequence<Self, T, U>>,
+        Self::Length: ArrayLength<B> + ArrayLength<U>,
+        Rhs: GenericSequence<B, Length = Self::Length>,
+        F: FnMut(Self::Item, Rhs::Item) -> U,
+    {
+        rhs.inverted_zip2(self, f)
+    }
+
+    /// Folds (or reduces) a sequence of data into a single value.
+    ///
+    /// If the fold function panics, any unused elements will be dropped.
+    fn fold<U, F>(self, init: U, f: F) -> U
+    where
+        F: FnMut(U, Self::Item) -> U,
+    {
+        self.into_iter().fold(init, f)
+    }
+}
+
+unsafe impl<'a, T, S: GenericSequence<T>> FunctionalSequence<T> for &'a S
+where
+    &'a S: GenericSequence<T>,
+{
+}
+
+unsafe impl<'a, T, S: GenericSequence<T>> FunctionalSequence<T> for &'a mut S
+where
+    &'a mut S: GenericSequence<T>,
+{
+}
--- a/third_party/rust/generic-array/src/hex.rs
+++ b/third_party/rust/generic-array/src/hex.rs
@@ -1,101 +1,102 @@
-//! Generic array are commonly used as a return value for hash digests, so
-//! it's a good idea to allow to hexlify them easily. This module implements
-//! `std::fmt::LowerHex` and `std::fmt::UpperHex` traits.
-//!
-//! Example:
-//!
-//! ```rust
-//! # #[macro_use]
-//! # extern crate generic_array;
-//! # extern crate typenum;
-//! # fn main() {
-//! let array = arr![u8; 10, 20, 30];
-//! assert_eq!(format!("{:x}", array), "0a141e");
-//! # }
-//! ```
-//!
-
-use {ArrayLength, GenericArray};
-use core::fmt;
-use core::ops::Add;
-use core::str;
-use typenum::*;
-
-static LOWER_CHARS: &'static [u8] = b"0123456789abcdef";
-static UPPER_CHARS: &'static [u8] = b"0123456789ABCDEF";
-
-impl<T: ArrayLength<u8>> fmt::LowerHex for GenericArray<u8, T>
-where
-    T: Add<T>,
-    <T as Add<T>>::Output: ArrayLength<u8>,
-{
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let max_digits = f.precision().unwrap_or_else(|| self.len());
-
-        if T::to_usize() < 1024 {
-            // For small arrays use a stack allocated
-            // buffer of 2x number of bytes
-            let mut res = GenericArray::<u8, Sum<T, T>>::default();
-
-            for (i, c) in self.iter().take(max_digits).enumerate() {
-                res[i * 2] = LOWER_CHARS[(c >> 4) as usize];
-                res[i * 2 + 1] = LOWER_CHARS[(c & 0xF) as usize];
-            }
-            f.write_str(
-                unsafe { str::from_utf8_unchecked(&res[..max_digits * 2]) },
-            )?;
-        } else {
-            // For large array use chunks of up to 1024 bytes (2048 hex chars)
-            let mut buf = [0u8; 2048];
-
-            for chunk in self[..max_digits].chunks(1024) {
-                for (i, c) in chunk.iter().enumerate() {
-                    buf[i * 2] = LOWER_CHARS[(c >> 4) as usize];
-                    buf[i * 2 + 1] = LOWER_CHARS[(c & 0xF) as usize];
-                }
-                f.write_str(unsafe {
-                    str::from_utf8_unchecked(&buf[..chunk.len() * 2])
-                })?;
-            }
-        }
-        Ok(())
-    }
-}
-
-impl<T: ArrayLength<u8>> fmt::UpperHex for GenericArray<u8, T>
-where
-    T: Add<T>,
-    <T as Add<T>>::Output: ArrayLength<u8>,
-{
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let max_digits = f.precision().unwrap_or_else(|| self.len());
-
-        if T::to_usize() < 1024 {
-            // For small arrays use a stack allocated
-            // buffer of 2x number of bytes
-            let mut res = GenericArray::<u8, Sum<T, T>>::default();
-
-            for (i, c) in self.iter().take(max_digits).enumerate() {
-                res[i * 2] = UPPER_CHARS[(c >> 4) as usize];
-                res[i * 2 + 1] = UPPER_CHARS[(c & 0xF) as usize];
-            }
-            f.write_str(
-                unsafe { str::from_utf8_unchecked(&res[..max_digits * 2]) },
-            )?;
-        } else {
-            // For large array use chunks of up to 1024 bytes (2048 hex chars)
-            let mut buf = [0u8; 2048];
-
-            for chunk in self[..max_digits].chunks(1024) {
-                for (i, c) in chunk.iter().enumerate() {
-                    buf[i * 2] = UPPER_CHARS[(c >> 4) as usize];
-                    buf[i * 2 + 1] = UPPER_CHARS[(c & 0xF) as usize];
-                }
-                f.write_str(unsafe {
-                    str::from_utf8_unchecked(&buf[..chunk.len() * 2])
-                })?;
-            }
-        }
-        Ok(())
-    }
-}
+//! Generic array are commonly used as a return value for hash digests, so
+//! it's a good idea to allow to hexlify them easily. This module implements
+//! `std::fmt::LowerHex` and `std::fmt::UpperHex` traits.
+//!
+//! Example:
+//!
+//! ```rust
+//! # #[macro_use]
+//! # extern crate generic_array;
+//! # extern crate typenum;
+//! # fn main() {
+//! let array = arr![u8; 10, 20, 30];
+//! assert_eq!(format!("{:x}", array), "0a141e");
+//! # }
+//! ```
+//!
+
+use {ArrayLength, GenericArray};
+use core::cmp::min;
+use core::fmt;
+use core::ops::Add;
+use core::str;
+use typenum::*;
+
+static LOWER_CHARS: &'static [u8] = b"0123456789abcdef";
+static UPPER_CHARS: &'static [u8] = b"0123456789ABCDEF";
+
+impl<T: ArrayLength<u8>> fmt::LowerHex for GenericArray<u8, T>
+where
+    T: Add<T>,
+    <T as Add<T>>::Output: ArrayLength<u8>,
+{
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let max_digits = f.precision().unwrap_or_else(|| self.len() * 2);
+        let max_hex = (max_digits >> 1) + (max_digits & 1);
+
+        if T::to_usize() < 1024 {
+            // For small arrays use a stack allocated
+            // buffer of 2x number of bytes
+            let mut res = GenericArray::<u8, Sum<T, T>>::default();
+
+            for (i, c) in self.iter().take(max_hex).enumerate() {
+                res[i * 2] = LOWER_CHARS[(c >> 4) as usize];
+                res[i * 2 + 1] = LOWER_CHARS[(c & 0xF) as usize];
+            }
+            f.write_str(unsafe { str::from_utf8_unchecked(&res[..max_digits]) })?;
+        } else {
+            // For large array use chunks of up to 1024 bytes (2048 hex chars)
+            let mut buf = [0u8; 2048];
+            let mut digits_left = max_digits;
+
+            for chunk in self[..max_hex].chunks(1024) {
+                for (i, c) in chunk.iter().enumerate() {
+                    buf[i * 2] = LOWER_CHARS[(c >> 4) as usize];
+                    buf[i * 2 + 1] = LOWER_CHARS[(c & 0xF) as usize];
+                }
+                let n = min(chunk.len() * 2, digits_left);
+                f.write_str(unsafe { str::from_utf8_unchecked(&buf[..n]) })?;
+                digits_left -= n;
+            }
+        }
+        Ok(())
+    }
+}
+
+impl<T: ArrayLength<u8>> fmt::UpperHex for GenericArray<u8, T>
+where
+    T: Add<T>,
+    <T as Add<T>>::Output: ArrayLength<u8>,
+{
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let max_digits = f.precision().unwrap_or_else(|| self.len() * 2);
+        let max_hex = (max_digits >> 1) + (max_digits & 1);
+
+        if T::to_usize() < 1024 {
+            // For small arrays use a stack allocated
+            // buffer of 2x number of bytes
+            let mut res = GenericArray::<u8, Sum<T, T>>::default();
+
+            for (i, c) in self.iter().take(max_hex).enumerate() {
+                res[i * 2] = UPPER_CHARS[(c >> 4) as usize];
+                res[i * 2 + 1] = UPPER_CHARS[(c & 0xF) as usize];
+            }
+            f.write_str(unsafe { str::from_utf8_unchecked(&res[..max_digits]) })?;
+        } else {
+            // For large array use chunks of up to 1024 bytes (2048 hex chars)
+            let mut buf = [0u8; 2048];
+            let mut digits_left = max_digits;
+
+            for chunk in self[..max_hex].chunks(1024) {
+                for (i, c) in chunk.iter().enumerate() {
+                    buf[i * 2] = UPPER_CHARS[(c >> 4) as usize];
+                    buf[i * 2 + 1] = UPPER_CHARS[(c & 0xF) as usize];
+                }
+                let n = min(chunk.len() * 2, digits_left);
+                f.write_str(unsafe { str::from_utf8_unchecked(&buf[..n]) })?;
+                digits_left -= n;
+            }
+        }
+        Ok(())
+    }
+}
--- a/third_party/rust/generic-array/src/impl_serde.rs
+++ b/third_party/rust/generic-array/src/impl_serde.rs
@@ -1,68 +1,108 @@
-//! Serde serialization/deserialization implementation
-
-use {ArrayLength, GenericArray};
-use core::fmt;
-use core::marker::PhantomData;
-use serde::{Deserialize, Deserializer, Serialize, Serializer};
-use serde::de::{self, SeqAccess, Visitor};
-
-impl<T, N> Serialize for GenericArray<T, N>
-where
-    T: Serialize,
-    N: ArrayLength<T>,
-{
-    #[inline]
-    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-    where
-        S: Serializer,
-    {
-        serializer.collect_seq(self.iter())
-    }
-}
-
-struct GAVisitor<T, N> {
-    _t: PhantomData<T>,
-    _n: PhantomData<N>,
-}
-
-impl<'de, T, N> Visitor<'de> for GAVisitor<T, N>
-where
-    T: Deserialize<'de> + Default,
-    N: ArrayLength<T>,
-{
-    type Value = GenericArray<T, N>;
-
-    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-        formatter.write_str("struct GenericArray")
-    }
-
-    fn visit_seq<A>(self, mut seq: A) -> Result<GenericArray<T, N>, A::Error>
-    where
-        A: SeqAccess<'de>,
-    {
-        let mut result = GenericArray::default();
-        for i in 0..N::to_usize() {
-            result[i] = seq.next_element()?.ok_or_else(
-                || de::Error::invalid_length(i, &self),
-            )?;
-        }
-        Ok(result)
-    }
-}
-
-impl<'de, T, N> Deserialize<'de> for GenericArray<T, N>
-where
-    T: Deserialize<'de> + Default,
-    N: ArrayLength<T>,
-{
-    fn deserialize<D>(deserializer: D) -> Result<GenericArray<T, N>, D::Error>
-    where
-        D: Deserializer<'de>,
-    {
-        let visitor = GAVisitor {
-            _t: PhantomData,
-            _n: PhantomData,
-        };
-        deserializer.deserialize_seq(visitor)
-    }
-}
+//! Serde serialization/deserialization implementation
+
+use core::fmt;
+use core::marker::PhantomData;
+use serde::de::{self, SeqAccess, Visitor};
+use serde::{ser::SerializeTuple, Deserialize, Deserializer, Serialize, Serializer};
+use {ArrayLength, GenericArray};
+
+impl<T, N> Serialize for GenericArray<T, N>
+where
+    T: Serialize,
+    N: ArrayLength<T>,
+{
+    #[inline]
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        let mut tup = serializer.serialize_tuple(N::to_usize())?;
+        for el in self {
+            tup.serialize_element(el)?;
+        }
+
+        tup.end()
+    }
+}
+
+struct GAVisitor<T, N> {
+    _t: PhantomData<T>,
+    _n: PhantomData<N>,
+}
+
+impl<'de, T, N> Visitor<'de> for GAVisitor<T, N>
+where
+    T: Deserialize<'de> + Default,
+    N: ArrayLength<T>,
+{
+    type Value = GenericArray<T, N>;
+
+    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        formatter.write_str("struct GenericArray")
+    }
+
+    fn visit_seq<A>(self, mut seq: A) -> Result<GenericArray<T, N>, A::Error>
+    where
+        A: SeqAccess<'de>,
+    {
+        let mut result = GenericArray::default();
+        for i in 0..N::to_usize() {
+            result[i] = seq
+                .next_element()?
+                .ok_or_else(|| de::Error::invalid_length(i, &self))?;
+        }
+        Ok(result)
+    }
+}
+
+impl<'de, T, N> Deserialize<'de> for GenericArray<T, N>
+where
+    T: Deserialize<'de> + Default,
+    N: ArrayLength<T>,
+{
+    fn deserialize<D>(deserializer: D) -> Result<GenericArray<T, N>, D::Error>
+    where
+        D: Deserializer<'de>,
+    {
+        let visitor = GAVisitor {
+            _t: PhantomData,
+            _n: PhantomData,
+        };
+        deserializer.deserialize_tuple(N::to_usize(), visitor)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use bincode;
+    use typenum;
+
+    #[test]
+    fn test_serialize() {
+        let array = GenericArray::<u8, typenum::U2>::default();
+        let serialized = bincode::serialize(&array);
+        assert!(serialized.is_ok());
+    }
+
+    #[test]
+    fn test_deserialize() {
+        let mut array = GenericArray::<u8, typenum::U2>::default();
+        array[0] = 1;
+        array[1] = 2;
+        let serialized = bincode::serialize(&array).unwrap();
+        let deserialized = bincode::deserialize::<GenericArray<u8, typenum::U2>>(&array);
+        assert!(deserialized.is_ok());
+        let array = deserialized.unwrap();
+        assert_eq!(array[0], 1);
+        assert_eq!(array[1], 2);
+    }
+
+    #[test]
+    fn test_serialized_size() {
+        let array = GenericArray::<u8, typenum::U1>::default();
+        let size = bincode::serialized_size(&array).unwrap();
+        assert_eq!(size, 1);
+    }
+
+}
--- a/third_party/rust/generic-array/src/impls.rs
+++ b/third_party/rust/generic-array/src/impls.rs
@@ -1,171 +1,173 @@
-use super::{ArrayLength, GenericArray};
-use core::borrow::{Borrow, BorrowMut};
-use core::cmp::Ordering;
-use core::fmt::{self, Debug};
-use core::hash::{Hash, Hasher};
-
-impl<T: Default, N> Default for GenericArray<T, N>
-where
-    N: ArrayLength<T>,
-{
-    #[inline]
-    fn default() -> Self {
-        Self::generate(|_| T::default())
-    }
-}
-
-impl<T: Clone, N> Clone for GenericArray<T, N>
-where
-    N: ArrayLength<T>,
-{
-    fn clone(&self) -> GenericArray<T, N> {
-        self.map_ref(|x| x.clone())
-    }
-}
-
-impl<T: Copy, N> Copy for GenericArray<T, N>
-where
-    N: ArrayLength<T>,
-    N::ArrayType: Copy,
-{
-}
-
-impl<T: PartialEq, N> PartialEq for GenericArray<T, N>
-where
-    N: ArrayLength<T>,
-{
-    fn eq(&self, other: &Self) -> bool {
-        **self == **other
-    }
-}
-impl<T: Eq, N> Eq for GenericArray<T, N>
-where
-    N: ArrayLength<T>,
-{
-}
-
-impl<T: PartialOrd, N> PartialOrd for GenericArray<T, N>
-where
-    N: ArrayLength<T>,
-{
-    fn partial_cmp(&self, other: &GenericArray<T, N>) -> Option<Ordering> {
-        PartialOrd::partial_cmp(self.as_slice(), other.as_slice())
-    }
-}
-
-impl<T: Ord, N> Ord for GenericArray<T, N>
-where
-    N: ArrayLength<T>,
-{
-    fn cmp(&self, other: &GenericArray<T, N>) -> Ordering {
-        Ord::cmp(self.as_slice(), other.as_slice())
-    }
-}
-
-impl<T: Debug, N> Debug for GenericArray<T, N>
-where
-    N: ArrayLength<T>,
-{
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        self[..].fmt(fmt)
-    }
-}
-
-impl<T, N> Borrow<[T]> for GenericArray<T, N>
-where
-    N: ArrayLength<T>,
-{
-    fn borrow(&self) -> &[T] {
-        &self[..]
-    }
-}
-
-impl<T, N> BorrowMut<[T]> for GenericArray<T, N>
-where
-    N: ArrayLength<T>,
-{
-    fn borrow_mut(&mut self) -> &mut [T] {
-        &mut self[..]
-    }
-}
-
-impl<T, N> AsRef<[T]> for GenericArray<T, N>
-where
-    N: ArrayLength<T>,
-{
-    fn as_ref(&self) -> &[T] {
-        &self[..]
-    }
-}
-
-impl<T, N> AsMut<[T]> for GenericArray<T, N>
-where
-    N: ArrayLength<T>,
-{
-    fn as_mut(&mut self) -> &mut [T] {
-        &mut self[..]
-    }
-}
-
-impl<T: Hash, N> Hash for GenericArray<T, N>
-where
-    N: ArrayLength<T>,
-{
-    fn hash<H>(&self, state: &mut H)
-    where
-        H: Hasher,
-    {
-        Hash::hash(&self[..], state)
-    }
-}
-
-macro_rules! impl_from {
-    ($($n: expr => $ty: ty),*) => {
-        $(
-            impl<T> From<[T; $n]> for GenericArray<T, $ty> {
-                fn from(arr: [T; $n]) -> Self {
-                    use core::mem::{forget, transmute_copy};
-                    let x = unsafe { transmute_copy(&arr) };
-                    forget(arr);
-                    x
-                }
-            }
-        )*
-
-    }
-}
-
-impl_from! {
-    1  => ::typenum::U1,
-    2  => ::typenum::U2,
-    3  => ::typenum::U3,
-    4  => ::typenum::U4,
-    5  => ::typenum::U5,
-    6  => ::typenum::U6,
-    7  => ::typenum::U7,
-    8  => ::typenum::U8,
-    9  => ::typenum::U9,
-    10 => ::typenum::U10,
-    11 => ::typenum::U11,
-    12 => ::typenum::U12,
-    13 => ::typenum::U13,
-    14 => ::typenum::U14,
-    15 => ::typenum::U15,
-    16 => ::typenum::U16,
-    17 => ::typenum::U17,
-    18 => ::typenum::U18,
-    19 => ::typenum::U19,
-    20 => ::typenum::U20,
-    21 => ::typenum::U21,
-    22 => ::typenum::U22,
-    23 => ::typenum::U23,
-    24 => ::typenum::U24,
-    25 => ::typenum::U25,
-    26 => ::typenum::U26,
-    27 => ::typenum::U27,
-    28 => ::typenum::U28,
-    29 => ::typenum::U29,
-    30 => ::typenum::U30,
-    31 => ::typenum::U31,
-    32 => ::typenum::U32
-}
\ No newline at end of file
+use super::{ArrayLength, GenericArray};
+use core::borrow::{Borrow, BorrowMut};
+use core::cmp::Ordering;
+use core::fmt::{self, Debug};
+use core::hash::{Hash, Hasher};
+use functional::*;
+use sequence::*;
+
+impl<T: Default, N> Default for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    #[inline]
+    fn default() -> Self {
+        Self::generate(|_| T::default())
+    }
+}
+
+impl<T: Clone, N> Clone for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn clone(&self) -> GenericArray<T, N> {
+        self.map(|x| x.clone())
+    }
+}
+
+impl<T: Copy, N> Copy for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+    N::ArrayType: Copy,
+{
+}
+
+impl<T: PartialEq, N> PartialEq for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn eq(&self, other: &Self) -> bool {
+        **self == **other
+    }
+}
+impl<T: Eq, N> Eq for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+}
+
+impl<T: PartialOrd, N> PartialOrd for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn partial_cmp(&self, other: &GenericArray<T, N>) -> Option<Ordering> {
+        PartialOrd::partial_cmp(self.as_slice(), other.as_slice())
+    }
+}
+
+impl<T: Ord, N> Ord for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn cmp(&self, other: &GenericArray<T, N>) -> Ordering {
+        Ord::cmp(self.as_slice(), other.as_slice())
+    }
+}
+
+impl<T: Debug, N> Debug for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        self[..].fmt(fmt)
+    }
+}
+
+impl<T, N> Borrow<[T]> for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn borrow(&self) -> &[T] {
+        &self[..]
+    }
+}
+
+impl<T, N> BorrowMut<[T]> for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn borrow_mut(&mut self) -> &mut [T] {
+        &mut self[..]
+    }
+}
+
+impl<T, N> AsRef<[T]> for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn as_ref(&self) -> &[T] {
+        &self[..]
+    }
+}
+
+impl<T, N> AsMut<[T]> for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn as_mut(&mut self) -> &mut [T] {
+        &mut self[..]
+    }
+}
+
+impl<T: Hash, N> Hash for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn hash<H>(&self, state: &mut H)
+    where
+        H: Hasher,
+    {
+        Hash::hash(&self[..], state)
+    }
+}
+
+macro_rules! impl_from {
+    ($($n: expr => $ty: ty),*) => {
+        $(
+            impl<T> From<[T; $n]> for GenericArray<T, $ty> {
+                fn from(arr: [T; $n]) -> Self {
+                    use core::mem::{forget, transmute_copy};
+                    let x = unsafe { transmute_copy(&arr) };
+                    forget(arr);
+                    x
+                }
+            }
+        )*
+
+    }
+}
+
+impl_from! {
+    1  => ::typenum::U1,
+    2  => ::typenum::U2,
+    3  => ::typenum::U3,
+    4  => ::typenum::U4,
+    5  => ::typenum::U5,
+    6  => ::typenum::U6,
+    7  => ::typenum::U7,
+    8  => ::typenum::U8,
+    9  => ::typenum::U9,
+    10 => ::typenum::U10,
+    11 => ::typenum::U11,
+    12 => ::typenum::U12,
+    13 => ::typenum::U13,
+    14 => ::typenum::U14,
+    15 => ::typenum::U15,
+    16 => ::typenum::U16,
+    17 => ::typenum::U17,
+    18 => ::typenum::U18,
+    19 => ::typenum::U19,
+    20 => ::typenum::U20,
+    21 => ::typenum::U21,
+    22 => ::typenum::U22,
+    23 => ::typenum::U23,
+    24 => ::typenum::U24,
+    25 => ::typenum::U25,
+    26 => ::typenum::U26,
+    27 => ::typenum::U27,
+    28 => ::typenum::U28,
+    29 => ::typenum::U29,
+    30 => ::typenum::U30,
+    31 => ::typenum::U31,
+    32 => ::typenum::U32
+}
--- a/third_party/rust/generic-array/src/iter.rs
+++ b/third_party/rust/generic-array/src/iter.rs
@@ -1,117 +1,190 @@
-//! `GenericArray` iterator implementation.
-
-use super::{ArrayLength, GenericArray};
-use core::{cmp, ptr};
-use core::mem::ManuallyDrop;
-
-/// An iterator that moves out of a `GenericArray`
-pub struct GenericArrayIter<T, N: ArrayLength<T>> {
-    // Invariants: index <= index_back <= N
-    // Only values in array[index..index_back] are alive at any given time.
-    // Values from array[..index] and array[index_back..] are already moved/dropped.
-    array: ManuallyDrop<GenericArray<T, N>>,
-    index: usize,
-    index_back: usize,
-}
-
-impl<T, N> IntoIterator for GenericArray<T, N>
-where
-    N: ArrayLength<T>,
-{
-    type Item = T;
-    type IntoIter = GenericArrayIter<T, N>;
-
-    fn into_iter(self) -> Self::IntoIter {
-        GenericArrayIter {
-            array: ManuallyDrop::new(self),
-            index: 0,
-            index_back: N::to_usize(),
-        }
-    }
-}
-
-impl<T, N> Drop for GenericArrayIter<T, N>
-where
-    N: ArrayLength<T>,
-{
-    fn drop(&mut self) {
-        // Drop values that are still alive.
-        for p in &mut self.array[self.index..self.index_back] {
-            unsafe {
-                ptr::drop_in_place(p);
-            }
-        }
-    }
-}
-
-impl<T, N> Iterator for GenericArrayIter<T, N>
-where
-    N: ArrayLength<T>,
-{
-    type Item = T;
-
-    fn next(&mut self) -> Option<T> {
-        if self.len() > 0 {
-            unsafe {
-                let p = self.array.get_unchecked(self.index);
-                self.index += 1;
-                Some(ptr::read(p))
-            }
-        } else {
-            None
-        }
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let len = self.len();
-        (len, Some(len))
-    }
-
-    fn count(self) -> usize {
-        self.len()
-    }
-
-    fn nth(&mut self, n: usize) -> Option<T> {
-        // First consume values prior to the nth.
-        let ndrop = cmp::min(n, self.len());
-        for p in &mut self.array[self.index..self.index + ndrop] {
-            self.index += 1;
-            unsafe {
-                ptr::drop_in_place(p);
-            }
-        }
-
-        self.next()
-    }
-
-    fn last(mut self) -> Option<T> {
-        // Note, everything else will correctly drop first as `self` leaves scope.
-        self.next_back()
-    }
-}
-
-impl<T, N> DoubleEndedIterator for GenericArrayIter<T, N>
-where
-    N: ArrayLength<T>,
-{
-    fn next_back(&mut self) -> Option<T> {
-        if self.len() > 0 {
-            self.index_back -= 1;
-            unsafe {
-                let p = self.array.get_unchecked(self.index_back);
-                Some(ptr::read(p))
-            }
-        } else {
-            None
-        }
-    }
-}
-
-impl<T, N> ExactSizeIterator for GenericArrayIter<T, N>
-where
-    N: ArrayLength<T>,
-{
-    fn len(&self) -> usize {
-        self.index_back - self.index
-    }
-}
+//! `GenericArray` iterator implementation.
+
+use super::{ArrayLength, GenericArray};
+use core::{cmp, ptr, fmt, mem};
+use core::mem::ManuallyDrop;
+
+/// An iterator that moves out of a `GenericArray`
+pub struct GenericArrayIter<T, N: ArrayLength<T>> {
+    // Invariants: index <= index_back <= N
+    // Only values in array[index..index_back] are alive at any given time.
+    // Values from array[..index] and array[index_back..] are already moved/dropped.
+    array: ManuallyDrop<GenericArray<T, N>>,
+    index: usize,
+    index_back: usize,
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+
+    fn send<I: Send>(_iter: I) {}
+
+    #[test]
+    fn test_send_iter() {
+        send(GenericArray::from([1, 2, 3, 4]).into_iter());
+    }
+}
+
+impl<T, N> GenericArrayIter<T, N>
+where
+    N: ArrayLength<T>,
+{
+    /// Returns the remaining items of this iterator as a slice
+    #[inline]
+    pub fn as_slice(&self) -> &[T] {
+        &self.array.as_slice()[self.index..self.index_back]
+    }
+
+    /// Returns the remaining items of this iterator as a mutable slice
+    #[inline]
+    pub fn as_mut_slice(&mut self) -> &mut [T] {
+        &mut self.array.as_mut_slice()[self.index..self.index_back]
+    }
+}
+
+impl<T, N> IntoIterator for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    type Item = T;
+    type IntoIter = GenericArrayIter<T, N>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        GenericArrayIter {
+            array: ManuallyDrop::new(self),
+            index: 0,
+            index_back: N::to_usize(),
+        }
+    }
+}
+
+// Based on work in rust-lang/rust#49000
+impl<T: fmt::Debug, N> fmt::Debug for GenericArrayIter<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_tuple("GenericArrayIter")
+            .field(&self.as_slice())
+            .finish()
+    }
+}
+
+impl<T, N> Drop for GenericArrayIter<T, N>
+where
+    N: ArrayLength<T>,
+{
+    #[inline]
+    fn drop(&mut self) {
+        // Drop values that are still alive.
+        for p in self.as_mut_slice() {
+            unsafe {
+                ptr::drop_in_place(p);
+            }
+        }
+    }
+}
+
+// Based on work in rust-lang/rust#49000
+impl<T: Clone, N> Clone for GenericArrayIter<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn clone(&self) -> Self {
+        // This places all cloned elements at the start of the new array iterator,
+        // not at their original indices.
+        unsafe {
+            let mut iter = GenericArrayIter {
+                array: ManuallyDrop::new(mem::uninitialized()),
+                index: 0,
+                index_back: 0,
+            };
+
+            for (dst, src) in iter.array.iter_mut().zip(self.as_slice()) {
+                ptr::write(dst, src.clone());
+
+                iter.index_back += 1;
+            }
+
+            iter
+        }
+    }
+}
+
+impl<T, N> Iterator for GenericArrayIter<T, N>
+where
+    N: ArrayLength<T>,
+{
+    type Item = T;
+
+    #[inline]
+    fn next(&mut self) -> Option<T> {
+        if self.index < self.index_back {
+            let p = unsafe { Some(ptr::read(self.array.get_unchecked(self.index))) };
+
+            self.index += 1;
+
+            p
+        } else {
+            None
+        }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let len = self.len();
+        (len, Some(len))
+    }
+
+    #[inline]
+    fn count(self) -> usize {
+        self.len()
+    }
+
+    fn nth(&mut self, n: usize) -> Option<T> {
+        // First consume values prior to the nth.
+        let ndrop = cmp::min(n, self.len());
+
+        for p in &mut self.array[self.index..self.index + ndrop] {
+            self.index += 1;
+
+            unsafe {
+                ptr::drop_in_place(p);
+            }
+        }
+
+        self.next()
+    }
+
+    fn last(mut self) -> Option<T> {
+        // Note, everything else will correctly drop first as `self` leaves scope.
+        self.next_back()
+    }
+}
+
+impl<T, N> DoubleEndedIterator for GenericArrayIter<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn next_back(&mut self) -> Option<T> {
+        if self.index < self.index_back {
+            self.index_back -= 1;
+
+            unsafe { Some(ptr::read(self.array.get_unchecked(self.index_back))) }
+        } else {
+            None
+        }
+    }
+}
+
+impl<T, N> ExactSizeIterator for GenericArrayIter<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn len(&self) -> usize {
+        self.index_back - self.index
+    }
+}
+
+// TODO: Implement `FusedIterator` and `TrustedLen` when stabilized
\ No newline at end of file
--- a/third_party/rust/generic-array/src/lib.rs
+++ b/third_party/rust/generic-array/src/lib.rs
@@ -1,464 +1,630 @@
-//! This crate implements a structure that can be used as a generic array type.use
-//! Core Rust array types `[T; N]` can't be used generically with
-//! respect to `N`, so for example this:
-//!
-//! ```{should_fail}
-//! struct Foo<T, N> {
-//!     data: [T; N]
-//! }
-//! ```
-//!
-//! won't work.
-//!
-//! **generic-array** exports a `GenericArray<T,N>` type, which lets
-//! the above be implemented as:
-//!
-//! ```
-//! # use generic_array::{ArrayLength, GenericArray};
-//! struct Foo<T, N: ArrayLength<T>> {
-//!     data: GenericArray<T,N>
-//! }
-//! ```
-//!
-//! The `ArrayLength<T>` trait is implemented by default for
-//! [unsigned integer types](../typenum/uint/index.html) from
-//! [typenum](../typenum/index.html).
-//!
-//! For ease of use, an `arr!` macro is provided - example below:
-//!
-//! ```
-//! # #[macro_use]
-//! # extern crate generic_array;
-//! # extern crate typenum;
-//! # fn main() {
-//! let array = arr![u32; 1, 2, 3];
-//! assert_eq!(array[2], 3);
-//! # }
-//! ```
-
-//#![deny(missing_docs)]
-#![no_std]
-
-pub extern crate typenum;
-#[cfg(feature = "serde")]
-extern crate serde;
-
-mod hex;
-mod impls;
-
-#[cfg(feature = "serde")]
-pub mod impl_serde;
-
-use core::{mem, ptr, slice};
-
-use core::marker::PhantomData;
-use core::mem::ManuallyDrop;
-pub use core::mem::transmute;
-use core::ops::{Deref, DerefMut};
-
-use typenum::bit::{B0, B1};
-use typenum::uint::{UInt, UTerm, Unsigned};
-
-#[cfg_attr(test, macro_use)]
-pub mod arr;
-pub mod iter;
-pub use iter::GenericArrayIter;
-
-/// Trait making `GenericArray` work, marking types to be used as length of an array
-pub unsafe trait ArrayLength<T>: Unsigned {
-    /// Associated type representing the array type for the number
-    type ArrayType;
-}
-
-unsafe impl<T> ArrayLength<T> for UTerm {
-    #[doc(hidden)]
-    type ArrayType = ();
-}
-
-/// Internal type used to generate a struct of appropriate size
-#[allow(dead_code)]
-#[repr(C)]
-#[doc(hidden)]
-pub struct GenericArrayImplEven<T, U> {
-    parent1: U,
-    parent2: U,
-    _marker: PhantomData<T>,
-}
-
-impl<T: Clone, U: Clone> Clone for GenericArrayImplEven<T, U> {
-    fn clone(&self) -> GenericArrayImplEven<T, U> {
-        GenericArrayImplEven {
-            parent1: self.parent1.clone(),
-            parent2: self.parent2.clone(),
-            _marker: PhantomData,
-        }
-    }
-}
-
-impl<T: Copy, U: Copy> Copy for GenericArrayImplEven<T, U> {}
-
-/// Internal type used to generate a struct of appropriate size
-#[allow(dead_code)]
-#[repr(C)]
-#[doc(hidden)]
-pub struct GenericArrayImplOdd<T, U> {
-    parent1: U,
-    parent2: U,
-    data: T,
-}
-
-impl<T: Clone, U: Clone> Clone for GenericArrayImplOdd<T, U> {
-    fn clone(&self) -> GenericArrayImplOdd<T, U> {
-        GenericArrayImplOdd {
-            parent1: self.parent1.clone(),
-            parent2: self.parent2.clone(),
-            data: self.data.clone(),
-        }
-    }
-}
-
-impl<T: Copy, U: Copy> Copy for GenericArrayImplOdd<T, U> {}
-
-unsafe impl<T, N: ArrayLength<T>> ArrayLength<T> for UInt<N, B0> {
-    #[doc(hidden)]
-    type ArrayType = GenericArrayImplEven<T, N::ArrayType>;
-}
-
-unsafe impl<T, N: ArrayLength<T>> ArrayLength<T> for UInt<N, B1> {
-    #[doc(hidden)]
-    type ArrayType = GenericArrayImplOdd<T, N::ArrayType>;
-}
-
-/// Struct representing a generic array - `GenericArray<T, N>` works like [T; N]
-#[allow(dead_code)]
-pub struct GenericArray<T, U: ArrayLength<T>> {
-    data: U::ArrayType,
-}
-
-impl<T, N> Deref for GenericArray<T, N>
-where
-    N: ArrayLength<T>,
-{
-    type Target = [T];
-
-    fn deref(&self) -> &[T] {
-        unsafe { slice::from_raw_parts(self as *const Self as *const T, N::to_usize()) }
-    }
-}
-
-impl<T, N> DerefMut for GenericArray<T, N>
-where
-    N: ArrayLength<T>,
-{
-    fn deref_mut(&mut self) -> &mut [T] {
-        unsafe { slice::from_raw_parts_mut(self as *mut Self as *mut T, N::to_usize()) }
-    }
-}
-
-struct ArrayBuilder<T, N: ArrayLength<T>> {
-    array: ManuallyDrop<GenericArray<T, N>>,
-    position: usize,
-}
-
-impl<T, N: ArrayLength<T>> ArrayBuilder<T, N> {
-    fn new() -> ArrayBuilder<T, N> {
-        ArrayBuilder {
-            array: ManuallyDrop::new(unsafe { mem::uninitialized() }),
-            position: 0,
-        }
-    }
-
-    fn into_inner(self) -> GenericArray<T, N> {
-        let array = unsafe { ptr::read(&self.array) };
-
-        mem::forget(self);
-
-        ManuallyDrop::into_inner(array)
-    }
-}
-
-impl<T, N: ArrayLength<T>> Drop for ArrayBuilder<T, N> {
-    fn drop(&mut self) {
-        for value in self.array.iter_mut().take(self.position) {
-            unsafe {
-                ptr::drop_in_place(value);
-            }
-        }
-    }
-}
-
-struct ArrayConsumer<T, N: ArrayLength<T>> {
-    array: ManuallyDrop<GenericArray<T, N>>,
-    position: usize,
-}
-
-impl<T, N: ArrayLength<T>> ArrayConsumer<T, N> {
-    fn new(array: GenericArray<T, N>) -> ArrayConsumer<T, N> {
-        ArrayConsumer {
-            array: ManuallyDrop::new(array),
-            position: 0,
-        }
-    }
-}
-
-impl<T, N: ArrayLength<T>> Drop for ArrayConsumer<T, N> {
-    fn drop(&mut self) {
-        for i in self.position..N::to_usize() {
-            unsafe {
-                ptr::drop_in_place(self.array.get_unchecked_mut(i));
-            }
-        }
-    }
-}
-
-impl<T, N> GenericArray<T, N>
-where
-    N: ArrayLength<T>,
-{
-    /// Initializes a new `GenericArray` instance using the given function.
-    ///
-    /// If the generator function panics while initializing the array,
-    /// any already initialized elements will be dropped.
-    pub fn generate<F>(f: F) -> GenericArray<T, N>
-    where
-        F: Fn(usize) -> T,
-    {
-        let mut destination = ArrayBuilder::new();
-
-        for (i, dst) in destination.array.iter_mut().enumerate() {
-            unsafe {
-                ptr::write(dst, f(i));
-            }
-
-            destination.position += 1;
-        }
-
-        destination.into_inner()
-    }
-
-    /// Map a function over a slice to a `GenericArray`.
-    ///
-    /// The length of the slice *must* be equal to the length of the array.
-    #[inline]
-    pub fn map_slice<S, F: Fn(&S) -> T>(s: &[S], f: F) -> GenericArray<T, N> {
-        assert_eq!(s.len(), N::to_usize());
-
-        Self::generate(|i| f(unsafe { s.get_unchecked(i) }))
-    }
-
-    /// Maps a `GenericArray` to another `GenericArray`.
-    ///
-    /// If the mapping function panics, any already initialized elements in the new array
-    /// will be dropped, AND any unused elements in the source array will also be dropped.
-    pub fn map<U, F>(self, f: F) -> GenericArray<U, N>
-    where
-        F: Fn(T) -> U,
-        N: ArrayLength<U>,
-    {
-        let mut source = ArrayConsumer::new(self);
-        let mut destination = ArrayBuilder::new();
-
-        for (dst, src) in destination.array.iter_mut().zip(source.array.iter()) {
-            unsafe {
-                ptr::write(dst, f(ptr::read(src)));
-            }
-
-            source.position += 1;
-            destination.position += 1;
-        }
-
-        destination.into_inner()
-    }
-
-    /// Maps a `GenericArray` to another `GenericArray` by reference.
-    ///
-    /// If the mapping function panics, any already initialized elements will be dropped.
-    #[inline]
-    pub fn map_ref<U, F>(&self, f: F) -> GenericArray<U, N>
-    where
-        F: Fn(&T) -> U,
-        N: ArrayLength<U>,
-    {
-        GenericArray::generate(|i| f(unsafe { self.get_unchecked(i) }))
-    }
-
-    /// Combines two `GenericArray` instances and iterates through both of them,
-    /// initializing a new `GenericArray` with the result of the zipped mapping function.
-    ///
-    /// If the mapping function panics, any already initialized elements in the new array
-    /// will be dropped, AND any unused elements in the source arrays will also be dropped.
-    pub fn zip<B, U, F>(self, rhs: GenericArray<B, N>, f: F) -> GenericArray<U, N>
-    where
-        F: Fn(T, B) -> U,
-        N: ArrayLength<B> + ArrayLength<U>,
-    {
-        let mut left = ArrayConsumer::new(self);
-        let mut right = ArrayConsumer::new(rhs);
-
-        let mut destination = ArrayBuilder::new();
-
-        for (dst, (lhs, rhs)) in
-            destination.array.iter_mut().zip(left.array.iter().zip(
-                right.array.iter(),
-            ))
-        {
-            unsafe {
-                ptr::write(dst, f(ptr::read(lhs), ptr::read(rhs)));
-            }
-
-            destination.position += 1;
-            left.position += 1;
-            right.position += 1;
-        }
-
-        destination.into_inner()
-    }
-
-    /// Combines two `GenericArray` instances and iterates through both of them by reference,
-    /// initializing a new `GenericArray` with the result of the zipped mapping function.
-    ///
-    /// If the mapping function panics, any already initialized elements will be dropped.
-    pub fn zip_ref<B, U, F>(&self, rhs: &GenericArray<B, N>, f: F) -> GenericArray<U, N>
-    where
-        F: Fn(&T, &B) -> U,
-        N: ArrayLength<B> + ArrayLength<U>,
-    {
-        GenericArray::generate(|i| unsafe {
-            f(self.get_unchecked(i), rhs.get_unchecked(i))
-        })
-    }
-
-    /// Extracts a slice containing the entire array.
-    #[inline]
-    pub fn as_slice(&self) -> &[T] {
-        self.deref()
-    }
-
-    /// Extracts a mutable slice containing the entire array.
-    #[inline]
-    pub fn as_mut_slice(&mut self) -> &mut [T] {
-        self.deref_mut()
-    }
-
-    /// Converts slice to a generic array reference with inferred length;
-    ///
-    /// Length of the slice must be equal to the length of the array.
-    #[inline]
-    pub fn from_slice(slice: &[T]) -> &GenericArray<T, N> {
-        assert_eq!(slice.len(), N::to_usize());
-
-        unsafe { &*(slice.as_ptr() as *const GenericArray<T, N>) }
-    }
-
-    /// Converts mutable slice to a mutable generic array reference
-    ///
-    /// Length of the slice must be equal to the length of the array.
-    #[inline]
-    pub fn from_mut_slice(slice: &mut [T]) -> &mut GenericArray<T, N> {
-        assert_eq!(slice.len(), N::to_usize());
-
-        unsafe { &mut *(slice.as_mut_ptr() as *mut GenericArray<T, N>) }
-    }
-}
-
-impl<T: Clone, N> GenericArray<T, N>
-where
-    N: ArrayLength<T>,
-{
-    /// Construct a `GenericArray` from a slice by cloning its content
-    ///
-    /// Length of the slice must be equal to the length of the array
-    #[inline]
-    pub fn clone_from_slice(list: &[T]) -> GenericArray<T, N> {
-        Self::from_exact_iter(list.iter().cloned()).expect(
-            "Slice must be the same length as the array",
-        )
-    }
-}
-
-impl<T, N> GenericArray<T, N>
-where
-    N: ArrayLength<T>,
-{
-    pub fn from_exact_iter<I>(iter: I) -> Option<Self>
-    where
-        I: IntoIterator<Item = T>,
-        <I as IntoIterator>::IntoIter: ExactSizeIterator,
-    {
-        let iter = iter.into_iter();
-
-        if iter.len() == N::to_usize() {
-            let mut destination = ArrayBuilder::new();
-
-            for (dst, src) in destination.array.iter_mut().zip(iter.into_iter()) {
-                unsafe {
-                    ptr::write(dst, src);
-                }
-
-                destination.position += 1;
-            }
-
-            let array = unsafe { ptr::read(&destination.array) };
-
-            mem::forget(destination);
-
-            Some(ManuallyDrop::into_inner(array))
-        } else {
-            None
-        }
-    }
-}
-
-impl<T, N> ::core::iter::FromIterator<T> for GenericArray<T, N>
-where
-    N: ArrayLength<T>,
-    T: Default,
-{
-    fn from_iter<I>(iter: I) -> GenericArray<T, N>
-    where
-        I: IntoIterator<Item = T>,
-    {
-        let mut destination = ArrayBuilder::new();
-
-        let defaults = ::core::iter::repeat(()).map(|_| T::default());
-
-        for (dst, src) in destination.array.iter_mut().zip(
-            iter.into_iter().chain(defaults),
-        )
-        {
-            unsafe {
-                ptr::write(dst, src);
-            }
-        }
-
-        destination.into_inner()
-    }
-}
-
-#[cfg(test)]
-mod test {
-    // Compile with:
-    // cargo rustc --lib --profile test --release --
-    //      -C target-cpu=native -C opt-level=3 --emit asm
-    // and view the assembly to make sure test_assembly generates
-    // SIMD instructions instead of a niave loop.
-
-    #[inline(never)]
-    pub fn black_box<T>(val: T) -> T {
-        use core::{mem, ptr};
-
-        let ret = unsafe { ptr::read_volatile(&val) };
-        mem::forget(val);
-        ret
-    }
-
-    #[test]
-    fn test_assembly() {
-        let a = black_box(arr![i32; 1, 3, 5, 7]);
-        let b = black_box(arr![i32; 2, 4, 6, 8]);
-
-        let c = a.zip_ref(&b, |l, r| l + r);
-
-        assert_eq!(c, arr![i32; 3, 7, 11, 15]);
-    }
-}
+//! This crate implements a structure that can be used as a generic array type.use
+//! Core Rust array types `[T; N]` can't be used generically with
+//! respect to `N`, so for example this:
+//!
+//! ```{should_fail}
+//! struct Foo<T, N> {
+//!     data: [T; N]
+//! }
+//! ```
+//!
+//! won't work.
+//!
+//! **generic-array** exports a `GenericArray<T,N>` type, which lets
+//! the above be implemented as:
+//!
+//! ```
+//! # use generic_array::{ArrayLength, GenericArray};
+//! struct Foo<T, N: ArrayLength<T>> {
+//!     data: GenericArray<T,N>
+//! }
+//! ```
+//!
+//! The `ArrayLength<T>` trait is implemented by default for
+//! [unsigned integer types](../typenum/uint/index.html) from
+//! [typenum](../typenum/index.html).
+//!
+//! For ease of use, an `arr!` macro is provided - example below:
+//!
+//! ```
+//! # #[macro_use]
+//! # extern crate generic_array;
+//! # extern crate typenum;
+//! # fn main() {
+//! let array = arr![u32; 1, 2, 3];
+//! assert_eq!(array[2], 3);
+//! # }
+//! ```
+
+#![deny(missing_docs)]
+#![no_std]
+
+#[cfg(feature = "serde")]
+extern crate serde;
+
+#[cfg(test)]
+extern crate bincode;
+
+pub extern crate typenum;
+
+mod hex;
+mod impls;
+
+#[cfg(feature = "serde")]
+pub mod impl_serde;
+
+use core::iter::FromIterator;
+use core::marker::PhantomData;
+use core::mem::ManuallyDrop;
+use core::ops::{Deref, DerefMut};
+use core::{mem, ptr, slice};
+use typenum::bit::{B0, B1};
+use typenum::uint::{UInt, UTerm, Unsigned};
+
+#[cfg_attr(test, macro_use)]
+pub mod arr;
+pub mod functional;
+pub mod iter;
+pub mod sequence;
+
+use functional::*;
+pub use iter::GenericArrayIter;
+use sequence::*;
+
+/// Trait making `GenericArray` work, marking types to be used as length of an array
+pub unsafe trait ArrayLength<T>: Unsigned {
+    /// Associated type representing the array type for the number
+    type ArrayType;
+}
+
+unsafe impl<T> ArrayLength<T> for UTerm {
+    #[doc(hidden)]
+    type ArrayType = ();
+}
+
+/// Internal type used to generate a struct of appropriate size
+#[allow(dead_code)]
+#[repr(C)]
+#[doc(hidden)]
+pub struct GenericArrayImplEven<T, U> {
+    parent1: U,
+    parent2: U,
+    _marker: PhantomData<T>,
+}
+
+impl<T: Clone, U: Clone> Clone for GenericArrayImplEven<T, U> {
+    fn clone(&self) -> GenericArrayImplEven<T, U> {
+        GenericArrayImplEven {
+            parent1: self.parent1.clone(),
+            parent2: self.parent2.clone(),
+            _marker: PhantomData,
+        }
+    }
+}
+
+impl<T: Copy, U: Copy> Copy for GenericArrayImplEven<T, U> {}
+
+/// Internal type used to generate a struct of appropriate size
+#[allow(dead_code)]
+#[repr(C)]
+#[doc(hidden)]
+pub struct GenericArrayImplOdd<T, U> {
+    parent1: U,
+    parent2: U,
+    data: T,
+}
+
+impl<T: Clone, U: Clone> Clone for GenericArrayImplOdd<T, U> {
+    fn clone(&self) -> GenericArrayImplOdd<T, U> {
+        GenericArrayImplOdd {
+            parent1: self.parent1.clone(),
+            parent2: self.parent2.clone(),
+            data: self.data.clone(),
+        }
+    }
+}
+
+impl<T: Copy, U: Copy> Copy for GenericArrayImplOdd<T, U> {}
+
+unsafe impl<T, N: ArrayLength<T>> ArrayLength<T> for UInt<N, B0> {
+    #[doc(hidden)]
+    type ArrayType = GenericArrayImplEven<T, N::ArrayType>;
+}
+
+unsafe impl<T, N: ArrayLength<T>> ArrayLength<T> for UInt<N, B1> {
+    #[doc(hidden)]
+    type ArrayType = GenericArrayImplOdd<T, N::ArrayType>;
+}
+
+/// Struct representing a generic array - `GenericArray<T, N>` works like [T; N]
+#[allow(dead_code)]
+pub struct GenericArray<T, U: ArrayLength<T>> {
+    data: U::ArrayType,
+}
+
+unsafe impl<T: Send, N: ArrayLength<T>> Send for GenericArray<T, N> {}
+unsafe impl<T: Sync, N: ArrayLength<T>> Sync for GenericArray<T, N> {}
+
+impl<T, N> Deref for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    type Target = [T];
+
+    fn deref(&self) -> &[T] {
+        unsafe { slice::from_raw_parts(self as *const Self as *const T, N::to_usize()) }
+    }
+}
+
+impl<T, N> DerefMut for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn deref_mut(&mut self) -> &mut [T] {
+        unsafe { slice::from_raw_parts_mut(self as *mut Self as *mut T, N::to_usize()) }
+    }
+}
+
+/// Creates an array one element at a time using a mutable iterator
+/// you can write to with `ptr::write`.
+///
+/// Incremenent the position while iterating to mark off created elements,
+/// which will be dropped if `into_inner` is not called.
+#[doc(hidden)]
+pub struct ArrayBuilder<T, N: ArrayLength<T>> {
+    array: ManuallyDrop<GenericArray<T, N>>,
+    position: usize,
+}
+
+impl<T, N: ArrayLength<T>> ArrayBuilder<T, N> {
+    #[doc(hidden)]
+    #[inline]
+    pub unsafe fn new() -> ArrayBuilder<T, N> {
+        ArrayBuilder {
+            array: ManuallyDrop::new(mem::uninitialized()),
+            position: 0,
+        }
+    }
+
+    /// Creates a mutable iterator for writing to the array using `ptr::write`.
+    ///
+    /// Increment the position value given as a mutable reference as you iterate
+    /// to mark how many elements have been created.
+    #[doc(hidden)]
+    #[inline]
+    pub unsafe fn iter_position(&mut self) -> (slice::IterMut<T>, &mut usize) {
+        (self.array.iter_mut(), &mut self.position)
+    }
+
+    /// When done writing (assuming all elements have been written to),
+    /// get the inner array.
+    #[doc(hidden)]
+    #[inline]
+    pub unsafe fn into_inner(self) -> GenericArray<T, N> {
+        let array = ptr::read(&self.array);
+
+        mem::forget(self);
+
+        ManuallyDrop::into_inner(array)
+    }
+}
+
+impl<T, N: ArrayLength<T>> Drop for ArrayBuilder<T, N> {
+    fn drop(&mut self) {
+        for value in &mut self.array[..self.position] {
+            unsafe {
+                ptr::drop_in_place(value);
+            }
+        }
+    }
+}
+
+/// Consumes an array.
+///
+/// Increment the position while iterating and any leftover elements
+/// will be dropped if position does not go to N
+#[doc(hidden)]
+pub struct ArrayConsumer<T, N: ArrayLength<T>> {
+    array: ManuallyDrop<GenericArray<T, N>>,
+    position: usize,
+}
+
+impl<T, N: ArrayLength<T>> ArrayConsumer<T, N> {
+    #[doc(hidden)]
+    #[inline]
+    pub unsafe fn new(array: GenericArray<T, N>) -> ArrayConsumer<T, N> {
+        ArrayConsumer {
+            array: ManuallyDrop::new(array),
+            position: 0,
+        }
+    }
+
+    /// Creates an iterator and mutable reference to the internal position
+    /// to keep track of consumed elements.
+    ///
+    /// Increment the position as you iterate to mark off consumed elements
+    #[doc(hidden)]
+    #[inline]
+    pub unsafe fn iter_position(&mut self) -> (slice::Iter<T>, &mut usize) {
+        (self.array.iter(), &mut self.position)
+    }
+}
+
+impl<T, N: ArrayLength<T>> Drop for ArrayConsumer<T, N> {
+    fn drop(&mut self) {
+        for value in &mut self.array[self.position..N::to_usize()] {
+            unsafe {
+                ptr::drop_in_place(value);
+            }
+        }
+    }
+}
+
+impl<'a, T: 'a, N> IntoIterator for &'a GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    type IntoIter = slice::Iter<'a, T>;
+    type Item = &'a T;
+
+    fn into_iter(self: &'a GenericArray<T, N>) -> Self::IntoIter {
+        self.as_slice().iter()
+    }
+}
+
+impl<'a, T: 'a, N> IntoIterator for &'a mut GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    type IntoIter = slice::IterMut<'a, T>;
+    type Item = &'a mut T;
+
+    fn into_iter(self: &'a mut GenericArray<T, N>) -> Self::IntoIter {
+        self.as_mut_slice().iter_mut()
+    }
+}
+
+impl<T, N> FromIterator<T> for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    fn from_iter<I>(iter: I) -> GenericArray<T, N>
+    where
+        I: IntoIterator<Item = T>,
+    {
+        unsafe {
+            let mut destination = ArrayBuilder::new();
+
+            {
+                let (destination_iter, position) = destination.iter_position();
+
+                for (src, dst) in iter.into_iter().zip(destination_iter) {
+                    ptr::write(dst, src);
+
+                    *position += 1;
+                }
+            }
+
+            if destination.position < N::to_usize() {
+                from_iter_length_fail(destination.position, N::to_usize());
+            }
+
+            destination.into_inner()
+        }
+    }
+}
+
+#[inline(never)]
+#[cold]
+fn from_iter_length_fail(length: usize, expected: usize) -> ! {
+    panic!(
+        "GenericArray::from_iter received {} elements but expected {}",
+        length, expected
+    );
+}
+
+unsafe impl<T, N> GenericSequence<T> for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+    Self: IntoIterator<Item = T>,
+{
+    type Length = N;
+    type Sequence = Self;
+
+    fn generate<F>(mut f: F) -> GenericArray<T, N>
+    where
+        F: FnMut(usize) -> T,
+    {
+        unsafe {
+            let mut destination = ArrayBuilder::new();
+
+            {
+                let (destination_iter, position) = destination.iter_position();
+
+                for (i, dst) in destination_iter.enumerate() {
+                    ptr::write(dst, f(i));
+
+                    *position += 1;
+                }
+            }
+
+            destination.into_inner()
+        }
+    }
+
+    #[doc(hidden)]
+    fn inverted_zip<B, U, F>(
+        self,
+        lhs: GenericArray<B, Self::Length>,
+        mut f: F,
+    ) -> MappedSequence<GenericArray<B, Self::Length>, B, U>
+    where
+        GenericArray<B, Self::Length>:
+            GenericSequence<B, Length = Self::Length> + MappedGenericSequence<B, U>,
+        Self: MappedGenericSequence<T, U>,
+        Self::Length: ArrayLength<B> + ArrayLength<U>,
+        F: FnMut(B, Self::Item) -> U,
+    {
+        unsafe {
+            let mut left = ArrayConsumer::new(lhs);
+            let mut right = ArrayConsumer::new(self);
+
+            let (left_array_iter, left_position) = left.iter_position();
+            let (right_array_iter, right_position) = right.iter_position();
+
+            FromIterator::from_iter(left_array_iter.zip(right_array_iter).map(|(l, r)| {
+                let left_value = ptr::read(l);
+                let right_value = ptr::read(r);
+
+                *left_position += 1;
+                *right_position += 1;
+
+                f(left_value, right_value)
+            }))
+        }
+    }
+
+    #[doc(hidden)]
+    fn inverted_zip2<B, Lhs, U, F>(self, lhs: Lhs, mut f: F) -> MappedSequence<Lhs, B, U>
+    where
+        Lhs: GenericSequence<B, Length = Self::Length> + MappedGenericSequence<B, U>,
+        Self: MappedGenericSequence<T, U>,
+        Self::Length: ArrayLength<B> + ArrayLength<U>,
+        F: FnMut(Lhs::Item, Self::Item) -> U,
+    {
+        unsafe {
+            let mut right = ArrayConsumer::new(self);
+
+            let (right_array_iter, right_position) = right.iter_position();
+
+            FromIterator::from_iter(
+                lhs.into_iter()
+                    .zip(right_array_iter)
+                    .map(|(left_value, r)| {
+                        let right_value = ptr::read(r);
+
+                        *right_position += 1;
+
+                        f(left_value, right_value)
+                    }),
+            )
+        }
+    }
+}
+
+unsafe impl<T, U, N> MappedGenericSequence<T, U> for GenericArray<T, N>
+where
+    N: ArrayLength<T> + ArrayLength<U>,
+    GenericArray<U, N>: GenericSequence<U, Length = N>,
+{
+    type Mapped = GenericArray<U, N>;
+}
+
+unsafe impl<T, N> FunctionalSequence<T> for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+    Self: GenericSequence<T, Item = T, Length = N>,
+{
+    fn map<U, F>(self, mut f: F) -> MappedSequence<Self, T, U>
+    where
+        Self::Length: ArrayLength<U>,
+        Self: MappedGenericSequence<T, U>,
+        F: FnMut(T) -> U,
+    {
+        unsafe {
+            let mut source = ArrayConsumer::new(self);
+
+            let (array_iter, position) = source.iter_position();
+
+            FromIterator::from_iter(array_iter.map(|src| {
+                let value = ptr::read(src);
+
+                *position += 1;
+
+                f(value)
+            }))
+        }
+    }
+
+    #[inline]
+    fn zip<B, Rhs, U, F>(self, rhs: Rhs, f: F) -> MappedSequence<Self, T, U>
+    where
+        Self: MappedGenericSequence<T, U>,
+        Rhs: MappedGenericSequence<B, U, Mapped = MappedSequence<Self, T, U>>,
+        Self::Length: ArrayLength<B> + ArrayLength<U>,
+        Rhs: GenericSequence<B, Length = Self::Length>,
+        F: FnMut(T, Rhs::Item) -> U,
+    {
+        rhs.inverted_zip(self, f)
+    }
+
+    fn fold<U, F>(self, init: U, mut f: F) -> U
+    where
+        F: FnMut(U, T) -> U,
+    {
+        unsafe {
+            let mut source = ArrayConsumer::new(self);
+
+            let (array_iter, position) = source.iter_position();
+
+            array_iter.fold(init, |acc, src| {
+                let value = ptr::read(src);
+
+                *position += 1;
+
+                f(acc, value)
+            })
+        }
+    }
+}
+
+impl<T, N> GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    /// Extracts a slice containing the entire array.
+    #[inline]
+    pub fn as_slice(&self) -> &[T] {
+        self.deref()
+    }
+
+    /// Extracts a mutable slice containing the entire array.
+    #[inline]
+    pub fn as_mut_slice(&mut self) -> &mut [T] {
+        self.deref_mut()
+    }
+
+    /// Converts slice to a generic array reference with inferred length;
+    ///
+    /// Length of the slice must be equal to the length of the array.
+    #[inline]
+    pub fn from_slice(slice: &[T]) -> &GenericArray<T, N> {
+        slice.into()
+    }
+
+    /// Converts mutable slice to a mutable generic array reference
+    ///
+    /// Length of the slice must be equal to the length of the array.
+    #[inline]
+    pub fn from_mut_slice(slice: &mut [T]) -> &mut GenericArray<T, N> {
+        slice.into()
+    }
+}
+
+impl<'a, T, N: ArrayLength<T>> From<&'a [T]> for &'a GenericArray<T, N> {
+    /// Converts slice to a generic array reference with inferred length;
+    ///
+    /// Length of the slice must be equal to the length of the array.
+    #[inline]
+    fn from(slice: &[T]) -> &GenericArray<T, N> {
+        assert_eq!(slice.len(), N::to_usize());
+
+        unsafe { &*(slice.as_ptr() as *const GenericArray<T, N>) }
+    }
+}
+
+impl<'a, T, N: ArrayLength<T>> From<&'a mut [T]> for &'a mut GenericArray<T, N> {
+    /// Converts mutable slice to a mutable generic array reference
+    ///
+    /// Length of the slice must be equal to the length of the array.
+    #[inline]
+    fn from(slice: &mut [T]) -> &mut GenericArray<T, N> {
+        assert_eq!(slice.len(), N::to_usize());
+
+        unsafe { &mut *(slice.as_mut_ptr() as *mut GenericArray<T, N>) }
+    }
+}
+
+impl<T: Clone, N> GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    /// Construct a `GenericArray` from a slice by cloning its content
+    ///
+    /// Length of the slice must be equal to the length of the array
+    #[inline]
+    pub fn clone_from_slice(list: &[T]) -> GenericArray<T, N> {
+        Self::from_exact_iter(list.iter().cloned())
+            .expect("Slice must be the same length as the array")
+    }
+}
+
+impl<T, N> GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+{
+    /// Creates a new `GenericArray` instance from an iterator with a known exact size.
+    ///
+    /// Returns `None` if the size is not equal to the number of elements in the `GenericArray`.
+    pub fn from_exact_iter<I>(iter: I) -> Option<Self>
+    where
+        I: IntoIterator<Item = T>,
+        <I as IntoIterator>::IntoIter: ExactSizeIterator,
+    {
+        let iter = iter.into_iter();
+
+        if iter.len() == N::to_usize() {
+            unsafe {
+                let mut destination = ArrayBuilder::new();
+
+                {
+                    let (destination_iter, position) = destination.iter_position();
+
+                    for (dst, src) in destination_iter.zip(iter.into_iter()) {
+                        ptr::write(dst, src);
+
+                        *position += 1;
+                    }
+                }
+
+                Some(destination.into_inner())
+            }
+        } else {
+            None
+        }
+    }
+}
+
+/// A reimplementation of the `transmute` function, avoiding problems
+/// when the compiler can't prove equal sizes.
+#[inline]
+#[doc(hidden)]
+pub unsafe fn transmute<A, B>(a: A) -> B {
+    let b = ::core::ptr::read(&a as *const A as *const B);
+    ::core::mem::forget(a);
+    b
+}
+
+#[cfg(test)]
+mod test {
+    // Compile with:
+    // cargo rustc --lib --profile test --release --
+    //      -C target-cpu=native -C opt-level=3 --emit asm
+    // and view the assembly to make sure test_assembly generates
+    // SIMD instructions instead of a niave loop.
+
+    #[inline(never)]
+    pub fn black_box<T>(val: T) -> T {
+        use core::{mem, ptr};
+
+        let ret = unsafe { ptr::read_volatile(&val) };
+        mem::forget(val);
+        ret
+    }
+
+    #[test]
+    fn test_assembly() {
+        use functional::*;
+
+        let a = black_box(arr![i32; 1, 3, 5, 7]);
+        let b = black_box(arr![i32; 2, 4, 6, 8]);
+
+        let c = (&a).zip(b, |l, r| l + r);
+
+        let d = a.fold(0, |a, x| a + x);
+
+        assert_eq!(c, arr![i32; 3, 7, 11, 15]);
+
+        assert_eq!(d, 16);
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/generic-array/src/sequence.rs
@@ -0,0 +1,320 @@
+//! Useful traits for manipulating sequences of data stored in `GenericArray`s
+
+use super::*;
+use core::{mem, ptr};
+use core::ops::{Add, Sub};
+use typenum::operator_aliases::*;
+
+/// Defines some sequence with an associated length and iteration capabilities.
+///
+/// This is useful for passing N-length generic arrays as generics.
+pub unsafe trait GenericSequence<T>: Sized + IntoIterator {
+    /// `GenericArray` associated length
+    type Length: ArrayLength<T>;
+
+    /// Concrete sequence type used in conjuction with reference implementations of `GenericSequence`
+    type Sequence: GenericSequence<T, Length = Self::Length> + FromIterator<T>;
+
+    /// Initializes a new sequence instance using the given function.
+    ///
+    /// If the generator function panics while initializing the sequence,
+    /// any already initialized elements will be dropped.
+    fn generate<F>(f: F) -> Self::Sequence
+    where
+        F: FnMut(usize) -> T;
+
+    #[doc(hidden)]
+    fn inverted_zip<B, U, F>(
+        self,
+        lhs: GenericArray<B, Self::Length>,
+        mut f: F,
+    ) -> MappedSequence<GenericArray<B, Self::Length>, B, U>
+    where
+        GenericArray<B, Self::Length>: GenericSequence<B, Length = Self::Length>
+            + MappedGenericSequence<B, U>,
+        Self: MappedGenericSequence<T, U>,
+        Self::Length: ArrayLength<B> + ArrayLength<U>,
+        F: FnMut(B, Self::Item) -> U,
+    {
+        unsafe {
+            let mut left = ArrayConsumer::new(lhs);
+
+            let (left_array_iter, left_position) = left.iter_position();
+
+            FromIterator::from_iter(
+                left_array_iter
+                    .zip(self.into_iter())
+                    .map(|(l, right_value)| {
+                        let left_value = ptr::read(l);
+
+                        *left_position += 1;
+
+                        f(left_value, right_value)
+                    })
+            )
+        }
+    }
+
+    #[doc(hidden)]
+    fn inverted_zip2<B, Lhs, U, F>(self, lhs: Lhs, mut f: F) -> MappedSequence<Lhs, B, U>
+    where
+        Lhs: GenericSequence<B, Length = Self::Length> + MappedGenericSequence<B, U>,
+        Self: MappedGenericSequence<T, U>,
+        Self::Length: ArrayLength<B> + ArrayLength<U>,
+        F: FnMut(Lhs::Item, Self::Item) -> U,
+    {
+        FromIterator::from_iter(lhs.into_iter().zip(self.into_iter()).map(|(l, r)| f(l, r)))
+    }
+}
+
+/// Accessor for `GenericSequence` item type, which is really `IntoIterator::Item`
+///
+/// For deeply nested generic mapped sequence types, like shown in `tests/generics.rs`,
+/// this can be useful for keeping things organized.
+pub type SequenceItem<T> = <T as IntoIterator>::Item;
+
+unsafe impl<'a, T: 'a, S: GenericSequence<T>> GenericSequence<T> for &'a S
+where
+    &'a S: IntoIterator,
+{
+    type Length = S::Length;
+    type Sequence = S::Sequence;
+
+    #[inline]
+    fn generate<F>(f: F) -> Self::Sequence
+    where
+        F: FnMut(usize) -> T,
+    {
+        S::generate(f)
+    }
+}
+
+unsafe impl<'a, T: 'a, S: GenericSequence<T>> GenericSequence<T> for &'a mut S
+where
+    &'a mut S: IntoIterator,
+{
+    type Length = S::Length;
+    type Sequence = S::Sequence;
+
+    #[inline]
+    fn generate<F>(f: F) -> Self::Sequence
+    where
+        F: FnMut(usize) -> T,
+    {
+        S::generate(f)
+    }
+}
+
+/// Defines any `GenericSequence` which can be lengthened or extended by appending
+/// or prepending an element to it.
+///
+/// Any lengthened sequence can be shortened back to the original using `pop_front` or `pop_back`
+pub unsafe trait Lengthen<T>: Sized + GenericSequence<T> {
+    /// `GenericSequence` that has one more element than `Self`
+    type Longer: Shorten<T, Shorter = Self>;
+
+    /// Returns a new array with the given element appended to the end of it.
+    ///
+    /// Example:
+    ///
+    /// ```ignore
+    /// let a = arr![i32; 1, 2, 3];
+    ///
+    /// let b = a.append(4);
+    ///
+    /// assert_eq!(b, arr![i32; 1, 2, 3, 4]);
+    /// ```
+    fn append(self, last: T) -> Self::Longer;
+
+    /// Returns a new array with the given element prepended to the front of it.
+    ///
+    /// Example:
+    ///
+    /// ```ignore
+    /// let a = arr![i32; 1, 2, 3];
+    ///
+    /// let b = a.prepend(4);
+    ///
+    /// assert_eq!(b, arr![i32; 4, 1, 2, 3]);
+    /// ```
+    fn prepend(self, first: T) -> Self::Longer;
+}
+
+/// Defines a `GenericSequence` which can be shortened by removing the first or last element from it.
+///
+/// Additionally, any shortened sequence can be lengthened by
+/// appending or prepending an element to it.
+pub unsafe trait Shorten<T>: Sized + GenericSequence<T> {
+    /// `GenericSequence` that has one less element than `Self`
+    type Shorter: Lengthen<T, Longer = Self>;
+
+    /// Returns a new array without the last element, and the last element.
+    ///
+    /// Example:
+    ///
+    /// ```ignore
+    /// let a = arr![i32; 1, 2, 3, 4];
+    ///
+    /// let (init, last) = a.pop_back();
+    ///
+    /// assert_eq!(init, arr![i32; 1, 2, 3]);
+    /// assert_eq!(last, 4);
+    /// ```
+    fn pop_back(self) -> (Self::Shorter, T);
+
+    /// Returns a new array without the first element, and the first element.
+    /// Example:
+    ///
+    /// ```ignore
+    /// let a = arr![i32; 1, 2, 3, 4];
+    ///
+    /// let (head, tail) = a.pop_front();
+    ///
+    /// assert_eq!(head, 1);
+    /// assert_eq!(tail, arr![i32; 2, 3, 4]);
+    /// ```
+    fn pop_front(self) -> (T, Self::Shorter);
+}
+
+unsafe impl<T, N: ArrayLength<T>> Lengthen<T> for GenericArray<T, N>
+where
+    N: Add<B1>,
+    Add1<N>: ArrayLength<T>,
+    Add1<N>: Sub<B1, Output = N>,
+    Sub1<Add1<N>>: ArrayLength<T>,
+{
+    type Longer = GenericArray<T, Add1<N>>;
+
+    fn append(self, last: T) -> Self::Longer {
+        let mut longer: Self::Longer = unsafe { mem::uninitialized() };
+
+        unsafe {
+            ptr::write(longer.as_mut_ptr() as *mut _, self);
+            ptr::write(&mut longer[N::to_usize()], last);
+        }
+
+        longer
+    }
+
+    fn prepend(self, first: T) -> Self::Longer {
+        let mut longer: Self::Longer = unsafe { mem::uninitialized() };
+
+        let longer_ptr = longer.as_mut_ptr();
+
+        unsafe {
+            ptr::write(longer_ptr as *mut _, first);
+            ptr::write(longer_ptr.offset(1) as *mut _, self);
+        }
+
+        longer
+    }
+}
+
+unsafe impl<T, N: ArrayLength<T>> Shorten<T> for GenericArray<T, N>
+where
+    N: Sub<B1>,
+    Sub1<N>: ArrayLength<T>,
+    Sub1<N>: Add<B1, Output = N>,
+    Add1<Sub1<N>>: ArrayLength<T>,
+{
+    type Shorter = GenericArray<T, Sub1<N>>;
+
+    fn pop_back(self) -> (Self::Shorter, T) {
+        let init_ptr = self.as_ptr();
+        let last_ptr = unsafe { init_ptr.offset(Sub1::<N>::to_usize() as isize) };
+
+        let init = unsafe { ptr::read(init_ptr as _) };
+        let last = unsafe { ptr::read(last_ptr as _) };
+
+        mem::forget(self);
+
+        (init, last)
+    }
+
+    fn pop_front(self) -> (T, Self::Shorter) {
+        let head_ptr = self.as_ptr();
+        let tail_ptr = unsafe { head_ptr.offset(1) };
+
+        let head = unsafe { ptr::read(head_ptr as _) };
+        let tail = unsafe { ptr::read(tail_ptr as _) };
+
+        mem::forget(self);
+
+        (head, tail)
+    }
+}
+
+/// Defines a `GenericSequence` that can be split into two parts at a given pivot index.
+pub unsafe trait Split<T, K>: GenericSequence<T>
+where
+    K: ArrayLength<T>,
+{
+    /// First part of the resulting split array
+    type First: GenericSequence<T>;
+    /// Second part of the resulting split array
+    type Second: GenericSequence<T>;
+
+    /// Splits an array at the given index, returning the separate parts of the array.
+    fn split(self) -> (Self::First, Self::Second);
+}
+
+unsafe impl<T, N, K> Split<T, K> for GenericArray<T, N>
+where
+    N: ArrayLength<T>,
+    K: ArrayLength<T>,
+    N: Sub<K>,
+    Diff<N, K>: ArrayLength<T>,
+{
+    type First = GenericArray<T, K>;
+    type Second = GenericArray<T, Diff<N, K>>;
+
+    fn split(self) -> (Self::First, Self::Second) {
+        let head_ptr = self.as_ptr();
+        let tail_ptr = unsafe { head_ptr.offset(K::to_usize() as isize) };
+
+        let head = unsafe { ptr::read(head_ptr as _) };
+        let tail = unsafe { ptr::read(tail_ptr as _) };
+
+        mem::forget(self);
+
+        (head, tail)
+    }
+}
+
+/// Defines `GenericSequence`s which can be joined together, forming a larger array.
+pub unsafe trait Concat<T, M>: GenericSequence<T>
+where
+    M: ArrayLength<T>,
+{
+    /// Sequence to be concatenated with `self`
+    type Rest: GenericSequence<T, Length = M>;
+
+    /// Resulting sequence formed by the concatenation.
+    type Output: GenericSequence<T>;
+
+    /// Concatenate, or join, two sequences.
+    fn concat(self, rest: Self::Rest) -> Self::Output;
+}
+
+unsafe impl<T, N, M> Concat<T, M> for GenericArray<T, N>
+where
+    N: ArrayLength<T> + Add<M>,
+    M: ArrayLength<T>,
+    Sum<N, M>: ArrayLength<T>,
+{
+    type Rest = GenericArray<T, M>;
+    type Output = GenericArray<T, Sum<N, M>>;
+
+    fn concat(self, rest: Self::Rest) -> Self::Output {
+        let mut output: Self::Output = unsafe { mem::uninitialized() };
+
+        let output_ptr = output.as_mut_ptr();
+
+        unsafe {
+            ptr::write(output_ptr as *mut _, self);
+            ptr::write(output_ptr.offset(N::to_usize() as isize) as *mut _, rest);
+        }
+
+        output
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/generic-array/tests/arr.rs
@@ -0,0 +1,27 @@
+#[macro_use]
+extern crate generic_array;
+extern crate typenum;
+
+#[test]
+fn empty_without_trailing_comma() {
+    let ar = arr![u8; ];
+    assert_eq!(format!("{:x}", ar), "");
+}
+
+#[test]
+fn empty_with_trailing_comma() {
+    let ar = arr![u8; , ];
+    assert_eq!(format!("{:x}", ar), "");
+}
+
+#[test]
+fn without_trailing_comma() {
+    let ar = arr![u8; 10, 20, 30];
+    assert_eq!(format!("{:x}", ar), "0a141e");
+}
+
+#[test]
+fn with_trailing_comma() {
+    let ar = arr![u8; 10, 20, 30, ];
+    assert_eq!(format!("{:x}", ar), "0a141e");
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/generic-array/tests/generics.rs
@@ -0,0 +1,98 @@
+#![recursion_limit = "128"]
+
+#[macro_use]
+extern crate generic_array;
+
+use generic_array::typenum::consts::U4;
+
+use std::fmt::Debug;
+use std::ops::Add;
+
+use generic_array::{GenericArray, ArrayLength};
+use generic_array::sequence::*;
+use generic_array::functional::*;
+
+/// Example function using generics to pass N-length sequences and map them
+pub fn generic_map<S>(s: S)
+where
+    S: FunctionalSequence<i32>,            // `.map`
+    S::Item: Add<i32, Output = i32>,       // `x + 1`
+    S: MappedGenericSequence<i32, i32>,    // `i32` -> `i32`
+    MappedSequence<S, i32, i32>: Debug,    // println!
+{
+    let a = s.map(|x| x + 1);
+
+    println!("{:?}", a);