Bug 1516304 - Re-vendor rust dependencies. r=kats
authorWR Updater Bot <graphics-team@mozilla.staktrace.com>
Tue, 25 Dec 2018 01:11:35 +0000
changeset 451894 e6dc0ee80b24e9625efd615f4632fc21b750bcdd
parent 451893 3f05c8bf3f70ab2c546b19178acc645dff73c002
child 451895 529855658a3a99bdf428d4cbcfd1be5ce53e3717
push id35269
push useraiakab@mozilla.com
push dateTue, 25 Dec 2018 09:50:14 +0000
treeherdermozilla-central@f90034ef430e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1516304
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1516304 - Re-vendor rust dependencies. r=kats Depends on D15315 Differential Revision: https://phabricator.services.mozilla.com/D15316
Cargo.lock
third_party/rust/block-buffer-0.3.3/.cargo-checksum.json
third_party/rust/block-buffer-0.3.3/Cargo.toml
third_party/rust/block-buffer-0.3.3/LICENSE-APACHE
third_party/rust/block-buffer-0.3.3/LICENSE-MIT
third_party/rust/block-buffer-0.3.3/src/lib.rs
third_party/rust/block-buffer-0.3.3/src/paddings.rs
third_party/rust/block-buffer/.cargo-checksum.json
third_party/rust/block-buffer/Cargo.toml
third_party/rust/block-buffer/src/lib.rs
third_party/rust/block-buffer/src/paddings.rs
third_party/rust/block-padding/.cargo-checksum.json
third_party/rust/block-padding/Cargo.toml
third_party/rust/block-padding/LICENSE-APACHE
third_party/rust/block-padding/LICENSE-MIT
third_party/rust/block-padding/src/lib.rs
third_party/rust/byte-tools-0.2.0/.cargo-checksum.json
third_party/rust/byte-tools-0.2.0/Cargo.toml
third_party/rust/byte-tools-0.2.0/LICENSE-APACHE
third_party/rust/byte-tools-0.2.0/LICENSE-MIT
third_party/rust/byte-tools-0.2.0/src/lib.rs
third_party/rust/byte-tools-0.2.0/src/read_single.rs
third_party/rust/byte-tools-0.2.0/src/read_slice.rs
third_party/rust/byte-tools-0.2.0/src/write_single.rs
third_party/rust/byte-tools-0.2.0/src/write_slice.rs
third_party/rust/byte-tools/.cargo-checksum.json
third_party/rust/byte-tools/Cargo.toml
third_party/rust/byte-tools/src/lib.rs
third_party/rust/byte-tools/src/read_single.rs
third_party/rust/byte-tools/src/read_slice.rs
third_party/rust/byte-tools/src/write_single.rs
third_party/rust/byte-tools/src/write_slice.rs
third_party/rust/digest-0.7.6/.cargo-checksum.json
third_party/rust/digest-0.7.6/Cargo.toml
third_party/rust/digest-0.7.6/LICENSE-APACHE
third_party/rust/digest-0.7.6/LICENSE-MIT
third_party/rust/digest-0.7.6/src/dev.rs
third_party/rust/digest-0.7.6/src/digest.rs
third_party/rust/digest-0.7.6/src/errors.rs
third_party/rust/digest-0.7.6/src/lib.rs
third_party/rust/digest/.cargo-checksum.json
third_party/rust/digest/Cargo.toml
third_party/rust/digest/src/dev.rs
third_party/rust/digest/src/digest.rs
third_party/rust/digest/src/dyn_digest.rs
third_party/rust/digest/src/errors.rs
third_party/rust/digest/src/lib.rs
third_party/rust/generic-array-0.9.0/.cargo-checksum.json
third_party/rust/generic-array-0.9.0/Cargo.toml
third_party/rust/generic-array-0.9.0/LICENSE
third_party/rust/generic-array-0.9.0/README.md
third_party/rust/generic-array-0.9.0/rustfmt.toml
third_party/rust/generic-array-0.9.0/src/arr.rs
third_party/rust/generic-array-0.9.0/src/hex.rs
third_party/rust/generic-array-0.9.0/src/impl_serde.rs
third_party/rust/generic-array-0.9.0/src/impls.rs
third_party/rust/generic-array-0.9.0/src/iter.rs
third_party/rust/generic-array-0.9.0/src/lib.rs
third_party/rust/generic-array-0.9.0/tests/hex.rs
third_party/rust/generic-array-0.9.0/tests/import_name.rs
third_party/rust/generic-array-0.9.0/tests/mod.rs
third_party/rust/generic-array/.cargo-checksum.json
third_party/rust/generic-array/CHANGELOG.md
third_party/rust/generic-array/Cargo.toml
third_party/rust/generic-array/LICENSE
third_party/rust/generic-array/README.md
third_party/rust/generic-array/rustfmt.toml
third_party/rust/generic-array/src/arr.rs
third_party/rust/generic-array/src/functional.rs
third_party/rust/generic-array/src/hex.rs
third_party/rust/generic-array/src/impl_serde.rs
third_party/rust/generic-array/src/impls.rs
third_party/rust/generic-array/src/iter.rs
third_party/rust/generic-array/src/lib.rs
third_party/rust/generic-array/src/sequence.rs
third_party/rust/generic-array/tests/arr.rs
third_party/rust/generic-array/tests/generics.rs
third_party/rust/generic-array/tests/hex.rs
third_party/rust/generic-array/tests/import_name.rs
third_party/rust/generic-array/tests/iter.rs
third_party/rust/generic-array/tests/mod.rs
third_party/rust/opaque-debug/.cargo-checksum.json
third_party/rust/opaque-debug/Cargo.toml
third_party/rust/opaque-debug/LICENSE-APACHE
third_party/rust/opaque-debug/LICENSE-MIT
third_party/rust/opaque-debug/src/lib.rs
third_party/rust/sha2-0.7.1/.cargo-checksum.json
third_party/rust/sha2-0.7.1/Cargo.toml
third_party/rust/sha2-0.7.1/LICENSE-APACHE
third_party/rust/sha2-0.7.1/LICENSE-MIT
third_party/rust/sha2-0.7.1/benches/sha256.rs
third_party/rust/sha2-0.7.1/benches/sha512.rs
third_party/rust/sha2-0.7.1/examples/sha256sum.rs
third_party/rust/sha2-0.7.1/examples/sha512sum.rs
third_party/rust/sha2-0.7.1/src/consts.rs
third_party/rust/sha2-0.7.1/src/lib.rs
third_party/rust/sha2-0.7.1/src/sha256.rs
third_party/rust/sha2-0.7.1/src/sha256_utils.rs
third_party/rust/sha2-0.7.1/src/sha512.rs
third_party/rust/sha2-0.7.1/src/sha512_utils.rs
third_party/rust/sha2-0.7.1/tests/data/sha224/test1.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha224/test1.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha224/test2.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha224/test2.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha224/test3.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha224/test3.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha256/one_million_a.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha256/test1.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha256/test1.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha256/test2.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha256/test2.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha256/test3.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha256/test3.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha384/test1.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha384/test1.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha384/test2.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha384/test2.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha384/test3.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha384/test3.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha512/one_million_a.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha512/test1.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha512/test1.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha512/test2.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha512/test2.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha512/test3.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha512/test3.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha512_224/test1.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha512_224/test1.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha512_224/test2.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha512_224/test2.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha512_224/test3.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha512_224/test3.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha512_256/test1.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha512_256/test1.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha512_256/test2.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha512_256/test2.output.bin
third_party/rust/sha2-0.7.1/tests/data/sha512_256/test3.input.bin
third_party/rust/sha2-0.7.1/tests/data/sha512_256/test3.output.bin
third_party/rust/sha2-0.7.1/tests/lib.rs
third_party/rust/sha2/.cargo-checksum.json
third_party/rust/sha2/Cargo.toml
third_party/rust/sha2/benches/sha256.rs
third_party/rust/sha2/benches/sha512.rs
third_party/rust/sha2/src/lib.rs
third_party/rust/sha2/src/sha256.rs
third_party/rust/sha2/src/sha256_utils.rs
third_party/rust/sha2/src/sha512.rs
third_party/rust/sha2/src/sha512_utils.rs
third_party/rust/sha2/tests/data/sha224.blb
third_party/rust/sha2/tests/data/sha224/test1.input.bin
third_party/rust/sha2/tests/data/sha224/test1.output.bin
third_party/rust/sha2/tests/data/sha224/test2.input.bin
third_party/rust/sha2/tests/data/sha224/test2.output.bin
third_party/rust/sha2/tests/data/sha224/test3.input.bin
third_party/rust/sha2/tests/data/sha224/test3.output.bin
third_party/rust/sha2/tests/data/sha256.blb
third_party/rust/sha2/tests/data/sha256/one_million_a.output.bin
third_party/rust/sha2/tests/data/sha256/test1.input.bin
third_party/rust/sha2/tests/data/sha256/test1.output.bin
third_party/rust/sha2/tests/data/sha256/test2.input.bin
third_party/rust/sha2/tests/data/sha256/test2.output.bin
third_party/rust/sha2/tests/data/sha256/test3.input.bin
third_party/rust/sha2/tests/data/sha256/test3.output.bin
third_party/rust/sha2/tests/data/sha256_one_million_a.bin
third_party/rust/sha2/tests/data/sha384.blb
third_party/rust/sha2/tests/data/sha384/test1.input.bin
third_party/rust/sha2/tests/data/sha384/test1.output.bin
third_party/rust/sha2/tests/data/sha384/test2.input.bin
third_party/rust/sha2/tests/data/sha384/test2.output.bin
third_party/rust/sha2/tests/data/sha384/test3.input.bin
third_party/rust/sha2/tests/data/sha384/test3.output.bin
third_party/rust/sha2/tests/data/sha512.blb
third_party/rust/sha2/tests/data/sha512/one_million_a.output.bin
third_party/rust/sha2/tests/data/sha512/test1.input.bin
third_party/rust/sha2/tests/data/sha512/test1.output.bin
third_party/rust/sha2/tests/data/sha512/test2.input.bin
third_party/rust/sha2/tests/data/sha512/test2.output.bin
third_party/rust/sha2/tests/data/sha512/test3.input.bin
third_party/rust/sha2/tests/data/sha512/test3.output.bin
third_party/rust/sha2/tests/data/sha512_224.blb
third_party/rust/sha2/tests/data/sha512_224/test1.input.bin
third_party/rust/sha2/tests/data/sha512_224/test1.output.bin
third_party/rust/sha2/tests/data/sha512_224/test2.input.bin
third_party/rust/sha2/tests/data/sha512_224/test2.output.bin
third_party/rust/sha2/tests/data/sha512_224/test3.input.bin
third_party/rust/sha2/tests/data/sha512_224/test3.output.bin
third_party/rust/sha2/tests/data/sha512_256.blb
third_party/rust/sha2/tests/data/sha512_256/test1.input.bin
third_party/rust/sha2/tests/data/sha512_256/test1.output.bin
third_party/rust/sha2/tests/data/sha512_256/test2.input.bin
third_party/rust/sha2/tests/data/sha512_256/test2.output.bin
third_party/rust/sha2/tests/data/sha512_256/test3.input.bin
third_party/rust/sha2/tests/data/sha512_256/test3.output.bin
third_party/rust/sha2/tests/data/sha512_one_million_a.bin
third_party/rust/sha2/tests/lib.rs
--- 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"
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);
+}
+
+/// Complex example function using generics to pass N-length sequences, zip them, and then map that result.
+///
+/// If used with `GenericArray` specifically this isn't necessary
+pub fn generic_sequence_zip_sum<A, B>(a: A, b: B) -> i32
+where
+    A: FunctionalSequence<i32>,                                                                 // `.zip`
+    B: FunctionalSequence<i32, Length = A::Length>,                                             // `.zip`
+    A: MappedGenericSequence<i32, i32>,                                                         // `i32` -> `i32`
+    B: MappedGenericSequence<i32, i32, Mapped = MappedSequence<A, i32, i32>>,                   // `i32` -> `i32`, prove A and B can map to the same output
+    A::Item: Add<B::Item, Output = i32>,                                                        // `l + r`
+    MappedSequence<A, i32, i32>: MappedGenericSequence<i32, i32> + FunctionalSequence<i32>,     // `.map`
+    SequenceItem<MappedSequence<A, i32, i32>>: Add<i32, Output=i32>,                            // `x + 1`
+    MappedSequence<MappedSequence<A, i32, i32>, i32, i32>: Debug,                               // `println!`
+    MappedSequence<MappedSequence<A, i32, i32>, i32, i32>: FunctionalSequence<i32>,             // `.fold`
+    SequenceItem<MappedSequence<MappedSequence<A, i32, i32>, i32, i32>>: Add<i32, Output=i32>   // `x + a`, note the order
+{
+    let c = a.zip(b, |l, r| l + r).map(|x| x + 1);
+
+    println!("{:?}", c);
+
+    c.fold(0, |a, x| x + a)
+}
+
+/// Super-simple fixed-length i32 `GenericArray`s
+pub fn generic_array_plain_zip_sum(a: GenericArray<i32, U4>, b: GenericArray<i32, U4>) -> i32 {
+    a.zip(b, |l, r| l + r).map(|x| x + 1).fold(0, |a, x| x + a)
+}
+
+pub fn generic_array_variable_length_zip_sum<N>(a: GenericArray<i32, N>, b: GenericArray<i32, N>) -> i32
+where
+    N: ArrayLength<i32>,
+{
+    a.zip(b, |l, r| l + r).map(|x| x + 1).fold(0, |a, x| x + a)
+}
+
+pub fn generic_array_same_type_variable_length_zip_sum<T, N>(a: GenericArray<T, N>, b: GenericArray<T, N>) -> i32
+where
+    N: ArrayLength<T> + ArrayLength<<T as Add<T>>::Output>,
+    T: Add<T, Output=i32>,
+{
+    a.zip(b, |l, r| l + r).map(|x| x + 1).fold(0, |a, x| x + a)
+}
+
+/// Complex example using fully generic `GenericArray`s with the same length.
+///
+/// It's mostly just the repeated `Add` traits, which would be present in other systems anyway.
+pub fn generic_array_zip_sum<A, B, N: ArrayLength<A> + ArrayLength<B>>(a: GenericArray<A, N>, b: GenericArray<B, N>) -> i32
+where
+    A: Add<B>,
+    N: ArrayLength<<A as Add<B>>::Output> +
+        ArrayLength<<<A as Add<B>>::Output as Add<i32>>::Output>,
+    <A as Add<B>>::Output: Add<i32>,
+    <<A as Add<B>>::Output as Add<i32>>::Output: Add<i32, Output=i32>,
+{
+    a.zip(b, |l, r| l + r).map(|x| x + 1).fold(0, |a, x| x + a)
+}
+
+#[test]
+fn test_generics() {
+    generic_map(arr![i32; 1, 2, 3, 4]);
+
+    assert_eq!(generic_sequence_zip_sum(arr![i32; 1, 2, 3, 4], arr![i32; 2, 3, 4, 5]), 28);
+
+    assert_eq!(generic_array_plain_zip_sum(arr![i32; 1, 2, 3, 4], arr![i32; 2, 3, 4, 5]), 28);
+
+    assert_eq!(generic_array_variable_length_zip_sum(arr![i32; 1, 2, 3, 4], arr![i32; 2, 3, 4, 5]), 28);
+
+    assert_eq!(generic_array_same_type_variable_length_zip_sum(arr![i32; 1, 2, 3, 4], arr![i32; 2, 3, 4, 5]), 28);
+
+    assert_eq!(generic_array_zip_sum(arr![i32; 1, 2, 3, 4], arr![i32; 2, 3, 4, 5]), 28);
+}
\ No newline at end of file
--- a/third_party/rust/generic-array/tests/hex.rs
+++ b/third_party/rust/generic-array/tests/hex.rs
@@ -1,44 +1,61 @@
-#[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");
-}
+#[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_lower_hex_truncated() {
+    let ar = GenericArray::<u8, U2048>::default();
+    assert_eq!(format!("{:.3001x}", ar), from_utf8(&[b'0'; 3001]).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 long_upper_hex_truncated() {
+    let ar = GenericArray::<u8, U2048>::default();
+    assert_eq!(format!("{:.2777X}", ar), from_utf8(&[b'0'; 2777]).unwrap());
+}
+
+#[test]
+fn truncated_lower_hex() {
+    let ar = arr![u8; 10, 20, 30, 40, 50];
+    assert_eq!(format!("{:.2x}", ar), "0a");
+    assert_eq!(format!("{:.3x}", ar), "0a1");
+    assert_eq!(format!("{:.4x}", ar), "0a14");
+}
+
+#[test]
+fn truncated_upper_hex() {
+    let ar = arr![u8; 30, 20, 10, 17, 0];
+    assert_eq!(format!("{:.4X}", ar), "1E14");
+    assert_eq!(format!("{:.5X}", ar), "1E140");
+    assert_eq!(format!("{:.6X}", ar), "1E140A");
+    assert_eq!(format!("{:.7X}", ar), "1E140A1");
+    assert_eq!(format!("{:.8X}", ar), "1E140A11");
+}
--- a/third_party/rust/generic-array/tests/import_name.rs
+++ b/third_party/rust/generic-array/tests/import_name.rs
@@ -1,10 +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;];
-}
+#[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/tests/iter.rs
@@ -0,0 +1,164 @@
+#[macro_use]
+extern crate generic_array;
+
+use std::cell::Cell;
+use std::ops::Drop;
+
+use generic_array::GenericArray;
+use generic_array::typenum::consts::U5;
+
+#[test]
+fn test_into_iter_as_slice() {
+    let array = arr![char; 'a', 'b', 'c'];
+    let mut into_iter = array.into_iter();
+    assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
+    let _ = into_iter.next().unwrap();
+    assert_eq!(into_iter.as_slice(), &['b', 'c']);
+    let _ = into_iter.next().unwrap();
+    let _ = into_iter.next().unwrap();
+    assert_eq!(into_iter.as_slice(), &[]);
+}
+
+#[test]
+fn test_into_iter_as_mut_slice() {
+    let array = arr![char; 'a', 'b', 'c'];
+    let mut into_iter = array.into_iter();
+    assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
+    into_iter.as_mut_slice()[0] = 'x';
+    into_iter.as_mut_slice()[1] = 'y';
+    assert_eq!(into_iter.next().unwrap(), 'x');
+    assert_eq!(into_iter.as_slice(), &['y', 'c']);
+}
+
+#[test]
+fn test_into_iter_debug() {
+    let array = arr![char; 'a', 'b', 'c'];
+    let into_iter = array.into_iter();
+    let debug = format!("{:?}", into_iter);
+    assert_eq!(debug, "GenericArrayIter(['a', 'b', 'c'])");
+}
+
+#[test]
+fn test_into_iter_clone() {
+    fn iter_equal<I: Iterator<Item = i32>>(it: I, slice: &[i32]) {
+        let v: Vec<i32> = it.collect();
+        assert_eq!(&v[..], slice);
+    }
+    let mut it = arr![i32; 1, 2, 3].into_iter();
+    iter_equal(it.clone(), &[1, 2, 3]);
+    assert_eq!(it.next(), Some(1));
+    let mut it = it.rev();
+    iter_equal(it.clone(), &[3, 2]);
+    assert_eq!(it.next(), Some(3));
+    iter_equal(it.clone(), &[2]);
+    assert_eq!(it.next(), Some(2));
+    iter_equal(it.clone(), &[]);
+    assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_into_iter_nth() {
+    let v = arr![i32; 0, 1, 2, 3, 4];
+    for i in 0..v.len() {
+        assert_eq!(v.clone().into_iter().nth(i).unwrap(), v[i]);
+    }
+    assert_eq!(v.clone().into_iter().nth(v.len()), None);
+
+    let mut iter = v.into_iter();
+    assert_eq!(iter.nth(2).unwrap(), v[2]);
+    assert_eq!(iter.nth(1).unwrap(), v[4]);
+}
+
+#[test]
+fn test_into_iter_last() {
+    let v = arr![i32; 0, 1, 2, 3, 4];
+    assert_eq!(v.into_iter().last().unwrap(), 4);
+    assert_eq!(arr![i32; 0].into_iter().last().unwrap(), 0);
+}
+
+#[test]
+fn test_into_iter_count() {
+    let v = arr![i32; 0, 1, 2, 3, 4];
+    assert_eq!(v.clone().into_iter().count(), 5);
+
+    let mut iter2 = v.into_iter();
+    iter2.next();
+    iter2.next();
+    assert_eq!(iter2.count(), 3);
+}
+
+#[test]
+fn test_into_iter_flat_map() {
+    assert!((0..5).flat_map(|i| arr![i32; 2 * i, 2 * i + 1]).eq(0..10));
+}
+
+#[test]
+fn test_into_iter_drops() {
+    struct R<'a> {
+       i: &'a Cell<usize>,
+    }
+
+    impl<'a> Drop for R<'a> {
+       fn drop(&mut self) {
+            self.i.set(self.i.get() + 1);
+        }
+    }
+
+    fn r(i: &Cell<usize>) -> R {
+        R {
+            i: i
+        }
+    }
+
+    fn v(i: &Cell<usize>) -> GenericArray<R, U5> {
+        arr![R; r(i), r(i), r(i), r(i), r(i)]
+    }
+
+    let i = Cell::new(0);
+    {
+        v(&i).into_iter();
+    }
+    assert_eq!(i.get(), 5);
+
+    let i = Cell::new(0);
+    {
+        let mut iter = v(&i).into_iter();
+        let _x = iter.next();
+        assert_eq!(i.get(), 0);
+        assert_eq!(iter.count(), 4);
+        assert_eq!(i.get(), 4);
+    }
+    assert_eq!(i.get(), 5);
+
+    let i = Cell::new(0);
+    {
+        let mut iter = v(&i).into_iter();
+        let _x = iter.nth(2);
+        assert_eq!(i.get(), 2);
+        let _y = iter.last();