Bug 1573039 - Part 2: Revendor dependencies. r=emilio
☠☠ backed out by 20955fd36fb9 ☠ ☠
authorBastien Orivel <eijebong@bananium.fr>
Sun, 11 Aug 2019 20:42:54 +0000
changeset 487389 97601fb2425d386a253fedbed9252ead1d45c6ba
parent 487388 2b68d7bddbb6ed1ebc6bba3ea4fbdf335ffdd4af
child 487390 20955fd36fb9aad88bb03de6de72868ac3fbf63e
push id92239
push usereijebong@bananium.fr
push dateSun, 11 Aug 2019 21:17:56 +0000
treeherderautoland@97601fb2425d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
bugs1573039
milestone70.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 1573039 - Part 2: Revendor dependencies. r=emilio Depends on D41488 Differential Revision: https://phabricator.services.mozilla.com/D41489
third_party/rust/crc32fast/.cargo-checksum.json
third_party/rust/crc32fast/Cargo.toml
third_party/rust/crc32fast/LICENSE-APACHE
third_party/rust/crc32fast/LICENSE-MIT
third_party/rust/crc32fast/README.md
third_party/rust/crc32fast/benches/bench.rs
third_party/rust/crc32fast/build.rs
third_party/rust/crc32fast/src/baseline.rs
third_party/rust/crc32fast/src/combine.rs
third_party/rust/crc32fast/src/lib.rs
third_party/rust/crc32fast/src/specialized/aarch64.rs
third_party/rust/crc32fast/src/specialized/mod.rs
third_party/rust/crc32fast/src/specialized/pclmulqdq.rs
third_party/rust/crc32fast/src/table.rs
third_party/rust/image/.cargo-checksum.json
third_party/rust/image/CHANGES.md
third_party/rust/image/Cargo.toml
third_party/rust/image/README.md
third_party/rust/image/benches/README.md
third_party/rust/image/src/animation.rs
third_party/rust/image/src/bmp/decoder.rs
third_party/rust/image/src/bmp/encoder.rs
third_party/rust/image/src/buffer.rs
third_party/rust/image/src/color.rs
third_party/rust/image/src/dxt.rs
third_party/rust/image/src/dynimage.rs
third_party/rust/image/src/flat.rs
third_party/rust/image/src/gif.rs
third_party/rust/image/src/hdr/decoder.rs
third_party/rust/image/src/hdr/encoder.rs
third_party/rust/image/src/hdr/hdr_decoder.rs
third_party/rust/image/src/hdr/hdr_encoder.rs
third_party/rust/image/src/hdr/mod.rs
third_party/rust/image/src/ico/decoder.rs
third_party/rust/image/src/ico/encoder.rs
third_party/rust/image/src/image.rs
third_party/rust/image/src/imageops/affine.rs
third_party/rust/image/src/imageops/colorops.rs
third_party/rust/image/src/imageops/mod.rs
third_party/rust/image/src/imageops/sample.rs
third_party/rust/image/src/jpeg/decoder.rs
third_party/rust/image/src/jpeg/encoder.rs
third_party/rust/image/src/lib.rs
third_party/rust/image/src/math/nq.rs
third_party/rust/image/src/png.rs
third_party/rust/image/src/pnm/decoder.rs
third_party/rust/image/src/pnm/encoder.rs
third_party/rust/image/src/pnm/header.rs
third_party/rust/image/src/pnm/mod.rs
third_party/rust/image/src/tga/decoder.rs
third_party/rust/image/src/tiff.rs
third_party/rust/image/src/utils/mod.rs
third_party/rust/image/src/webp/decoder.rs
third_party/rust/image/src/webp/transform.rs
third_party/rust/image/src/webp/vp8.rs
third_party/rust/png/.cargo-checksum.json
third_party/rust/png/Cargo.toml
third_party/rust/png/README.md
third_party/rust/png/benches/README.md
third_party/rust/png/benches/decoder.rs
third_party/rust/png/examples/pngcheck.rs
third_party/rust/png/examples/show.rs
third_party/rust/png/src/common.rs
third_party/rust/png/src/crc.rs
third_party/rust/png/src/decoder/mod.rs
third_party/rust/png/src/decoder/stream.rs
third_party/rust/png/src/encoder.rs
third_party/rust/png/src/filter.rs
third_party/rust/png/src/lib.rs
third_party/rust/png/src/traits.rs
third_party/rust/png/src/utils.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crc32fast/.cargo-checksum.json
@@ -0,0 +1,1 @@
+{"files":{"Cargo.toml":"c85c0241394119d8887c5e5624aba9a1a1fd21578f1a1e3f2a0d50d95d752cff","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"61d383b05b87d78f94d2937e2580cce47226d17823c0430fbcad09596537efcf","README.md":"c0891c7ff327441bf16da593b0e721951f9f6d10bb26f9356aba6a7b0b0c4575","benches/bench.rs":"9a45a7ebc8fecf7f9976bea0e3c00c13731c0b3566536b0bc83788986e801770","build.rs":"4ccc50c3da67eb27f0b622440d2b7aee2f73fa9c71884571f3c041122231d105","src/baseline.rs":"bbe8fe49ceccbf9749052fa9c2756cf95f0fc79a063e5d3b509e3600283464ea","src/combine.rs":"7147fc4002190d36d253ea5e194e0419035b087304bcb17887efe09a8a198815","src/lib.rs":"25c55822d7fd53ff1ff0769bcffbdbcade00d45ac042a541b7189c2e94b91ee7","src/specialized/aarch64.rs":"cc8097e68f1269cee32aa856b4f7e4ba7b7472df6c2f4cecd600d292a838fe83","src/specialized/mod.rs":"bc92450e8522e9df202b346b3a209153cbb0d6587804cbfd2b947fda0f190ed6","src/specialized/pclmulqdq.rs":"6ace803b42ff70a571fd8b5f3f7c2d5a836873ce28759381c2882319b8edba70","src/table.rs":"3201c520d97c5e2cf80b8a03d72fa2e3f1270bbdf93c2fbf85498a8ea39bc64b"},"package":"ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crc32fast/Cargo.toml
@@ -0,0 +1,41 @@
+# 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 = "crc32fast"
+version = "1.2.0"
+authors = ["Sam Rijs <srijs@airpost.net>", "Alex Crichton <alex@alexcrichton.com>"]
+description = "Fast, SIMD-accelerated CRC32 (IEEE) checksum computation"
+readme = "README.md"
+keywords = ["checksum", "crc", "crc32", "simd", "fast"]
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/srijs/rust-crc32fast"
+
+[[bench]]
+name = "bench"
+harness = false
+[dependencies.cfg-if]
+version = "0.1"
+[dev-dependencies.bencher]
+version = "0.1"
+
+[dev-dependencies.quickcheck]
+version = "0.6"
+default-features = false
+
+[dev-dependencies.rand]
+version = "0.4"
+
+[features]
+default = ["std"]
+nightly = []
+std = []
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crc32fast/LICENSE-APACHE
@@ -0,0 +1,202 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright {yyyy} {name of copyright owner}
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crc32fast/LICENSE-MIT
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2018 Sam Rijs, Alex Crichton and contributors
+
+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/crc32fast/README.md
@@ -0,0 +1,81 @@
+# crc32fast [![Build Status][travis-img]][travis] [![Crates.io][crates-img]][crates] [![Documentation][docs-img]][docs]
+
+[travis-img]:   https://travis-ci.com/srijs/rust-crc32fast.svg?branch=master
+[travis]:       https://travis-ci.com/srijs/rust-crc32fast
+[crates-img]:   https://img.shields.io/crates/v/crc32fast.svg
+[crates]:       https://crates.io/crates/crc32fast
+[docs-img]:     https://docs.rs/crc32fast/badge.svg
+[docs]:         https://docs.rs/crc32fast
+
+_Fast, SIMD-accelerated CRC32 (IEEE) checksum computation_
+
+## Usage
+
+```rust
+extern crate crc32fast;
+
+use crc32fast::Hasher;
+
+let mut hasher = Hasher::new();
+hasher.update(b"foo bar baz");
+let checksum = hasher.finalize();
+```
+
+## Performance
+
+This crate contains multiple CRC32 implementations:
+
+- A fast baseline implementation which processes up to 16 bytes per iteration
+- An optimized implementation for modern `x86` using `sse` and `pclmulqdq` instructions
+- An optimized implementation for `aarch64` using `crc32` instructions
+
+Calling the `Hasher::new` constructor at runtime will perform a feature detection to select the most
+optimal implementation for the current CPU feature set.
+
+| crate                               | version | variant   | ns/iter | MB/s |
+|-------------------------------------|---------|-----------|---------|------|
+| [crc](https://crates.io/crates/crc) | 1.8.1   | n/a       |   4,926 |  207 |
+| crc32fast (this crate)              | 1.0.0   | baseline  |     683 | 1499 |
+| crc32fast (this crate)              | 1.0.0   | pclmulqdq |     140 | 7314 |
+
+## Memory Safety
+
+Due to the use of SIMD intrinsics for the optimized implementations, this crate contains some amount of `unsafe` code.
+
+In order to ensure memory safety, the relevant code has been fuzz tested using [afl.rs](https://github.com/rust-fuzz/afl.rs) with millions of iterations in both `debug` and `release` build settings. You can inspect the test setup in the `fuzz` sub-directory, which also has instructions on how to run the tests yourself.
+
+On top of that, every commit is tested using an address sanitizer in CI to catch any out of bounds memory accesses.
+
+Even though neither fuzzing not sanitization has revealed any safety bugs yet, please don't hesitate to file an issue if you run into any crashes or other unexpected behaviour.
+
+## Available feature flags
+
+### `std` (default: enabled)
+
+This library supports being built without the Rust `std` library, which is useful for low-level use-cases such as embedded where no operating system is available. To build the crate in a `no_std` context, disable the default `std` feature.
+
+Note: Because runtime CPU feature detection requires OS support, the specialized SIMD implementations will be unavailable when the `std` feature is disabled.
+
+### `nightly` (default: disabled)
+
+This feature flag enables unstable features that are only available on the `nightly` channel. Keep in mind that when enabling this feature flag, you
+might experience breaking changes when updating compiler versions.
+
+Currently, enabling this feature flag will make the optimized `aarch64` implementation available.
+
+## License
+
+This project is licensed under either of
+
+ * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
+   http://www.apache.org/licenses/LICENSE-2.0)
+ * MIT license ([LICENSE-MIT](LICENSE-MIT) or
+   http://opensource.org/licenses/MIT)
+
+at your option.
+
+### Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in this project by you, as defined in the Apache-2.0 license,
+shall be dual licensed as above, without any additional terms or conditions.
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crc32fast/benches/bench.rs
@@ -0,0 +1,49 @@
+#[macro_use]
+extern crate bencher;
+extern crate crc32fast;
+extern crate rand;
+
+use bencher::Bencher;
+use crc32fast::Hasher;
+use rand::Rng;
+
+fn bench(b: &mut Bencher, size: usize, hasher_init: Hasher) {
+    let mut bytes = vec![0u8; size];
+    rand::thread_rng().fill_bytes(&mut bytes);
+
+    b.iter(|| {
+        let mut hasher = hasher_init.clone();
+        hasher.update(&bytes);
+        bencher::black_box(hasher.finalize())
+    });
+
+    b.bytes = size as u64;
+}
+
+fn bench_kilobyte_baseline(b: &mut Bencher) {
+    bench(b, 1024, Hasher::internal_new_baseline(0))
+}
+
+fn bench_kilobyte_specialized(b: &mut Bencher) {
+    bench(b, 1024, Hasher::internal_new_specialized(0).unwrap())
+}
+
+fn bench_megabyte_baseline(b: &mut Bencher) {
+    bench(b, 1024 * 1024, Hasher::internal_new_baseline(0))
+}
+
+fn bench_megabyte_specialized(b: &mut Bencher) {
+    bench(b, 1024 * 1024, Hasher::internal_new_specialized(0).unwrap())
+}
+
+benchmark_group!(
+    bench_baseline,
+    bench_kilobyte_baseline,
+    bench_megabyte_baseline
+);
+benchmark_group!(
+    bench_specialized,
+    bench_kilobyte_specialized,
+    bench_megabyte_specialized
+);
+benchmark_main!(bench_baseline, bench_specialized);
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crc32fast/build.rs
@@ -0,0 +1,35 @@
+use std::env;
+use std::process::Command;
+use std::str;
+
+fn main() {
+    println!("cargo:rerun-if-changed=build.rs");
+
+    let minor = match rustc_minor_version() {
+        Some(n) => n,
+        None => return,
+    };
+
+    if minor >= 27 {
+        println!("cargo:rustc-cfg=crc32fast_stdarchx86");
+    }
+}
+
+fn rustc_minor_version() -> Option<u32> {
+    macro_rules! otry {
+        ($e:expr) => {
+            match $e {
+                Some(e) => e,
+                None => return None,
+            }
+        };
+    }
+    let rustc = otry!(env::var_os("RUSTC"));
+    let output = otry!(Command::new(rustc).arg("--version").output().ok());
+    let version = otry!(str::from_utf8(&output.stdout).ok());
+    let mut pieces = version.split('.');
+    if pieces.next() != Some("rustc 1") {
+        return None;
+    }
+    otry!(pieces.next()).parse().ok()
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crc32fast/src/baseline.rs
@@ -0,0 +1,94 @@
+use table::CRC32_TABLE;
+
+#[derive(Clone)]
+pub struct State {
+    state: u32,
+}
+
+impl State {
+    pub fn new(state: u32) -> Self {
+        State { state }
+    }
+
+    pub fn update(&mut self, buf: &[u8]) {
+        self.state = update_fast_16(self.state, buf);
+    }
+
+    pub fn finalize(self) -> u32 {
+        self.state
+    }
+
+    pub fn reset(&mut self) {
+        self.state = 0;
+    }
+
+    pub fn combine(&mut self, other: u32, amount: u64) {
+        self.state = ::combine::combine(self.state, other, amount);
+    }
+}
+
+pub(crate) fn update_fast_16(prev: u32, mut buf: &[u8]) -> u32 {
+    const UNROLL: usize = 4;
+    const BYTES_AT_ONCE: usize = 16 * UNROLL;
+
+    let mut crc = !prev;
+
+    while buf.len() >= BYTES_AT_ONCE {
+        for _ in 0..UNROLL {
+            crc = CRC32_TABLE[0x0][buf[0xf] as usize]
+                ^ CRC32_TABLE[0x1][buf[0xe] as usize]
+                ^ CRC32_TABLE[0x2][buf[0xd] as usize]
+                ^ CRC32_TABLE[0x3][buf[0xc] as usize]
+                ^ CRC32_TABLE[0x4][buf[0xb] as usize]
+                ^ CRC32_TABLE[0x5][buf[0xa] as usize]
+                ^ CRC32_TABLE[0x6][buf[0x9] as usize]
+                ^ CRC32_TABLE[0x7][buf[0x8] as usize]
+                ^ CRC32_TABLE[0x8][buf[0x7] as usize]
+                ^ CRC32_TABLE[0x9][buf[0x6] as usize]
+                ^ CRC32_TABLE[0xa][buf[0x5] as usize]
+                ^ CRC32_TABLE[0xb][buf[0x4] as usize]
+                ^ CRC32_TABLE[0xc][buf[0x3] as usize ^ ((crc >> 0x18) & 0xFF) as usize]
+                ^ CRC32_TABLE[0xd][buf[0x2] as usize ^ ((crc >> 0x10) & 0xFF) as usize]
+                ^ CRC32_TABLE[0xe][buf[0x1] as usize ^ ((crc >> 0x08) & 0xFF) as usize]
+                ^ CRC32_TABLE[0xf][buf[0x0] as usize ^ ((crc >> 0x00) & 0xFF) as usize];
+            buf = &buf[16..];
+        }
+    }
+
+    update_slow(!crc, buf)
+}
+
+pub(crate) fn update_slow(prev: u32, buf: &[u8]) -> u32 {
+    let mut crc = !prev;
+
+    for &byte in buf.iter() {
+        crc = CRC32_TABLE[0][((crc as u8) ^ byte) as usize] ^ (crc >> 8);
+    }
+
+    !crc
+}
+
+#[cfg(test)]
+mod test {
+    #[test]
+    fn slow() {
+        assert_eq!(super::update_slow(0, b""), 0);
+
+        // test vectors from the iPXE project (input and output are bitwise negated)
+        assert_eq!(super::update_slow(!0x12345678, b""), !0x12345678);
+        assert_eq!(super::update_slow(!0xffffffff, b"hello world"), !0xf2b5ee7a);
+        assert_eq!(super::update_slow(!0xffffffff, b"hello"), !0xc9ef5979);
+        assert_eq!(super::update_slow(!0xc9ef5979, b" world"), !0xf2b5ee7a);
+
+        // Some vectors found on Rosetta code
+        assert_eq!(super::update_slow(0, b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"), 0x190A55AD);
+        assert_eq!(super::update_slow(0, b"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"), 0xFF6CAB0B);
+        assert_eq!(super::update_slow(0, b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"), 0x91267E8A);
+    }
+
+    quickcheck! {
+        fn fast_16_is_the_same_as_slow(crc: u32, bytes: Vec<u8>) -> bool {
+            super::update_fast_16(crc, &bytes) == super::update_slow(crc, &bytes)
+        }
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crc32fast/src/combine.rs
@@ -0,0 +1,77 @@
+const GF2_DIM: usize = 32;
+
+fn gf2_matrix_times(mat: &[u32; GF2_DIM], mut vec: u32) -> u32 {
+    let mut sum = 0;
+    let mut idx = 0;
+    while vec > 0 {
+        if vec & 1 == 1 {
+            sum ^= mat[idx];
+        }
+        vec >>= 1;
+        idx += 1;
+    }
+    return sum;
+}
+
+fn gf2_matrix_square(square: &mut [u32; GF2_DIM], mat: &[u32; GF2_DIM]) {
+    for n in 0..GF2_DIM {
+        square[n] = gf2_matrix_times(mat, mat[n]);
+    }
+}
+
+pub(crate) fn combine(mut crc1: u32, crc2: u32, mut len2: u64) -> u32 {
+    let mut row: u32;
+    let mut even = [0u32; GF2_DIM]; /* even-power-of-two zeros operator */
+    let mut odd = [0u32; GF2_DIM]; /* odd-power-of-two zeros operator */
+
+    /* degenerate case (also disallow negative lengths) */
+    if len2 <= 0 {
+        return crc1;
+    }
+
+    /* put operator for one zero bit in odd */
+    odd[0] = 0xedb88320; /* CRC-32 polynomial */
+    row = 1;
+    for n in 1..GF2_DIM {
+        odd[n] = row;
+        row <<= 1;
+    }
+
+    /* put operator for two zero bits in even */
+    gf2_matrix_square(&mut even, &odd);
+
+    /* put operator for four zero bits in odd */
+    gf2_matrix_square(&mut odd, &even);
+
+    /* apply len2 zeros to crc1 (first square will put the operator for one
+       zero byte, eight zero bits, in even) */
+    loop {
+        /* apply zeros operator for this bit of len2 */
+        gf2_matrix_square(&mut even, &odd);
+        if len2 & 1 == 1 {
+            crc1 = gf2_matrix_times(&even, crc1);
+        }
+        len2 >>= 1;
+
+        /* if no more bits set, then done */
+        if len2 == 0 {
+            break;
+        }
+
+        /* another iteration of the loop with odd and even swapped */
+        gf2_matrix_square(&mut odd, &even);
+        if len2 & 1 == 1 {
+            crc1 = gf2_matrix_times(&odd, crc1);
+        }
+        len2 >>= 1;
+
+        /* if no more bits set, then done */
+        if len2 == 0 {
+            break;
+        }
+    }
+
+    /* return combined crc */
+    crc1 ^= crc2;
+    return crc1;
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crc32fast/src/lib.rs
@@ -0,0 +1,178 @@
+//! ## Example
+//!
+//! ```rust
+//! use crc32fast::Hasher;
+//!
+//! let mut hasher = Hasher::new();
+//! hasher.update(b"foo bar baz");
+//! let checksum = hasher.finalize();
+//! ```
+//!
+//! ## Performance
+//!
+//! This crate contains multiple CRC32 implementations:
+//!
+//! - A fast baseline implementation which processes up to 16 bytes per iteration
+//! - An optimized implementation for modern `x86` using `sse` and `pclmulqdq` instructions
+//!
+//! Calling the `Hasher::new` constructor at runtime will perform a feature detection to select the most
+//! optimal implementation for the current CPU feature set.
+
+#![cfg_attr(not(feature = "std"), no_std)]
+#![cfg_attr(
+    all(feature = "nightly", target_arch = "aarch64"),
+    feature(stdsimd, aarch64_target_feature)
+)]
+
+#[deny(missing_docs)]
+#[cfg(test)]
+#[macro_use]
+extern crate quickcheck;
+
+#[macro_use]
+extern crate cfg_if;
+
+#[cfg(feature = "std")]
+use std as core;
+
+use core::fmt;
+use core::hash;
+
+mod baseline;
+mod combine;
+mod specialized;
+mod table;
+
+#[derive(Clone)]
+enum State {
+    Baseline(baseline::State),
+    Specialized(specialized::State),
+}
+
+#[derive(Clone)]
+/// Represents an in-progress CRC32 computation.
+pub struct Hasher {
+    amount: u64,
+    state: State,
+}
+
+const DEFAULT_INIT_STATE: u32 = 0;
+
+impl Hasher {
+    /// Create a new `Hasher`.
+    ///
+    /// This will perform a CPU feature detection at runtime to select the most
+    /// optimal implementation for the current processor architecture.
+    pub fn new() -> Self {
+        Self::new_with_initial(DEFAULT_INIT_STATE)
+    }
+
+    /// Create a new `Hasher` with an initial CRC32 state.
+    ///
+    /// This works just like `Hasher::new`, except that it allows for an initial
+    /// CRC32 state to be passed in.
+    pub fn new_with_initial(init: u32) -> Self {
+        Self::internal_new_specialized(init).unwrap_or_else(|| Self::internal_new_baseline(init))
+    }
+
+    #[doc(hidden)]
+    // Internal-only API. Don't use.
+    pub fn internal_new_baseline(init: u32) -> Self {
+        Hasher {
+            amount: 0,
+            state: State::Baseline(baseline::State::new(init)),
+        }
+    }
+
+    #[doc(hidden)]
+    // Internal-only API. Don't use.
+    pub fn internal_new_specialized(init: u32) -> Option<Self> {
+        {
+            if let Some(state) = specialized::State::new(init) {
+                return Some(Hasher {
+                    amount: 0,
+                    state: State::Specialized(state),
+                });
+            }
+        }
+        None
+    }
+
+    /// Process the given byte slice and update the hash state.
+    pub fn update(&mut self, buf: &[u8]) {
+        self.amount += buf.len() as u64;
+        match self.state {
+            State::Baseline(ref mut state) => state.update(buf),
+            State::Specialized(ref mut state) => state.update(buf),
+        }
+    }
+
+    /// Finalize the hash state and return the computed CRC32 value.
+    pub fn finalize(self) -> u32 {
+        match self.state {
+            State::Baseline(state) => state.finalize(),
+            State::Specialized(state) => state.finalize(),
+        }
+    }
+
+    /// Reset the hash state.
+    pub fn reset(&mut self) {
+        self.amount = 0;
+        match self.state {
+            State::Baseline(ref mut state) => state.reset(),
+            State::Specialized(ref mut state) => state.reset(),
+        }
+    }
+
+    /// Combine the hash state with the hash state for the subsequent block of bytes.
+    pub fn combine(&mut self, other: &Self) {
+        self.amount += other.amount;
+        let other_crc = other.clone().finalize();
+        match self.state {
+            State::Baseline(ref mut state) => state.combine(other_crc, other.amount),
+            State::Specialized(ref mut state) => state.combine(other_crc, other.amount),
+        }
+    }
+}
+
+impl fmt::Debug for Hasher {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("crc32fast::Hasher").finish()
+    }
+}
+
+impl Default for Hasher {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+impl hash::Hasher for Hasher {
+    fn write(&mut self, bytes: &[u8]) {
+        self.update(bytes)
+    }
+
+    fn finish(&self) -> u64 {
+        u64::from(self.clone().finalize())
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::Hasher;
+
+    quickcheck! {
+        fn combine(bytes_1: Vec<u8>, bytes_2: Vec<u8>) -> bool {
+            let mut hash_a = Hasher::new();
+            hash_a.update(&bytes_1);
+            hash_a.update(&bytes_2);
+            let mut hash_b = Hasher::new();
+            hash_b.update(&bytes_2);
+            let mut hash_c = Hasher::new();
+            hash_c.update(&bytes_1);
+            hash_c.combine(&hash_b);
+
+            hash_a.finalize() == hash_c.finalize()
+        }
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crc32fast/src/specialized/aarch64.rs
@@ -0,0 +1,88 @@
+use std::arch::aarch64 as arch;
+
+#[derive(Clone)]
+pub struct State {
+    state: u32,
+}
+
+impl State {
+    pub fn new(state: u32) -> Option<Self> {
+        if is_aarch64_feature_detected!("crc") {
+            // SAFETY: The conditions above ensure that all
+            //         required instructions are supported by the CPU.
+            Some(Self { state })
+        } else {
+            None
+        }
+    }
+
+    pub fn update(&mut self, buf: &[u8]) {
+        // SAFETY: The `State::new` constructor ensures that all
+        //         required instructions are supported by the CPU.
+        self.state = unsafe { calculate(self.state, buf) }
+    }
+
+    pub fn finalize(self) -> u32 {
+        self.state
+    }
+
+    pub fn reset(&mut self) {
+        self.state = 0;
+    }
+
+    pub fn combine(&mut self, other: u32, amount: u64) {
+        self.state = ::combine::combine(self.state, other, amount);
+    }
+}
+
+// target_feature is necessary to allow rustc to inline the crc32* wrappers
+#[target_feature(enable = "crc")]
+pub unsafe fn calculate(crc: u32, data: &[u8]) -> u32 {
+    let mut c32 = !crc;
+    let (pre_quad, quads, post_quad) = data.align_to::<u64>();
+
+    c32 = pre_quad.iter().fold(c32, |acc, &b| arch::__crc32b(acc, b));
+
+    // unrolling increases performance by a lot
+    let mut quad_iter = quads.chunks_exact(8);
+    for chunk in &mut quad_iter {
+        c32 = arch::__crc32d(c32, chunk[0]);
+        c32 = arch::__crc32d(c32, chunk[1]);
+        c32 = arch::__crc32d(c32, chunk[2]);
+        c32 = arch::__crc32d(c32, chunk[3]);
+        c32 = arch::__crc32d(c32, chunk[4]);
+        c32 = arch::__crc32d(c32, chunk[5]);
+        c32 = arch::__crc32d(c32, chunk[6]);
+        c32 = arch::__crc32d(c32, chunk[7]);
+    }
+    c32 = quad_iter
+        .remainder()
+        .iter()
+        .fold(c32, |acc, &q| arch::__crc32d(acc, q));
+
+    c32 = post_quad.iter().fold(c32, |acc, &b| arch::__crc32b(acc, b));
+
+    !c32
+}
+
+#[cfg(test)]
+mod test {
+    quickcheck! {
+        fn check_against_baseline(init: u32, chunks: Vec<(Vec<u8>, usize)>) -> bool {
+            let mut baseline = super::super::super::baseline::State::new(init);
+            let mut aarch64 = super::State::new(init).expect("not supported");
+            for (chunk, mut offset) in chunks {
+                // simulate random alignments by offsetting the slice by up to 15 bytes
+                offset &= 0xF;
+                if chunk.len() <= offset {
+                    baseline.update(&chunk);
+                    aarch64.update(&chunk);
+                } else {
+                    baseline.update(&chunk[offset..]);
+                    aarch64.update(&chunk[offset..]);
+                }
+            }
+            aarch64.finalize() == baseline.finalize()
+        }
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crc32fast/src/specialized/mod.rs
@@ -0,0 +1,36 @@
+cfg_if! {
+    if #[cfg(all(
+        crc32fast_stdarchx86,
+        any(target_arch = "x86", target_arch = "x86_64")
+    ))] {
+        mod pclmulqdq;
+        pub use self::pclmulqdq::State;
+    } else if #[cfg(all(feature = "nightly", target_arch = "aarch64"))] {
+        mod aarch64;
+        pub use self::aarch64::State;
+    } else {
+        #[derive(Clone)]
+        pub enum State {}
+        impl State {
+            pub fn new(_: u32) -> Option<Self> {
+                None
+            }
+
+            pub fn update(&mut self, _buf: &[u8]) {
+                match *self {}
+            }
+
+            pub fn finalize(self) -> u32 {
+                match self{}
+            }
+
+            pub fn reset(&mut self) {
+                match *self {}
+            }
+
+            pub fn combine(&mut self, _other: u32, _amount: u64) {
+                match *self {}
+            }
+        }
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crc32fast/src/specialized/pclmulqdq.rs
@@ -0,0 +1,225 @@
+#[cfg(target_arch = "x86")]
+use core::arch::x86 as arch;
+#[cfg(target_arch = "x86_64")]
+use core::arch::x86_64 as arch;
+
+#[derive(Clone)]
+pub struct State {
+    state: u32,
+}
+
+impl State {
+    #[cfg(not(feature = "std"))]
+    pub fn new(state: u32) -> Option<Self> {
+        if cfg!(target_feature = "pclmulqdq")
+            && cfg!(target_feature = "sse2")
+            && cfg!(target_feature = "sse4.1")
+        {
+            // SAFETY: The conditions above ensure that all
+            //         required instructions are supported by the CPU.
+            Some(Self { state })
+        } else {
+            None
+        }
+    }
+
+    #[cfg(feature = "std")]
+    pub fn new(state: u32) -> Option<Self> {
+        if is_x86_feature_detected!("pclmulqdq")
+            && is_x86_feature_detected!("sse2")
+            && is_x86_feature_detected!("sse4.1")
+        {
+            // SAFETY: The conditions above ensure that all
+            //         required instructions are supported by the CPU.
+            Some(Self { state })
+        } else {
+            None
+        }
+    }
+
+    pub fn update(&mut self, buf: &[u8]) {
+        // SAFETY: The `State::new` constructor ensures that all
+        //         required instructions are supported by the CPU.
+        self.state = unsafe { calculate(self.state, buf) }
+    }
+
+    pub fn finalize(self) -> u32 {
+        self.state
+    }
+
+    pub fn reset(&mut self) {
+        self.state = 0;
+    }
+
+    pub fn combine(&mut self, other: u32, amount: u64) {
+        self.state = ::combine::combine(self.state, other, amount);
+    }
+}
+
+const K1: i64 = 0x154442bd4;
+const K2: i64 = 0x1c6e41596;
+const K3: i64 = 0x1751997d0;
+const K4: i64 = 0x0ccaa009e;
+const K5: i64 = 0x163cd6124;
+const K6: i64 = 0x1db710640;
+
+const P_X: i64 = 0x1DB710641;
+const U_PRIME: i64 = 0x1F7011641;
+
+#[cfg(feature = "std")]
+unsafe fn debug(s: &str, a: arch::__m128i) -> arch::__m128i {
+    if false {
+        union A {
+            a: arch::__m128i,
+            b: [u8; 16],
+        }
+        let x = A { a }.b;
+        print!(" {:20} | ", s);
+        for x in x.iter() {
+            print!("{:02x} ", x);
+        }
+        println!();
+    }
+    return a;
+}
+
+#[cfg(not(feature = "std"))]
+unsafe fn debug(_s: &str, a: arch::__m128i) -> arch::__m128i {
+    a
+}
+
+#[target_feature(enable = "pclmulqdq", enable = "sse2", enable = "sse4.1")]
+pub unsafe fn calculate(crc: u32, mut data: &[u8]) -> u32 {
+    // In theory we can accelerate smaller chunks too, but for now just rely on
+    // the fallback implementation as it's too much hassle and doesn't seem too
+    // beneficial.
+    if data.len() < 128 {
+        return ::baseline::update_fast_16(crc, data);
+    }
+
+    // Step 1: fold by 4 loop
+    let mut x3 = get(&mut data);
+    let mut x2 = get(&mut data);
+    let mut x1 = get(&mut data);
+    let mut x0 = get(&mut data);
+
+    // fold in our initial value, part of the incremental crc checksum
+    x3 = arch::_mm_xor_si128(x3, arch::_mm_cvtsi32_si128(!crc as i32));
+
+    let k1k2 = arch::_mm_set_epi64x(K2, K1);
+    while data.len() >= 64 {
+        x3 = reduce128(x3, get(&mut data), k1k2);
+        x2 = reduce128(x2, get(&mut data), k1k2);
+        x1 = reduce128(x1, get(&mut data), k1k2);
+        x0 = reduce128(x0, get(&mut data), k1k2);
+    }
+
+    let k3k4 = arch::_mm_set_epi64x(K4, K3);
+    let mut x = reduce128(x3, x2, k3k4);
+    x = reduce128(x, x1, k3k4);
+    x = reduce128(x, x0, k3k4);
+
+    // Step 2: fold by 1 loop
+    while data.len() >= 16 {
+        x = reduce128(x, get(&mut data), k3k4);
+    }
+
+    debug("128 > 64 init", x);
+
+    // Perform step 3, reduction from 128 bits to 64 bits. This is
+    // significantly different from the paper and basically doesn't follow it
+    // at all. It's not really clear why, but implementations of this algorithm
+    // in Chrome/Linux diverge in the same way. It is beyond me why this is
+    // different than the paper, maybe the paper has like errata or something?
+    // Unclear.
+    //
+    // It's also not clear to me what's actually happening here and/or why, but
+    // algebraically what's happening is:
+    //
+    // x = (x[0:63] • K4) ^ x[64:127]           // 96 bit result
+    // x = ((x[0:31] as u64) • K5) ^ x[32:95]   // 64 bit result
+    //
+    // It's... not clear to me what's going on here. The paper itself is pretty
+    // vague on this part but definitely uses different constants at least.
+    // It's not clear to me, reading the paper, where the xor operations are
+    // happening or why things are shifting around. This implementation...
+    // appears to work though!
+    drop(K6);
+    let x = arch::_mm_xor_si128(
+        arch::_mm_clmulepi64_si128(x, k3k4, 0x10),
+        arch::_mm_srli_si128(x, 8),
+    );
+    let x = arch::_mm_xor_si128(
+        arch::_mm_clmulepi64_si128(
+            arch::_mm_and_si128(x, arch::_mm_set_epi32(0, 0, 0, !0)),
+            arch::_mm_set_epi64x(0, K5),
+            0x00,
+        ),
+        arch::_mm_srli_si128(x, 4),
+    );
+    debug("128 > 64 xx", x);
+
+    // Perform a Barrett reduction from our now 64 bits to 32 bits. The
+    // algorithm for this is described at the end of the paper, and note that
+    // this also implements the "bit reflected input" variant.
+    let pu = arch::_mm_set_epi64x(U_PRIME, P_X);
+
+    // T1(x) = ⌊(R(x) % x^32)⌋ • μ
+    let t1 = arch::_mm_clmulepi64_si128(
+        arch::_mm_and_si128(x, arch::_mm_set_epi32(0, 0, 0, !0)),
+        pu,
+        0x10,
+    );
+    // T2(x) = ⌊(T1(x) % x^32)⌋ • P(x)
+    let t2 = arch::_mm_clmulepi64_si128(
+        arch::_mm_and_si128(t1, arch::_mm_set_epi32(0, 0, 0, !0)),
+        pu,
+        0x00,
+    );
+    // We're doing the bit-reflected variant, so get the upper 32-bits of the
+    // 64-bit result instead of the lower 32-bits.
+    //
+    // C(x) = R(x) ^ T2(x) / x^32
+    let c = arch::_mm_extract_epi32(arch::_mm_xor_si128(x, t2), 1) as u32;
+
+    if !data.is_empty() {
+        ::baseline::update_fast_16(!c, data)
+    } else {
+        !c
+    }
+}
+
+unsafe fn reduce128(a: arch::__m128i, b: arch::__m128i, keys: arch::__m128i) -> arch::__m128i {
+    let t1 = arch::_mm_clmulepi64_si128(a, keys, 0x00);
+    let t2 = arch::_mm_clmulepi64_si128(a, keys, 0x11);
+    arch::_mm_xor_si128(arch::_mm_xor_si128(b, t1), t2)
+}
+
+unsafe fn get(a: &mut &[u8]) -> arch::__m128i {
+    debug_assert!(a.len() >= 16);
+    let r = arch::_mm_loadu_si128(a.as_ptr() as *const arch::__m128i);
+    *a = &a[16..];
+    return r;
+}
+
+#[cfg(test)]
+mod test {
+    quickcheck! {
+        fn check_against_baseline(init: u32, chunks: Vec<(Vec<u8>, usize)>) -> bool {
+            let mut baseline = super::super::super::baseline::State::new(init);
+            let mut pclmulqdq = super::State::new(init).expect("not supported");
+            for (chunk, mut offset) in chunks {
+                // simulate random alignments by offsetting the slice by up to 15 bytes
+                offset &= 0xF;
+                if chunk.len() <= offset {
+                    baseline.update(&chunk);
+                    pclmulqdq.update(&chunk);
+                } else {
+                    baseline.update(&chunk[offset..]);
+                    pclmulqdq.update(&chunk[offset..]);
+                }
+            }
+            pclmulqdq.finalize() == baseline.finalize()
+        }
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/crc32fast/src/table.rs
@@ -0,0 +1,626 @@
+pub const CRC32_TABLE: [[u32; 256]; 16] = [
+    [
+        0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535,
+        0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd,
+        0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d,
+        0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+        0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+        0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+        0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac,
+        0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+        0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab,
+        0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+        0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb,
+        0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+        0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea,
+        0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce,
+        0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+        0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+        0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409,
+        0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+        0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739,
+        0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+        0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268,
+        0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0,
+        0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8,
+        0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+        0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+        0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703,
+        0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7,
+        0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+        0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae,
+        0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+        0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6,
+        0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+        0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d,
+        0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5,
+        0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+        0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+        0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+    ],
+    [
+        0x00000000, 0x191B3141, 0x32366282, 0x2B2D53C3, 0x646CC504, 0x7D77F445, 0x565AA786,
+        0x4F4196C7, 0xC8D98A08, 0xD1C2BB49, 0xFAEFE88A, 0xE3F4D9CB, 0xACB54F0C, 0xB5AE7E4D,
+        0x9E832D8E, 0x87981CCF, 0x4AC21251, 0x53D92310, 0x78F470D3, 0x61EF4192, 0x2EAED755,
+        0x37B5E614, 0x1C98B5D7, 0x05838496, 0x821B9859, 0x9B00A918, 0xB02DFADB, 0xA936CB9A,
+        0xE6775D5D, 0xFF6C6C1C, 0xD4413FDF, 0xCD5A0E9E, 0x958424A2, 0x8C9F15E3, 0xA7B24620,
+        0xBEA97761, 0xF1E8E1A6, 0xE8F3D0E7, 0xC3DE8324, 0xDAC5B265, 0x5D5DAEAA, 0x44469FEB,
+        0x6F6BCC28, 0x7670FD69, 0x39316BAE, 0x202A5AEF, 0x0B07092C, 0x121C386D, 0xDF4636F3,
+        0xC65D07B2, 0xED705471, 0xF46B6530, 0xBB2AF3F7, 0xA231C2B6, 0x891C9175, 0x9007A034,
+        0x179FBCFB, 0x0E848DBA, 0x25A9DE79, 0x3CB2EF38, 0x73F379FF, 0x6AE848BE, 0x41C51B7D,
+        0x58DE2A3C, 0xF0794F05, 0xE9627E44, 0xC24F2D87, 0xDB541CC6, 0x94158A01, 0x8D0EBB40,
+        0xA623E883, 0xBF38D9C2, 0x38A0C50D, 0x21BBF44C, 0x0A96A78F, 0x138D96CE, 0x5CCC0009,
+        0x45D73148, 0x6EFA628B, 0x77E153CA, 0xBABB5D54, 0xA3A06C15, 0x888D3FD6, 0x91960E97,
+        0xDED79850, 0xC7CCA911, 0xECE1FAD2, 0xF5FACB93, 0x7262D75C, 0x6B79E61D, 0x4054B5DE,
+        0x594F849F, 0x160E1258, 0x0F152319, 0x243870DA, 0x3D23419B, 0x65FD6BA7, 0x7CE65AE6,
+        0x57CB0925, 0x4ED03864, 0x0191AEA3, 0x188A9FE2, 0x33A7CC21, 0x2ABCFD60, 0xAD24E1AF,
+        0xB43FD0EE, 0x9F12832D, 0x8609B26C, 0xC94824AB, 0xD05315EA, 0xFB7E4629, 0xE2657768,
+        0x2F3F79F6, 0x362448B7, 0x1D091B74, 0x04122A35, 0x4B53BCF2, 0x52488DB3, 0x7965DE70,
+        0x607EEF31, 0xE7E6F3FE, 0xFEFDC2BF, 0xD5D0917C, 0xCCCBA03D, 0x838A36FA, 0x9A9107BB,
+        0xB1BC5478, 0xA8A76539, 0x3B83984B, 0x2298A90A, 0x09B5FAC9, 0x10AECB88, 0x5FEF5D4F,
+        0x46F46C0E, 0x6DD93FCD, 0x74C20E8C, 0xF35A1243, 0xEA412302, 0xC16C70C1, 0xD8774180,
+        0x9736D747, 0x8E2DE606, 0xA500B5C5, 0xBC1B8484, 0x71418A1A, 0x685ABB5B, 0x4377E898,
+        0x5A6CD9D9, 0x152D4F1E, 0x0C367E5F, 0x271B2D9C, 0x3E001CDD, 0xB9980012, 0xA0833153,
+        0x8BAE6290, 0x92B553D1, 0xDDF4C516, 0xC4EFF457, 0xEFC2A794, 0xF6D996D5, 0xAE07BCE9,
+        0xB71C8DA8, 0x9C31DE6B, 0x852AEF2A, 0xCA6B79ED, 0xD37048AC, 0xF85D1B6F, 0xE1462A2E,
+        0x66DE36E1, 0x7FC507A0, 0x54E85463, 0x4DF36522, 0x02B2F3E5, 0x1BA9C2A4, 0x30849167,
+        0x299FA026, 0xE4C5AEB8, 0xFDDE9FF9, 0xD6F3CC3A, 0xCFE8FD7B, 0x80A96BBC, 0x99B25AFD,
+        0xB29F093E, 0xAB84387F, 0x2C1C24B0, 0x350715F1, 0x1E2A4632, 0x07317773, 0x4870E1B4,
+        0x516BD0F5, 0x7A468336, 0x635DB277, 0xCBFAD74E, 0xD2E1E60F, 0xF9CCB5CC, 0xE0D7848D,
+        0xAF96124A, 0xB68D230B, 0x9DA070C8, 0x84BB4189, 0x03235D46, 0x1A386C07, 0x31153FC4,
+        0x280E0E85, 0x674F9842, 0x7E54A903, 0x5579FAC0, 0x4C62CB81, 0x8138C51F, 0x9823F45E,
+        0xB30EA79D, 0xAA1596DC, 0xE554001B, 0xFC4F315A, 0xD7626299, 0xCE7953D8, 0x49E14F17,
+        0x50FA7E56, 0x7BD72D95, 0x62CC1CD4, 0x2D8D8A13, 0x3496BB52, 0x1FBBE891, 0x06A0D9D0,
+        0x5E7EF3EC, 0x4765C2AD, 0x6C48916E, 0x7553A02F, 0x3A1236E8, 0x230907A9, 0x0824546A,
+        0x113F652B, 0x96A779E4, 0x8FBC48A5, 0xA4911B66, 0xBD8A2A27, 0xF2CBBCE0, 0xEBD08DA1,
+        0xC0FDDE62, 0xD9E6EF23, 0x14BCE1BD, 0x0DA7D0FC, 0x268A833F, 0x3F91B27E, 0x70D024B9,
+        0x69CB15F8, 0x42E6463B, 0x5BFD777A, 0xDC656BB5, 0xC57E5AF4, 0xEE530937, 0xF7483876,
+        0xB809AEB1, 0xA1129FF0, 0x8A3FCC33, 0x9324FD72,
+    ],
+    [
+        0x00000000, 0x01C26A37, 0x0384D46E, 0x0246BE59, 0x0709A8DC, 0x06CBC2EB, 0x048D7CB2,
+        0x054F1685, 0x0E1351B8, 0x0FD13B8F, 0x0D9785D6, 0x0C55EFE1, 0x091AF964, 0x08D89353,
+        0x0A9E2D0A, 0x0B5C473D, 0x1C26A370, 0x1DE4C947, 0x1FA2771E, 0x1E601D29, 0x1B2F0BAC,
+        0x1AED619B, 0x18ABDFC2, 0x1969B5F5, 0x1235F2C8, 0x13F798FF, 0x11B126A6, 0x10734C91,
+        0x153C5A14, 0x14FE3023, 0x16B88E7A, 0x177AE44D, 0x384D46E0, 0x398F2CD7, 0x3BC9928E,
+        0x3A0BF8B9, 0x3F44EE3C, 0x3E86840B, 0x3CC03A52, 0x3D025065, 0x365E1758, 0x379C7D6F,
+        0x35DAC336, 0x3418A901, 0x3157BF84, 0x3095D5B3, 0x32D36BEA, 0x331101DD, 0x246BE590,
+        0x25A98FA7, 0x27EF31FE, 0x262D5BC9, 0x23624D4C, 0x22A0277B, 0x20E69922, 0x2124F315,
+        0x2A78B428, 0x2BBADE1F, 0x29FC6046, 0x283E0A71, 0x2D711CF4, 0x2CB376C3, 0x2EF5C89A,
+        0x2F37A2AD, 0x709A8DC0, 0x7158E7F7, 0x731E59AE, 0x72DC3399, 0x7793251C, 0x76514F2B,
+        0x7417F172, 0x75D59B45, 0x7E89DC78, 0x7F4BB64F, 0x7D0D0816, 0x7CCF6221, 0x798074A4,
+        0x78421E93, 0x7A04A0CA, 0x7BC6CAFD, 0x6CBC2EB0, 0x6D7E4487, 0x6F38FADE, 0x6EFA90E9,
+        0x6BB5866C, 0x6A77EC5B, 0x68315202, 0x69F33835, 0x62AF7F08, 0x636D153F, 0x612BAB66,
+        0x60E9C151, 0x65A6D7D4, 0x6464BDE3, 0x662203BA, 0x67E0698D, 0x48D7CB20, 0x4915A117,
+        0x4B531F4E, 0x4A917579, 0x4FDE63FC, 0x4E1C09CB, 0x4C5AB792, 0x4D98DDA5, 0x46C49A98,
+        0x4706F0AF, 0x45404EF6, 0x448224C1, 0x41CD3244, 0x400F5873, 0x4249E62A, 0x438B8C1D,
+        0x54F16850, 0x55330267, 0x5775BC3E, 0x56B7D609, 0x53F8C08C, 0x523AAABB, 0x507C14E2,
+        0x51BE7ED5, 0x5AE239E8, 0x5B2053DF, 0x5966ED86, 0x58A487B1, 0x5DEB9134, 0x5C29FB03,
+        0x5E6F455A, 0x5FAD2F6D, 0xE1351B80, 0xE0F771B7, 0xE2B1CFEE, 0xE373A5D9, 0xE63CB35C,
+        0xE7FED96B, 0xE5B86732, 0xE47A0D05, 0xEF264A38, 0xEEE4200F, 0xECA29E56, 0xED60F461,
+        0xE82FE2E4, 0xE9ED88D3, 0xEBAB368A, 0xEA695CBD, 0xFD13B8F0, 0xFCD1D2C7, 0xFE976C9E,
+        0xFF5506A9, 0xFA1A102C, 0xFBD87A1B, 0xF99EC442, 0xF85CAE75, 0xF300E948, 0xF2C2837F,
+        0xF0843D26, 0xF1465711, 0xF4094194, 0xF5CB2BA3, 0xF78D95FA, 0xF64FFFCD, 0xD9785D60,
+        0xD8BA3757, 0xDAFC890E, 0xDB3EE339, 0xDE71F5BC, 0xDFB39F8B, 0xDDF521D2, 0xDC374BE5,
+        0xD76B0CD8, 0xD6A966EF, 0xD4EFD8B6, 0xD52DB281, 0xD062A404, 0xD1A0CE33, 0xD3E6706A,
+        0xD2241A5D, 0xC55EFE10, 0xC49C9427, 0xC6DA2A7E, 0xC7184049, 0xC25756CC, 0xC3953CFB,
+        0xC1D382A2, 0xC011E895, 0xCB4DAFA8, 0xCA8FC59F, 0xC8C97BC6, 0xC90B11F1, 0xCC440774,
+        0xCD866D43, 0xCFC0D31A, 0xCE02B92D, 0x91AF9640, 0x906DFC77, 0x922B422E, 0x93E92819,
+        0x96A63E9C, 0x976454AB, 0x9522EAF2, 0x94E080C5, 0x9FBCC7F8, 0x9E7EADCF, 0x9C381396,
+        0x9DFA79A1, 0x98B56F24, 0x99770513, 0x9B31BB4A, 0x9AF3D17D, 0x8D893530, 0x8C4B5F07,
+        0x8E0DE15E, 0x8FCF8B69, 0x8A809DEC, 0x8B42F7DB, 0x89044982, 0x88C623B5, 0x839A6488,
+        0x82580EBF, 0x801EB0E6, 0x81DCDAD1, 0x8493CC54, 0x8551A663, 0x8717183A, 0x86D5720D,
+        0xA9E2D0A0, 0xA820BA97, 0xAA6604CE, 0xABA46EF9, 0xAEEB787C, 0xAF29124B, 0xAD6FAC12,
+        0xACADC625, 0xA7F18118, 0xA633EB2F, 0xA4755576, 0xA5B73F41, 0xA0F829C4, 0xA13A43F3,
+        0xA37CFDAA, 0xA2BE979D, 0xB5C473D0, 0xB40619E7, 0xB640A7BE, 0xB782CD89, 0xB2CDDB0C,
+        0xB30FB13B, 0xB1490F62, 0xB08B6555, 0xBBD72268, 0xBA15485F, 0xB853F606, 0xB9919C31,
+        0xBCDE8AB4, 0xBD1CE083, 0xBF5A5EDA, 0xBE9834ED,
+    ],
+    [
+        0x00000000, 0xB8BC6765, 0xAA09C88B, 0x12B5AFEE, 0x8F629757, 0x37DEF032, 0x256B5FDC,
+        0x9DD738B9, 0xC5B428EF, 0x7D084F8A, 0x6FBDE064, 0xD7018701, 0x4AD6BFB8, 0xF26AD8DD,
+        0xE0DF7733, 0x58631056, 0x5019579F, 0xE8A530FA, 0xFA109F14, 0x42ACF871, 0xDF7BC0C8,
+        0x67C7A7AD, 0x75720843, 0xCDCE6F26, 0x95AD7F70, 0x2D111815, 0x3FA4B7FB, 0x8718D09E,
+        0x1ACFE827, 0xA2738F42, 0xB0C620AC, 0x087A47C9, 0xA032AF3E, 0x188EC85B, 0x0A3B67B5,
+        0xB28700D0, 0x2F503869, 0x97EC5F0C, 0x8559F0E2, 0x3DE59787, 0x658687D1, 0xDD3AE0B4,
+        0xCF8F4F5A, 0x7733283F, 0xEAE41086, 0x525877E3, 0x40EDD80D, 0xF851BF68, 0xF02BF8A1,
+        0x48979FC4, 0x5A22302A, 0xE29E574F, 0x7F496FF6, 0xC7F50893, 0xD540A77D, 0x6DFCC018,
+        0x359FD04E, 0x8D23B72B, 0x9F9618C5, 0x272A7FA0, 0xBAFD4719, 0x0241207C, 0x10F48F92,
+        0xA848E8F7, 0x9B14583D, 0x23A83F58, 0x311D90B6, 0x89A1F7D3, 0x1476CF6A, 0xACCAA80F,
+        0xBE7F07E1, 0x06C36084, 0x5EA070D2, 0xE61C17B7, 0xF4A9B859, 0x4C15DF3C, 0xD1C2E785,
+        0x697E80E0, 0x7BCB2F0E, 0xC377486B, 0xCB0D0FA2, 0x73B168C7, 0x6104C729, 0xD9B8A04C,
+        0x446F98F5, 0xFCD3FF90, 0xEE66507E, 0x56DA371B, 0x0EB9274D, 0xB6054028, 0xA4B0EFC6,
+        0x1C0C88A3, 0x81DBB01A, 0x3967D77F, 0x2BD27891, 0x936E1FF4, 0x3B26F703, 0x839A9066,
+        0x912F3F88, 0x299358ED, 0xB4446054, 0x0CF80731, 0x1E4DA8DF, 0xA6F1CFBA, 0xFE92DFEC,
+        0x462EB889, 0x549B1767, 0xEC277002, 0x71F048BB, 0xC94C2FDE, 0xDBF98030, 0x6345E755,
+        0x6B3FA09C, 0xD383C7F9, 0xC1366817, 0x798A0F72, 0xE45D37CB, 0x5CE150AE, 0x4E54FF40,
+        0xF6E89825, 0xAE8B8873, 0x1637EF16, 0x048240F8, 0xBC3E279D, 0x21E91F24, 0x99557841,
+        0x8BE0D7AF, 0x335CB0CA, 0xED59B63B, 0x55E5D15E, 0x47507EB0, 0xFFEC19D5, 0x623B216C,
+        0xDA874609, 0xC832E9E7, 0x708E8E82, 0x28ED9ED4, 0x9051F9B1, 0x82E4565F, 0x3A58313A,
+        0xA78F0983, 0x1F336EE6, 0x0D86C108, 0xB53AA66D, 0xBD40E1A4, 0x05FC86C1, 0x1749292F,
+        0xAFF54E4A, 0x322276F3, 0x8A9E1196, 0x982BBE78, 0x2097D91D, 0x78F4C94B, 0xC048AE2E,
+        0xD2FD01C0, 0x6A4166A5, 0xF7965E1C, 0x4F2A3979, 0x5D9F9697, 0xE523F1F2, 0x4D6B1905,
+        0xF5D77E60, 0xE762D18E, 0x5FDEB6EB, 0xC2098E52, 0x7AB5E937, 0x680046D9, 0xD0BC21BC,
+        0x88DF31EA, 0x3063568F, 0x22D6F961, 0x9A6A9E04, 0x07BDA6BD, 0xBF01C1D8, 0xADB46E36,
+        0x15080953, 0x1D724E9A, 0xA5CE29FF, 0xB77B8611, 0x0FC7E174, 0x9210D9CD, 0x2AACBEA8,
+        0x38191146, 0x80A57623, 0xD8C66675, 0x607A0110, 0x72CFAEFE, 0xCA73C99B, 0x57A4F122,
+        0xEF189647, 0xFDAD39A9, 0x45115ECC, 0x764DEE06, 0xCEF18963, 0xDC44268D, 0x64F841E8,
+        0xF92F7951, 0x41931E34, 0x5326B1DA, 0xEB9AD6BF, 0xB3F9C6E9, 0x0B45A18C, 0x19F00E62,
+        0xA14C6907, 0x3C9B51BE, 0x842736DB, 0x96929935, 0x2E2EFE50, 0x2654B999, 0x9EE8DEFC,
+        0x8C5D7112, 0x34E11677, 0xA9362ECE, 0x118A49AB, 0x033FE645, 0xBB838120, 0xE3E09176,
+        0x5B5CF613, 0x49E959FD, 0xF1553E98, 0x6C820621, 0xD43E6144, 0xC68BCEAA, 0x7E37A9CF,
+        0xD67F4138, 0x6EC3265D, 0x7C7689B3, 0xC4CAEED6, 0x591DD66F, 0xE1A1B10A, 0xF3141EE4,
+        0x4BA87981, 0x13CB69D7, 0xAB770EB2, 0xB9C2A15C, 0x017EC639, 0x9CA9FE80, 0x241599E5,
+        0x36A0360B, 0x8E1C516E, 0x866616A7, 0x3EDA71C2, 0x2C6FDE2C, 0x94D3B949, 0x090481F0,
+        0xB1B8E695, 0xA30D497B, 0x1BB12E1E, 0x43D23E48, 0xFB6E592D, 0xE9DBF6C3, 0x516791A6,
+        0xCCB0A91F, 0x740CCE7A, 0x66B96194, 0xDE0506F1,
+    ],
+    [
+        0x00000000, 0x3D6029B0, 0x7AC05360, 0x47A07AD0, 0xF580A6C0, 0xC8E08F70, 0x8F40F5A0,
+        0xB220DC10, 0x30704BC1, 0x0D106271, 0x4AB018A1, 0x77D03111, 0xC5F0ED01, 0xF890C4B1,
+        0xBF30BE61, 0x825097D1, 0x60E09782, 0x5D80BE32, 0x1A20C4E2, 0x2740ED52, 0x95603142,
+        0xA80018F2, 0xEFA06222, 0xD2C04B92, 0x5090DC43, 0x6DF0F5F3, 0x2A508F23, 0x1730A693,
+        0xA5107A83, 0x98705333, 0xDFD029E3, 0xE2B00053, 0xC1C12F04, 0xFCA106B4, 0xBB017C64,
+        0x866155D4, 0x344189C4, 0x0921A074, 0x4E81DAA4, 0x73E1F314, 0xF1B164C5, 0xCCD14D75,
+        0x8B7137A5, 0xB6111E15, 0x0431C205, 0x3951EBB5, 0x7EF19165, 0x4391B8D5, 0xA121B886,
+        0x9C419136, 0xDBE1EBE6, 0xE681C256, 0x54A11E46, 0x69C137F6, 0x2E614D26, 0x13016496,
+        0x9151F347, 0xAC31DAF7, 0xEB91A027, 0xD6F18997, 0x64D15587, 0x59B17C37, 0x1E1106E7,
+        0x23712F57, 0x58F35849, 0x659371F9, 0x22330B29, 0x1F532299, 0xAD73FE89, 0x9013D739,
+        0xD7B3ADE9, 0xEAD38459, 0x68831388, 0x55E33A38, 0x124340E8, 0x2F236958, 0x9D03B548,
+        0xA0639CF8, 0xE7C3E628, 0xDAA3CF98, 0x3813CFCB, 0x0573E67B, 0x42D39CAB, 0x7FB3B51B,
+        0xCD93690B, 0xF0F340BB, 0xB7533A6B, 0x8A3313DB, 0x0863840A, 0x3503ADBA, 0x72A3D76A,
+        0x4FC3FEDA, 0xFDE322CA, 0xC0830B7A, 0x872371AA, 0xBA43581A, 0x9932774D, 0xA4525EFD,
+        0xE3F2242D, 0xDE920D9D, 0x6CB2D18D, 0x51D2F83D, 0x167282ED, 0x2B12AB5D, 0xA9423C8C,
+        0x9422153C, 0xD3826FEC, 0xEEE2465C, 0x5CC29A4C, 0x61A2B3FC, 0x2602C92C, 0x1B62E09C,
+        0xF9D2E0CF, 0xC4B2C97F, 0x8312B3AF, 0xBE729A1F, 0x0C52460F, 0x31326FBF, 0x7692156F,
+        0x4BF23CDF, 0xC9A2AB0E, 0xF4C282BE, 0xB362F86E, 0x8E02D1DE, 0x3C220DCE, 0x0142247E,
+        0x46E25EAE, 0x7B82771E, 0xB1E6B092, 0x8C869922, 0xCB26E3F2, 0xF646CA42, 0x44661652,
+        0x79063FE2, 0x3EA64532, 0x03C66C82, 0x8196FB53, 0xBCF6D2E3, 0xFB56A833, 0xC6368183,
+        0x74165D93, 0x49767423, 0x0ED60EF3, 0x33B62743, 0xD1062710, 0xEC660EA0, 0xABC67470,
+        0x96A65DC0, 0x248681D0, 0x19E6A860, 0x5E46D2B0, 0x6326FB00, 0xE1766CD1, 0xDC164561,
+        0x9BB63FB1, 0xA6D61601, 0x14F6CA11, 0x2996E3A1, 0x6E369971, 0x5356B0C1, 0x70279F96,
+        0x4D47B626, 0x0AE7CCF6, 0x3787E546, 0x85A73956, 0xB8C710E6, 0xFF676A36, 0xC2074386,
+        0x4057D457, 0x7D37FDE7, 0x3A978737, 0x07F7AE87, 0xB5D77297, 0x88B75B27, 0xCF1721F7,
+        0xF2770847, 0x10C70814, 0x2DA721A4, 0x6A075B74, 0x576772C4, 0xE547AED4, 0xD8278764,
+        0x9F87FDB4, 0xA2E7D404, 0x20B743D5, 0x1DD76A65, 0x5A7710B5, 0x67173905, 0xD537E515,
+        0xE857CCA5, 0xAFF7B675, 0x92979FC5, 0xE915E8DB, 0xD475C16B, 0x93D5BBBB, 0xAEB5920B,
+        0x1C954E1B, 0x21F567AB, 0x66551D7B, 0x5B3534CB, 0xD965A31A, 0xE4058AAA, 0xA3A5F07A,
+        0x9EC5D9CA, 0x2CE505DA, 0x11852C6A, 0x562556BA, 0x6B457F0A, 0x89F57F59, 0xB49556E9,
+        0xF3352C39, 0xCE550589, 0x7C75D999, 0x4115F029, 0x06B58AF9, 0x3BD5A349, 0xB9853498,
+        0x84E51D28, 0xC34567F8, 0xFE254E48, 0x4C059258, 0x7165BBE8, 0x36C5C138, 0x0BA5E888,
+        0x28D4C7DF, 0x15B4EE6F, 0x521494BF, 0x6F74BD0F, 0xDD54611F, 0xE03448AF, 0xA794327F,
+        0x9AF41BCF, 0x18A48C1E, 0x25C4A5AE, 0x6264DF7E, 0x5F04F6CE, 0xED242ADE, 0xD044036E,
+        0x97E479BE, 0xAA84500E, 0x4834505D, 0x755479ED, 0x32F4033D, 0x0F942A8D, 0xBDB4F69D,
+        0x80D4DF2D, 0xC774A5FD, 0xFA148C4D, 0x78441B9C, 0x4524322C, 0x028448FC, 0x3FE4614C,
+        0x8DC4BD5C, 0xB0A494EC, 0xF704EE3C, 0xCA64C78C,
+    ],
+    [
+        0x00000000, 0xCB5CD3A5, 0x4DC8A10B, 0x869472AE, 0x9B914216, 0x50CD91B3, 0xD659E31D,
+        0x1D0530B8, 0xEC53826D, 0x270F51C8, 0xA19B2366, 0x6AC7F0C3, 0x77C2C07B, 0xBC9E13DE,
+        0x3A0A6170, 0xF156B2D5, 0x03D6029B, 0xC88AD13E, 0x4E1EA390, 0x85427035, 0x9847408D,
+        0x531B9328, 0xD58FE186, 0x1ED33223, 0xEF8580F6, 0x24D95353, 0xA24D21FD, 0x6911F258,
+        0x7414C2E0, 0xBF481145, 0x39DC63EB, 0xF280B04E, 0x07AC0536, 0xCCF0D693, 0x4A64A43D,
+        0x81387798, 0x9C3D4720, 0x57619485, 0xD1F5E62B, 0x1AA9358E, 0xEBFF875B, 0x20A354FE,
+        0xA6372650, 0x6D6BF5F5, 0x706EC54D, 0xBB3216E8, 0x3DA66446, 0xF6FAB7E3, 0x047A07AD,
+        0xCF26D408, 0x49B2A6A6, 0x82EE7503, 0x9FEB45BB, 0x54B7961E, 0xD223E4B0, 0x197F3715,
+        0xE82985C0, 0x23755665, 0xA5E124CB, 0x6EBDF76E, 0x73B8C7D6, 0xB8E41473, 0x3E7066DD,
+        0xF52CB578, 0x0F580A6C, 0xC404D9C9, 0x4290AB67, 0x89CC78C2, 0x94C9487A, 0x5F959BDF,
+        0xD901E971, 0x125D3AD4, 0xE30B8801, 0x28575BA4, 0xAEC3290A, 0x659FFAAF, 0x789ACA17,
+        0xB3C619B2, 0x35526B1C, 0xFE0EB8B9, 0x0C8E08F7, 0xC7D2DB52, 0x4146A9FC, 0x8A1A7A59,
+        0x971F4AE1, 0x5C439944, 0xDAD7EBEA, 0x118B384F, 0xE0DD8A9A, 0x2B81593F, 0xAD152B91,
+        0x6649F834, 0x7B4CC88C, 0xB0101B29, 0x36846987, 0xFDD8BA22, 0x08F40F5A, 0xC3A8DCFF,
+        0x453CAE51, 0x8E607DF4, 0x93654D4C, 0x58399EE9, 0xDEADEC47, 0x15F13FE2, 0xE4A78D37,
+        0x2FFB5E92, 0xA96F2C3C, 0x6233FF99, 0x7F36CF21, 0xB46A1C84, 0x32FE6E2A, 0xF9A2BD8F,
+        0x0B220DC1, 0xC07EDE64, 0x46EAACCA, 0x8DB67F6F, 0x90B34FD7, 0x5BEF9C72, 0xDD7BEEDC,
+        0x16273D79, 0xE7718FAC, 0x2C2D5C09, 0xAAB92EA7, 0x61E5FD02, 0x7CE0CDBA, 0xB7BC1E1F,
+        0x31286CB1, 0xFA74BF14, 0x1EB014D8, 0xD5ECC77D, 0x5378B5D3, 0x98246676, 0x852156CE,
+        0x4E7D856B, 0xC8E9F7C5, 0x03B52460, 0xF2E396B5, 0x39BF4510, 0xBF2B37BE, 0x7477E41B,
+        0x6972D4A3, 0xA22E0706, 0x24BA75A8, 0xEFE6A60D, 0x1D661643, 0xD63AC5E6, 0x50AEB748,
+        0x9BF264ED, 0x86F75455, 0x4DAB87F0, 0xCB3FF55E, 0x006326FB, 0xF135942E, 0x3A69478B,
+        0xBCFD3525, 0x77A1E680, 0x6AA4D638, 0xA1F8059D, 0x276C7733, 0xEC30A496, 0x191C11EE,
+        0xD240C24B, 0x54D4B0E5, 0x9F886340, 0x828D53F8, 0x49D1805D, 0xCF45F2F3, 0x04192156,
+        0xF54F9383, 0x3E134026, 0xB8873288, 0x73DBE12D, 0x6EDED195, 0xA5820230, 0x2316709E,
+        0xE84AA33B, 0x1ACA1375, 0xD196C0D0, 0x5702B27E, 0x9C5E61DB, 0x815B5163, 0x4A0782C6,
+        0xCC93F068, 0x07CF23CD, 0xF6999118, 0x3DC542BD, 0xBB513013, 0x700DE3B6, 0x6D08D30E,
+        0xA65400AB, 0x20C07205, 0xEB9CA1A0, 0x11E81EB4, 0xDAB4CD11, 0x5C20BFBF, 0x977C6C1A,
+        0x8A795CA2, 0x41258F07, 0xC7B1FDA9, 0x0CED2E0C, 0xFDBB9CD9, 0x36E74F7C, 0xB0733DD2,
+        0x7B2FEE77, 0x662ADECF, 0xAD760D6A, 0x2BE27FC4, 0xE0BEAC61, 0x123E1C2F, 0xD962CF8A,
+        0x5FF6BD24, 0x94AA6E81, 0x89AF5E39, 0x42F38D9C, 0xC467FF32, 0x0F3B2C97, 0xFE6D9E42,
+        0x35314DE7, 0xB3A53F49, 0x78F9ECEC, 0x65FCDC54, 0xAEA00FF1, 0x28347D5F, 0xE368AEFA,
+        0x16441B82, 0xDD18C827, 0x5B8CBA89, 0x90D0692C, 0x8DD55994, 0x46898A31, 0xC01DF89F,
+        0x0B412B3A, 0xFA1799EF, 0x314B4A4A, 0xB7DF38E4, 0x7C83EB41, 0x6186DBF9, 0xAADA085C,
+        0x2C4E7AF2, 0xE712A957, 0x15921919, 0xDECECABC, 0x585AB812, 0x93066BB7, 0x8E035B0F,
+        0x455F88AA, 0xC3CBFA04, 0x089729A1, 0xF9C19B74, 0x329D48D1, 0xB4093A7F, 0x7F55E9DA,
+        0x6250D962, 0xA90C0AC7, 0x2F987869, 0xE4C4ABCC,
+    ],
+    [
+        0x00000000, 0xA6770BB4, 0x979F1129, 0x31E81A9D, 0xF44F2413, 0x52382FA7, 0x63D0353A,
+        0xC5A73E8E, 0x33EF4E67, 0x959845D3, 0xA4705F4E, 0x020754FA, 0xC7A06A74, 0x61D761C0,
+        0x503F7B5D, 0xF64870E9, 0x67DE9CCE, 0xC1A9977A, 0xF0418DE7, 0x56368653, 0x9391B8DD,
+        0x35E6B369, 0x040EA9F4, 0xA279A240, 0x5431D2A9, 0xF246D91D, 0xC3AEC380, 0x65D9C834,
+        0xA07EF6BA, 0x0609FD0E, 0x37E1E793, 0x9196EC27, 0xCFBD399C, 0x69CA3228, 0x582228B5,
+        0xFE552301, 0x3BF21D8F, 0x9D85163B, 0xAC6D0CA6, 0x0A1A0712, 0xFC5277FB, 0x5A257C4F,
+        0x6BCD66D2, 0xCDBA6D66, 0x081D53E8, 0xAE6A585C, 0x9F8242C1, 0x39F54975, 0xA863A552,
+        0x0E14AEE6, 0x3FFCB47B, 0x998BBFCF, 0x5C2C8141, 0xFA5B8AF5, 0xCBB39068, 0x6DC49BDC,
+        0x9B8CEB35, 0x3DFBE081, 0x0C13FA1C, 0xAA64F1A8, 0x6FC3CF26, 0xC9B4C492, 0xF85CDE0F,
+        0x5E2BD5BB, 0x440B7579, 0xE27C7ECD, 0xD3946450, 0x75E36FE4, 0xB044516A, 0x16335ADE,
+        0x27DB4043, 0x81AC4BF7, 0x77E43B1E, 0xD19330AA, 0xE07B2A37, 0x460C2183, 0x83AB1F0D,
+        0x25DC14B9, 0x14340E24, 0xB2430590, 0x23D5E9B7, 0x85A2E203, 0xB44AF89E, 0x123DF32A,
+        0xD79ACDA4, 0x71EDC610, 0x4005DC8D, 0xE672D739, 0x103AA7D0, 0xB64DAC64, 0x87A5B6F9,
+        0x21D2BD4D, 0xE47583C3, 0x42028877, 0x73EA92EA, 0xD59D995E, 0x8BB64CE5, 0x2DC14751,
+        0x1C295DCC, 0xBA5E5678, 0x7FF968F6, 0xD98E6342, 0xE86679DF, 0x4E11726B, 0xB8590282,
+        0x1E2E0936, 0x2FC613AB, 0x89B1181F, 0x4C162691, 0xEA612D25, 0xDB8937B8, 0x7DFE3C0C,
+        0xEC68D02B, 0x4A1FDB9F, 0x7BF7C102, 0xDD80CAB6, 0x1827F438, 0xBE50FF8C, 0x8FB8E511,
+        0x29CFEEA5, 0xDF879E4C, 0x79F095F8, 0x48188F65, 0xEE6F84D1, 0x2BC8BA5F, 0x8DBFB1EB,
+        0xBC57AB76, 0x1A20A0C2, 0x8816EAF2, 0x2E61E146, 0x1F89FBDB, 0xB9FEF06F, 0x7C59CEE1,
+        0xDA2EC555, 0xEBC6DFC8, 0x4DB1D47C, 0xBBF9A495, 0x1D8EAF21, 0x2C66B5BC, 0x8A11BE08,
+        0x4FB68086, 0xE9C18B32, 0xD82991AF, 0x7E5E9A1B, 0xEFC8763C, 0x49BF7D88, 0x78576715,
+        0xDE206CA1, 0x1B87522F, 0xBDF0599B, 0x8C184306, 0x2A6F48B2, 0xDC27385B, 0x7A5033EF,
+        0x4BB82972, 0xEDCF22C6, 0x28681C48, 0x8E1F17FC, 0xBFF70D61, 0x198006D5, 0x47ABD36E,
+        0xE1DCD8DA, 0xD034C247, 0x7643C9F3, 0xB3E4F77D, 0x1593FCC9, 0x247BE654, 0x820CEDE0,
+        0x74449D09, 0xD23396BD, 0xE3DB8C20, 0x45AC8794, 0x800BB91A, 0x267CB2AE, 0x1794A833,
+        0xB1E3A387, 0x20754FA0, 0x86024414, 0xB7EA5E89, 0x119D553D, 0xD43A6BB3, 0x724D6007,
+        0x43A57A9A, 0xE5D2712E, 0x139A01C7, 0xB5ED0A73, 0x840510EE, 0x22721B5A, 0xE7D525D4,
+        0x41A22E60, 0x704A34FD, 0xD63D3F49, 0xCC1D9F8B, 0x6A6A943F, 0x5B828EA2, 0xFDF58516,
+        0x3852BB98, 0x9E25B02C, 0xAFCDAAB1, 0x09BAA105, 0xFFF2D1EC, 0x5985DA58, 0x686DC0C5,
+        0xCE1ACB71, 0x0BBDF5FF, 0xADCAFE4B, 0x9C22E4D6, 0x3A55EF62, 0xABC30345, 0x0DB408F1,
+        0x3C5C126C, 0x9A2B19D8, 0x5F8C2756, 0xF9FB2CE2, 0xC813367F, 0x6E643DCB, 0x982C4D22,
+        0x3E5B4696, 0x0FB35C0B, 0xA9C457BF, 0x6C636931, 0xCA146285, 0xFBFC7818, 0x5D8B73AC,
+        0x03A0A617, 0xA5D7ADA3, 0x943FB73E, 0x3248BC8A, 0xF7EF8204, 0x519889B0, 0x6070932D,
+        0xC6079899, 0x304FE870, 0x9638E3C4, 0xA7D0F959, 0x01A7F2ED, 0xC400CC63, 0x6277C7D7,
+        0x539FDD4A, 0xF5E8D6FE, 0x647E3AD9, 0xC209316D, 0xF3E12BF0, 0x55962044, 0x90311ECA,
+        0x3646157E, 0x07AE0FE3, 0xA1D90457, 0x579174BE, 0xF1E67F0A, 0xC00E6597, 0x66796E23,
+        0xA3DE50AD, 0x05A95B19, 0x34414184, 0x92364A30,
+    ],
+    [
+        0x00000000, 0xCCAA009E, 0x4225077D, 0x8E8F07E3, 0x844A0EFA, 0x48E00E64, 0xC66F0987,
+        0x0AC50919, 0xD3E51BB5, 0x1F4F1B2B, 0x91C01CC8, 0x5D6A1C56, 0x57AF154F, 0x9B0515D1,
+        0x158A1232, 0xD92012AC, 0x7CBB312B, 0xB01131B5, 0x3E9E3656, 0xF23436C8, 0xF8F13FD1,
+        0x345B3F4F, 0xBAD438AC, 0x767E3832, 0xAF5E2A9E, 0x63F42A00, 0xED7B2DE3, 0x21D12D7D,
+        0x2B142464, 0xE7BE24FA, 0x69312319, 0xA59B2387, 0xF9766256, 0x35DC62C8, 0xBB53652B,
+        0x77F965B5, 0x7D3C6CAC, 0xB1966C32, 0x3F196BD1, 0xF3B36B4F, 0x2A9379E3, 0xE639797D,
+        0x68B67E9E, 0xA41C7E00, 0xAED97719, 0x62737787, 0xECFC7064, 0x205670FA, 0x85CD537D,
+        0x496753E3, 0xC7E85400, 0x0B42549E, 0x01875D87, 0xCD2D5D19, 0x43A25AFA, 0x8F085A64,
+        0x562848C8, 0x9A824856, 0x140D4FB5, 0xD8A74F2B, 0xD2624632, 0x1EC846AC, 0x9047414F,
+        0x5CED41D1, 0x299DC2ED, 0xE537C273, 0x6BB8C590, 0xA712C50E, 0xADD7CC17, 0x617DCC89,
+        0xEFF2CB6A, 0x2358CBF4, 0xFA78D958, 0x36D2D9C6, 0xB85DDE25, 0x74F7DEBB, 0x7E32D7A2,
+        0xB298D73C, 0x3C17D0DF, 0xF0BDD041, 0x5526F3C6, 0x998CF358, 0x1703F4BB, 0xDBA9F425,
+        0xD16CFD3C, 0x1DC6FDA2, 0x9349FA41, 0x5FE3FADF, 0x86C3E873, 0x4A69E8ED, 0xC4E6EF0E,
+        0x084CEF90, 0x0289E689, 0xCE23E617, 0x40ACE1F4, 0x8C06E16A, 0xD0EBA0BB, 0x1C41A025,
+        0x92CEA7C6, 0x5E64A758, 0x54A1AE41, 0x980BAEDF, 0x1684A93C, 0xDA2EA9A2, 0x030EBB0E,
+        0xCFA4BB90, 0x412BBC73, 0x8D81BCED, 0x8744B5F4, 0x4BEEB56A, 0xC561B289, 0x09CBB217,
+        0xAC509190, 0x60FA910E, 0xEE7596ED, 0x22DF9673, 0x281A9F6A, 0xE4B09FF4, 0x6A3F9817,
+        0xA6959889, 0x7FB58A25, 0xB31F8ABB, 0x3D908D58, 0xF13A8DC6, 0xFBFF84DF, 0x37558441,
+        0xB9DA83A2, 0x7570833C, 0x533B85DA, 0x9F918544, 0x111E82A7, 0xDDB48239, 0xD7718B20,
+        0x1BDB8BBE, 0x95548C5D, 0x59FE8CC3, 0x80DE9E6F, 0x4C749EF1, 0xC2FB9912, 0x0E51998C,
+        0x04949095, 0xC83E900B, 0x46B197E8, 0x8A1B9776, 0x2F80B4F1, 0xE32AB46F, 0x6DA5B38C,
+        0xA10FB312, 0xABCABA0B, 0x6760BA95, 0xE9EFBD76, 0x2545BDE8, 0xFC65AF44, 0x30CFAFDA,
+        0xBE40A839, 0x72EAA8A7, 0x782FA1BE, 0xB485A120, 0x3A0AA6C3, 0xF6A0A65D, 0xAA4DE78C,
+        0x66E7E712, 0xE868E0F1, 0x24C2E06F, 0x2E07E976, 0xE2ADE9E8, 0x6C22EE0B, 0xA088EE95,
+        0x79A8FC39, 0xB502FCA7, 0x3B8DFB44, 0xF727FBDA, 0xFDE2F2C3, 0x3148F25D, 0xBFC7F5BE,
+        0x736DF520, 0xD6F6D6A7, 0x1A5CD639, 0x94D3D1DA, 0x5879D144, 0x52BCD85D, 0x9E16D8C3,
+        0x1099DF20, 0xDC33DFBE, 0x0513CD12, 0xC9B9CD8C, 0x4736CA6F, 0x8B9CCAF1, 0x8159C3E8,
+        0x4DF3C376, 0xC37CC495, 0x0FD6C40B, 0x7AA64737, 0xB60C47A9, 0x3883404A, 0xF42940D4,
+        0xFEEC49CD, 0x32464953, 0xBCC94EB0, 0x70634E2E, 0xA9435C82, 0x65E95C1C, 0xEB665BFF,
+        0x27CC5B61, 0x2D095278, 0xE1A352E6, 0x6F2C5505, 0xA386559B, 0x061D761C, 0xCAB77682,
+        0x44387161, 0x889271FF, 0x825778E6, 0x4EFD7878, 0xC0727F9B, 0x0CD87F05, 0xD5F86DA9,
+        0x19526D37, 0x97DD6AD4, 0x5B776A4A, 0x51B26353, 0x9D1863CD, 0x1397642E, 0xDF3D64B0,
+        0x83D02561, 0x4F7A25FF, 0xC1F5221C, 0x0D5F2282, 0x079A2B9B, 0xCB302B05, 0x45BF2CE6,
+        0x89152C78, 0x50353ED4, 0x9C9F3E4A, 0x121039A9, 0xDEBA3937, 0xD47F302E, 0x18D530B0,
+        0x965A3753, 0x5AF037CD, 0xFF6B144A, 0x33C114D4, 0xBD4E1337, 0x71E413A9, 0x7B211AB0,
+        0xB78B1A2E, 0x39041DCD, 0xF5AE1D53, 0x2C8E0FFF, 0xE0240F61, 0x6EAB0882, 0xA201081C,
+        0xA8C40105, 0x646E019B, 0xEAE10678, 0x264B06E6,
+    ],
+    [
+        0x00000000, 0x177B1443, 0x2EF62886, 0x398D3CC5, 0x5DEC510C, 0x4A97454F, 0x731A798A,
+        0x64616DC9, 0xBBD8A218, 0xACA3B65B, 0x952E8A9E, 0x82559EDD, 0xE634F314, 0xF14FE757,
+        0xC8C2DB92, 0xDFB9CFD1, 0xACC04271, 0xBBBB5632, 0x82366AF7, 0x954D7EB4, 0xF12C137D,
+        0xE657073E, 0xDFDA3BFB, 0xC8A12FB8, 0x1718E069, 0x0063F42A, 0x39EEC8EF, 0x2E95DCAC,
+        0x4AF4B165, 0x5D8FA526, 0x640299E3, 0x73798DA0, 0x82F182A3, 0x958A96E0, 0xAC07AA25,
+        0xBB7CBE66, 0xDF1DD3AF, 0xC866C7EC, 0xF1EBFB29, 0xE690EF6A, 0x392920BB, 0x2E5234F8,
+        0x17DF083D, 0x00A41C7E, 0x64C571B7, 0x73BE65F4, 0x4A335931, 0x5D484D72, 0x2E31C0D2,
+        0x394AD491, 0x00C7E854, 0x17BCFC17, 0x73DD91DE, 0x64A6859D, 0x5D2BB958, 0x4A50AD1B,
+        0x95E962CA, 0x82927689, 0xBB1F4A4C, 0xAC645E0F, 0xC80533C6, 0xDF7E2785, 0xE6F31B40,
+        0xF1880F03, 0xDE920307, 0xC9E91744, 0xF0642B81, 0xE71F3FC2, 0x837E520B, 0x94054648,
+        0xAD887A8D, 0xBAF36ECE, 0x654AA11F, 0x7231B55C, 0x4BBC8999, 0x5CC79DDA, 0x38A6F013,
+        0x2FDDE450, 0x1650D895, 0x012BCCD6, 0x72524176, 0x65295535, 0x5CA469F0, 0x4BDF7DB3,
+        0x2FBE107A, 0x38C50439, 0x014838FC, 0x16332CBF, 0xC98AE36E, 0xDEF1F72D, 0xE77CCBE8,
+        0xF007DFAB, 0x9466B262, 0x831DA621, 0xBA909AE4, 0xADEB8EA7, 0x5C6381A4, 0x4B1895E7,
+        0x7295A922, 0x65EEBD61, 0x018FD0A8, 0x16F4C4EB, 0x2F79F82E, 0x3802EC6D, 0xE7BB23BC,
+        0xF0C037FF, 0xC94D0B3A, 0xDE361F79, 0xBA5772B0, 0xAD2C66F3, 0x94A15A36, 0x83DA4E75,
+        0xF0A3C3D5, 0xE7D8D796, 0xDE55EB53, 0xC92EFF10, 0xAD4F92D9, 0xBA34869A, 0x83B9BA5F,
+        0x94C2AE1C, 0x4B7B61CD, 0x5C00758E, 0x658D494B, 0x72F65D08, 0x169730C1, 0x01EC2482,
+        0x38611847, 0x2F1A0C04, 0x6655004F, 0x712E140C, 0x48A328C9, 0x5FD83C8A, 0x3BB95143,
+        0x2CC24500, 0x154F79C5, 0x02346D86, 0xDD8DA257, 0xCAF6B614, 0xF37B8AD1, 0xE4009E92,
+        0x8061F35B, 0x971AE718, 0xAE97DBDD, 0xB9ECCF9E, 0xCA95423E, 0xDDEE567D, 0xE4636AB8,
+        0xF3187EFB, 0x97791332, 0x80020771, 0xB98F3BB4, 0xAEF42FF7, 0x714DE026, 0x6636F465,
+        0x5FBBC8A0, 0x48C0DCE3, 0x2CA1B12A, 0x3BDAA569, 0x025799AC, 0x152C8DEF, 0xE4A482EC,
+        0xF3DF96AF, 0xCA52AA6A, 0xDD29BE29, 0xB948D3E0, 0xAE33C7A3, 0x97BEFB66, 0x80C5EF25,
+        0x5F7C20F4, 0x480734B7, 0x718A0872, 0x66F11C31, 0x029071F8, 0x15EB65BB, 0x2C66597E,
+        0x3B1D4D3D, 0x4864C09D, 0x5F1FD4DE, 0x6692E81B, 0x71E9FC58, 0x15889191, 0x02F385D2,
+        0x3B7EB917, 0x2C05AD54, 0xF3BC6285, 0xE4C776C6, 0xDD4A4A03, 0xCA315E40, 0xAE503389,
+        0xB92B27CA, 0x80A61B0F, 0x97DD0F4C, 0xB8C70348, 0xAFBC170B, 0x96312BCE, 0x814A3F8D,
+        0xE52B5244, 0xF2504607, 0xCBDD7AC2, 0xDCA66E81, 0x031FA150, 0x1464B513, 0x2DE989D6,
+        0x3A929D95, 0x5EF3F05C, 0x4988E41F, 0x7005D8DA, 0x677ECC99, 0x14074139, 0x037C557A,
+        0x3AF169BF, 0x2D8A7DFC, 0x49EB1035, 0x5E900476, 0x671D38B3, 0x70662CF0, 0xAFDFE321,
+        0xB8A4F762, 0x8129CBA7, 0x9652DFE4, 0xF233B22D, 0xE548A66E, 0xDCC59AAB, 0xCBBE8EE8,
+        0x3A3681EB, 0x2D4D95A8, 0x14C0A96D, 0x03BBBD2E, 0x67DAD0E7, 0x70A1C4A4, 0x492CF861,
+        0x5E57EC22, 0x81EE23F3, 0x969537B0, 0xAF180B75, 0xB8631F36, 0xDC0272FF, 0xCB7966BC,
+        0xF2F45A79, 0xE58F4E3A, 0x96F6C39A, 0x818DD7D9, 0xB800EB1C, 0xAF7BFF5F, 0xCB1A9296,
+        0xDC6186D5, 0xE5ECBA10, 0xF297AE53, 0x2D2E6182, 0x3A5575C1, 0x03D84904, 0x14A35D47,
+        0x70C2308E, 0x67B924CD, 0x5E341808, 0x494F0C4B,
+    ],
+    [
+        0x00000000, 0xEFC26B3E, 0x04F5D03D, 0xEB37BB03, 0x09EBA07A, 0xE629CB44, 0x0D1E7047,
+        0xE2DC1B79, 0x13D740F4, 0xFC152BCA, 0x172290C9, 0xF8E0FBF7, 0x1A3CE08E, 0xF5FE8BB0,
+        0x1EC930B3, 0xF10B5B8D, 0x27AE81E8, 0xC86CEAD6, 0x235B51D5, 0xCC993AEB, 0x2E452192,
+        0xC1874AAC, 0x2AB0F1AF, 0xC5729A91, 0x3479C11C, 0xDBBBAA22, 0x308C1121, 0xDF4E7A1F,
+        0x3D926166, 0xD2500A58, 0x3967B15B, 0xD6A5DA65, 0x4F5D03D0, 0xA09F68EE, 0x4BA8D3ED,
+        0xA46AB8D3, 0x46B6A3AA, 0xA974C894, 0x42437397, 0xAD8118A9, 0x5C8A4324, 0xB348281A,
+        0x587F9319, 0xB7BDF827, 0x5561E35E, 0xBAA38860, 0x51943363, 0xBE56585D, 0x68F38238,
+        0x8731E906, 0x6C065205, 0x83C4393B, 0x61182242, 0x8EDA497C, 0x65EDF27F, 0x8A2F9941,
+        0x7B24C2CC, 0x94E6A9F2, 0x7FD112F1, 0x901379CF, 0x72CF62B6, 0x9D0D0988, 0x763AB28B,
+        0x99F8D9B5, 0x9EBA07A0, 0x71786C9E, 0x9A4FD79D, 0x758DBCA3, 0x9751A7DA, 0x7893CCE4,
+        0x93A477E7, 0x7C661CD9, 0x8D6D4754, 0x62AF2C6A, 0x89989769, 0x665AFC57, 0x8486E72E,
+        0x6B448C10, 0x80733713, 0x6FB15C2D, 0xB9148648, 0x56D6ED76, 0xBDE15675, 0x52233D4B,
+        0xB0FF2632, 0x5F3D4D0C, 0xB40AF60F, 0x5BC89D31, 0xAAC3C6BC, 0x4501AD82, 0xAE361681,
+        0x41F47DBF, 0xA32866C6, 0x4CEA0DF8, 0xA7DDB6FB, 0x481FDDC5, 0xD1E70470, 0x3E256F4E,
+        0xD512D44D, 0x3AD0BF73, 0xD80CA40A, 0x37CECF34, 0xDCF97437, 0x333B1F09, 0xC2304484,
+        0x2DF22FBA, 0xC6C594B9, 0x2907FF87, 0xCBDBE4FE, 0x24198FC0, 0xCF2E34C3, 0x20EC5FFD,
+        0xF6498598, 0x198BEEA6, 0xF2BC55A5, 0x1D7E3E9B, 0xFFA225E2, 0x10604EDC, 0xFB57F5DF,
+        0x14959EE1, 0xE59EC56C, 0x0A5CAE52, 0xE16B1551, 0x0EA97E6F, 0xEC756516, 0x03B70E28,
+        0xE880B52B, 0x0742DE15, 0xE6050901, 0x09C7623F, 0xE2F0D93C, 0x0D32B202, 0xEFEEA97B,
+        0x002CC245, 0xEB1B7946, 0x04D91278, 0xF5D249F5, 0x1A1022CB, 0xF12799C8, 0x1EE5F2F6,
+        0xFC39E98F, 0x13FB82B1, 0xF8CC39B2, 0x170E528C, 0xC1AB88E9, 0x2E69E3D7, 0xC55E58D4,
+        0x2A9C33EA, 0xC8402893, 0x278243AD, 0xCCB5F8AE, 0x23779390, 0xD27CC81D, 0x3DBEA323,
+        0xD6891820, 0x394B731E, 0xDB976867, 0x34550359, 0xDF62B85A, 0x30A0D364, 0xA9580AD1,
+        0x469A61EF, 0xADADDAEC, 0x426FB1D2, 0xA0B3AAAB, 0x4F71C195, 0xA4467A96, 0x4B8411A8,
+        0xBA8F4A25, 0x554D211B, 0xBE7A9A18, 0x51B8F126, 0xB364EA5F, 0x5CA68161, 0xB7913A62,
+        0x5853515C, 0x8EF68B39, 0x6134E007, 0x8A035B04, 0x65C1303A, 0x871D2B43, 0x68DF407D,
+        0x83E8FB7E, 0x6C2A9040, 0x9D21CBCD, 0x72E3A0F3, 0x99D41BF0, 0x761670CE, 0x94CA6BB7,
+        0x7B080089, 0x903FBB8A, 0x7FFDD0B4, 0x78BF0EA1, 0x977D659F, 0x7C4ADE9C, 0x9388B5A2,
+        0x7154AEDB, 0x9E96C5E5, 0x75A17EE6, 0x9A6315D8, 0x6B684E55, 0x84AA256B, 0x6F9D9E68,
+        0x805FF556, 0x6283EE2F, 0x8D418511, 0x66763E12, 0x89B4552C, 0x5F118F49, 0xB0D3E477,
+        0x5BE45F74, 0xB426344A, 0x56FA2F33, 0xB938440D, 0x520FFF0E, 0xBDCD9430, 0x4CC6CFBD,
+        0xA304A483, 0x48331F80, 0xA7F174BE, 0x452D6FC7, 0xAAEF04F9, 0x41D8BFFA, 0xAE1AD4C4,
+        0x37E20D71, 0xD820664F, 0x3317DD4C, 0xDCD5B672, 0x3E09AD0B, 0xD1CBC635, 0x3AFC7D36,
+        0xD53E1608, 0x24354D85, 0xCBF726BB, 0x20C09DB8, 0xCF02F686, 0x2DDEEDFF, 0xC21C86C1,
+        0x292B3DC2, 0xC6E956FC, 0x104C8C99, 0xFF8EE7A7, 0x14B95CA4, 0xFB7B379A, 0x19A72CE3,
+        0xF66547DD, 0x1D52FCDE, 0xF29097E0, 0x039BCC6D, 0xEC59A753, 0x076E1C50, 0xE8AC776E,
+        0x0A706C17, 0xE5B20729, 0x0E85BC2A, 0xE147D714,
+    ],
+    [
+        0x00000000, 0xC18EDFC0, 0x586CB9C1, 0x99E26601, 0xB0D97382, 0x7157AC42, 0xE8B5CA43,
+        0x293B1583, 0xBAC3E145, 0x7B4D3E85, 0xE2AF5884, 0x23218744, 0x0A1A92C7, 0xCB944D07,
+        0x52762B06, 0x93F8F4C6, 0xAEF6C4CB, 0x6F781B0B, 0xF69A7D0A, 0x3714A2CA, 0x1E2FB749,
+        0xDFA16889, 0x46430E88, 0x87CDD148, 0x1435258E, 0xD5BBFA4E, 0x4C599C4F, 0x8DD7438F,
+        0xA4EC560C, 0x656289CC, 0xFC80EFCD, 0x3D0E300D, 0x869C8FD7, 0x47125017, 0xDEF03616,
+        0x1F7EE9D6, 0x3645FC55, 0xF7CB2395, 0x6E294594, 0xAFA79A54, 0x3C5F6E92, 0xFDD1B152,
+        0x6433D753, 0xA5BD0893, 0x8C861D10, 0x4D08C2D0, 0xD4EAA4D1, 0x15647B11, 0x286A4B1C,
+        0xE9E494DC, 0x7006F2DD, 0xB1882D1D, 0x98B3389E, 0x593DE75E, 0xC0DF815F, 0x01515E9F,
+        0x92A9AA59, 0x53277599, 0xCAC51398, 0x0B4BCC58, 0x2270D9DB, 0xE3FE061B, 0x7A1C601A,
+        0xBB92BFDA, 0xD64819EF, 0x17C6C62F, 0x8E24A02E, 0x4FAA7FEE, 0x66916A6D, 0xA71FB5AD,
+        0x3EFDD3AC, 0xFF730C6C, 0x6C8BF8AA, 0xAD05276A, 0x34E7416B, 0xF5699EAB, 0xDC528B28,
+        0x1DDC54E8, 0x843E32E9, 0x45B0ED29, 0x78BEDD24, 0xB93002E4, 0x20D264E5, 0xE15CBB25,
+        0xC867AEA6, 0x09E97166, 0x900B1767, 0x5185C8A7, 0xC27D3C61, 0x03F3E3A1, 0x9A1185A0,
+        0x5B9F5A60, 0x72A44FE3, 0xB32A9023, 0x2AC8F622, 0xEB4629E2, 0x50D49638, 0x915A49F8,
+        0x08B82FF9, 0xC936F039, 0xE00DE5BA, 0x21833A7A, 0xB8615C7B, 0x79EF83BB, 0xEA17777D,
+        0x2B99A8BD, 0xB27BCEBC, 0x73F5117C, 0x5ACE04FF, 0x9B40DB3F, 0x02A2BD3E, 0xC32C62FE,
+        0xFE2252F3, 0x3FAC8D33, 0xA64EEB32, 0x67C034F2, 0x4EFB2171, 0x8F75FEB1, 0x169798B0,
+        0xD7194770, 0x44E1B3B6, 0x856F6C76, 0x1C8D0A77, 0xDD03D5B7, 0xF438C034, 0x35B61FF4,
+        0xAC5479F5, 0x6DDAA635, 0x77E1359F, 0xB66FEA5F, 0x2F8D8C5E, 0xEE03539E, 0xC738461D,
+        0x06B699DD, 0x9F54FFDC, 0x5EDA201C, 0xCD22D4DA, 0x0CAC0B1A, 0x954E6D1B, 0x54C0B2DB,
+        0x7DFBA758, 0xBC757898, 0x25971E99, 0xE419C159, 0xD917F154, 0x18992E94, 0x817B4895,
+        0x40F59755, 0x69CE82D6, 0xA8405D16, 0x31A23B17, 0xF02CE4D7, 0x63D41011, 0xA25ACFD1,
+        0x3BB8A9D0, 0xFA367610, 0xD30D6393, 0x1283BC53, 0x8B61DA52, 0x4AEF0592, 0xF17DBA48,
+        0x30F36588, 0xA9110389, 0x689FDC49, 0x41A4C9CA, 0x802A160A, 0x19C8700B, 0xD846AFCB,
+        0x4BBE5B0D, 0x8A3084CD, 0x13D2E2CC, 0xD25C3D0C, 0xFB67288F, 0x3AE9F74F, 0xA30B914E,
+        0x62854E8E, 0x5F8B7E83, 0x9E05A143, 0x07E7C742, 0xC6691882, 0xEF520D01, 0x2EDCD2C1,
+        0xB73EB4C0, 0x76B06B00, 0xE5489FC6, 0x24C64006, 0xBD242607, 0x7CAAF9C7, 0x5591EC44,
+        0x941F3384, 0x0DFD5585, 0xCC738A45, 0xA1A92C70, 0x6027F3B0, 0xF9C595B1, 0x384B4A71,
+        0x11705FF2, 0xD0FE8032, 0x491CE633, 0x889239F3, 0x1B6ACD35, 0xDAE412F5, 0x430674F4,
+        0x8288AB34, 0xABB3BEB7, 0x6A3D6177, 0xF3DF0776, 0x3251D8B6, 0x0F5FE8BB, 0xCED1377B,
+        0x5733517A, 0x96BD8EBA, 0xBF869B39, 0x7E0844F9, 0xE7EA22F8, 0x2664FD38, 0xB59C09FE,
+        0x7412D63E, 0xEDF0B03F, 0x2C7E6FFF, 0x05457A7C, 0xC4CBA5BC, 0x5D29C3BD, 0x9CA71C7D,
+        0x2735A3A7, 0xE6BB7C67, 0x7F591A66, 0xBED7C5A6, 0x97ECD025, 0x56620FE5, 0xCF8069E4,
+        0x0E0EB624, 0x9DF642E2, 0x5C789D22, 0xC59AFB23, 0x041424E3, 0x2D2F3160, 0xECA1EEA0,
+        0x754388A1, 0xB4CD5761, 0x89C3676C, 0x484DB8AC, 0xD1AFDEAD, 0x1021016D, 0x391A14EE,
+        0xF894CB2E, 0x6176AD2F, 0xA0F872EF, 0x33008629, 0xF28E59E9, 0x6B6C3FE8, 0xAAE2E028,
+        0x83D9F5AB, 0x42572A6B, 0xDBB54C6A, 0x1A3B93AA,
+    ],
+    [
+        0x00000000, 0x9BA54C6F, 0xEC3B9E9F, 0x779ED2F0, 0x03063B7F, 0x98A37710, 0xEF3DA5E0,
+        0x7498E98F, 0x060C76FE, 0x9DA93A91, 0xEA37E861, 0x7192A40E, 0x050A4D81, 0x9EAF01EE,
+        0xE931D31E, 0x72949F71, 0x0C18EDFC, 0x97BDA193, 0xE0237363, 0x7B863F0C, 0x0F1ED683,
+        0x94BB9AEC, 0xE325481C, 0x78800473, 0x0A149B02, 0x91B1D76D, 0xE62F059D, 0x7D8A49F2,
+        0x0912A07D, 0x92B7EC12, 0xE5293EE2, 0x7E8C728D, 0x1831DBF8, 0x83949797, 0xF40A4567,
+        0x6FAF0908, 0x1B37E087, 0x8092ACE8, 0xF70C7E18, 0x6CA93277, 0x1E3DAD06, 0x8598E169,
+        0xF2063399, 0x69A37FF6, 0x1D3B9679, 0x869EDA16, 0xF10008E6, 0x6AA54489, 0x14293604,
+        0x8F8C7A6B, 0xF812A89B, 0x63B7E4F4, 0x172F0D7B, 0x8C8A4114, 0xFB1493E4, 0x60B1DF8B,
+        0x122540FA, 0x89800C95, 0xFE1EDE65, 0x65BB920A, 0x11237B85, 0x8A8637EA, 0xFD18E51A,
+        0x66BDA975, 0x3063B7F0, 0xABC6FB9F, 0xDC58296F, 0x47FD6500, 0x33658C8F, 0xA8C0C0E0,
+        0xDF5E1210, 0x44FB5E7F, 0x366FC10E, 0xADCA8D61, 0xDA545F91, 0x41F113FE, 0x3569FA71,
+        0xAECCB61E, 0xD95264EE, 0x42F72881, 0x3C7B5A0C, 0xA7DE1663, 0xD040C493, 0x4BE588FC,
+        0x3F7D6173, 0xA4D82D1C, 0xD346FFEC, 0x48E3B383, 0x3A772CF2, 0xA1D2609D, 0xD64CB26D,
+        0x4DE9FE02, 0x3971178D, 0xA2D45BE2, 0xD54A8912, 0x4EEFC57D, 0x28526C08, 0xB3F72067,
+        0xC469F297, 0x5FCCBEF8, 0x2B545777, 0xB0F11B18, 0xC76FC9E8, 0x5CCA8587, 0x2E5E1AF6,
+        0xB5FB5699, 0xC2658469, 0x59C0C806, 0x2D582189, 0xB6FD6DE6, 0xC163BF16, 0x5AC6F379,
+        0x244A81F4, 0xBFEFCD9B, 0xC8711F6B, 0x53D45304, 0x274CBA8B, 0xBCE9F6E4, 0xCB772414,
+        0x50D2687B, 0x2246F70A, 0xB9E3BB65, 0xCE7D6995, 0x55D825FA, 0x2140CC75, 0xBAE5801A,
+        0xCD7B52EA, 0x56DE1E85, 0x60C76FE0, 0xFB62238F, 0x8CFCF17F, 0x1759BD10, 0x63C1549F,
+        0xF86418F0, 0x8FFACA00, 0x145F866F, 0x66CB191E, 0xFD6E5571, 0x8AF08781, 0x1155CBEE,
+        0x65CD2261, 0xFE686E0E, 0x89F6BCFE, 0x1253F091, 0x6CDF821C, 0xF77ACE73, 0x80E41C83,
+        0x1B4150EC, 0x6FD9B963, 0xF47CF50C, 0x83E227FC, 0x18476B93, 0x6AD3F4E2, 0xF176B88D,
+        0x86E86A7D, 0x1D4D2612, 0x69D5CF9D, 0xF27083F2, 0x85EE5102, 0x1E4B1D6D, 0x78F6B418,
+        0xE353F877, 0x94CD2A87, 0x0F6866E8, 0x7BF08F67, 0xE055C308, 0x97CB11F8, 0x0C6E5D97,
+        0x7EFAC2E6, 0xE55F8E89, 0x92C15C79, 0x09641016, 0x7DFCF999, 0xE659B5F6, 0x91C76706,
+        0x0A622B69, 0x74EE59E4, 0xEF4B158B, 0x98D5C77B, 0x03708B14, 0x77E8629B, 0xEC4D2EF4,
+        0x9BD3FC04, 0x0076B06B, 0x72E22F1A, 0xE9476375, 0x9ED9B185, 0x057CFDEA, 0x71E41465,
+        0xEA41580A, 0x9DDF8AFA, 0x067AC695, 0x50A4D810, 0xCB01947F, 0xBC9F468F, 0x273A0AE0,
+        0x53A2E36F, 0xC807AF00, 0xBF997DF0, 0x243C319F, 0x56A8AEEE, 0xCD0DE281, 0xBA933071,
+        0x21367C1E, 0x55AE9591, 0xCE0BD9FE, 0xB9950B0E, 0x22304761, 0x5CBC35EC, 0xC7197983,
+        0xB087AB73, 0x2B22E71C, 0x5FBA0E93, 0xC41F42FC, 0xB381900C, 0x2824DC63, 0x5AB04312,
+        0xC1150F7D, 0xB68BDD8D, 0x2D2E91E2, 0x59B6786D, 0xC2133402, 0xB58DE6F2, 0x2E28AA9D,
+        0x489503E8, 0xD3304F87, 0xA4AE9D77, 0x3F0BD118, 0x4B933897, 0xD03674F8, 0xA7A8A608,
+        0x3C0DEA67, 0x4E997516, 0xD53C3979, 0xA2A2EB89, 0x3907A7E6, 0x4D9F4E69, 0xD63A0206,
+        0xA1A4D0F6, 0x3A019C99, 0x448DEE14, 0xDF28A27B, 0xA8B6708B, 0x33133CE4, 0x478BD56B,
+        0xDC2E9904, 0xABB04BF4, 0x3015079B, 0x428198EA, 0xD924D485, 0xAEBA0675, 0x351F4A1A,
+        0x4187A395, 0xDA22EFFA, 0xADBC3D0A, 0x36197165,
+    ],
+    [
+        0x00000000, 0xDD96D985, 0x605CB54B, 0xBDCA6CCE, 0xC0B96A96, 0x1D2FB313, 0xA0E5DFDD,
+        0x7D730658, 0x5A03D36D, 0x87950AE8, 0x3A5F6626, 0xE7C9BFA3, 0x9ABAB9FB, 0x472C607E,
+        0xFAE60CB0, 0x2770D535, 0xB407A6DA, 0x69917F5F, 0xD45B1391, 0x09CDCA14, 0x74BECC4C,
+        0xA92815C9, 0x14E27907, 0xC974A082, 0xEE0475B7, 0x3392AC32, 0x8E58C0FC, 0x53CE1979,
+        0x2EBD1F21, 0xF32BC6A4, 0x4EE1AA6A, 0x937773EF, 0xB37E4BF5, 0x6EE89270, 0xD322FEBE,
+        0x0EB4273B, 0x73C72163, 0xAE51F8E6, 0x139B9428, 0xCE0D4DAD, 0xE97D9898, 0x34EB411D,
+        0x89212DD3, 0x54B7F456, 0x29C4F20E, 0xF4522B8B, 0x49984745, 0x940E9EC0, 0x0779ED2F,
+        0xDAEF34AA, 0x67255864, 0xBAB381E1, 0xC7C087B9, 0x1A565E3C, 0xA79C32F2, 0x7A0AEB77,
+        0x5D7A3E42, 0x80ECE7C7, 0x3D268B09, 0xE0B0528C, 0x9DC354D4, 0x40558D51, 0xFD9FE19F,
+        0x2009381A, 0xBD8D91AB, 0x601B482E, 0xDDD124E0, 0x0047FD65, 0x7D34FB3D, 0xA0A222B8,
+        0x1D684E76, 0xC0FE97F3, 0xE78E42C6, 0x3A189B43, 0x87D2F78D, 0x5A442E08, 0x27372850,
+        0xFAA1F1D5, 0x476B9D1B, 0x9AFD449E, 0x098A3771, 0xD41CEEF4, 0x69D6823A, 0xB4405BBF,
+        0xC9335DE7, 0x14A58462, 0xA96FE8AC, 0x74F93129, 0x5389E41C, 0x8E1F3D99, 0x33D55157,
+        0xEE4388D2, 0x93308E8A, 0x4EA6570F, 0xF36C3BC1, 0x2EFAE244, 0x0EF3DA5E, 0xD36503DB,
+        0x6EAF6F15, 0xB339B690, 0xCE4AB0C8, 0x13DC694D, 0xAE160583, 0x7380DC06, 0x54F00933,
+        0x8966D0B6, 0x34ACBC78, 0xE93A65FD, 0x944963A5, 0x49DFBA20, 0xF415D6EE, 0x29830F6B,
+        0xBAF47C84, 0x6762A501, 0xDAA8C9CF, 0x073E104A, 0x7A4D1612, 0xA7DBCF97, 0x1A11A359,
+        0xC7877ADC, 0xE0F7AFE9, 0x3D61766C, 0x80AB1AA2, 0x5D3DC327, 0x204EC57F, 0xFDD81CFA,
+        0x40127034, 0x9D84A9B1, 0xA06A2517, 0x7DFCFC92, 0xC036905C, 0x1DA049D9, 0x60D34F81,
+        0xBD459604, 0x008FFACA, 0xDD19234F, 0xFA69F67A, 0x27FF2FFF, 0x9A354331, 0x47A39AB4,
+        0x3AD09CEC, 0xE7464569, 0x5A8C29A7, 0x871AF022, 0x146D83CD, 0xC9FB5A48, 0x74313686,
+        0xA9A7EF03, 0xD4D4E95B, 0x094230DE, 0xB4885C10, 0x691E8595, 0x4E6E50A0, 0x93F88925,
+        0x2E32E5EB, 0xF3A43C6E, 0x8ED73A36, 0x5341E3B3, 0xEE8B8F7D, 0x331D56F8, 0x13146EE2,
+        0xCE82B767, 0x7348DBA9, 0xAEDE022C, 0xD3AD0474, 0x0E3BDDF1, 0xB3F1B13F, 0x6E6768BA,
+        0x4917BD8F, 0x9481640A, 0x294B08C4, 0xF4DDD141, 0x89AED719, 0x54380E9C, 0xE9F26252,
+        0x3464BBD7, 0xA713C838, 0x7A8511BD, 0xC74F7D73, 0x1AD9A4F6, 0x67AAA2AE, 0xBA3C7B2B,
+        0x07F617E5, 0xDA60CE60, 0xFD101B55, 0x2086C2D0, 0x9D4CAE1E, 0x40DA779B, 0x3DA971C3,
+        0xE03FA846, 0x5DF5C488, 0x80631D0D, 0x1DE7B4BC, 0xC0716D39, 0x7DBB01F7, 0xA02DD872,
+        0xDD5EDE2A, 0x00C807AF, 0xBD026B61, 0x6094B2E4, 0x47E467D1, 0x9A72BE54, 0x27B8D29A,
+        0xFA2E0B1F, 0x875D0D47, 0x5ACBD4C2, 0xE701B80C, 0x3A976189, 0xA9E01266, 0x7476CBE3,
+        0xC9BCA72D, 0x142A7EA8, 0x695978F0, 0xB4CFA175, 0x0905CDBB, 0xD493143E, 0xF3E3C10B,
+        0x2E75188E, 0x93BF7440, 0x4E29ADC5, 0x335AAB9D, 0xEECC7218, 0x53061ED6, 0x8E90C753,
+        0xAE99FF49, 0x730F26CC, 0xCEC54A02, 0x13539387, 0x6E2095DF, 0xB3B64C5A, 0x0E7C2094,
+        0xD3EAF911, 0xF49A2C24, 0x290CF5A1, 0x94C6996F, 0x495040EA, 0x342346B2, 0xE9B59F37,
+        0x547FF3F9, 0x89E92A7C, 0x1A9E5993, 0xC7088016, 0x7AC2ECD8, 0xA754355D, 0xDA273305,
+        0x07B1EA80, 0xBA7B864E, 0x67ED5FCB, 0x409D8AFE, 0x9D0B537B, 0x20C13FB5, 0xFD57E630,
+        0x8024E068, 0x5DB239ED, 0xE0785523, 0x3DEE8CA6,
+    ],
+    [
+        0x00000000, 0x9D0FE176, 0xE16EC4AD, 0x7C6125DB, 0x19AC8F1B, 0x84A36E6D, 0xF8C24BB6,
+        0x65CDAAC0, 0x33591E36, 0xAE56FF40, 0xD237DA9B, 0x4F383BED, 0x2AF5912D, 0xB7FA705B,
+        0xCB9B5580, 0x5694B4F6, 0x66B23C6C, 0xFBBDDD1A, 0x87DCF8C1, 0x1AD319B7, 0x7F1EB377,
+        0xE2115201, 0x9E7077DA, 0x037F96AC, 0x55EB225A, 0xC8E4C32C, 0xB485E6F7, 0x298A0781,
+        0x4C47AD41, 0xD1484C37, 0xAD2969EC, 0x3026889A, 0xCD6478D8, 0x506B99AE, 0x2C0ABC75,
+        0xB1055D03, 0xD4C8F7C3, 0x49C716B5, 0x35A6336E, 0xA8A9D218, 0xFE3D66EE, 0x63328798,
+        0x1F53A243, 0x825C4335, 0xE791E9F5, 0x7A9E0883, 0x06FF2D58, 0x9BF0CC2E, 0xABD644B4,
+        0x36D9A5C2, 0x4AB88019, 0xD7B7616F, 0xB27ACBAF, 0x2F752AD9, 0x53140F02, 0xCE1BEE74,
+        0x988F5A82, 0x0580BBF4, 0x79E19E2F, 0xE4EE7F59, 0x8123D599, 0x1C2C34EF, 0x604D1134,
+        0xFD42F042, 0x41B9F7F1, 0xDCB61687, 0xA0D7335C, 0x3DD8D22A, 0x581578EA, 0xC51A999C,
+        0xB97BBC47, 0x24745D31, 0x72E0E9C7, 0xEFEF08B1, 0x938E2D6A, 0x0E81CC1C, 0x6B4C66DC,
+        0xF64387AA, 0x8A22A271, 0x172D4307, 0x270BCB9D, 0xBA042AEB, 0xC6650F30, 0x5B6AEE46,
+        0x3EA74486, 0xA3A8A5F0, 0xDFC9802B, 0x42C6615D, 0x1452D5AB, 0x895D34DD, 0xF53C1106,
+        0x6833F070, 0x0DFE5AB0, 0x90F1BBC6, 0xEC909E1D, 0x719F7F6B, 0x8CDD8F29, 0x11D26E5F,
+        0x6DB34B84, 0xF0BCAAF2, 0x95710032, 0x087EE144, 0x741FC49F, 0xE91025E9, 0xBF84911F,
+        0x228B7069, 0x5EEA55B2, 0xC3E5B4C4, 0xA6281E04, 0x3B27FF72, 0x4746DAA9, 0xDA493BDF,
+        0xEA6FB345, 0x77605233, 0x0B0177E8, 0x960E969E, 0xF3C33C5E, 0x6ECCDD28, 0x12ADF8F3,
+        0x8FA21985, 0xD936AD73, 0x44394C05, 0x385869DE, 0xA55788A8, 0xC09A2268, 0x5D95C31E,
+        0x21F4E6C5, 0xBCFB07B3, 0x8373EFE2, 0x1E7C0E94, 0x621D2B4F, 0xFF12CA39, 0x9ADF60F9,
+        0x07D0818F, 0x7BB1A454, 0xE6BE4522, 0xB02AF1D4, 0x2D2510A2, 0x51443579, 0xCC4BD40F,
+        0xA9867ECF, 0x34899FB9, 0x48E8BA62, 0xD5E75B14, 0xE5C1D38E, 0x78CE32F8, 0x04AF1723,
+        0x99A0F655, 0xFC6D5C95, 0x6162BDE3, 0x1D039838, 0x800C794E, 0xD698CDB8, 0x4B972CCE,
+        0x37F60915, 0xAAF9E863, 0xCF3442A3, 0x523BA3D5, 0x2E5A860E, 0xB3556778, 0x4E17973A,
+        0xD318764C, 0xAF795397, 0x3276B2E1, 0x57BB1821, 0xCAB4F957, 0xB6D5DC8C, 0x2BDA3DFA,
+        0x7D4E890C, 0xE041687A, 0x9C204DA1, 0x012FACD7, 0x64E20617, 0xF9EDE761, 0x858CC2BA,
+        0x188323CC, 0x28A5AB56, 0xB5AA4A20, 0xC9CB6FFB, 0x54C48E8D, 0x3109244D, 0xAC06C53B,
+        0xD067E0E0, 0x4D680196, 0x1BFCB560, 0x86F35416, 0xFA9271CD, 0x679D90BB, 0x02503A7B,
+        0x9F5FDB0D, 0xE33EFED6, 0x7E311FA0, 0xC2CA1813, 0x5FC5F965, 0x23A4DCBE, 0xBEAB3DC8,
+        0xDB669708, 0x4669767E, 0x3A0853A5, 0xA707B2D3, 0xF1930625, 0x6C9CE753, 0x10FDC288,
+        0x8DF223FE, 0xE83F893E, 0x75306848, 0x09514D93, 0x945EACE5, 0xA478247F, 0x3977C509,
+        0x4516E0D2, 0xD81901A4, 0xBDD4AB64, 0x20DB4A12, 0x5CBA6FC9, 0xC1B58EBF, 0x97213A49,
+        0x0A2EDB3F, 0x764FFEE4, 0xEB401F92, 0x8E8DB552, 0x13825424, 0x6FE371FF, 0xF2EC9089,
+        0x0FAE60CB, 0x92A181BD, 0xEEC0A466, 0x73CF4510, 0x1602EFD0, 0x8B0D0EA6, 0xF76C2B7D,
+        0x6A63CA0B, 0x3CF77EFD, 0xA1F89F8B, 0xDD99BA50, 0x40965B26, 0x255BF1E6, 0xB8541090,
+        0xC435354B, 0x593AD43D, 0x691C5CA7, 0xF413BDD1, 0x8872980A, 0x157D797C, 0x70B0D3BC,
+        0xEDBF32CA, 0x91DE1711, 0x0CD1F667, 0x5A454291, 0xC74AA3E7, 0xBB2B863C, 0x2624674A,
+        0x43E9CD8A, 0xDEE62CFC, 0xA2870927, 0x3F88E851,
+    ],
+    [
+        0x00000000, 0xB9FBDBE8, 0xA886B191, 0x117D6A79, 0x8A7C6563, 0x3387BE8B, 0x22FAD4F2,
+        0x9B010F1A, 0xCF89CC87, 0x7672176F, 0x670F7D16, 0xDEF4A6FE, 0x45F5A9E4, 0xFC0E720C,
+        0xED731875, 0x5488C39D, 0x44629F4F, 0xFD9944A7, 0xECE42EDE, 0x551FF536, 0xCE1EFA2C,
+        0x77E521C4, 0x66984BBD, 0xDF639055, 0x8BEB53C8, 0x32108820, 0x236DE259, 0x9A9639B1,
+        0x019736AB, 0xB86CED43, 0xA911873A, 0x10EA5CD2, 0x88C53E9E, 0x313EE576, 0x20438F0F,
+        0x99B854E7, 0x02B95BFD, 0xBB428015, 0xAA3FEA6C, 0x13C43184, 0x474CF219, 0xFEB729F1,
+        0xEFCA4388, 0x56319860, 0xCD30977A, 0x74CB4C92, 0x65B626EB, 0xDC4DFD03, 0xCCA7A1D1,
+        0x755C7A39, 0x64211040, 0xDDDACBA8, 0x46DBC4B2, 0xFF201F5A, 0xEE5D7523, 0x57A6AECB,
+        0x032E6D56, 0xBAD5B6BE, 0xABA8DCC7, 0x1253072F, 0x89520835, 0x30A9D3DD, 0x21D4B9A4,
+        0x982F624C, 0xCAFB7B7D, 0x7300A095, 0x627DCAEC, 0xDB861104, 0x40871E1E, 0xF97CC5F6,
+        0xE801AF8F, 0x51FA7467, 0x0572B7FA, 0xBC896C12, 0xADF4066B, 0x140FDD83, 0x8F0ED299,
+        0x36F50971, 0x27886308, 0x9E73B8E0, 0x8E99E432, 0x37623FDA, 0x261F55A3, 0x9FE48E4B,
+        0x04E58151, 0xBD1E5AB9, 0xAC6330C0, 0x1598EB28, 0x411028B5, 0xF8EBF35D, 0xE9969924,
+        0x506D42CC, 0xCB6C4DD6, 0x7297963E, 0x63EAFC47, 0xDA1127AF, 0x423E45E3, 0xFBC59E0B,
+        0xEAB8F472, 0x53432F9A, 0xC8422080, 0x71B9FB68, 0x60C49111, 0xD93F4AF9, 0x8DB78964,
+        0x344C528C, 0x253138F5, 0x9CCAE31D, 0x07CBEC07, 0xBE3037EF, 0xAF4D5D96, 0x16B6867E,
+        0x065CDAAC, 0xBFA70144, 0xAEDA6B3D, 0x1721B0D5, 0x8C20BFCF, 0x35DB6427, 0x24A60E5E,
+        0x9D5DD5B6, 0xC9D5162B, 0x702ECDC3, 0x6153A7BA, 0xD8A87C52, 0x43A97348, 0xFA52A8A0,
+        0xEB2FC2D9, 0x52D41931, 0x4E87F0BB, 0xF77C2B53, 0xE601412A, 0x5FFA9AC2, 0xC4FB95D8,
+        0x7D004E30, 0x6C7D2449, 0xD586FFA1, 0x810E3C3C, 0x38F5E7D4, 0x29888DAD, 0x90735645,
+        0x0B72595F, 0xB28982B7, 0xA3F4E8CE, 0x1A0F3326, 0x0AE56FF4, 0xB31EB41C, 0xA263DE65,
+        0x1B98058D, 0x80990A97, 0x3962D17F, 0x281FBB06, 0x91E460EE, 0xC56CA373, 0x7C97789B,
+        0x6DEA12E2, 0xD411C90A, 0x4F10C610, 0xF6EB1DF8, 0xE7967781, 0x5E6DAC69, 0xC642CE25,
+        0x7FB915CD, 0x6EC47FB4, 0xD73FA45C, 0x4C3EAB46, 0xF5C570AE, 0xE4B81AD7, 0x5D43C13F,
+        0x09CB02A2, 0xB030D94A, 0xA14DB333, 0x18B668DB, 0x83B767C1, 0x3A4CBC29, 0x2B31D650,
+        0x92CA0DB8, 0x8220516A, 0x3BDB8A82, 0x2AA6E0FB, 0x935D3B13, 0x085C3409, 0xB1A7EFE1,
+        0xA0DA8598, 0x19215E70, 0x4DA99DED, 0xF4524605, 0xE52F2C7C, 0x5CD4F794, 0xC7D5F88E,
+        0x7E2E2366, 0x6F53491F, 0xD6A892F7, 0x847C8BC6, 0x3D87502E, 0x2CFA3A57, 0x9501E1BF,
+        0x0E00EEA5, 0xB7FB354D, 0xA6865F34, 0x1F7D84DC, 0x4BF54741, 0xF20E9CA9, 0xE373F6D0,
+        0x5A882D38, 0xC1892222, 0x7872F9CA, 0x690F93B3, 0xD0F4485B, 0xC01E1489, 0x79E5CF61,
+        0x6898A518, 0xD1637EF0, 0x4A6271EA, 0xF399AA02, 0xE2E4C07B, 0x5B1F1B93, 0x0F97D80E,
+        0xB66C03E6, 0xA711699F, 0x1EEAB277, 0x85EBBD6D, 0x3C106685, 0x2D6D0CFC, 0x9496D714,
+        0x0CB9B558, 0xB5426EB0, 0xA43F04C9, 0x1DC4DF21, 0x86C5D03B, 0x3F3E0BD3, 0x2E4361AA,
+        0x97B8BA42, 0xC33079DF, 0x7ACBA237, 0x6BB6C84E, 0xD24D13A6, 0x494C1CBC, 0xF0B7C754,
+        0xE1CAAD2D, 0x583176C5, 0x48DB2A17, 0xF120F1FF, 0xE05D9B86, 0x59A6406E, 0xC2A74F74,
+        0x7B5C949C, 0x6A21FEE5, 0xD3DA250D, 0x8752E690, 0x3EA93D78, 0x2FD45701, 0x962F8CE9,
+        0x0D2E83F3, 0xB4D5581B, 0xA5A83262, 0x1C53E98A,
+    ],
+    [
+        0x00000000, 0xAE689191, 0x87A02563, 0x29C8B4F2, 0xD4314C87, 0x7A59DD16, 0x539169E4,
+        0xFDF9F875, 0x73139F4F, 0xDD7B0EDE, 0xF4B3BA2C, 0x5ADB2BBD, 0xA722D3C8, 0x094A4259,
+        0x2082F6AB, 0x8EEA673A, 0xE6273E9E, 0x484FAF0F, 0x61871BFD, 0xCFEF8A6C, 0x32167219,
+        0x9C7EE388, 0xB5B6577A, 0x1BDEC6EB, 0x9534A1D1, 0x3B5C3040, 0x129484B2, 0xBCFC1523,
+        0x4105ED56, 0xEF6D7CC7, 0xC6A5C835, 0x68CD59A4, 0x173F7B7D, 0xB957EAEC, 0x909F5E1E,
+        0x3EF7CF8F, 0xC30E37FA, 0x6D66A66B, 0x44AE1299, 0xEAC68308, 0x642CE432, 0xCA4475A3,
+        0xE38CC151, 0x4DE450C0, 0xB01DA8B5, 0x1E753924, 0x37BD8DD6, 0x99D51C47, 0xF11845E3,
+        0x5F70D472, 0x76B86080, 0xD8D0F111, 0x25290964, 0x8B4198F5, 0xA2892C07, 0x0CE1BD96,
+        0x820BDAAC, 0x2C634B3D, 0x05ABFFCF, 0xABC36E5E, 0x563A962B, 0xF85207BA, 0xD19AB348,
+        0x7FF222D9, 0x2E7EF6FA, 0x8016676B, 0xA9DED399, 0x07B64208, 0xFA4FBA7D, 0x54272BEC,
+        0x7DEF9F1E, 0xD3870E8F, 0x5D6D69B5, 0xF305F824, 0xDACD4CD6, 0x74A5DD47, 0x895C2532,
+        0x2734B4A3, 0x0EFC0051, 0xA09491C0, 0xC859C864, 0x663159F5, 0x4FF9ED07, 0xE1917C96,
+        0x1C6884E3, 0xB2001572, 0x9BC8A180, 0x35A03011, 0xBB4A572B, 0x1522C6BA, 0x3CEA7248,
+        0x9282E3D9, 0x6F7B1BAC, 0xC1138A3D, 0xE8DB3ECF, 0x46B3AF5E, 0x39418D87, 0x97291C16,
+        0xBEE1A8E4, 0x10893975, 0xED70C100, 0x43185091, 0x6AD0E463, 0xC4B875F2, 0x4A5212C8,
+        0xE43A8359, 0xCDF237AB, 0x639AA63A, 0x9E635E4F, 0x300BCFDE, 0x19C37B2C, 0xB7ABEABD,
+        0xDF66B319, 0x710E2288, 0x58C6967A, 0xF6AE07EB, 0x0B57FF9E, 0xA53F6E0F, 0x8CF7DAFD,
+        0x229F4B6C, 0xAC752C56, 0x021DBDC7, 0x2BD50935, 0x85BD98A4, 0x784460D1, 0xD62CF140,
+        0xFFE445B2, 0x518CD423, 0x5CFDEDF4, 0xF2957C65, 0xDB5DC897, 0x75355906, 0x88CCA173,
+        0x26A430E2, 0x0F6C8410, 0xA1041581, 0x2FEE72BB, 0x8186E32A, 0xA84E57D8, 0x0626C649,
+        0xFBDF3E3C, 0x55B7AFAD, 0x7C7F1B5F, 0xD2178ACE, 0xBADAD36A, 0x14B242FB, 0x3D7AF609,
+        0x93126798, 0x6EEB9FED, 0xC0830E7C, 0xE94BBA8E, 0x47232B1F, 0xC9C94C25, 0x67A1DDB4,
+        0x4E696946, 0xE001F8D7, 0x1DF800A2, 0xB3909133, 0x9A5825C1, 0x3430B450, 0x4BC29689,
+        0xE5AA0718, 0xCC62B3EA, 0x620A227B, 0x9FF3DA0E, 0x319B4B9F, 0x1853FF6D, 0xB63B6EFC,
+        0x38D109C6, 0x96B99857, 0xBF712CA5, 0x1119BD34, 0xECE04541, 0x4288D4D0, 0x6B406022,
+        0xC528F1B3, 0xADE5A817, 0x038D3986, 0x2A458D74, 0x842D1CE5, 0x79D4E490, 0xD7BC7501,
+        0xFE74C1F3, 0x501C5062, 0xDEF63758, 0x709EA6C9, 0x5956123B, 0xF73E83AA, 0x0AC77BDF,
+        0xA4AFEA4E, 0x8D675EBC, 0x230FCF2D, 0x72831B0E, 0xDCEB8A9F, 0xF5233E6D, 0x5B4BAFFC,
+        0xA6B25789, 0x08DAC618, 0x211272EA, 0x8F7AE37B, 0x01908441, 0xAFF815D0, 0x8630A122,
+        0x285830B3, 0xD5A1C8C6, 0x7BC95957, 0x5201EDA5, 0xFC697C34, 0x94A42590, 0x3ACCB401,
+        0x130400F3, 0xBD6C9162, 0x40956917, 0xEEFDF886, 0xC7354C74, 0x695DDDE5, 0xE7B7BADF,
+        0x49DF2B4E, 0x60179FBC, 0xCE7F0E2D, 0x3386F658, 0x9DEE67C9, 0xB426D33B, 0x1A4E42AA,
+        0x65BC6073, 0xCBD4F1E2, 0xE21C4510, 0x4C74D481, 0xB18D2CF4, 0x1FE5BD65, 0x362D0997,
+        0x98459806, 0x16AFFF3C, 0xB8C76EAD, 0x910FDA5F, 0x3F674BCE, 0xC29EB3BB, 0x6CF6222A,
+        0x453E96D8, 0xEB560749, 0x839B5EED, 0x2DF3CF7C, 0x043B7B8E, 0xAA53EA1F, 0x57AA126A,
+        0xF9C283FB, 0xD00A3709, 0x7E62A698, 0xF088C1A2, 0x5EE05033, 0x7728E4C1, 0xD9407550,
+        0x24B98D25, 0x8AD11CB4, 0xA319A846, 0x0D7139D7,
+    ],
+];
--- a/third_party/rust/image/.cargo-checksum.json
+++ b/third_party/rust/image/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"CHANGES.md":"57cd46de14af5277954df2d56b141fb8fd7eff75a026e11805281c167df13013","Cargo.toml":"42a0083afb5bffbcfde1f58caac0c9afe9642784afff80fdc5eefc3657c8abb1","LICENSE":"c7766d2e29f88a4be81b6ac6216c62d2d0918c7d3f2fc98be6fecac8f6595e60","README.md":"387f486de9a191fde35fd2ed93390824dd3f6b86b4971071a229ab9c4c4b82fc","benches/encode_jpeg.rs":"614f7ff101d8737fec76db00520d86d7a30cc4e1482e30c0414bfac868373427","benches/load.rs":"b50384f027734a1b6df6612f56b70ba95978138eb0d3894a8b8dbe0748d984bd","docs/2019-04-23-memory-unsafety.md":"b59a9af84bdb5efa1bc1f33c8aa22ff42590701817fb03f55ca2dd50af91bb8d","release.sh":"70f8d6272ab65f5ca80ac95e6ceeeb5041f9c183c87a1fdac2b7f2d16e0827d4","src/animation.rs":"c4bcc97aac7d929162e7d1e782ef4e20f3df72a891893ac68d8cda3b7aa431b3","src/bmp/decoder.rs":"f1abbda7c984122d990e1509cbdd6b1d488a49845662dc74815587f7befb302a","src/bmp/encoder.rs":"60b0ad7f086eead46799d78dd10fc7f1a27c6385d6a6c4ee2afd533e6ad1418f","src/bmp/mod.rs":"7105812c5bc077c8619359b6201110feeccec20b01f29a8f84aaef02be9b87d4","src/buffer.rs":"2e5a7d983794e71068f065a801b5483106fcf51fd74487ddd0c3f76a97f49ea0","src/color.rs":"6dde85a7fbc44d536bf7648fe1172277c6e9e3fbcd514df9bd53f277a10f85db","src/dxt.rs":"e17eef3e9abf53e89abb3a62264fb830639f2a63e48098d54e6e052b00e57342","src/dynimage.rs":"a9f598bf40bec92230dd5226cee87685d55dbb0053a54593c7083d7a394139d1","src/flat.rs":"01fd4f5a777d1e292b6f2a6a25cbac0d40ab8317898097caa32b28ba27d9baaf","src/gif.rs":"99df3010c731b6ad6f6a77a63c3b6071a801f4e171bbe01717fa273212f4767e","src/hdr/hdr_decoder.rs":"3ec4b069be9bfb43a646d9f6f13586fed93b47ac70c7fdb51ec36ef4199ecbd3","src/hdr/hdr_encoder.rs":"ed0d1845b1414bcdec641f2e158a364c04b717d41662ef40adb63bd32762c56f","src/hdr/mod.rs":"72f33fe6479cf4ce87765715c896bf0374bd2f4e0f98f50a63e084c0ff313ea8","src/ico/decoder.rs":"e3ea1fb1ff41b8cff58dd260902e8061cf6b44ca8721a68f76dce6a66ea4be19","src/ico/encoder.rs":"be5c290922c2fa91a174e22a221fce7730a1696e31c8a6e7dd45950afd63c80d","src/ico/mod.rs":"d94e6878c79c97eb9d9f9f9f9fb479ec8ccc1c8e788030ebe3b045ed44c0be5c","src/image.rs":"508dead9a324042c5307362ed246865bf5436391369a2e13d0192bd4949ab894","src/imageops/affine.rs":"46835b6c6eee3542f893789927053399a8d173a69c38685a48bfa632bd417140","src/imageops/colorops.rs":"5bff8d20a280793d0510d2e04f47f81b6b2be13a363cefe18264db0e1e3f6554","src/imageops/mod.rs":"148553f9ed42f256b1c59f61686fe247e560e5253d64492813ad2670f39223af","src/imageops/sample.rs":"4de9f0ab52459d446fe289c3e962d577c9b7019f85fd3ffd325c76d634256675","src/jpeg/decoder.rs":"9a3aa05db5d652901428a64e912670443a5c98843695394795e173cfb4a13549","src/jpeg/encoder.rs":"6ec6f205dbbb869ed3858a1c2e82b468d1b9341243f23c81ffbdcfcd79debd07","src/jpeg/entropy.rs":"31856ebc9b8647552e3ebe50f6c0608dadb181e75f8ce502395e6a713c12ad25","src/jpeg/mod.rs":"14a2ee879f88d27aca68a59d6b29112c66e1d61eaf9cad80ff73beabe1c092fe","src/jpeg/transform.rs":"c28670debd1cb6576c190495c64fa30610a2c29db65a2d3be3f625439df87031","src/lib.rs":"46dd648fab4da71d963552769325b03f10a2202780e2d6a2e23dbbdd960acaa7","src/math/mod.rs":"36b79d81c9192a3ec1e6107762623e1e7572d50825472ab824ab5d7b199e9380","src/math/nq.rs":"c6d25ac0f19db5d75668e0448df3580ddf0028261eb81517cc8c0acfaa0616cd","src/math/utils.rs":"2ae7ac728c6831559da97ed31d133cad81b3b5fe64998829b5579f34330a548e","src/png.rs":"2d356edc8d70670b72e712decb7b3e79c019f7ff8ef681acd579bcb311780d4c","src/pnm/autobreak.rs":"811445935b9217232af805a9f5521c2471b4397b804c0a5a2a87bb3240fcee96","src/pnm/decoder.rs":"c171eaaebfcfe760ba54dd3d61e62546cb114357672319e15344f4b8b2d6e700","src/pnm/encoder.rs":"d0980927546841d604b4f8dee06bd433b6a99cef3a6cdd721e819228805d00f5","src/pnm/header.rs":"42cf54d491095a4c5af706f6d67904387239f50430b167a12da74e2513c35065","src/pnm/mod.rs":"addb907337e7ef24c47de251b46ccafc9ea1f6d34f4141e14cf6da2481740fb6","src/tga/decoder.rs":"f021616befc9edf5d8f2d4912e296d5bc4f954b1f68c9f51d2d01a4288ddcbec","src/tga/mod.rs":"0a8001c03350156fad3ed9aefb3b3fb2a9112414cce2a0b31070cb1859ef2548","src/tiff.rs":"60297f928ad4ad94b2b57bb1c0b5800de8af9549fae6090f82a15ac995ce40b7","src/traits.rs":"58a12b0ddd1d7386447693d682a1df771e29263daeb5c27ad8829462ef3d1423","src/utils/mod.rs":"b1a3573f429d5bbe4ef13128152808a47f0e91602331f63ea65638edb29d9ed8","src/webp/decoder.rs":"963cea7fe4732ca74e8fa06b8fe32192158917664d2f2f7fd61fb160f42e7daf","src/webp/mod.rs":"f06f5e78091f7a0913fb5cd74d4880a71754ac4f33ee34f502474154be0af27a","src/webp/transform.rs":"f4eb9230045bc5bc277f0bd686014646716c2ebcb126f7d51b9fac622076517a","src/webp/vp8.rs":"d4f82d581ff1f689f46db1e662654577d99ef7e436273d6b07b9004bd50b09a7"},"package":"293e54ce142a936a39da748ba8178ae6aa1914b82d846a4278f11590c89bf116"}
\ No newline at end of file
+{"files":{"CHANGES.md":"c791f6ca0016110889db58e22a8a7a0f38fec9c1e4f5066c2367a7c240324dc6","Cargo.toml":"706b43137bd0e8115d6dce2bf140ecd658a7c1cacc7849c7d80583f890c79642","LICENSE":"c7766d2e29f88a4be81b6ac6216c62d2d0918c7d3f2fc98be6fecac8f6595e60","README.md":"ad289be7955af45c631d8f398fb0d6e22c5bf81bfc8ce2e46d6c67a5128b1e28","benches/README.md":"87b2ea4d1cea80c1e24fc18f1222a7ee1a38f5a92e98110bb84a4827fb997b62","benches/encode_jpeg.rs":"614f7ff101d8737fec76db00520d86d7a30cc4e1482e30c0414bfac868373427","benches/load.rs":"b50384f027734a1b6df6612f56b70ba95978138eb0d3894a8b8dbe0748d984bd","docs/2019-04-23-memory-unsafety.md":"b59a9af84bdb5efa1bc1f33c8aa22ff42590701817fb03f55ca2dd50af91bb8d","release.sh":"70f8d6272ab65f5ca80ac95e6ceeeb5041f9c183c87a1fdac2b7f2d16e0827d4","src/animation.rs":"9afe0c9ee5de50c35f075839ecde79ad8be95627c8efbe68b5a69028a4061908","src/bmp/decoder.rs":"6a6ae94414e9fcc874041c29922ce11d27f840a2281e905babc9d0c15859cb9f","src/bmp/encoder.rs":"f97c6e0dc9c9404bd5191821d30f08410416a5a7cf516682de83888f3052e828","src/bmp/mod.rs":"7105812c5bc077c8619359b6201110feeccec20b01f29a8f84aaef02be9b87d4","src/buffer.rs":"bfd76adf1770ec544d9aecba1990fca8cc32b31de9e4b78eb717f47b0f93a60c","src/color.rs":"d43f63f8e38a356cbc45677e4cfc7043bbd9b0904883ce4792ab0267fdc64179","src/dxt.rs":"c887e91615dadff094f1e1f1d746b85366f704581e384febddd98be983aabbee","src/dynimage.rs":"353e4238e64671a6dffafa32be38cfe90fadb05e3b8b88a4696b5cc532bad827","src/flat.rs":"3fed74ddb298336f36337f789d11934cf9aad25615133f3b5c21f59fc61b34f2","src/gif.rs":"96d258a24f87a039b1447d647945e41c1eeedbc3b6c631edc001962c65da722a","src/hdr/decoder.rs":"c9ca526389b6f045cf7a46af0aeb34f114ebf985ca271a6b30b5a2387382d121","src/hdr/encoder.rs":"0555eed8ea351ad73a9af349f990311d660f35f4f46719d01b88fad41942f2e8","src/hdr/mod.rs":"96eb63b7e43f117cb46b8ffe705b477426dde75881f2dea63cab29ffd820e01d","src/ico/decoder.rs":"07fccb6e968e6821cda9ef1e9af77c4fbf969030fdd76dab516eb67462dc321e","src/ico/encoder.rs":"941b226433b25399e51ed4b9204e896b4a1cad6552cbd44c60b2b6d97627e52c","src/ico/mod.rs":"d94e6878c79c97eb9d9f9f9f9fb479ec8ccc1c8e788030ebe3b045ed44c0be5c","src/image.rs":"70192ee57a9daff27041c25ef32f8f911d0e4d7e40751e361b3eac80ed989431","src/imageops/affine.rs":"74ecc183bd739eb3168122613d245dd939770b8328a5e9e0737f0c24640f49c6","src/imageops/colorops.rs":"cd58e6553f3da0790e1cb406e50da0400658843440bbb47d016daf1965018b7f","src/imageops/mod.rs":"3856c7917c2a3805f1aced1f499da6b121b4ccb08f2b7a66eda5592641c06c2e","src/imageops/sample.rs":"8d746c4cedec21e249dab3585bd61c0e475a88e0917fea9378c36d4afddeb9aa","src/jpeg/decoder.rs":"df206c5bae9c39fd34dc41d304e5dc29df0d581ba7ed47f8604c3b7a756573c3","src/jpeg/encoder.rs":"66c28cfc9abca2db71f76016934c533d2843b2dfc64a3cb92d23d5bec417702b","src/jpeg/entropy.rs":"31856ebc9b8647552e3ebe50f6c0608dadb181e75f8ce502395e6a713c12ad25","src/jpeg/mod.rs":"14a2ee879f88d27aca68a59d6b29112c66e1d61eaf9cad80ff73beabe1c092fe","src/jpeg/transform.rs":"c28670debd1cb6576c190495c64fa30610a2c29db65a2d3be3f625439df87031","src/lib.rs":"1d0073935d587f57c0485208bac5e37333e66838cf09699d0ea42afe3e2beac0","src/math/mod.rs":"36b79d81c9192a3ec1e6107762623e1e7572d50825472ab824ab5d7b199e9380","src/math/nq.rs":"a3fe77839826ca1d446f496f53e33d081a623a248c087f1a08b8afb1eca4bcda","src/math/utils.rs":"2ae7ac728c6831559da97ed31d133cad81b3b5fe64998829b5579f34330a548e","src/png.rs":"5ba453410ada2026bcf935426639b93356f6e4b7edd2b8acd6a42c5770955eb6","src/pnm/autobreak.rs":"811445935b9217232af805a9f5521c2471b4397b804c0a5a2a87bb3240fcee96","src/pnm/decoder.rs":"25ac23fc8e67ea42d479a103e3cda1b51a4421950be9ee2c11eeec17552081c8","src/pnm/encoder.rs":"c87dc870e15515ff9ffcd003310904f303ba416fef72352e2a314357c4cae96a","src/pnm/header.rs":"81a0cf72c3b113b490054f4f2201b448cbb1fed63fc1354e457a94294bf3761f","src/pnm/mod.rs":"74ec15ee6d92dec08e7d0870bf31ad3c30687b2c52f74abdeb4bf127f3afda23","src/tga/decoder.rs":"f05fa02aba31bc5b423644be31f1c8b874e6557b8db211bc837d07dcee455bca","src/tga/mod.rs":"0a8001c03350156fad3ed9aefb3b3fb2a9112414cce2a0b31070cb1859ef2548","src/tiff.rs":"5fb6019db0ffbbad6a2c2aa083dd31514917885a030cd9aed8e89322aac6ef5f","src/traits.rs":"58a12b0ddd1d7386447693d682a1df771e29263daeb5c27ad8829462ef3d1423","src/utils/mod.rs":"5a9d379f45d6d626d63e6839f93cd41ed33d67186b205fe3a574a956b52dc4e7","src/webp/decoder.rs":"82666a293692c3043e3bcf6ab988e470f6b2f9cedf0b6b1202bb974d4ebbeddc","src/webp/mod.rs":"f06f5e78091f7a0913fb5cd74d4880a71754ac4f33ee34f502474154be0af27a","src/webp/transform.rs":"9772d4a3172122200482e09d763e554f41d8de8ab629f94c10d64ccac038faa1","src/webp/vp8.rs":"2d1f4522ceb43d541462030b2125e637a9b63ccc0205af5cfbb2f60cc879433e"},"package":"663a975007e0b49903e2e8ac0db2c432c465855f2d65f17883ba1476e85f0b42"}
\ No newline at end of file
--- a/third_party/rust/image/CHANGES.md
+++ b/third_party/rust/image/CHANGES.md
@@ -3,16 +3,51 @@
 Rust image aims to be a pure-Rust implementation of various popular image formats. Accompanying reading/write support, rust image provides basic imaging processing function. See `README.md` for further details.
 
 ## Known issues
  - Interlaced (progressive) or animated images are not well supported.
  - Images with *n* bit/channel (*n ≠ 8*) are not well supported.
 
 ## Changes
 
+### Version 0.22
+
+- The required Rust version is now `1.34.2`.
+- Note the website and blog: [image-rs.org][1] and [blog.image-rs.org][2]
+- `PixelMut` now only on `ImageBuffer` and removed from `GenericImage`
+  interface. Prefer iterating manually in the generic case.
+- Replaced an unsafe interface in the hdr decoder with a safe variant.
+- Support loading 2-bit BMP images
+- Add method to save an `ImageBuffer`/`DynamicImage` with specified format
+- Update tiff to `0.3` with a writer
+- Update png to `0.15`, fixes reading of interlaced sub-byte pixels
+- Always use custom struct for `ImageDecoder::Reader`
+- Added `apply_without_alpha` and `map_without_alpha` to `Pixel` trait
+- Pixel information now with associated constants instead of static methods
+- Changed color structs to tuple types with single component. Improves
+  ergonomics of destructuring assignment and construction.
+- Add lifetime parameter on `ImageDecoder` trait.
+- Remove unecessary `'static` bounds on affine operations
+- Add function to retrieve image dimensions without loading full image
+- Allow different image types in overlay and replace
+- Iterators over rows of `ImageBuffer`, mutable variants
+
+[1]: https://www.image-rs.org
+[2]: https://blog.image-rs.org
+
+### Version 0.21.2
+
+- Fixed a variety of crashes and opaque errors in webp
+- Updated the png limits to be less restrictive
+- Reworked even more `unsafe` operations into safe alternatives
+- Derived Debug on FilterType and Deref on Pixel
+- Removed a restriction on DXT to always require power of two dimensions
+- Change the encoding of RGBA in bmp using bitfields
+- Corrected various urls
+
 ### Version 0.21.1
 
 - A fairly important bugfix backport
 - Fixed a potentially memory safety issue in the hdr and tiff decoders, see #885
 - See [the full advisory](docs/2019-04-23-memory-unsafety.md) for an analysis
 - Fixes `ImageBuffer` index calculation for very, very large images
 - Fix some crashes while parsing specific incomplete pnm images
 - Added comprehensive fuzzing for the pam image types
--- a/third_party/rust/image/Cargo.toml
+++ b/third_party/rust/image/Cargo.toml
@@ -1,32 +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
+# 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 = "image"
-version = "0.21.1"
+version = "0.22.1"
 authors = ["ccgn", "bvssvni <bvssvni@gmail.com>", "nwin", "TyOverby <ty@pre-alpha.com>", "HeroicKatora", "Calum", "CensoredUsername <cens.username@gmail.com>", "fintelia <fintelia@gmail.com>"]
 exclude = ["src/png/testdata/*", "examples/*", "tests/*"]
 description = "Imaging library written in Rust. Provides basic filters and decoders for the most common image formats."
-homepage = "https://github.com/PistonDevelopers/image"
+homepage = "https://github.com/image-rs/image"
 documentation = "https://docs.rs/image"
 readme = "README.md"
 categories = ["multimedia::images", "multimedia::encoding"]
 license = "MIT"
-repository = "https://github.com/PistonDevelopers/image.git"
+repository = "https://github.com/image-rs/image.git"
 
 [lib]
 name = "image"
 path = "./src/lib.rs"
 [dependencies.byteorder]
 version = "1.2.1"
 
 [dependencies.gif]
@@ -47,28 +47,31 @@ version = "0.1.32"
 [dependencies.num-rational]
 version = "0.2.1"
 default-features = false
 
 [dependencies.num-traits]
 version = "0.2.0"
 
 [dependencies.png]
-version = "0.14"
+version = "0.15"
 optional = true
 
 [dependencies.scoped_threadpool]
 version = "0.1"
 optional = true
 
 [dependencies.tiff]
-version = "0.2.0"
+version = "0.3.1"
 optional = true
+[dev-dependencies.crc32fast]
+version = "1.2.0"
+
 [dev-dependencies.glob]
-version = "0.2.10"
+version = "0.3"
 
 [dev-dependencies.num-complex]
 version = "0.2.0"
 
 [dev-dependencies.quickcheck]
 version = "0.6.2"
 
 [features]
--- a/third_party/rust/image/README.md
+++ b/third_party/rust/image/README.md
@@ -1,53 +1,36 @@
-# Image [![Build Status](https://travis-ci.org/PistonDevelopers/image.svg?branch=master)](https://travis-ci.org/PistonDevelopers/image)
+# Image [![crates.io](https://img.shields.io/crates/v/image.svg)](https://crates.io/crates/image) [![Build Status](https://travis-ci.org/image-rs/image.svg?branch=master)](https://travis-ci.org/image-rs/image) [![Gitter](https://badges.gitter.im/image-rs/image.svg)](https://gitter.im/image-rs/image?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
 
 Maintainers: @nwin, @ccgn
 
-[How to contribute](https://github.com/PistonDevelopers/piston/blob/master/CONTRIBUTING.md)
+[How to contribute](https://github.com/image-rs/organization/blob/master/CONTRIBUTING.md)
 
 ## An Image Processing Library
 
 This crate provides basic imaging processing functions and methods for converting to and from image formats.
 
 All image processing functions provided operate on types that implement the ```GenericImage``` trait and return an ```ImageBuffer```.
 
-### Usage
-
-Add the following to the Cargo.toml in your project:
-
-```toml
-[dependencies]
-image = "*"
-```
-
-and import using ```extern crate```:
-
-```rust
-extern crate image;
-
-// use image::
-```
-
 ## 1. Documentation
 
 https://docs.rs/image
 
 ## 2. Supported Image Formats
 ```image``` provides implementations of common image format encoders and decoders.
 
 ### 2.1 Supported Image Formats
 | Format | Decoding | Encoding |
 | ------ | -------- | -------- |
 | PNG    | All supported color types | Same as decoding|
 | JPEG   | Baseline and progressive | Baseline JPEG |
 | GIF    | Yes | Yes |
 | BMP    | Yes | RGB(8), RGBA(8), Gray(8), GrayA(8) |
 | ICO    | Yes | Yes |
-| TIFF   | Baseline(no fax support) + LZW + PackBits | No |
+| TIFF   | Baseline(no fax support) + LZW + PackBits | RGB(8), RGBA(8), Gray(8) |
 | Webp   | Lossy(Luma channel only) | No |
 | PNM    | PBM, PGM, PPM, standard PAM | Yes |
 
 ### 2.2 The ```ImageDecoder``` Trait
 All image format decoders implement the ```ImageDecoder``` trait which provides the following methods:
 + **dimensions**: Return a tuple containing the width and height of the image
 + **colortype**: Return the color type of the image.
 + **row_len**: Returns the length in bytes of one decoded row of the image
@@ -64,16 +47,17 @@ All image format decoders implement the 
 
 All pixels are parameterised by their component type.
 
 ## 4 Images
 ### 4.1 The ```GenericImage``` Trait
 A trait that provides functions for manipulating images, parameterised over the image's pixel type.
 
 ```rust
+# use image::{Pixel, Pixels};
 pub trait GenericImage {
     /// The pixel type.
     type Pixel: Pixel;
 
     /// The width and height of this image.
     fn dimensions(&self) -> (u32, u32);
 
     /// The bounding rectangle of this image.
@@ -96,38 +80,38 @@ pub trait GenericImage {
 ```image``` provides two main ways of representing image data:
 
 #### 4.2.1 ```ImageBuffer```
 An image parameterised by its Pixel types, represented by a width and height and a vector of pixels. It provides direct access to its pixels and implements the ```GenericImage``` trait.
 
 ```rust
 extern crate image;
 
-use image::{GenericImage, ImageBuffer};
+use image::{GenericImage, GenericImageView, ImageBuffer, RgbImage};
 
-// Construct a new ImageBuffer with the specified width and height.
-let img = ImageBuffer::new(512, 512);
+// Construct a new RGB ImageBuffer with the specified width and height.
+let img: RgbImage = ImageBuffer::new(512, 512);
 
 // Construct a new by repeated calls to the supplied closure.
-let img = ImageBuffer::from_fn(512, 512, |x, y| {
+let mut img = ImageBuffer::from_fn(512, 512, |x, y| {
     if x % 2 == 0 {
         image::Luma([0u8])
     } else {
         image::Luma([255u8])
     }
 });
 
 // Obtain the image's width and height.
 let (width, height) = img.dimensions();
 
 // Access the pixel at coordinate (100, 100).
 let pixel = img[(100, 100)];
 
 // Or use the ```get_pixel``` method from the ```GenericImage``` trait.
-let pixel = img.get_pixel(100, 100);
+let pixel = *img.get_pixel(100, 100);
 
 // Put a pixel at coordinate (100, 100).
 img.put_pixel(100, 100, pixel);
 
 // Iterate over all pixels in the image.
 for pixel in img.pixels() {
     // Do something with pixel.
 }
@@ -142,20 +126,20 @@ For convenience ```DynamicImage```'s rei
 
 #### 4.2.3 ```SubImage```
 A view into another image, delimited by the coordinates of a rectangle.
 This is used to perform image processing functions on a subregion of an image.
 
 ```rust
 extern crate image;
 
-use image::{GenericImage, ImageBuffer, imageops};
+use image::{GenericImageView, ImageBuffer, RgbImage, imageops};
 
-let ref mut img = ImageBuffer::new(512, 512);
-let subimg = imageops::crop(img, 0, 0, 100, 100);
+let mut img: RgbImage = ImageBuffer::new(512, 512);
+let subimg = imageops::crop(&mut img, 0, 0, 100, 100);
 
 assert!(subimg.dimensions() == (100, 100));
 ```
 
 ## 5 Image Processing Functions
 These are the functions defined in the ```imageops``` module. All functions operate on types that implement the ```GenericImage``` trait.
 
 + **blur**: Performs a Gaussian blur on the supplied image.
@@ -175,39 +159,39 @@ These are the functions defined in the `
 + **unsharpen**: Performs an unsharpen mask on the supplied image
 
 ## 6 Examples
 ### 6.1 Opening And Saving Images
 ```image``` provides the ```open``` function for opening images from a path.
 
 The image format is determined from the path's file extension.
 
-```rust
+```rust,no_run
 extern crate image;
 
 use image::GenericImageView;
 
 fn main() {
     // Use the open function to load an image from a Path.
     // ```open``` returns a `DynamicImage` on success.
-    let img = image::open("test.jpg").unwrap();
+    let img = image::open("tests/images/jpg/progressive/cat.jpg").unwrap();
 
     // The dimensions method returns the images width and height.
     println!("dimensions {:?}", img.dimensions());
 
     // The color method returns the image's `ColorType`.
     println!("{:?}", img.color());
 
     // Write the contents of this image to the Writer in PNG format.
     img.save("test.png").unwrap();
 }
 ```
 
 ### 6.2 Generating Fractals
-```rust
+```rust,no_run
 //! An example of generating julia fractals.
 extern crate image;
 extern crate num_complex;
 
 fn main() {
     let imgx = 800;
     let imgy = 800;
 
@@ -235,37 +219,37 @@ fn main() {
 
             let mut i = 0;
             while i < 255 && z.norm() <= 2.0 {
                 z = z * z + c;
                 i += 1;
             }
 
             let pixel = imgbuf.get_pixel_mut(x, y);
-            let data = (*pixel as image::Rgb<u8>).data;
+            let image::Rgb(data) = *pixel;
             *pixel = image::Rgb([data[0], i as u8, data[2]]);
         }
     }
 
     // Save the image as “fractal.png”, the format is deduced from the path
     imgbuf.save("fractal.png").unwrap();
 }
 ```
 
 Example output:
 
 <img src="examples/fractal.png" alt="A Julia Fractal, c: -0.4 + 0.6i" width="500" />
 
 ### 6.3 Writing raw buffers
 If the high level interface is not needed because the image was obtained by other means, `image` provides the function `save_buffer` to save a buffer to a file.
 
-```rust
+```rust,no_run
 extern crate image;
 
 fn main() {
 
-    let buffer: &[u8] = ...; // Generate the image data
+    let buffer: &[u8] = unimplemented!(); // Generate the image data
 
     // Save the buffer as "image.png"
     image::save_buffer("image.png", buffer, 800, 600, image::RGB(8)).unwrap()
 }
 
 ```
new file mode 100644
--- /dev/null
+++ b/third_party/rust/image/benches/README.md
@@ -0,0 +1,6 @@
+# Getting started with benchmarking
+
+To run the benchmarks you need a nightly rust toolchain.
+Then you launch it with
+
+    cargo +nightly bench --features=benchmarks
--- a/third_party/rust/image/src/animation.rs
+++ b/third_party/rust/image/src/animation.rs
@@ -2,22 +2,22 @@ use std::iter::Iterator;
 
 use num_rational::Ratio;
 
 use buffer::RgbaImage;
 use image::ImageResult;
 
 /// An implementation dependent iterator, reading the frames as requested
 pub struct Frames<'a> {
-    iterator: Box<Iterator<Item = ImageResult<Frame>> + 'a>
+    iterator: Box<dyn Iterator<Item = ImageResult<Frame>> + 'a>
 }
 
 impl<'a> Frames<'a> {
     /// Creates a new `Frames` from an implementation specific iterator.
-    pub fn new(iterator: Box<Iterator<Item = ImageResult<Frame>> + 'a>) -> Self {
+    pub fn new(iterator: Box<dyn Iterator<Item = ImageResult<Frame>> + 'a>) -> Self {
         Frames { iterator }
     }
 
     /// Steps through the iterator from the current frame until the end and pushes each frame into
     /// a `Vec`.
     /// If en error is encountered that error is returned instead.
     /// 
     /// Note: This is equivalent to `Frames::collect::<ImageResult<Vec<Frame>>>()`
--- a/third_party/rust/image/src/bmp/decoder.rs
+++ b/third_party/rust/image/src/bmp/decoder.rs
@@ -1,12 +1,12 @@
-use std::cmp;
-use std::io;
-use std::io::{Cursor, Read, Seek, SeekFrom};
+use std::{cmp, mem};
+use std::io::{self, Cursor, Read, Seek, SeekFrom};
 use std::iter::{repeat, Iterator, Rev};
+use std::marker::PhantomData;
 use std::slice::ChunksMut;
 
 use byteorder::{LittleEndian, ReadBytesExt};
 
 use color::ColorType;
 use image::{self, ImageDecoder, ImageDecoderExt, ImageError, ImageResult, Progress};
 
 const BITMAPCOREHEADER_SIZE: u32 = 12;
@@ -212,38 +212,38 @@ where
 {
     // An overflow should already have been checked for when this is called,
     // though we check anyhow, as it somehow seems to increase performance slightly.
     let row_width = channels.checked_mul(width as usize).unwrap();
     let full_image_size = row_width.checked_mul(height as usize).unwrap();
 
     if !top_down {
         for row in buffer.chunks_mut(row_width).rev() {
-            try!(func(row));
+            func(row)?;
         }
 
         // If we need more space, extend the buffer.
         if buffer.len() < full_image_size {
             let new_space = extend_buffer(buffer, full_image_size, false);
             for row in new_space.chunks_mut(row_width).rev() {
-                try!(func(row));
+                func(row)?;
             }
         }
     } else {
         for row in buffer.chunks_mut(row_width) {
-            try!(func(row));
+            func(row)?;
         }
         if buffer.len() < full_image_size {
             // If the image is stored in top-down order, we can simply use the extend function
             // from vec to extend the buffer..
             let extend = full_image_size - buffer.len();
             buffer.extend(repeat(0xFF).take(extend));
             let len = buffer.len();
             for row in buffer[len - row_width..].chunks_mut(row_width) {
-                try!(func(row));
+                func(row)?;
             }
         };
     }
     Ok(())
 }
 
 fn set_8bit_pixel_run<'a, T: Iterator<Item = &'a u8>>(
     pixel_iter: &mut ChunksMut<u8>,
@@ -288,16 +288,47 @@ fn set_4bit_pixel_run<'a, T: Iterator<It
             };
         }
         set_pixel!(idx >> 4);
         set_pixel!(idx & 0xf);
     }
     true
 }
 
+fn set_2bit_pixel_run<'a, T: Iterator<Item = &'a u8>>(
+    pixel_iter: &mut ChunksMut<u8>,
+    palette: &[(u8, u8, u8)],
+    indices: T,
+    mut n_pixels: usize,
+) -> bool {
+    for idx in indices {
+        macro_rules! set_pixel {
+            ($i:expr) => {
+                if n_pixels == 0 {
+                    break;
+                }
+                if let Some(pixel) = pixel_iter.next() {
+                    let (r, g, b) = palette[$i as usize];
+                    pixel[0] = r;
+                    pixel[1] = g;
+                    pixel[2] = b;
+                } else {
+                    return false;
+                }
+                n_pixels -= 1;
+            };
+        }
+        set_pixel!((idx >> 6) & 0x3u8);
+        set_pixel!((idx >> 4) & 0x3u8);
+        set_pixel!((idx >> 2) & 0x3u8);
+        set_pixel!( idx       & 0x3u8);
+    }
+    true
+}
+
 fn set_1bit_pixel_run<'a, T: Iterator<Item = &'a u8>>(
     pixel_iter: &mut ChunksMut<u8>,
     palette: &[(u8, u8, u8)],
     indices: T,
 ) {
     for idx in indices {
         let mut bit = 0x80;
         loop {
@@ -374,20 +405,20 @@ impl Bitfields {
     fn from_mask(
         r_mask: u32,
         g_mask: u32,
         b_mask: u32,
         a_mask: u32,
         max_len: u32,
     ) -> ImageResult<Bitfields> {
         let bitfields = Bitfields {
-            r: try!(Bitfield::from_mask(r_mask, max_len)),
-            g: try!(Bitfield::from_mask(g_mask, max_len)),
-            b: try!(Bitfield::from_mask(b_mask, max_len)),
-            a: try!(Bitfield::from_mask(a_mask, max_len)),
+            r: Bitfield::from_mask(r_mask, max_len)?,
+            g: Bitfield::from_mask(g_mask, max_len)?,
+            b: Bitfield::from_mask(b_mask, max_len)?,
+            a: Bitfield::from_mask(a_mask, max_len)?,
         };
         if bitfields.r.len == 0 || bitfields.g.len == 0 || bitfields.b.len == 0 {
             return Err(ImageError::FormatError("Missing bitfield mask".to_string()));
         }
         Ok(bitfields)
     }
 }
 
@@ -535,28 +566,28 @@ impl<R: Read + Seek> BMPDecoder<R> {
         &mut self.r
     }
 
     fn read_file_header(&mut self) -> ImageResult<()> {
         if self.no_file_header {
             return Ok(());
         }
         let mut signature = [0; 2];
-        try!(self.r.read_exact(&mut signature));
+        self.r.read_exact(&mut signature)?;
 
         if signature != b"BM"[..] {
             return Err(ImageError::FormatError(
                 "BMP signature not found".to_string(),
             ));
         }
 
         // The next 8 bytes represent file size, followed the 4 reserved bytes
         // We're not interesting these values
-        try!(self.r.read_u32::<LittleEndian>());
-        try!(self.r.read_u32::<LittleEndian>());
+        self.r.read_u32::<LittleEndian>()?;
+        self.r.read_u32::<LittleEndian>()?;
 
         self.data_offset = u64::from(self.r.read_u32::<LittleEndian>()?);
 
         Ok(())
     }
 
     /// Read BITMAPCOREHEADER https://msdn.microsoft.com/en-us/library/vs/alm/dd183372(v=vs.85).aspx
     ///
@@ -571,37 +602,37 @@ impl<R: Read + Seek> BMPDecoder<R> {
             self.width,
             self.height,
             self.num_channels()
         ));
 
         // Number of planes (format specifies that this should be 1).
         if try!(self.r.read_u16::<LittleEndian>()) != 1 {
             return Err(ImageError::FormatError(
-                "Invalid number of planes.".to_string(),
+                "More than one plane".to_string(),
             ));
         }
 
-        self.bit_count = try!(self.r.read_u16::<LittleEndian>());
+        self.bit_count = self.r.read_u16::<LittleEndian>()?;
         self.image_type = match self.bit_count {
             1 | 4 | 8 => ImageType::Palette,
             24 => ImageType::RGB24,
             _ => return Err(ImageError::FormatError("Invalid bit count".to_string())),
         };
 
         Ok(())
     }
 
     /// Read BITMAPINFOHEADER https://msdn.microsoft.com/en-us/library/vs/alm/dd183376(v=vs.85).aspx
     /// or BITMAPV{2|3|4|5}HEADER.
     ///
     /// returns Err if any of the values are invalid.
     fn read_bitmap_info_header(&mut self) -> ImageResult<()> {
-        self.width = try!(self.r.read_i32::<LittleEndian>());
-        self.height = try!(self.r.read_i32::<LittleEndian>());
+        self.width = self.r.read_i32::<LittleEndian>()?;
+        self.height = self.r.read_i32::<LittleEndian>()?;
 
         // Width can not be negative
         if self.width < 0 {
             return Err(ImageError::FormatError("Negative width".to_string()));
         } else if self.width > MAX_WIDTH_HEIGHT || self.height > MAX_WIDTH_HEIGHT {
             // Limit very large image sizes to avoid OOM issues. Images with these sizes are
             // unlikely to be valid anyhow.
             return Err(ImageError::FormatError("Image too large".to_string()));
@@ -621,40 +652,40 @@ impl<R: Read + Seek> BMPDecoder<R> {
             self.width,
             self.height,
             self.num_channels()
         ));
 
         // Number of planes (format specifies that this should be 1).
         if try!(self.r.read_u16::<LittleEndian>()) != 1 {
             return Err(ImageError::FormatError(
-                "Invalid number of planes.".to_string(),
+                "More than one plane".to_string(),
             ));
         }
 
-        self.bit_count = try!(self.r.read_u16::<LittleEndian>());
-        let image_type_u32 = try!(self.r.read_u32::<LittleEndian>());
+        self.bit_count = self.r.read_u16::<LittleEndian>()?;
+        let image_type_u32 = self.r.read_u32::<LittleEndian>()?;
 
         // Top-down dibs can not be compressed.
         if self.top_down && image_type_u32 != 0 && image_type_u32 != 3 {
             return Err(ImageError::FormatError(
                 "Invalid image type for top-down image.".to_string(),
             ));
         }
         self.image_type = match image_type_u32 {
             0 => match self.bit_count {
-                1 | 4 | 8 => ImageType::Palette,
+                1 | 2 | 4 | 8 => ImageType::Palette,
                 16 => ImageType::RGB16,
                 24 => ImageType::RGB24,
                 32 => if self.add_alpha_channel {
                     ImageType::RGBA32
                 } else {
                     ImageType::RGB32
                 },
-                _ => return Err(ImageError::FormatError("Invalid RGB bit count".to_string())),
+                _ => return Err(ImageError::FormatError(format!("Invalid RGB bit count {}", self.bit_count).to_string())),
             },
             1 => match self.bit_count {
                 8 => ImageType::RLE8,
                 _ => {
                     return Err(ImageError::FormatError(
                         "Invalid RLE8 bit count".to_string(),
                     ))
                 }
@@ -683,33 +714,33 @@ impl<R: Read + Seek> BMPDecoder<R> {
                 ))
             }
         };
 
         // The next 12 bytes represent data array size in bytes,
         // followed the horizontal and vertical printing resolutions
         // We will calculate the pixel array size using width & height of image
         // We're not interesting the horz or vert printing resolutions
-        try!(self.r.read_u32::<LittleEndian>());
-        try!(self.r.read_u32::<LittleEndian>());
-        try!(self.r.read_u32::<LittleEndian>());
+        self.r.read_u32::<LittleEndian>()?;
+        self.r.read_u32::<LittleEndian>()?;
+        self.r.read_u32::<LittleEndian>()?;
 
-        self.colors_used = try!(self.r.read_u32::<LittleEndian>());
+        self.colors_used = self.r.read_u32::<LittleEndian>()?;
 
         // The next 4 bytes represent number of "important" colors
         // We're not interested in this value, so we'll skip it
-        try!(self.r.read_u32::<LittleEndian>());
+        self.r.read_u32::<LittleEndian>()?;
 
         Ok(())
     }
 
     fn read_bitmasks(&mut self) -> ImageResult<()> {
-        let r_mask = try!(self.r.read_u32::<LittleEndian>());
-        let g_mask = try!(self.r.read_u32::<LittleEndian>());
-        let b_mask = try!(self.r.read_u32::<LittleEndian>());
+        let r_mask = self.r.read_u32::<LittleEndian>()?;
+        let g_mask = self.r.read_u32::<LittleEndian>()?;
+        let b_mask = self.r.read_u32::<LittleEndian>()?;
 
         let a_mask = match self.bmp_header_type {
             BMPHeaderType::V3 | BMPHeaderType::V4 | BMPHeaderType::V5 => {
                 try!(self.r.read_u32::<LittleEndian>())
             }
             _ => 0,
         };
 
@@ -727,19 +758,19 @@ impl<R: Read + Seek> BMPDecoder<R> {
             self.add_alpha_channel = true;
         }
 
         Ok(())
     }
 
     fn read_metadata(&mut self) -> ImageResult<()> {
         if !self.has_loaded_metadata {
-            try!(self.read_file_header());
-            let bmp_header_offset = try!(self.r.seek(SeekFrom::Current(0)));
-            let bmp_header_size = try!(self.r.read_u32::<LittleEndian>());
+            self.read_file_header()?;
+            let bmp_header_offset = self.r.seek(SeekFrom::Current(0))?;
+            let bmp_header_size = self.r.read_u32::<LittleEndian>()?;
             let bmp_header_end = bmp_header_offset + u64::from(bmp_header_size);
 
             self.bmp_header_type = match bmp_header_size {
                 BITMAPCOREHEADER_SIZE => BMPHeaderType::Core,
                 BITMAPINFOHEADER_SIZE => BMPHeaderType::Info,
                 BITMAPV2HEADER_SIZE => BMPHeaderType::V2,
                 BITMAPV3HEADER_SIZE => BMPHeaderType::V3,
                 BITMAPV4HEADER_SIZE => BMPHeaderType::V4,
@@ -748,55 +779,55 @@ impl<R: Read + Seek> BMPDecoder<R> {
                     return Err(ImageError::UnsupportedError(
                         "Unsupported Bitmap Header".to_string(),
                     ))
                 }
             };
 
             match self.bmp_header_type {
                 BMPHeaderType::Core => {
-                    try!(self.read_bitmap_core_header());
+                    self.read_bitmap_core_header()?;
                 }
                 BMPHeaderType::Info
                 | BMPHeaderType::V2
                 | BMPHeaderType::V3
                 | BMPHeaderType::V4
                 | BMPHeaderType::V5 => {
-                    try!(self.read_bitmap_info_header());
+                    self.read_bitmap_info_header()?;
                 }
             };
 
             match self.image_type {
-                ImageType::Bitfields16 | ImageType::Bitfields32 => try!(self.read_bitmasks()),
+                ImageType::Bitfields16 | ImageType::Bitfields32 => self.read_bitmasks()?,
                 _ => {}
             };
 
-            try!(self.r.seek(SeekFrom::Start(bmp_header_end)));
+            self.r.seek(SeekFrom::Start(bmp_header_end))?;
 
             match self.image_type {
-                ImageType::Palette | ImageType::RLE4 | ImageType::RLE8 => try!(self.read_palette()),
+                ImageType::Palette | ImageType::RLE4 | ImageType::RLE8 => self.read_palette()?,
                 _ => {}
             };
 
             if self.no_file_header {
                 // Use the offset of the end of metadata instead of reading a BMP file header.
-                self.data_offset = try!(self.r.seek(SeekFrom::Current(0)));
+                self.data_offset = self.r.seek(SeekFrom::Current(0))?;
             }
 
             self.has_loaded_metadata = true;
         }
         Ok(())
     }
 
     #[cfg(feature = "ico")]
     #[doc(hidden)]
     pub fn read_metadata_in_ico_format(&mut self) -> ImageResult<()> {
         self.no_file_header = true;
         self.add_alpha_channel = true;
-        try!(self.read_metadata());
+        self.read_metadata()?;
 
         // The height field in an ICO file is doubled to account for the AND mask
         // (whether or not an AND mask is actually present).
         self.height /= 2;
         Ok(())
     }
 
     fn get_palette_size(&mut self) -> ImageResult<usize> {
@@ -820,35 +851,35 @@ impl<R: Read + Seek> BMPDecoder<R> {
             _ => 4,
         }
     }
 
     fn read_palette(&mut self) -> ImageResult<()> {
         const MAX_PALETTE_SIZE: usize = 256; // Palette indices are u8.
 
         let bytes_per_color = self.bytes_per_color();
-        let palette_size = try!(self.get_palette_size());
+        let palette_size = self.get_palette_size()?;
         let max_length = MAX_PALETTE_SIZE * bytes_per_color;
 
         let length = palette_size * bytes_per_color;
         let mut buf = Vec::with_capacity(max_length);
 
         // Resize and read the palette entries to the buffer.
         // We limit the buffer to at most 256 colours to avoid any oom issues as
         // 8-bit images can't reference more than 256 indexes anyhow.
         buf.resize(cmp::min(length, max_length), 0);
-        try!(self.r.by_ref().read_exact(&mut buf));
+        self.r.by_ref().read_exact(&mut buf)?;
 
         // Allocate 256 entries even if palette_size is smaller, to prevent corrupt files from
         // causing an out-of-bounds array access.
         if length < max_length {
             buf.resize(max_length, 0);
         } else if length > max_length {
             // Ignore any excess palette colors.
-            try!(self.r.seek(SeekFrom::Current((length - max_length) as i64)));
+            self.r.seek(SeekFrom::Current((length - max_length) as i64))?;
         };
 
         let p: Vec<(u8, u8, u8)> = (0..MAX_PALETTE_SIZE)
             .map(|i| {
                 let b = buf[bytes_per_color * i];
                 let g = buf[bytes_per_color * i + 1];
                 let r = buf[bytes_per_color * i + 2];
                 (r, g, b)
@@ -900,31 +931,34 @@ impl<R: Read + Seek> BMPDecoder<R> {
         let num_channels = self.num_channels();
         let row_byte_length = ((i32::from(self.bit_count) * self.width + 31) / 32 * 4) as usize;
         let mut indices = vec![0; row_byte_length];
         let palette = self.palette.as_ref().unwrap();
         let bit_count = self.bit_count;
         let reader = &mut self.r;
         let width = self.width as usize;
 
-        try!(reader.seek(SeekFrom::Start(self.data_offset)));
+        reader.seek(SeekFrom::Start(self.data_offset))?;
 
         try!(with_rows(
             &mut pixel_data,
             self.width,
             self.height,
             num_channels,
             self.top_down,
             |row| {
-                try!(reader.read_exact(&mut indices));
+                reader.read_exact(&mut indices)?;
                 let mut pixel_iter = row.chunks_mut(num_channels);
                 match bit_count {
                     1 => {
                         set_1bit_pixel_run(&mut pixel_iter, palette, indices.iter());
                     }
+                    2 => {
+                        set_2bit_pixel_run(&mut pixel_iter, palette, indices.iter(), width);
+                    }
                     4 => {
                         set_4bit_pixel_run(&mut pixel_iter, palette, indices.iter(), width);
                     }
                     8 => {
                         set_8bit_pixel_run(&mut pixel_iter, palette, indices.iter(), width);
                     }
                     _ => panic!(),
                 };
@@ -941,17 +975,17 @@ impl<R: Read + Seek> BMPDecoder<R> {
         let row_padding_len = self.width as usize % 2 * 2;
         let row_padding = &mut [0; 2][..row_padding_len];
         let bitfields = match bitfields {
             Some(b) => b,
             None => self.bitfields.as_ref().unwrap(),
         };
         let reader = &mut self.r;
 
-        try!(reader.seek(SeekFrom::Start(self.data_offset)));
+        reader.seek(SeekFrom::Start(self.data_offset))?;
 
         try!(with_rows(
             &mut pixel_data,
             self.width,
             self.height,
             num_channels,
             self.top_down,
             |row| {
@@ -975,27 +1009,27 @@ impl<R: Read + Seek> BMPDecoder<R> {
     /// Read image data from a reader in 32-bit formats that use bitfields.
     fn read_32_bit_pixel_data(&mut self) -> ImageResult<Vec<u8>> {
         let mut pixel_data = self.create_pixel_data();
         let num_channels = self.num_channels();
 
         let bitfields = self.bitfields.as_ref().unwrap();
 
         let reader = &mut self.r;
-        try!(reader.seek(SeekFrom::Start(self.data_offset)));
+        reader.seek(SeekFrom::Start(self.data_offset))?;
 
         try!(with_rows(
             &mut pixel_data,
             self.width,
             self.height,
             num_channels,
             self.top_down,
             |row| {
                 for pixel in row.chunks_mut(num_channels) {
-                    let data = try!(reader.read_u32::<LittleEndian>());
+                    let data = reader.read_u32::<LittleEndian>()?;
 
                     pixel[0] = bitfields.r.read(data);
                     pixel[1] = bitfields.g.read(data);
                     pixel[2] = bitfields.b.read(data);
                     if num_channels == 4 {
                         pixel[3] = bitfields.a.read(data);
                     }
                 }
@@ -1011,74 +1045,74 @@ impl<R: Read + Seek> BMPDecoder<R> {
         let mut pixel_data = self.create_pixel_data();
         let num_channels = self.num_channels();
         let row_padding_len = match *format {
             FormatFullBytes::RGB24 => (4 - (self.width as usize * 3) % 4) % 4,
             _ => 0,
         };
         let row_padding = &mut [0; 4][..row_padding_len];
 
-        try!(self.r.seek(SeekFrom::Start(self.data_offset)));
+        self.r.seek(SeekFrom::Start(self.data_offset))?;
 
         let reader = &mut self.r;
 
         try!(with_rows(
             &mut pixel_data,
             self.width,
             self.height,
             num_channels,
             self.top_down,
             |row| {
                 for pixel in row.chunks_mut(num_channels) {
                     if *format == FormatFullBytes::Format888 {
-                        try!(reader.read_u8());
+                        reader.read_u8()?;
                     }
 
                     // Read the colour values (b, g, r).
                     // Reading 3 bytes and reversing them is significantly faster than reading one
                     // at a time.
-                    try!(reader.read_exact(&mut pixel[0..3]));
+                    reader.read_exact(&mut pixel[0..3])?;
                     pixel[0..3].reverse();
 
                     if *format == FormatFullBytes::RGB32 {
-                        try!(reader.read_u8());
+                        reader.read_u8()?;
                     }
 
                     // Read the alpha channel if present
                     if *format == FormatFullBytes::RGBA32 {
-                        try!(reader.read_exact(&mut pixel[3..4]));
+                        reader.read_exact(&mut pixel[3..4])?;
                     }
                 }
                 reader.read_exact(row_padding)
             }
         ));
 
         Ok(pixel_data)
     }
 
     fn read_rle_data(&mut self, image_type: ImageType) -> ImageResult<Vec<u8>> {
         // Seek to the start of the actual image data.
-        try!(self.r.seek(SeekFrom::Start(self.data_offset)));
+        self.r.seek(SeekFrom::Start(self.data_offset))?;
 
         let full_image_size = try!(
             num_bytes(self.width, self.height, self.num_channels()).ok_or_else(|| {
                 ImageError::FormatError("Image buffer would be too large!".to_owned())
             })
         );
         let mut pixel_data = self.create_pixel_data();
         let (skip_pixels, skip_rows, eof_hit) =
-            try!(self.read_rle_data_step(&mut pixel_data, image_type, 0, 0));
+            self.read_rle_data_step(&mut pixel_data, image_type, 0, 0)?;
         // Extend the buffer if there is still data left.
         // If eof_hit is true, it means that we hit an end-of-file marker in the last step and
         // we won't extend the buffer further to avoid small files with a large specified size causing memory issues.
         // This is only a rudimentary check, a file could still create a large buffer, but the
         // file would now have to at least have some data in it.
         if pixel_data.len() < full_image_size && !eof_hit {
             let new = extend_buffer(&mut pixel_data, full_image_size, true);
-            try!(self.read_rle_data_step(new, image_type, skip_pixels, skip_rows));
+            self.read_rle_data_step(new, image_type, skip_pixels, skip_rows)?;
         }
         Ok(pixel_data)
     }
 
     fn read_rle_data_step(
         &mut self,
         mut pixel_data: &mut [u8],
         image_type: ImageType,
@@ -1250,41 +1284,57 @@ impl<R: Read + Seek> BMPDecoder<R> {
                 None => Err(ImageError::FormatError(
                     "Missing 32-bit bitfield masks".to_string(),
                 )),
             },
         }
     }
 }
 
-impl<R: Read + Seek> ImageDecoder for BMPDecoder<R> {
-    type Reader = Cursor<Vec<u8>>;
+/// Wrapper struct around a `Cursor<Vec<u8>>`
+pub struct BmpReader<R>(Cursor<Vec<u8>>, PhantomData<R>);
+impl<R> Read for BmpReader<R> {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        self.0.read(buf)
+    }
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
+        if self.0.position() == 0 && buf.is_empty() {
+            mem::swap(buf, self.0.get_mut());
+            Ok(buf.len())
+        } else {
+            self.0.read_to_end(buf)
+        }
+    }
+}
+
+impl<'a, R: 'a + Read + Seek> ImageDecoder<'a> for BMPDecoder<R> {
+    type Reader = BmpReader<R>;
 
     fn dimensions(&self) -> (u64, u64) {
         (self.width as u64, self.height as u64)
     }
 
     fn colortype(&self) -> ColorType {
         if self.add_alpha_channel {
             ColorType::RGBA(8)
         } else {
             ColorType::RGB(8)
         }
     }
 
     fn into_reader(self) -> ImageResult<Self::Reader> {
-        Ok(Cursor::new(self.read_image()?))
+        Ok(BmpReader(Cursor::new(self.read_image()?), PhantomData))
     }
 
     fn read_image(mut self) -> ImageResult<Vec<u8>> {
         self.read_image_data()
     }
 }
 
-impl<R: Read + Seek> ImageDecoderExt for BMPDecoder<R> {
+impl<'a, R: 'a + Read + Seek> ImageDecoderExt<'a> for BMPDecoder<R> {
     fn read_rect_with_progress<F: Fn(Progress)>(
         &mut self,
         x: u64,
         y: u64,
         width: u64,
         height: u64,
         buf: &mut [u8],
         progress_callback: F,
--- a/third_party/rust/image/src/bmp/encoder.rs
+++ b/third_party/rust/image/src/bmp/encoder.rs
@@ -1,13 +1,17 @@
 use byteorder::{LittleEndian, WriteBytesExt};
 use std::io::{self, Write};
 
 use color;
 
+const BITMAPFILEHEADER_SIZE: u32 = 14;
+const BITMAPINFOHEADER_SIZE: u32 = 40;
+const BITMAPV4HEADER_SIZE: u32 = 108;
+
 /// The representation of a BMP encoder.
 pub struct BMPEncoder<'a, W: 'a> {
     writer: &'a mut W,
 }
 
 impl<'a, W: Write + 'a> BMPEncoder<'a, W> {
     /// Create a new encoder that writes its output to ```w```.
     pub fn new(w: &'a mut W) -> Self {
@@ -19,60 +23,82 @@ impl<'a, W: Write + 'a> BMPEncoder<'a, W
     /// and ```ColorType``` ```c```.
     pub fn encode(
         &mut self,
         image: &[u8],
         width: u32,
         height: u32,
         c: color::ColorType,
     ) -> io::Result<()> {
-        let bmp_header_size = 14;
-        let dib_header_size = 40; // using BITMAPINFOHEADER
+        let bmp_header_size = BITMAPFILEHEADER_SIZE;
 
-        let (raw_pixel_size, written_pixel_size, palette_color_count) = try!(get_pixel_info(c));
+        let (dib_header_size, written_pixel_size, palette_color_count) = get_pixel_info(c)?;
         let row_pad_size = (4 - (width * written_pixel_size) % 4) % 4; // each row must be padded to a multiple of 4 bytes
 
         let image_size = width * height * written_pixel_size + (height * row_pad_size);
         let palette_size = palette_color_count * 4; // all palette colors are BGRA
         let file_size = bmp_header_size + dib_header_size + palette_size + image_size;
 
         // write BMP header
-        try!(self.writer.write_u8(b'B'));
-        try!(self.writer.write_u8(b'M'));
-        try!(self.writer.write_u32::<LittleEndian>(file_size)); // file size
-        try!(self.writer.write_u16::<LittleEndian>(0)); // reserved 1
-        try!(self.writer.write_u16::<LittleEndian>(0)); // reserved 2
+        self.writer.write_u8(b'B')?;
+        self.writer.write_u8(b'M')?;
+        self.writer.write_u32::<LittleEndian>(file_size)?; // file size
+        self.writer.write_u16::<LittleEndian>(0)?; // reserved 1
+        self.writer.write_u16::<LittleEndian>(0)?; // reserved 2
         try!(
             self.writer
                 .write_u32::<LittleEndian>(bmp_header_size + dib_header_size + palette_size)
         ); // image data offset
 
         // write DIB header
-        try!(self.writer.write_u32::<LittleEndian>(dib_header_size));
-        try!(self.writer.write_i32::<LittleEndian>(width as i32));
-        try!(self.writer.write_i32::<LittleEndian>(height as i32));
-        try!(self.writer.write_u16::<LittleEndian>(1)); // color planes
+        self.writer.write_u32::<LittleEndian>(dib_header_size)?;
+        self.writer.write_i32::<LittleEndian>(width as i32)?;
+        self.writer.write_i32::<LittleEndian>(height as i32)?;
+        self.writer.write_u16::<LittleEndian>(1)?; // color planes
         try!(
             self.writer
                 .write_u16::<LittleEndian>((written_pixel_size * 8) as u16)
         ); // bits per pixel
-        try!(self.writer.write_u32::<LittleEndian>(0)); // compression method - no compression
-        try!(self.writer.write_u32::<LittleEndian>(image_size));
-        try!(self.writer.write_i32::<LittleEndian>(0)); // horizontal ppm
-        try!(self.writer.write_i32::<LittleEndian>(0)); // vertical ppm
-        try!(self.writer.write_u32::<LittleEndian>(palette_color_count));
-        try!(self.writer.write_u32::<LittleEndian>(0)); // all colors are important
+        if dib_header_size >= BITMAPV4HEADER_SIZE {
+            // Assume BGRA32
+            self.writer.write_u32::<LittleEndian>(3)?; // compression method - bitfields
+        } else {
+            self.writer.write_u32::<LittleEndian>(0)?; // compression method - no compression
+        }
+        self.writer.write_u32::<LittleEndian>(image_size)?;
+        self.writer.write_i32::<LittleEndian>(0)?; // horizontal ppm
+        self.writer.write_i32::<LittleEndian>(0)?; // vertical ppm
+        self.writer.write_u32::<LittleEndian>(palette_color_count)?;
+        self.writer.write_u32::<LittleEndian>(0)?; // all colors are important
+        if dib_header_size >= BITMAPV4HEADER_SIZE {
+            // Assume BGRA32
+            self.writer.write_u32::<LittleEndian>(0xff << 16)?; // red mask
+            self.writer.write_u32::<LittleEndian>(0xff << 8)?; // green mask
+            self.writer.write_u32::<LittleEndian>(0xff << 0)?; // blue mask
+            self.writer.write_u32::<LittleEndian>(0xff << 24)?; // alpha mask
+            self.writer.write_u32::<LittleEndian>(0x73524742)?; // colorspace - sRGB
+            // endpoints (3x3) and gamma (3)
+            for _ in 0..12 {
+                self.writer.write_u32::<LittleEndian>(0)?;
+            }
+        }
 
         // write image data
         match c {
-            color::ColorType::RGB(8) | color::ColorType::RGBA(8) => {
-                try!(self.encode_rgb(image, width, height, row_pad_size, raw_pixel_size))
+            color::ColorType::RGB(8) => {
+                self.encode_rgb(image, width, height, row_pad_size, 3)?
+            }
+            color::ColorType::RGBA(8) => {
+                self.encode_rgba(image, width, height, row_pad_size, 4)?
             }
-            color::ColorType::Gray(8) | color::ColorType::GrayA(8) => {
-                try!(self.encode_gray(image, width, height, row_pad_size, raw_pixel_size))
+            color::ColorType::Gray(8) => {
+                self.encode_gray(image, width, height, row_pad_size, 1)?
+            }
+            color::ColorType::GrayA(8) => {
+                self.encode_gray(image, width, height, row_pad_size, 2)?
             }
             _ => {
                 return Err(io::Error::new(
                     io::ErrorKind::InvalidInput,
                     &get_unsupported_error_message(c)[..],
                 ))
             }
         }
@@ -94,23 +120,55 @@ impl<'a, W: Write + 'a> BMPEncoder<'a, W
             // from the bottom up
             let row_start = (height - row - 1) * y_stride;
             for col in 0..width {
                 let pixel_start = (row_start + (col * x_stride)) as usize;
                 let r = image[pixel_start];
                 let g = image[pixel_start + 1];
                 let b = image[pixel_start + 2];
                 // written as BGR
-                try!(self.writer.write_u8(b));
-                try!(self.writer.write_u8(g));
-                try!(self.writer.write_u8(r));
+                self.writer.write_u8(b)?;
+                self.writer.write_u8(g)?;
+                self.writer.write_u8(r)?;
                 // alpha is never written as it's not widely supported
             }
 
-            try!(self.write_row_pad(row_pad_size));
+            self.write_row_pad(row_pad_size)?;
+        }
+
+        Ok(())
+    }
+
+    fn encode_rgba(
+        &mut self,
+        image: &[u8],
+        width: u32,
+        height: u32,
+        row_pad_size: u32,
+        bytes_per_pixel: u32,
+    ) -> io::Result<()> {
+        let x_stride = bytes_per_pixel;
+        let y_stride = width * x_stride;
+        for row in 0..height {
+            // from the bottom up
+            let row_start = (height - row - 1) * y_stride;
+            for col in 0..width {
+                let pixel_start = (row_start + (col * x_stride)) as usize;
+                let r = image[pixel_start];
+                let g = image[pixel_start + 1];
+                let b = image[pixel_start + 2];
+                let a = image[pixel_start + 3];
+                // written as BGRA
+                self.writer.write_u8(b)?;
+                self.writer.write_u8(g)?;
+                self.writer.write_u8(r)?;
+                self.writer.write_u8(a)?;
+            }
+
+            self.write_row_pad(row_pad_size)?;
         }
 
         Ok(())
     }
 
     fn encode_gray(
         &mut self,
         image: &[u8],
@@ -118,64 +176,64 @@ impl<'a, W: Write + 'a> BMPEncoder<'a, W
         height: u32,
         row_pad_size: u32,
         bytes_per_pixel: u32,
     ) -> io::Result<()> {
         // write grayscale palette
         for val in 0..256 {
             // each color is written as BGRA, where A is always 0 and since only grayscale is being written, B = G = R = index
             let val = val as u8;
-            try!(self.writer.write_u8(val));
-            try!(self.writer.write_u8(val));
-            try!(self.writer.write_u8(val));
-            try!(self.writer.write_u8(0));
+            self.writer.write_u8(val)?;
+            self.writer.write_u8(val)?;
+            self.writer.write_u8(val)?;
+            self.writer.write_u8(0)?;
         }
 
         // write image data
         let x_stride = bytes_per_pixel;
         let y_stride = width * x_stride;
         for row in 0..height {
             // from the bottom up
             let row_start = (height - row - 1) * y_stride;
             for col in 0..width {
                 let pixel_start = (row_start + (col * x_stride)) as usize;
                 // color value is equal to the palette index
-                try!(self.writer.write_u8(image[pixel_start]));
+                self.writer.write_u8(image[pixel_start])?;
                 // alpha is never written as it's not widely supported
             }
 
-            try!(self.write_row_pad(row_pad_size));
+            self.write_row_pad(row_pad_size)?;
         }
 
         Ok(())
     }
 
     fn write_row_pad(&mut self, row_pad_size: u32) -> io::Result<()> {
         for _ in 0..row_pad_size {
-            try!(self.writer.write_u8(0));
+            self.writer.write_u8(0)?;
         }
 
         Ok(())
     }
 }
 
 fn get_unsupported_error_message(c: color::ColorType) -> String {
     format!(
         "Unsupported color type {:?}.  Supported types: RGB(8), RGBA(8), Gray(8), GrayA(8).",
         c
     )
 }
 
-/// Returns a tuple representing: (raw pixel size, written pixel size, palette color count).
+/// Returns a tuple representing: (dib header size, written pixel size, palette color count).
 fn get_pixel_info(c: color::ColorType) -> io::Result<(u32, u32, u32)> {
     let sizes = match c {
-        color::ColorType::RGB(8) => (3, 3, 0),
-        color::ColorType::RGBA(8) => (4, 3, 0),
-        color::ColorType::Gray(8) => (1, 1, 256),
-        color::ColorType::GrayA(8) => (2, 1, 256),
+        color::ColorType::RGB(8) => (BITMAPINFOHEADER_SIZE, 3, 0),
+        color::ColorType::RGBA(8) => (BITMAPV4HEADER_SIZE, 4, 0),
+        color::ColorType::Gray(8) => (BITMAPINFOHEADER_SIZE, 1, 256),
+        color::ColorType::GrayA(8) => (BITMAPINFOHEADER_SIZE, 1, 256),
         _ => {
             return Err(io::Error::new(
                 io::ErrorKind::InvalidInput,
                 &get_unsupported_error_message(c)[..],
             ))
         }
     };
 
@@ -210,22 +268,19 @@ mod tests {
         assert_eq!(3, decoded.len());
         assert_eq!(255, decoded[0]);
         assert_eq!(0, decoded[1]);
         assert_eq!(0, decoded[2]);
     }
 
     #[test]
     fn round_trip_single_pixel_rgba() {
-        let image = [255u8, 0, 0, 0]; // single red pixel
+        let image = [1, 2, 3, 4];
         let decoded = round_trip_image(&image, 1, 1, ColorType::RGBA(8));
-        assert_eq!(3, decoded.len());
-        assert_eq!(255, decoded[0]);
-        assert_eq!(0, decoded[1]);
-        assert_eq!(0, decoded[2]);
+        assert_eq!(&decoded[..], &image[..]);
     }
 
     #[test]
     fn round_trip_3px_rgb() {
         let image = [0u8; 3 * 3 * 3]; // 3x3 pixels, 3 bytes per pixel
         let _decoded = round_trip_image(&image, 3, 3, ColorType::RGB(8));
     }
 
--- a/third_party/rust/image/src/buffer.rs
+++ b/third_party/rust/image/src/buffer.rs
@@ -2,43 +2,59 @@ use num_traits::Zero;
 use std::io;
 use std::marker::PhantomData;
 use std::ops::{Deref, DerefMut, Index, IndexMut, Range};
 use std::path::Path;
 use std::slice::{Chunks, ChunksMut};
 
 use color::{ColorType, FromColor, Luma, LumaA, Rgb, Rgba, Bgr, Bgra};
 use flat::{FlatSamples, SampleLayout};
-use dynimage::save_buffer;
-use image::{GenericImage, GenericImageView};
+use dynimage::{save_buffer, save_buffer_with_format};
+use image::{GenericImage, GenericImageView, ImageFormat};
 use traits::Primitive;
 use utils::expand_packed;
 
 /// A generalized pixel.
 ///
 /// A pixel object is usually not used standalone but as a view into an image buffer.
 pub trait Pixel: Copy + Clone {
     /// The underlying subpixel type.
     type Subpixel: Primitive;
 
+    /// The number of channels of this pixel type.
+    const CHANNEL_COUNT: u8;
     /// Returns the number of channels of this pixel type.
-    fn channel_count() -> u8;
+    #[deprecated(note="please use CHANNEL_COUNT associated constant")]
+    fn channel_count() -> u8 {
+        Self::CHANNEL_COUNT
+    }
 
     /// Returns the components as a slice.
     fn channels(&self) -> &[Self::Subpixel];
 
     /// Returns the components as a mutable slice
     fn channels_mut(&mut self) -> &mut [Self::Subpixel];
 
+    /// A string that can help to interpret the meaning each channel
+    /// See [gimp babl](http://gegl.org/babl/).
+    const COLOR_MODEL: &'static str;
     /// Returns a string that can help to interpret the meaning each channel
     /// See [gimp babl](http://gegl.org/babl/).
-    fn color_model() -> &'static str;
+    #[deprecated(note="please use COLOR_MODEL associated constant")]
+    fn color_model() -> &'static str {
+        Self::COLOR_MODEL
+    }
 
+    /// ColorType for this pixel format
+    const COLOR_TYPE: ColorType;
     /// Returns the ColorType for this pixel format
-    fn color_type() -> ColorType;
+    #[deprecated(note="please use COLOR_TYPE associated constant")]
+    fn color_type() -> ColorType {
+        Self::COLOR_TYPE
+    }
 
     /// Returns the channels of this pixel as a 4 tuple. If the pixel
     /// has less than 4 channels the remainder is filled with the maximum value
     ///
     /// TODO deprecate
     fn channels4(
         &self,
     ) -> (
@@ -107,16 +123,35 @@ pub trait Pixel: Copy + Clone {
         G: FnMut(Self::Subpixel) -> Self::Subpixel;
 
     /// Apply the function ```f``` to each channel except the alpha channel.
     /// Apply the function ```g``` to the alpha channel. Works in-place.
     fn apply_with_alpha<F, G>(&mut self, f: F, g: G)
     where
         F: FnMut(Self::Subpixel) -> Self::Subpixel,
         G: FnMut(Self::Subpixel) -> Self::Subpixel;
+    
+    /// Apply the function ```f``` to each channel except the alpha channel. 
+    fn map_without_alpha<F>(&self, f: F) -> Self 
+    where 
+        F: FnMut(Self::Subpixel) -> Self::Subpixel,
+    {
+        let mut this = *self;
+        this.apply_with_alpha(f, |x| x);
+        this
+    }
+
+    /// Apply the function ```f``` to each channel except the alpha channel. 
+    /// Works in place.
+    fn apply_without_alpha<F>(&mut self, f: F) 
+    where 
+        F: FnMut(Self::Subpixel) -> Self::Subpixel,
+    {
+        self.apply_with_alpha(f, |x| x);
+    }
 
     /// Apply the function ```f``` to each channel of this pixel and
     /// ```other``` pairwise.
     fn map2<F>(&self, other: &Self, f: F) -> Self
     where
         F: FnMut(Self::Subpixel, Self::Subpixel) -> Self::Subpixel;
 
     /// Apply the function ```f``` to each channel of this pixel and
@@ -207,16 +242,102 @@ where
     #[inline(always)]
     fn next_back(&mut self) -> Option<&'a mut P> {
         self.chunks
             .next_back()
             .map(|v| <P as Pixel>::from_slice_mut(v))
     }
 }
 
+/// Iterate over rows of an image
+pub struct Rows<'a, P: Pixel + 'a>
+where
+    <P as Pixel>::Subpixel: 'a,
+{
+    chunks: Chunks<'a, P::Subpixel>,
+}
+
+impl<'a, P: Pixel + 'a> Iterator for Rows<'a, P>
+where
+    P::Subpixel: 'a,
+{
+    type Item = Pixels<'a, P>;
+
+    #[inline(always)]
+    fn next(&mut self) -> Option<Pixels<'a, P>> {
+        self.chunks.next().map(|row| Pixels {
+            chunks: row.chunks(<P as Pixel>::CHANNEL_COUNT as usize),
+        })
+    }
+}
+
+impl<'a, P: Pixel + 'a> ExactSizeIterator for Rows<'a, P>
+where
+    P::Subpixel: 'a,
+{
+    fn len(&self) -> usize {
+        self.chunks.len()
+    }
+}
+
+impl<'a, P: Pixel + 'a> DoubleEndedIterator for Rows<'a, P>
+where
+    P::Subpixel: 'a,
+{
+    #[inline(always)]
+    fn next_back(&mut self) -> Option<Pixels<'a, P>> {
+        self.chunks.next_back().map(|row| Pixels {
+            chunks: row.chunks(<P as Pixel>::CHANNEL_COUNT as usize),
+        })
+    }
+}
+
+/// Iterate over mutable rows of an image
+pub struct RowsMut<'a, P: Pixel + 'a>
+where
+    <P as Pixel>::Subpixel: 'a,
+{
+    chunks: ChunksMut<'a, P::Subpixel>,
+}
+
+impl<'a, P: Pixel + 'a> Iterator for RowsMut<'a, P>
+where
+    P::Subpixel: 'a,
+{
+    type Item = PixelsMut<'a, P>;
+
+    #[inline(always)]
+    fn next(&mut self) -> Option<PixelsMut<'a, P>> {
+        self.chunks.next().map(|row| PixelsMut {
+            chunks: row.chunks_mut(<P as Pixel>::CHANNEL_COUNT as usize),
+        })
+    }
+}
+
+impl<'a, P: Pixel + 'a> ExactSizeIterator for RowsMut<'a, P>
+where
+    P::Subpixel: 'a,
+{
+    fn len(&self) -> usize {
+        self.chunks.len()
+    }
+}
+
+impl<'a, P: Pixel + 'a> DoubleEndedIterator for RowsMut<'a, P>
+where
+    P::Subpixel: 'a,
+{
+    #[inline(always)]
+    fn next_back(&mut self) -> Option<PixelsMut<'a, P>> {
+        self.chunks.next_back().map(|row| PixelsMut {
+            chunks: row.chunks_mut(<P as Pixel>::CHANNEL_COUNT as usize),
+        })
+    }
+}
+
 /// Enumerate the pixels of an image.
 pub struct EnumeratePixels<'a, P: Pixel + 'a>
 where
     <P as Pixel>::Subpixel: 'a,
 {
     pixels: Pixels<'a, P>,
     x: u32,
     y: u32,
@@ -232,32 +353,72 @@ where
     #[inline(always)]
     fn next(&mut self) -> Option<(u32, u32, &'a P)> {
         if self.x >= self.width {
             self.x = 0;
             self.y += 1;
         }
         let (x, y) = (self.x, self.y);
         self.x += 1;
-        match self.pixels.next() {
-            None => None,
-            Some(p) => Some((x, y, p)),
-        }
+        self.pixels.next().map(|p| (x, y, p))
     }
 }
 
 impl<'a, P: Pixel + 'a> ExactSizeIterator for EnumeratePixels<'a, P>
 where
     P::Subpixel: 'a,
 {
     fn len(&self) -> usize {
         self.pixels.len()
     }
 }
 
+/// Enumerate the rows of an image.
+pub struct EnumerateRows<'a, P: Pixel + 'a>
+where
+    <P as Pixel>::Subpixel: 'a,
+{
+    rows: Rows<'a, P>,
+    y: u32,
+    width: u32,
+}
+
+impl<'a, P: Pixel + 'a> Iterator for EnumerateRows<'a, P>
+where
+    P::Subpixel: 'a,
+{
+    type Item = (u32, EnumeratePixels<'a, P>);
+
+    #[inline(always)]
+    fn next(&mut self) -> Option<(u32, EnumeratePixels<'a, P>)> {
+        let y = self.y;
+        self.y += 1;
+        self.rows.next().map(|r| {
+            (
+                y,
+                EnumeratePixels {
+                    x: 0,
+                    y,
+                    width: self.width,
+                    pixels: r,
+                },
+            )
+        })
+    }
+}
+
+impl<'a, P: Pixel + 'a> ExactSizeIterator for EnumerateRows<'a, P>
+where
+    P::Subpixel: 'a,
+{
+    fn len(&self) -> usize {
+        self.rows.len()
+    }
+}
+
 /// Enumerate the pixels of an image.
 pub struct EnumeratePixelsMut<'a, P: Pixel + 'a>
 where
     <P as Pixel>::Subpixel: 'a,
 {
     pixels: PixelsMut<'a, P>,
     x: u32,
     y: u32,
@@ -273,42 +434,85 @@ where
     #[inline(always)]
     fn next(&mut self) -> Option<(u32, u32, &'a mut P)> {
         if self.x >= self.width {
             self.x = 0;
             self.y += 1;
         }
         let (x, y) = (self.x, self.y);
         self.x += 1;
-        match self.pixels.next() {
-            None => None,
-            Some(p) => Some((x, y, p)),
-        }
+        self.pixels.next().map(|p| (x, y, p))
     }
 }
 
 impl<'a, P: Pixel + 'a> ExactSizeIterator for EnumeratePixelsMut<'a, P>
 where
     P::Subpixel: 'a,
 {
     fn len(&self) -> usize {
         self.pixels.len()
     }
 }
 
+/// Enumerate the rows of an image.
+pub struct EnumerateRowsMut<'a, P: Pixel + 'a>
+where
+    <P as Pixel>::Subpixel: 'a,
+{
+    rows: RowsMut<'a, P>,
+    y: u32,
+    width: u32,
+}
+
+impl<'a, P: Pixel + 'a> Iterator for EnumerateRowsMut<'a, P>
+where
+    P::Subpixel: 'a,
+{
+    type Item = (u32, EnumeratePixelsMut<'a, P>);
+
+    #[inline(always)]
+    fn next(&mut self) -> Option<(u32, EnumeratePixelsMut<'a, P>)> {
+        let y = self.y;
+        self.y += 1;
+        self.rows.next().map(|r| {
+            (
+                y,
+                EnumeratePixelsMut {
+                    x: 0,
+                    y,
+                    width: self.width,
+                    pixels: r,
+                },
+            )
+        })
+    }
+}
+
+impl<'a, P: Pixel + 'a> ExactSizeIterator for EnumerateRowsMut<'a, P>
+where
+    P::Subpixel: 'a,
+{
+    fn len(&self) -> usize {
+        self.rows.len()
+    }
+}
+
 /// Generic image buffer
 #[derive(Debug)]
 pub struct ImageBuffer<P: Pixel, Container> {
     width: u32,
     height: u32,
     _phantom: PhantomData<P>,
     data: Container,
 }
 
 // generic implementation, shared along all image buffers
+//
+// TODO: Is the 'static bound on `I::Pixel` really required? Can we avoid it?  Remember to remove
+// the bounds on `imageops` in case this changes!
 impl<P, Container> ImageBuffer<P, Container>
 where
     P: Pixel + 'static,
     P::Subpixel: 'static,
     Container: Deref<Target = [P::Subpixel]>,
 {
     /// Contructs a buffer from a generic container
     /// (for example a `Vec` or a slice)
@@ -346,32 +550,52 @@ where
     /// The height of this image.
     pub fn height(&self) -> u32 {
         self.height
     }
 
     /// Returns an iterator over the pixels of this image.
     pub fn pixels(&self) -> Pixels<P> {
         Pixels {
-            chunks: self.data.chunks(<P as Pixel>::channel_count() as usize),
+            chunks: self.data.chunks(<P as Pixel>::CHANNEL_COUNT as usize),
+        }
+    }
+
+    /// Returns an iterator over the rows of this image.
+    pub fn rows(&self) -> Rows<P> {
+        Rows {
+            chunks: self
+                .data
+                .chunks(<P as Pixel>::CHANNEL_COUNT as usize * self.width as usize),
         }
     }
 
     /// Enumerates over the pixels of the image.
     /// The iterator yields the coordinates of each pixel
     /// along with a reference to them.
     pub fn enumerate_pixels(&self) -> EnumeratePixels<P> {
         EnumeratePixels {
             pixels: self.pixels(),
             x: 0,
             y: 0,
             width: self.width,
         }
     }
 
+    /// Enumerates over the rows of the image.
+    /// The iterator yields the y-coordinate of each row
+    /// along with a reference to them.
+    pub fn enumerate_rows(&self) -> EnumerateRows<P> {
+        EnumerateRows {
+            rows: self.rows(),
+            y: 0,
+            width: self.width,
+        }
+    }
+
     /// Gets a reference to the pixel at location `(x, y)`
     ///
     /// # Panics
     ///
     /// Panics if `(x, y)` is out of the bounds `(width, height)`.
     pub fn get_pixel(&self, x: u32, y: u32) -> &P {
         match self.pixel_indices(x, y) {
             None => panic!("Image index {:?} out of bounds {:?}", (x, y), (self.width, self.height)),
@@ -385,105 +609,124 @@ where
     /// length. Note that as a corrolary we also have that the index calculation of pixels inside
     /// the bounds will not overflow.
     fn check_image_fits(width: u32, height: u32, len: usize) -> bool {
         let checked_len = Self::image_buffer_len(width, height);
         checked_len.map(|min_len| min_len <= len).unwrap_or(false)
     }
 
     fn image_buffer_len(width: u32, height: u32) -> Option<usize> {
-        Some(<P as Pixel>::channel_count() as usize)
+        Some(<P as Pixel>::CHANNEL_COUNT as usize)
             .and_then(|size| size.checked_mul(width as usize))
             .and_then(|size| size.checked_mul(height as usize))
     }
 
     #[inline(always)]
     fn pixel_indices(&self, x: u32, y: u32) -> Option<Range<usize>> {
         if x >= self.width || y >= self.height {
             return None
         }
 
-        Some(unsafe {
-            self.unsafe_pixel_indices(x, y)
-        })
+        Some(self.pixel_indices_unchecked(x, y))
     }
 
     #[inline(always)]
-    unsafe fn unsafe_pixel_indices(&self, x: u32, y: u32) -> Range<usize> {
-        let no_channels = <P as Pixel>::channel_count() as usize;
+    fn pixel_indices_unchecked(&self, x: u32, y: u32) -> Range<usize> {
+        let no_channels = <P as Pixel>::CHANNEL_COUNT as usize;
         // If in bounds, this can't overflow as we have tested that at construction!
         let min_index = (y as usize*self.width as usize + x as usize)*no_channels;
         min_index..min_index+no_channels
     }
 
     /// Get the format of the buffer when viewed as a matrix of samples.
     pub fn sample_layout(&self) -> SampleLayout {
         // None of these can overflow, as all our memory is addressable.
-        SampleLayout::row_major_packed(<P as Pixel>::channel_count(), self.width, self.height)
+        SampleLayout::row_major_packed(<P as Pixel>::CHANNEL_COUNT, self.width, self.height)
     }
 
     /// Return the raw sample buffer with its stride an dimension information.
     ///
     /// The returned buffer is guaranteed to be well formed in all cases. It is layed out by
     /// colors, width then height, meaning `channel_stride <= width_stride <= height_stride`. All
     /// strides are in numbers of elements but those are mostly `u8` in which case the strides are
     /// also byte strides.
     pub fn into_flat_samples(self) -> FlatSamples<Container>
         where Container: AsRef<[P::Subpixel]> 
     {
         // None of these can overflow, as all our memory is addressable.
         let layout = self.sample_layout();
         FlatSamples {
             samples: self.data,
             layout,
-            color_hint: Some(P::color_type()),
+            color_hint: Some(P::COLOR_TYPE),
         }
     }
 
     /// Return a view on the raw sample buffer.
     ///
     /// See `flattened` for more details.
     pub fn as_flat_samples(&self) -> FlatSamples<&[P::Subpixel]>
         where Container: AsRef<[P::Subpixel]> 
     {
         let layout = self.sample_layout();
         FlatSamples {
             samples: self.data.as_ref(),
             layout,
-            color_hint: Some(P::color_type()),
+            color_hint: Some(P::COLOR_TYPE),
         }
     }
 }
 
 impl<P, Container> ImageBuffer<P, Container>
 where
     P: Pixel + 'static,
     P::Subpixel: 'static,
     Container: Deref<Target = [P::Subpixel]> + DerefMut,
 {
     /// Returns an iterator over the mutable pixels of this image.
     pub fn pixels_mut(&mut self) -> PixelsMut<P> {
         PixelsMut {
-            chunks: self.data.chunks_mut(<P as Pixel>::channel_count() as usize),
+            chunks: self.data.chunks_mut(<P as Pixel>::CHANNEL_COUNT as usize),
+        }
+    }
+
+    /// Returns an iterator over the mutable rows of this image.
+    pub fn rows_mut(&mut self) -> RowsMut<P> {
+        RowsMut {
+            chunks: self
+                .data
+                .chunks_mut(<P as Pixel>::CHANNEL_COUNT as usize * self.width as usize),
         }
     }
 
     /// Enumerates over the pixels of the image.
     /// The iterator yields the coordinates of each pixel
     /// along with a mutable reference to them.
     pub fn enumerate_pixels_mut(&mut self) -> EnumeratePixelsMut<P> {
         let width = self.width;
         EnumeratePixelsMut {
             pixels: self.pixels_mut(),
             x: 0,
             y: 0,
             width,
         }
     }
 
+    /// Enumerates over the rows of the image.
+    /// The iterator yields the y-coordinate of each row
+    /// along with a mutable reference to them.
+    pub fn enumerate_rows_mut(&mut self) -> EnumerateRowsMut<P> {
+        let width = self.width;
+        EnumerateRowsMut {
+            rows: self.rows_mut(),
+            y: 0,
+            width,
+        }
+    }
+
     /// Gets a reference to the mutable pixel at location `(x, y)`
     ///
     /// # Panics
     ///
     /// Panics if `(x, y)` is out of the bounds `(width, height)`.
     pub fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut P {
         match self.pixel_indices(x, y) {
             None => panic!("Image index {:?} out of bounds {:?}", (x, y), (self.width, self.height)),
@@ -515,17 +758,43 @@ where
         Q: AsRef<Path>,
     {
         // This is valid as the subpixel is u8.
         save_buffer(
             path,
             self,
             self.width(),
             self.height(),
-            <P as Pixel>::color_type(),
+            <P as Pixel>::COLOR_TYPE,
+        )
+    }
+}
+
+impl<P, Container> ImageBuffer<P, Container>
+where
+    P: Pixel<Subpixel = u8> + 'static,
+    Container: Deref<Target = [u8]>,
+{
+    /// Saves the buffer to a file at the specified path in
+    /// the specified format.
+    ///
+    /// See [`save_buffer_with_format`](fn.save_buffer_with_format.html) for
+    /// supported types.
+    pub fn save_with_format<Q>(&self, path: Q, format: ImageFormat) -> io::Result<()>
+    where
+        Q: AsRef<Path>,
+    {
+        // This is valid as the subpixel is u8.
+        save_buffer_with_format(
+            path,
+            self,
+            self.width(),
+            self.height(),
+            <P as Pixel>::COLOR_TYPE,
+            format,
         )
     }
 }
 
 impl<P, Container> Deref for ImageBuffer<P, Container>
 where
     P: Pixel + 'static,
     P::Subpixel: 'static,
@@ -607,17 +876,17 @@ where
 
     fn get_pixel(&self, x: u32, y: u32) -> P {
         *self.get_pixel(x, y)
     }
 
     /// Returns the pixel located at (x, y), ignoring bounds checking.
     #[inline(always)]
     unsafe fn unsafe_get_pixel(&self, x: u32, y: u32) -> P {
-        let indices = self.unsafe_pixel_indices(x, y);
+        let indices = self.pixel_indices_unchecked(x, y);
         *<P as Pixel>::from_slice(self.data.get_unchecked(indices))
     }
 
     fn inner(&self) -> &Self::InnerImageView {
         self
     }
 }
 
@@ -635,17 +904,17 @@ where
 
     fn put_pixel(&mut self, x: u32, y: u32, pixel: P) {
         *self.get_pixel_mut(x, y) = pixel
     }
 
     /// Puts a pixel at location (x, y), ignoring bounds checking.
     #[inline(always)]
     unsafe fn unsafe_put_pixel(&mut self, x: u32, y: u32, pixel: P) {
-        let indices = self.unsafe_pixel_indices(x, y);
+        let indices = self.pixel_indices_unchecked(x, y);
         let p = <P as Pixel>::from_slice_mut(self.data.get_unchecked_mut(indices));
         *p = pixel
     }
 
     /// Put a pixel at location (x, y), taking into account alpha channels
     ///
     /// DEPRECATED: This method will be removed. Blend the pixel directly instead.
     fn blend_pixel(&mut self, x: u32, y: u32, p: P) {
@@ -748,19 +1017,17 @@ impl GrayImage {
     pub fn expand_palette(
         self,
         palette: &[(u8, u8, u8)],
         transparent_idx: Option<u8>,
     ) -> RgbaImage {
         let (width, height) = self.dimensions();
         let mut data = self.into_raw();
         let entries = data.len();
-        data.reserve_exact(entries.checked_mul(3).unwrap()); // 3 additional channels
-                                                             // set_len is save since type is u8 an the data never read
-        unsafe { data.set_len(entries.checked_mul(4).unwrap()) }; // 4 channels in total
+        data.resize(entries.checked_mul(4).unwrap(), 0);
         let mut buffer = ImageBuffer::from_vec(width, height, data).unwrap();
         expand_packed(&mut buffer, 4, 8, |idx, pixel| {
             let (r, g, b) = palette[idx as usize];
             let a = if let Some(t_idx) = transparent_idx {
                 if t_idx == idx {
                     0
                 } else {
                     255
--- a/third_party/rust/image/src/color.rs
+++ b/third_party/rust/image/src/color.rs
@@ -63,50 +63,41 @@ macro_rules! define_colors {
     )*} => {
 
 $( // START Structure definitions
 
 #[$doc]
 #[derive(PartialEq, Eq, Clone, Debug, Copy, Hash)]
 #[repr(C)]
 #[allow(missing_docs)]
-pub struct $ident<T: Primitive> { pub data: [T; $channels] }
-#[allow(non_snake_case, missing_docs)]
-pub fn $ident<T: Primitive>(data: [T; $channels]) -> $ident<T> {
-    $ident {
-        data: data
-    }
-}
+pub struct $ident<T: Primitive> (pub [T; $channels]);
 
 impl<T: Primitive + 'static> Pixel for $ident<T> {
 
     type Subpixel = T;
 
-    fn channel_count() -> u8 {
-        $channels
-    }
-    fn color_model() -> &'static str {
-        $interpretation
-    }
-    fn color_type() -> ColorType {
-        ColorType::$color_type(mem::size_of::<T>() as u8 * 8)
-    }
+    const CHANNEL_COUNT: u8 = $channels;
+
+    const COLOR_MODEL: &'static str = $interpretation;
+
+    const COLOR_TYPE: ColorType = ColorType::$color_type(mem::size_of::<T>() as u8 * 8); 
+
     #[inline(always)]
     fn channels(&self) -> &[T] {
-        &self.data
+        &self.0
     }
     #[inline(always)]
     fn channels_mut(&mut self) -> &mut [T] {
-        &mut self.data
+        &mut self.0
     }
 
     #[allow(trivial_casts)]
     fn channels4(&self) -> (T, T, T, T) {
         let mut channels = [T::max_value(); 4];
-        channels[0..$channels].copy_from_slice(&self.data);
+        channels[0..$channels].copy_from_slice(&self.0);
         (channels[0], channels[1], channels[2], channels[3])
     }
 
     fn from_channels(a: T, b: T, c: T, d: T,) -> $ident<T> {
         *<$ident<T> as Pixel>::from_slice(&[a, b, c, d][..$channels])
     }
 
     fn from_slice(slice: &[T]) -> &$ident<T> {
@@ -114,88 +105,88 @@ impl<T: Primitive + 'static> Pixel for $
         unsafe { &*(slice.as_ptr() as *const $ident<T>) }
     }
     fn from_slice_mut(slice: &mut [T]) -> &mut $ident<T> {
         assert_eq!(slice.len(), $channels);
         unsafe { &mut *(slice.as_ptr() as *mut $ident<T>) }
     }
 
     fn to_rgb(&self) -> Rgb<T> {
-        let mut pix = Rgb {data: [Zero::zero(), Zero::zero(), Zero::zero()]};
+        let mut pix = Rgb([Zero::zero(), Zero::zero(), Zero::zero()]);
         pix.from_color(self);
         pix
     }
 
     fn to_bgr(&self) -> Bgr<T> {
-        let mut pix = Bgr {data: [Zero::zero(), Zero::zero(), Zero::zero()]};
+        let mut pix = Bgr([Zero::zero(), Zero::zero(), Zero::zero()]);
         pix.from_color(self);
         pix
     }
 
     fn to_rgba(&self) -> Rgba<T> {
-        let mut pix = Rgba {data: [Zero::zero(), Zero::zero(), Zero::zero(), Zero::zero()]};
+        let mut pix = Rgba([Zero::zero(), Zero::zero(), Zero::zero(), Zero::zero()]);
         pix.from_color(self);
         pix
     }
 
     fn to_bgra(&self) -> Bgra<T> {
-        let mut pix = Bgra {data: [Zero::zero(), Zero::zero(), Zero::zero(), Zero::zero()]};
+        let mut pix = Bgra([Zero::zero(), Zero::zero(), Zero::zero(), Zero::zero()]);
         pix.from_color(self);
         pix
     }
 
     fn to_luma(&self) -> Luma<T> {
-        let mut pix = Luma {data: [Zero::zero()]};
+        let mut pix = Luma([Zero::zero()]);
         pix.from_color(self);
         pix
     }
 
     fn to_luma_alpha(&self) -> LumaA<T> {
-        let mut pix = LumaA {data: [Zero::zero(), Zero::zero()]};
+        let mut pix = LumaA([Zero::zero(), Zero::zero()]);
         pix.from_color(self);
         pix
     }
 
     fn map<F>(& self, f: F) -> $ident<T> where F: FnMut(T) -> T {
         let mut this = (*self).clone();
         this.apply(f);
         this
     }
 
     fn apply<F>(&mut self, mut f: F) where F: FnMut(T) -> T {
-        for v in &mut self.data {
+        for v in &mut self.0 {
             *v = f(*v)
         }
     }
 
     fn map_with_alpha<F, G>(&self, f: F, g: G) -> $ident<T> where F: FnMut(T) -> T, G: FnMut(T) -> T {
         let mut this = (*self).clone();
         this.apply_with_alpha(f, g);
         this
     }
 
     #[allow(trivial_casts)]
     fn apply_with_alpha<F, G>(&mut self, mut f: F, mut g: G) where F: FnMut(T) -> T, G: FnMut(T) -> T {
-        for v in self.data[..$channels as usize-$alphas as usize].iter_mut() {
+        for v in self.0[..$channels as usize-$alphas as usize].iter_mut() {
             *v = f(*v)
         }
         if $alphas as usize != 0 {
-            let v = &mut self.data[$channels as usize-$alphas as usize];
+            let v = &mut self.0[$channels as usize-$alphas as usize];
             *v = g(*v)
         }
     }
 
     fn map2<F>(&self, other: &Self, f: F) -> $ident<T> where F: FnMut(T, T) -> T {
         let mut this = (*self).clone();
         this.apply2(other, f);
         this
     }
 
     fn apply2<F>(&mut self, other: &$ident<T>, mut f: F) where F: FnMut(T, T) -> T {
-        for (a, &b) in self.data.iter_mut().zip(other.data.iter()) {
+        for (a, &b) in self.0.iter_mut().zip(other.0.iter()) {
             *a = f(*a, b)
         }
     }
 
     fn invert(&mut self) {
         Invert::invert(self)
     }
 
@@ -203,24 +194,24 @@ impl<T: Primitive + 'static> Pixel for $
         Blend::blend(self, other)
     }
 }
 
 impl<T: Primitive> Index<usize> for $ident<T> {
     type Output = T;
     #[inline(always)]
     fn index(&self, _index: usize) -> &T {
-        &self.data[_index]
+        &self.0[_index]
     }
 }
 
 impl<T: Primitive> IndexMut<usize> for $ident<T> {
     #[inline(always)]
     fn index_mut(&mut self, _index: usize) -> &mut T {
-        &mut self.data[_index]
+        &mut self.0[_index]
     }
 }
 
 )* // END Structure definitions
 
     }
 }
 
@@ -584,18 +575,18 @@ pub trait Blend {
     /// Blends a color in-place.
     fn blend(&mut self, other: &Self);
 }
 
 impl<T: Primitive> Blend for LumaA<T> {
     fn blend(&mut self, other: &LumaA<T>) {
         let max_t = T::max_value();
         let max_t = max_t.to_f32().unwrap();
-        let (bg_luma, bg_a) = (self.data[0], self.data[1]);
-        let (fg_luma, fg_a) = (other.data[0], other.data[1]);
+        let (bg_luma, bg_a) = (self.0[0], self.0[1]);
+        let (fg_luma, fg_a) = (other.0[0], other.0[1]);
 
         let (bg_luma, bg_a) = (
             bg_luma.to_f32().unwrap() / max_t,
             bg_a.to_f32().unwrap() / max_t,
         );
         let (fg_luma, fg_a) = (
             fg_luma.to_f32().unwrap() / max_t,
             fg_a.to_f32().unwrap() / max_t,
@@ -626,18 +617,18 @@ impl<T: Primitive> Blend for Luma<T> {
 
 impl<T: Primitive> Blend for Rgba<T> {
     fn blend(&mut self, other: &Rgba<T>) {
         // http://stackoverflow.com/questions/7438263/alpha-compositing-algorithm-blend-modes#answer-11163848
 
         // First, as we don't know what type our pixel is, we have to convert to floats between 0.0 and 1.0
         let max_t = T::max_value();
         let max_t = max_t.to_f32().unwrap();
-        let (bg_r, bg_g, bg_b, bg_a) = (self.data[0], self.data[1], self.data[2], self.data[3]);
-        let (fg_r, fg_g, fg_b, fg_a) = (other.data[0], other.data[1], other.data[2], other.data[3]);
+        let (bg_r, bg_g, bg_b, bg_a) = (self.0[0], self.0[1], self.0[2], self.0[3]);
+        let (fg_r, fg_g, fg_b, fg_a) = (other.0[0], other.0[1], other.0[2], other.0[3]);
         let (bg_r, bg_g, bg_b, bg_a) = (
             bg_r.to_f32().unwrap() / max_t,
             bg_g.to_f32().unwrap() / max_t,
             bg_b.to_f32().unwrap() / max_t,
             bg_a.to_f32().unwrap() / max_t,
         );
         let (fg_r, fg_g, fg_b, fg_a) = (
             fg_r.to_f32().unwrap() / max_t,
@@ -684,18 +675,18 @@ impl<T: Primitive> Blend for Rgba<T> {
 
 impl<T: Primitive> Blend for Bgra<T> {
     fn blend(&mut self, other: &Bgra<T>) {
         // http://stackoverflow.com/questions/7438263/alpha-compositing-algorithm-blend-modes#answer-11163848
 
         // First, as we don't know what type our pixel is, we have to convert to floats between 0.0 and 1.0
         let max_t = T::max_value();
         let max_t = max_t.to_f32().unwrap();
-        let (bg_r, bg_g, bg_b, bg_a) = (self.data[2], self.data[1], self.data[0], self.data[3]);
-        let (fg_r, fg_g, fg_b, fg_a) = (other.data[2], other.data[1], other.data[0], other.data[3]);
+        let (bg_r, bg_g, bg_b, bg_a) = (self.0[2], self.0[1], self.0[0], self.0[3]);
+        let (fg_r, fg_g, fg_b, fg_a) = (other.0[2], other.0[1], other.0[0], other.0[3]);
         let (bg_r, bg_g, bg_b, bg_a) = (
             bg_r.to_f32().unwrap() / max_t,
             bg_g.to_f32().unwrap() / max_t,
             bg_b.to_f32().unwrap() / max_t,
             bg_a.to_f32().unwrap() / max_t,
         );
         let (fg_r, fg_g, fg_b, fg_a) = (
             fg_r.to_f32().unwrap() / max_t,
@@ -754,73 +745,73 @@ impl<T: Primitive> Blend for Bgr<T> {
 /// Invert a color
 pub trait Invert {
     /// Inverts a color in-place.
     fn invert(&mut self);
 }
 
 impl<T: Primitive> Invert for LumaA<T> {
     fn invert(&mut self) {
-        let l = self.data;
+        let l = self.0;
         let max = T::max_value();
 
         *self = LumaA([max - l[0], l[1]])
     }
 }
 
 impl<T: Primitive> Invert for Luma<T> {
     fn invert(&mut self) {
-        let l = self.data;
+        let l = self.0;
 
         let max = T::max_value();
         let l1 = max - l[0];
 
-        *self = Luma { data: [l1] }
+        *self = Luma([l1])
     }
 }
 
 impl<T: Primitive> Invert for Rgba<T> {
     fn invert(&mut self) {
-        let rgba = self.data;
+        let rgba = self.0;
 
         let max = T::max_value();
 
         *self = Rgba([max - rgba[0], max - rgba[1], max - rgba[2], rgba[3]])
     }
 }
 
 
 impl<T: Primitive> Invert for Bgra<T> {
     fn invert(&mut self) {
-        let bgra = self.data;
+        let bgra = self.0;
 
         let max = T::max_value();
 
         *self = Bgra([max - bgra[2], max - bgra[1], max - bgra[0], bgra[3]])
     }
 }
 
 
 impl<T: Primitive> Invert for Rgb<T> {
     fn invert(&mut self) {
-        let rgb = self.data;
+        let rgb = self.0;
 
         let max = T::max_value();
 
         let r1 = max - rgb[0];
         let g1 = max - rgb[1];
         let b1 = max - rgb[2];
 
         *self = Rgb([r1, g1, b1])
     }
 }
 
 impl<T: Primitive> Invert for Bgr<T> {
     fn invert(&mut self) {
-        let bgr = self.data;
+        let bgr = self.0;
 
         let max = T::max_value();
 
         let r1 = max - bgr[2];
         let g1 = max - bgr[1];
         let b1 = max - bgr[0];
 
         *self = Bgr([b1, g1, r1])
@@ -828,162 +819,162 @@ impl<T: Primitive> Invert for Bgr<T> {
 }
 
 #[cfg(test)]
 mod tests {
     use super::{LumaA, Pixel, Rgb, Rgba, Bgr, Bgra};
 
     #[test]
     fn test_apply_with_alpha_rgba() {
-        let mut rgba = Rgba { data: [0, 0, 0, 0] };
+        let mut rgba = Rgba([0, 0, 0, 0]);
         rgba.apply_with_alpha(|s| s, |_| 0xFF);
-        assert_eq!(
-            rgba,
-            Rgba {
-                data: [0, 0, 0, 0xFF]
-            }
-        );
+        assert_eq!(rgba, Rgba([0, 0, 0, 0xFF]));
     }
 
     #[test]
     fn test_apply_with_alpha_bgra() {
-        let mut bgra = Bgra { data: [0, 0, 0, 0] };
+        let mut bgra = Bgra([0, 0, 0, 0]);
         bgra.apply_with_alpha(|s| s, |_| 0xFF);
-        assert_eq!(
-            bgra,
-            Bgra {
-                data: [0, 0, 0, 0xFF]
-            }
-        );
+        assert_eq!(bgra, Bgra([0, 0, 0, 0xFF]));
     }
 
     #[test]
     fn test_apply_with_alpha_rgb() {
-        let mut rgb = Rgb { data: [0, 0, 0] };
+        let mut rgb = Rgb([0, 0, 0]);
         rgb.apply_with_alpha(|s| s, |_| panic!("bug"));
-        assert_eq!(rgb, Rgb { data: [0, 0, 0] });
+        assert_eq!(rgb, Rgb([0, 0, 0]));
     }
 
     #[test]
     fn test_apply_with_alpha_bgr() {
-        let mut bgr = Bgr { data: [0, 0, 0] };
+        let mut bgr = Bgr([0, 0, 0]);
         bgr.apply_with_alpha(|s| s, |_| panic!("bug"));
-        assert_eq!(bgr, Bgr { data: [0, 0, 0] });
+        assert_eq!(bgr, Bgr([0, 0, 0]));
     }
 
 
     #[test]
     fn test_map_with_alpha_rgba() {
-        let rgba = Rgba { data: [0, 0, 0, 0] }.map_with_alpha(|s| s, |_| 0xFF);
-        assert_eq!(
-            rgba,
-            Rgba {
-                data: [0, 0, 0, 0xFF]
-            }
-        );
+        let rgba = Rgba([0, 0, 0, 0]).map_with_alpha(|s| s, |_| 0xFF);
+        assert_eq!(rgba, Rgba([0, 0, 0, 0xFF]));
     }
 
     #[test]
     fn test_map_with_alpha_rgb() {
-        let rgb = Rgb { data: [0, 0, 0] }.map_with_alpha(|s| s, |_| panic!("bug"));
-        assert_eq!(rgb, Rgb { data: [0, 0, 0] });
+        let rgb = Rgb([0, 0, 0]).map_with_alpha(|s| s, |_| panic!("bug"));
+        assert_eq!(rgb, Rgb([0, 0, 0]));
     }
 
     #[test]
     fn test_map_with_alpha_bgr() {
-        let bgr = Bgr { data: [0, 0, 0] }.map_with_alpha(|s| s, |_| panic!("bug"));
-        assert_eq!(bgr, Bgr { data: [0, 0, 0] });
+        let bgr = Bgr([0, 0, 0]).map_with_alpha(|s| s, |_| panic!("bug"));
+        assert_eq!(bgr, Bgr([0, 0, 0]));
     }
 
 
     #[test]
     fn test_map_with_alpha_bgra() {
-        let bgra = Bgra { data: [0, 0, 0, 0] }.map_with_alpha(|s| s, |_| 0xFF);
-        assert_eq!(
-            bgra,
-            Bgra {
-                data: [0, 0, 0, 0xFF]
-            }
-        );
+        let bgra = Bgra([0, 0, 0, 0]).map_with_alpha(|s| s, |_| 0xFF);
+        assert_eq!(bgra, Bgra([0, 0, 0, 0xFF]));
     }
 
     #[test]
     fn test_blend_luma_alpha() {
-        let ref mut a = LumaA {
-            data: [255 as u8, 255],
-        };
-        let b = LumaA {
-            data: [255 as u8, 255],
-        };
+        let ref mut a = LumaA([255 as u8, 255]);
+        let b = LumaA([255 as u8, 255]);
         a.blend(&b);
-        assert_eq!(a.data[0], 255);
-        assert_eq!(a.data[1], 255);
+        assert_eq!(a.0[0], 255);
+        assert_eq!(a.0[1], 255);
 
-        let ref mut a = LumaA {
-            data: [255 as u8, 0],
-        };
-        let b = LumaA {
-            data: [255 as u8, 255],
-        };
+        let ref mut a = LumaA([255 as u8, 0]);
+        let b = LumaA([255 as u8, 255]);
         a.blend(&b);
-        assert_eq!(a.data[0], 255);
-        assert_eq!(a.data[1], 255);
+        assert_eq!(a.0[0], 255);
+        assert_eq!(a.0[1], 255);
 
-        let ref mut a = LumaA {
-            data: [255 as u8, 255],
-        };
-        let b = LumaA {
-            data: [255 as u8, 0],
-        };
+        let ref mut a = LumaA([255 as u8, 255]);
+        let b = LumaA([255 as u8, 0]);
         a.blend(&b);
-        assert_eq!(a.data[0], 255);
-        assert_eq!(a.data[1], 255);
+        assert_eq!(a.0[0], 255);
+        assert_eq!(a.0[1], 255);
 
-        let ref mut a = LumaA {
-            data: [255 as u8, 0],
-        };
-        let b = LumaA {
-            data: [255 as u8, 0],
-        };
+        let ref mut a = LumaA([255 as u8, 0]);
+        let b = LumaA([255 as u8, 0]);
         a.blend(&b);
-        assert_eq!(a.data[0], 255);
-        assert_eq!(a.data[1], 0);
+        assert_eq!(a.0[0], 255);
+        assert_eq!(a.0[1], 0);
     }
 
     #[test]
     fn test_blend_rgba() {
-        let ref mut a = Rgba {
-            data: [255 as u8, 255, 255, 255],
-        };
-        let b = Rgba {
-            data: [255 as u8, 255, 255, 255],
-        };
+        let ref mut a = Rgba([255 as u8, 255, 255, 255]);
+        let b = Rgba([255 as u8, 255, 255, 255]);
         a.blend(&b);
-        assert_eq!(a.data, [255, 255, 255, 255]);
+        assert_eq!(a.0, [255, 255, 255, 255]);
+
+        let ref mut a = Rgba([255 as u8, 255, 255, 0]);
+        let b = Rgba([255 as u8, 255, 255, 255]);
+        a.blend(&b);
+        assert_eq!(a.0, [255, 255, 255, 255]);
+
+        let ref mut a = Rgba([255 as u8, 255, 255, 255]);
+        let b = Rgba([255 as u8, 255, 255, 0]);
+        a.blend(&b);
+        assert_eq!(a.0, [255, 255, 255, 255]);
 
-        let ref mut a = Rgba {
-            data: [255 as u8, 255, 255, 0],
-        };
-        let b = Rgba {
-            data: [255 as u8, 255, 255, 255],
-        };
+        let ref mut a = Rgba([255 as u8, 255, 255, 0]);
+        let b = Rgba([255 as u8, 255, 255, 0]);
         a.blend(&b);
-        assert_eq!(a.data, [255, 255, 255, 255]);
+        assert_eq!(a.0, [255, 255, 255, 0]);
+    }    
+
+    #[test]
+    fn test_apply_without_alpha_rgba() {
+        let mut rgba = Rgba([0, 0, 0, 0]);
+        rgba.apply_without_alpha(|s| s + 1);
+        assert_eq!(rgba, Rgba([1, 1, 1, 0]));
+    }
+
+    #[test]
+    fn test_apply_without_alpha_bgra() {
+        let mut bgra = Bgra([0, 0, 0, 0]);
+        bgra.apply_without_alpha(|s| s + 1);
+        assert_eq!(bgra, Bgra([1, 1, 1, 0]));
+    }
 
-        let ref mut a = Rgba {
-            data: [255 as u8, 255, 255, 255],
-        };
-        let b = Rgba {
-            data: [255 as u8, 255, 255, 0],
-        };
-        a.blend(&b);
-        assert_eq!(a.data, [255, 255, 255, 255]);
+    #[test]
+    fn test_apply_without_alpha_rgb() {
+        let mut rgb = Rgb([0, 0, 0]);
+        rgb.apply_without_alpha(|s| s + 1);
+        assert_eq!(rgb, Rgb([1, 1, 1]));
+    }
+
+    #[test]
+    fn test_apply_without_alpha_bgr() {
+        let mut bgr = Bgr([0, 0, 0]);
+        bgr.apply_without_alpha(|s| s + 1);
+        assert_eq!(bgr, Bgr([1, 1, 1]));
+    }
 
-        let ref mut a = Rgba {
-            data: [255 as u8, 255, 255, 0],
-        };
-        let b = Rgba {
-            data: [255 as u8, 255, 255, 0],
-        };
-        a.blend(&b);
-        assert_eq!(a.data, [255, 255, 255, 0]);
+    #[test]
+    fn test_map_without_alpha_rgba() {
+        let rgba = Rgba([0, 0, 0, 0]).map_without_alpha(|s| s + 1);
+        assert_eq!(rgba, Rgba([1, 1, 1, 0]));
+    }
+
+    #[test]
+    fn test_map_without_alpha_rgb() {
+        let rgb = Rgb([0, 0, 0]).map_without_alpha(|s| s + 1);
+        assert_eq!(rgb, Rgb([1, 1, 1]));
+    }
+
+    #[test]
+    fn test_map_without_alpha_bgr() {
+        let bgr = Bgr([0, 0, 0]).map_without_alpha(|s| s + 1);
+        assert_eq!(bgr, Bgr([1, 1, 1]));
+    }
+
+    #[test]
+    fn test_map_without_alpha_bgra() {
+        let bgra = Bgra([0, 0, 0, 0]).map_without_alpha(|s| s + 1);
+        assert_eq!(bgra, Bgra([1, 1, 1, 0]));
     }
 }
--- a/third_party/rust/image/src/dxt.rs
+++ b/third_party/rust/image/src/dxt.rs
@@ -78,19 +78,16 @@ impl<R: Read> DXTDecoder<R> {
         height: u32,
         variant: DXTVariant,
     ) -> Result<DXTDecoder<R>, ImageError> {
         if width % 4 != 0 || height % 4 != 0 {
             return Err(ImageError::DimensionError);
         }
         let width_blocks = width / 4;
         let height_blocks = height / 4;
-        if width.count_ones() != 1 || height.count_ones() != 1 {
-            return Err(ImageError::DimensionError);
-        }
         Ok(DXTDecoder {
             inner: r,
             width_blocks,
             height_blocks,
             variant,
             row: 0,
         })
     }
@@ -108,17 +105,17 @@ impl<R: Read> DXTDecoder<R> {
         }
         self.row += 1;
         Ok(buf.len())
     }
 }
 
 // Note that, due to the way that DXT compression works, a scanline is considered to consist out of
 // 4 lines of pixels.
-impl<R: Read> ImageDecoder for DXTDecoder<R> {
+impl<'a, R: 'a + Read> ImageDecoder<'a> for DXTDecoder<R> {
     type Reader = DXTReader<R>;
 
     fn dimensions(&self) -> (u64, u64) {
         (self.width_blocks as u64 * 4, self.height_blocks as u64 * 4)
     }
 
     fn colortype(&self) -> ColorType {
         self.variant.colortype()
@@ -147,17 +144,17 @@ impl<R: Read> ImageDecoder for DXTDecode
         let mut dest = vec![0u8; self.total_bytes() as usize];
         for chunk in dest.chunks_mut(self.scanline_bytes() as usize) {
             self.read_scanline(chunk)?;
         }
         Ok(dest)
     }
 }
 
-impl<R: Read + Seek> ImageDecoderExt for DXTDecoder<R> {
+impl<'a, R: 'a + Read + Seek> ImageDecoderExt<'a> for DXTDecoder<R> {
     fn read_rect_with_progress<F: Fn(Progress)>(
         &mut self,
         x: u64,
         y: u64,
         width: u64,
         height: u64,
         buf: &mut [u8],
         progress_callback: F,
@@ -211,19 +208,16 @@ impl<W: Write> DXTEncoder<W> {
         height: u32,
         variant: DXTVariant,
     ) -> ImageResult<()> {
         if width % 4 != 0 || height % 4 != 0 {
             return Err(ImageError::DimensionError);
         }
         let width_blocks = width / 4;
         let height_blocks = height / 4;
-        if width.count_ones() != 1 || height.count_ones() != 1 {
-            return Err(ImageError::DimensionError);
-        }
 
         let stride = variant.decoded_bytes_per_block();
 
         assert!(data.len() >= width_blocks as usize * height_blocks as usize * stride);
 
         for chunk in data.chunks(width_blocks as usize * stride) {
             let data = match variant {
                 DXTVariant::DXT1 => encode_dxt1_row(chunk),
@@ -619,17 +613,17 @@ fn encode_dxt_colors(source: &[u8], dest
     let mut color1 = enc565_encode(chosen_colors[1]);
 
     // determine encoding. Note that color0 == color1 is impossible at this point
     if color0 > color1 {
         if chosen_use_0 {
             swap(&mut color0, &mut color1);
             // Indexes are packed 2 bits wide, swap index 0/1 but preserve 2/3.
             let filter = (chosen_indices & 0xAAAA_AAAA) >> 1;
-            chosen_indices ^= filter ^ 0x555_5555;
+            chosen_indices ^= filter ^ 0x5555_5555;
         }
     } else if !chosen_use_0 {
         swap(&mut color0, &mut color1);
         // Indexes are packed 2 bits wide, swap index 0/1 and 2/3.
         chosen_indices ^= 0x5555_5555;
     }
 
     // encode everything.
--- a/third_party/rust/image/src/dynimage.rs
+++ b/third_party/rust/image/src/dynimage.rs
@@ -1,13 +1,14 @@
 use num_iter;
 use std::fs::File;
 use std::io;
 use std::io::{BufRead, BufReader, BufWriter, Seek, Write};
 use std::path::Path;
+use std::u32;
 
 #[cfg(feature = "bmp")]
 use bmp;
 #[cfg(feature = "gif_codec")]
 use gif;
 #[cfg(feature = "hdr")]
 use hdr;
 #[cfg(feature = "ico")]
@@ -486,41 +487,41 @@ impl DynamicImage {
                         color=color::ColorType::RGBA(8);
                     },
                     DynamicImage::ImageBgr8(_) => {
                         bytes=self.to_rgb().iter().cloned().collect();
                         color=color::ColorType::RGB(8);
                     },
                     _ => {},
                 }
-                try!(p.encode(&bytes, width, height, color));
+                p.encode(&bytes, width, height, color)?;
                 Ok(())
             }
             #[cfg(feature = "pnm")]
             image::ImageOutputFormat::PNM(subtype) => {
                 let mut p = pnm::PNMEncoder::new(w).with_subtype(subtype);
                 match *self {
                     DynamicImage::ImageBgra8(_) => {
                         bytes=self.to_rgba().iter().cloned().collect();
                         color=color::ColorType::RGBA(8);
                     },
                     DynamicImage::ImageBgr8(_) => {
                         bytes=self.to_rgb().iter().cloned().collect();
                         color=color::ColorType::RGB(8);
                     },
                     _ => {},
                 }
-                try!(p.encode(&bytes[..], width, height, color));
+                p.encode(&bytes[..], width, height, color)?;
                 Ok(())
             }
             #[cfg(feature = "jpeg")]
             image::ImageOutputFormat::JPEG(quality) => {
                 let mut j = jpeg::JPEGEncoder::new_with_quality(w, quality);
 
-                try!(j.encode(&bytes, width, height, color));
+                j.encode(&bytes, width, height, color)?;
                 Ok(())
             }
 
             #[cfg(feature = "gif_codec")]
             image::ImageOutputFormat::GIF => {
                 let mut g = gif::Encoder::new(w);
 
                 try!(g.encode(&gif::Frame::from_rgba(
@@ -530,24 +531,24 @@ impl DynamicImage {
                 )));
                 Ok(())
             }
 
             #[cfg(feature = "ico")]
             image::ImageOutputFormat::ICO => {
                 let i = ico::ICOEncoder::new(w);
 
-                try!(i.encode(&bytes, width, height, color));
+                i.encode(&bytes, width, height, color)?;
                 Ok(())
             }
 
             #[cfg(feature = "bmp")]
             image::ImageOutputFormat::BMP => {
                 let mut b = bmp::BMPEncoder::new(w);
-                try!(b.encode(&bytes, width, height, color));
+                b.encode(&bytes, width, height, color)?;
                 Ok(())
             }
 
             image::ImageOutputFormat::Unsupported(msg) => {
                 Err(image::ImageError::UnsupportedError(msg))
             }
         }
     }
@@ -558,16 +559,30 @@ impl DynamicImage {
     pub fn save<Q>(&self, path: Q) -> io::Result<()>
     where
         Q: AsRef<Path>,
     {
         dynamic_map!(*self, ref p -> {
             p.save(path)
         })
     }
+
+    /// Saves the buffer to a file at the specified path in
+    /// the specified format.
+    ///
+    /// See [`save_buffer_with_format`](fn.save_buffer_with_format.html) for
+    /// supported types.
+    pub fn save_with_format<Q>(&self, path: Q, format: ImageFormat) -> io::Result<()>
+    where
+        Q: AsRef<Path>,
+    {
+        dynamic_map!(*self, ref p -> {
+            p.save_with_format(path, format)
+        })
+    }
 }
 
 #[allow(deprecated)]
 impl GenericImageView for DynamicImage {
     type Pixel = color::Rgba<u8>;
     type InnerImageView = Self;
 
     fn dimensions(&self) -> (u32, u32) {
@@ -620,20 +635,20 @@ impl GenericImage for DynamicImage {
     }
 
     fn inner_mut(&mut self) -> &mut Self::InnerImage {
         self
     }
 }
 
 /// Decodes an image and stores it into a dynamic image
-pub fn decoder_to_image<I: ImageDecoder>(codec: I) -> ImageResult<DynamicImage> {
+pub fn decoder_to_image<'a, I: ImageDecoder<'a>>(codec: I) -> ImageResult<DynamicImage> {
     let color = codec.colortype();
     let (w, h) = codec.dimensions();
-    let buf = try!(codec.read_image());
+    let buf = codec.read_image()?;
 
     // TODO: Avoid this cast by having ImageBuffer use u64's
     assert!(w <= u32::max_value() as u64);
     assert!(h <= u32::max_value() as u64);
     let (w, h) = (w as u32, h as u32);
 
     let image = match color {
         color::ColorType::RGB(8) => {
@@ -755,23 +770,77 @@ fn open_impl(path: &Path) -> ImageResult
                 format
             )))
         }
     };
 
     load(fin, format)
 }
 
+/// Read the dimensions of the image located at the specified path.
+/// This is faster than fully loading the image and then getting its dimensions.
+pub fn image_dimensions<P>(path: P) -> ImageResult<(u32, u32)>
+where
+    P: AsRef<Path>
+{
+    // thin wrapper function to strip generics before calling open_impl
+    image_dimensions_impl(path.as_ref())
+}
+
+fn image_dimensions_impl(path: &Path) -> ImageResult<(u32, u32)> {
+    let fin = File::open(path)?;
+    let fin = BufReader::new(fin);
+
+    let ext = path
+        .extension()
+        .and_then(|s| s.to_str())
+        .map_or("".to_string(), |s| s.to_ascii_lowercase());
+
+    let (w, h): (u64, u64) = match &ext[..] {
+        #[cfg(feature = "jpeg")]
+        "jpg" | "jpeg" => jpeg::JPEGDecoder::new(fin)?.dimensions(),
+        #[cfg(feature = "png_codec")]
+        "png" => png::PNGDecoder::new(fin)?.dimensions(),
+        #[cfg(feature = "gif_codec")]
+        "gif" => gif::Decoder::new(fin)?.dimensions(),
+        #[cfg(feature = "webp")]
+        "webp" => webp::WebpDecoder::new(fin)?.dimensions(),
+        #[cfg(feature = "tiff")]
+        "tif" | "tiff" => tiff::TIFFDecoder::new(fin)?.dimensions(),
+        #[cfg(feature = "tga")]
+        "tga" => tga::TGADecoder::new(fin)?.dimensions(),
+        #[cfg(feature = "bmp")]
+        "bmp" => bmp::BMPDecoder::new(fin)?.dimensions(),
+        #[cfg(feature = "ico")]
+        "ico" => ico::ICODecoder::new(fin)?.dimensions(),
+        #[cfg(feature = "hdr")]
+        "hdr" => hdr::HDRAdapter::new(fin)?.dimensions(),
+        #[cfg(feature = "pnm")]
+        "pbm" | "pam" | "ppm" | "pgm" => {
+            pnm::PNMDecoder::new(fin)?.dimensions()
+        }
+        format => return Err(image::ImageError::UnsupportedError(format!(
+            "Image format image/{:?} is not supported.",
+            format
+        ))),
+    };
+    if w >= u32::MAX as u64 || h >= u32::MAX as u64 {
+        return Err(image::ImageError::DimensionError);
+    }
+    Ok((w as u32, h as u32))
+}
+
+
 /// Saves the supplied buffer to a file at the path specified.
 ///
 /// The image format is derived from the file extension. The buffer is assumed to have
 /// the correct format according to the specified color type.
 
 /// This will lead to corrupted files if the buffer contains malformed data. Currently only
-/// jpeg and png files are supported.
+/// jpeg, png, ico, pnm, bmp and tiff files are supported.
 pub fn save_buffer<P>(
     path: P,
     buf: &[u8],
     width: u32,
     height: u32,
     color: color::ColorType,
 ) -> io::Result<()>
 where
@@ -783,17 +852,17 @@ where
 
 fn save_buffer_impl(
     path: &Path,
     buf: &[u8],
     width: u32,
     height: u32,
     color: color::ColorType,
 ) -> io::Result<()> {
-    let fout = &mut BufWriter::new(try!(File::create(path)));
+    let fout = &mut BufWriter::new(File::create(path)?);
     let ext = path.extension()
         .and_then(|s| s.to_str())
         .map_or("".to_string(), |s| s.to_ascii_lowercase());
 
     match &*ext {
         #[cfg(feature = "ico")]
         "ico" => ico::ICOEncoder::new(fout).encode(buf, width, height, color),
         #[cfg(feature = "jpeg")]
@@ -811,23 +880,79 @@ fn save_buffer_impl(
         #[cfg(feature = "pnm")]
         "ppm" => pnm::PNMEncoder::new(fout)
             .with_subtype(pnm::PNMSubtype::Pixmap(pnm::SampleEncoding::Binary))
             .encode(buf, width, height, color),
         #[cfg(feature = "pnm")]
         "pam" => pnm::PNMEncoder::new(fout).encode(buf, width, height, color),
         #[cfg(feature = "bmp")]
         "bmp" => bmp::BMPEncoder::new(fout).encode(buf, width, height, color),
+        #[cfg(feature = "tiff")]
+        "tif" | "tiff" => tiff::TiffEncoder::new(fout).encode(buf, width, height, color)
+            .map_err(|e| io::Error::new(io::ErrorKind::Other, Box::new(e))), // FIXME: see https://github.com/image-rs/image/issues/921
         format => Err(io::Error::new(
             io::ErrorKind::InvalidInput,
             &format!("Unsupported image format image/{:?}", format)[..],
         )),
     }
 }
 
+/// Saves the supplied buffer to a file at the path specified
+/// in the specified format.
+///
+/// The buffer is assumed to have the correct format according
+/// to the specified color type.
+/// This will lead to corrupted files if the buffer contains
+/// malformed data. Currently only jpeg, png, ico, bmp and
+/// tiff files are supported.
+pub fn save_buffer_with_format<P>(
+    path: P,
+    buf: &[u8],
+    width: u32,
+    height: u32,
+    color: color::ColorType,
+    format: ImageFormat,
+) -> io::Result<()>
+where
+    P: AsRef<Path>,
+{
+    // thin wrapper function to strip generics
+    save_buffer_with_format_impl(path.as_ref(), buf, width, height, color, format)
+}
+
+fn save_buffer_with_format_impl(
+    path: &Path,
+    buf: &[u8],
+    width: u32,
+    height: u32,
+    color: color::ColorType,
+    format: ImageFormat,
+) -> io::Result<()> {
+    let fout = &mut BufWriter::new(File::create(path)?);
+
+    match format {
+        #[cfg(feature = "ico")]
+        image::ImageFormat::ICO => ico::ICOEncoder::new(fout).encode(buf, width, height, color),
+        #[cfg(feature = "jpeg")]
+        image::ImageFormat::JPEG => jpeg::JPEGEncoder::new(fout).encode(buf, width, height, color),
+        #[cfg(feature = "png_codec")]
+        image::ImageFormat::PNG => png::PNGEncoder::new(fout).encode(buf, width, height, color),
+        #[cfg(feature = "bmp")]
+        image::ImageFormat::BMP => bmp::BMPEncoder::new(fout).encode(buf, width, height, color),
+        #[cfg(feature = "tiff")]
+        image::ImageFormat::TIFF => tiff::TiffEncoder::new(fout)
+            .encode(buf, width, height, color)
+            .map_err(|e| io::Error::new(io::ErrorKind::Other, Box::new(e))),
+        _ => Err(io::Error::new(
+            io::ErrorKind::InvalidInput,
+            &format!("Unsupported image format image/{:?}", format)[..],
+        )),
+    }
+}
+
 /// Create a new image from a Reader
 pub fn load<R: BufRead + Seek>(r: R, format: ImageFormat) -> ImageResult<DynamicImage> {
     #[allow(deprecated, unreachable_patterns)]
     // Default is unreachable if all features are supported.
     match format {
         #[cfg(feature = "png_codec")]
         image::ImageFormat::PNG => decoder_to_image(png::PNGDecoder::new(r)?),
         #[cfg(feature = "gif_codec")]
@@ -855,17 +980,17 @@ pub fn load<R: BufRead + Seek>(r: R, for
     }
 }
 
 static MAGIC_BYTES: [(&'static [u8], ImageFormat); 17] = [
     (b"\x89PNG\r\n\x1a\n", ImageFormat::PNG),
     (&[0xff, 0xd8, 0xff], ImageFormat::JPEG),
     (b"GIF89a", ImageFormat::GIF),
     (b"GIF87a", ImageFormat::GIF),
-    (b"WEBP", ImageFormat::WEBP),
+    (b"RIFF", ImageFormat::WEBP), // TODO: better magic byte detection, see https://github.com/image-rs/image/issues/660
     (b"MM.*", ImageFormat::TIFF),
     (b"II*.", ImageFormat::TIFF),
     (b"BM", ImageFormat::BMP),
     (&[0, 0, 1, 0], ImageFormat::ICO),
     (b"#?RADIANCE", ImageFormat::HDR),
     (b"P1", ImageFormat::PNM),
     (b"P2", ImageFormat::PNM),
     (b"P3", ImageFormat::PNM),
@@ -1028,9 +1153,17 @@ mod test {
             &[0b11110000, 0b00001111],
             vec![255, 255, 0, 0, 0, 0, 255, 255]);
         // Bit depth 4, skip is half a byte
         check(
             4, 1, 2,
             &[0b11110011, 0b00001100],
             vec![255, 0]);
     }
+
+    #[cfg(feature = "jpeg")]
+    #[test]
+    fn image_dimensions() {
+        let im_path = "./tests/images/jpg/progressive/cat.jpg";
+        let dims = super::image_dimensions(im_path).unwrap();
+        assert_eq!(dims, (320, 240));
+    }
 }
--- a/third_party/rust/image/src/flat.rs
+++ b/third_party/rust/image/src/flat.rs
@@ -554,18 +554,18 @@ impl<Buffer> FlatSamples<Buffer> {
     ///
     /// This first ensures that all in-bounds coordinates refer to valid indices in the sample
     /// buffer. It also checks that the specified pixel format expects the same number of channels
     /// that are present in this buffer. Neither are larger nor a smaller number will be accepted.
     /// There is no automatic conversion.
     pub fn as_view<P>(&self) -> Result<View<&[P::Subpixel], P>, Error> 
         where P: Pixel, Buffer: AsRef<[P::Subpixel]>,
     {
-        if self.layout.channels != P::channel_count() {
-            return Err(Error::WrongColor(P::color_type()))
+        if self.layout.channels != P::CHANNEL_COUNT {
+            return Err(Error::WrongColor(P::COLOR_TYPE))
         }
 
         let as_ref = self.samples.as_ref();
         if !self.layout.fits(as_ref.len()) {
             return Err(Error::TooLarge)
         }
 
         Ok(View {
@@ -591,18 +591,18 @@ impl<Buffer> FlatSamples<Buffer> {
     /// There is no automatic conversion.
     ///
     /// **WARNING**: Note that of course samples may alias, so that the mutable reference returned
     /// for one sample can in fact modify other samples as well. Sometimes exactly this is
     /// intended.
     pub fn as_view_with_mut_samples<P>(&mut self) -> Result<View<&mut [P::Subpixel], P>, Error>
         where P: Pixel, Buffer: AsMut<[P::Subpixel]>,
     {
-        if self.layout.channels != P::channel_count() {
-            return Err(Error::WrongColor(P::color_type()))
+        if self.layout.channels != P::CHANNEL_COUNT {
+            return Err(Error::WrongColor(P::COLOR_TYPE))
         }
 
         let as_mut = self.samples.as_mut();
         if !self.layout.fits(as_mut.len()) {
             return Err(Error::TooLarge)
         }
 
         Ok(View {
@@ -628,18 +628,18 @@ impl<Buffer> FlatSamples<Buffer> {
     /// `ImageBuffer::from_raw`.
     pub fn as_view_mut<P>(&mut self) -> Result<ViewMut<&mut [P::Subpixel], P>, Error>
         where P: Pixel, Buffer: AsMut<[P::Subpixel]>,
     {
         if !self.layout.is_normal(NormalForm::PixelPacked) {
             return Err(Error::NormalFormRequired(NormalForm::PixelPacked))
         }
 
-        if self.layout.channels != P::channel_count() {
-            return Err(Error::WrongColor(P::color_type()))
+        if self.layout.channels != P::CHANNEL_COUNT {
+            return Err(Error::WrongColor(P::COLOR_TYPE))
         }
 
         let as_mut = self.samples.as_mut();
         if !self.layout.fits(as_mut.len()) {
             return Err(Error::TooLarge)
         }
 
         Ok(ViewMut {
@@ -712,18 +712,18 @@ impl<Buffer> FlatSamples<Buffer> {
         P: Pixel + 'static,
         P::Subpixel: 'static,
         Buffer: Deref<Target=[P::Subpixel]>,
     {
         if !self.is_normal(NormalForm::RowMajorPacked) {
             return Err((Error::NormalFormRequired(NormalForm::RowMajorPacked), self))
         }
 
-        if self.layout.channels != P::channel_count() {
-            return Err((Error::WrongColor(P::color_type()), self))
+        if self.layout.channels != P::CHANNEL_COUNT {
+            return Err((Error::WrongColor(P::COLOR_TYPE), self))
         }
 
         if !self.fits(self.samples.deref().len()) {
             return Err((Error::TooLarge, self))
         }
 
 
         Ok(ImageBuffer::from_raw(self.layout.width, self.layout.height, self.samples).unwrap_or_else(
@@ -1275,17 +1275,17 @@ impl<Buffer, P: Pixel> GenericImageView 
 
     fn get_pixel(&self, x: u32, y: u32) -> Self::Pixel {
         if !self.inner.in_bounds(0, x, y) {
             panic_pixel_out_of_bounds((x, y), self.dimensions())
         }
 
         let image = self.inner.samples.as_ref();
         let base_index = self.inner.in_bounds_index(0, x, y);
-        let channels = P::channel_count() as usize;
+        let channels = P::CHANNEL_COUNT as usize;
 
         let mut buffer = [Zero::zero(); 256];
         buffer.iter_mut().enumerate().take(channels).for_each(|(c, to)| {
             let index = base_index + c*self.inner.layout.channel_stride;
             *to = image[index];
         });
 
         P::from_slice(&buffer[..channels]).clone()
@@ -1320,17 +1320,17 @@ impl<Buffer, P: Pixel> GenericImageView 
 
     fn get_pixel(&self, x: u32, y: u32) -> Self::Pixel {
         if !self.inner.in_bounds(0, x, y) {
             panic_pixel_out_of_bounds((x, y), self.dimensions())
         }
 
         let image = self.inner.samples.as_ref();
         let base_index = self.inner.in_bounds_index(0, x, y);
-        let channels = P::channel_count() as usize;
+        let channels = P::CHANNEL_COUNT as usize;
 
         let mut buffer = [Zero::zero(); 256];
         buffer.iter_mut().enumerate().take(channels).for_each(|(c, to)| {
             let index = base_index + c*self.inner.layout.channel_stride;
             *to = image[index];
         });
 
         P::from_slice(&buffer[..channels]).clone()
@@ -1347,17 +1347,17 @@ impl<Buffer, P: Pixel> GenericImage for 
     type InnerImage = Self;
 
     fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut Self::Pixel {
         if !self.inner.in_bounds(0, x, y) {
             panic_pixel_out_of_bounds((x, y), self.dimensions())
         }
 
         let base_index = self.inner.in_bounds_index(0, x, y);
-        let channel_count = <P as Pixel>::channel_count() as usize;
+        let channel_count = <P as Pixel>::CHANNEL_COUNT as usize;
         let pixel_range = base_index..base_index + channel_count;
         P::from_slice_mut(&mut self.inner.samples.as_mut()[pixel_range])
     }
 
     fn put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel) {
         *self.get_pixel_mut(x, y) = pixel;
     }
 
@@ -1456,22 +1456,20 @@ mod tests {
                 height_stride: 6,
             },
             color_hint: None,
         };
 
         {
             let mut view = buffer.as_view_mut::<LumaA<usize>>()
                 .expect("This should be a valid mutable buffer");
-            #[allow(deprecated)]
-            let pixel_count = view.pixels_mut()
-                .enumerate()
-                .map(|(idx, (_, _, pixel))| *pixel = LumaA([2*idx, 2*idx + 1]))
-                .count();
-            assert_eq!(pixel_count, 9);
+            assert_eq!(view.dimensions(), (3, 3));
+            for i in 0..9 {
+                *view.get_pixel_mut(i % 3, i / 3) = LumaA([2 * i as usize, 2 * i as usize + 1]);
+            }
         }
 
         buffer.samples.iter()
             .enumerate()
             .for_each(|(idx, sample)| assert_eq!(idx, *sample));
     }
 
     #[test]
--- a/third_party/rust/image/src/gif.rs
+++ b/third_party/rust/image/src/gif.rs
@@ -25,17 +25,19 @@
 //! # }
 //! ```
 #![cfg_attr(feature = "cargo-clippy", allow(while_let_loop))]
 
 extern crate gif;
 extern crate num_rational;
 
 use std::clone::Clone;
-use std::io::{Cursor, Read, Write};
+use std::io::{self, Cursor, Read, Write};
+use std::marker::PhantomData;
+use std::mem;
 
 use self::gif::{ColorOutput, SetParameter};
 pub use self::gif::{DisposalMethod, Frame};
 
 use animation;
 use buffer::{ImageBuffer, Pixel};
 use color;
 use color::Rgba;
@@ -54,29 +56,45 @@ impl<R: Read> Decoder<R> {
         decoder.set(ColorOutput::RGBA);
 
         Ok(Decoder {
             reader: decoder.read_info()?,
         })
     }
 }
 
-impl<R: Read> ImageDecoder for Decoder<R> {
-    type Reader = Cursor<Vec<u8>>;
+/// Wrapper struct around a `Cursor<Vec<u8>>`
+pub struct GifReader<R>(Cursor<Vec<u8>>, PhantomData<R>);
+impl<R> Read for GifReader<R> {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        self.0.read(buf)
+    }
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
+        if self.0.position() == 0 && buf.is_empty() {
+            mem::swap(buf, self.0.get_mut());
+            Ok(buf.len())
+        } else {
+            self.0.read_to_end(buf)
+        }
+    }
+}
+
+impl<'a, R: 'a + Read> ImageDecoder<'a> for Decoder<R> {
+    type Reader = GifReader<R>;
 
     fn dimensions(&self) -> (u64, u64) {
         (self.reader.width() as u64, self.reader.height() as u64)
     }
 
     fn colortype(&self) -> color::ColorType {
         color::ColorType::RGBA(8)
     }
 
     fn into_reader(self) -> ImageResult<Self::Reader> {
-        Ok(Cursor::new(self.read_image()?))
+        Ok(GifReader(Cursor::new(self.read_image()?), PhantomData))
     }
 
     fn read_image(mut self) -> ImageResult<Vec<u8>> {
         if self.reader.next_frame_info()?.is_some() {
             let mut buf = vec![0; self.reader.buffer_size()];
             self.reader.read_into_buffer(&mut buf)?;
             Ok(buf)
         } else {
@@ -189,17 +207,17 @@ impl<R: Read> Iterator for GifFrameItera
                 "Unknown error occured while reading gif frame".into()
             ))),
         };
 
         // loop over all pixels, checking if any pixels from the non disposed
         // frame need to be used
         for (x, y, pixel) in image_buffer.enumerate_pixels_mut() {
             let previous_img_buffer = &self.non_disposed_frame;
-            let mut adjusted_pixel: &mut Rgba<u8> = pixel;
+            let adjusted_pixel: &mut Rgba<u8> = pixel;
             let previous_pixel: &Rgba<u8> = previous_img_buffer.get_pixel(x, y);
 
             let pixel_alpha = adjusted_pixel.channels()[3];
 
             // If a pixel is not visible then we show the non disposed frame pixel instead
             if pixel_alpha == 0 {
                 adjusted_pixel.blend(previous_pixel);
             }
@@ -257,17 +275,17 @@ impl<W: Write> Encoder<W> {
     }
     /// Encodes a frame.
     pub fn encode(&mut self, frame: &Frame) -> ImageResult<()> {
         let result;
         if let Some(ref mut encoder) = self.gif_encoder {
             result = encoder.write_frame(frame).map_err(|err| err.into());
         } else {
             let writer = self.w.take().unwrap();
-            let mut encoder = try!(gif::Encoder::new(writer, frame.width, frame.height, &[]));
+            let mut encoder = gif::Encoder::new(writer, frame.width, frame.height, &[])?;
             result = encoder.write_frame(&frame).map_err(|err| err.into());
             self.gif_encoder = Some(encoder);
         }
         result
     }
 
     /// Encodes Frames.
     /// Consider using `try_encode_frames` instead to encode an `animation::Frames` like iterator.
rename from third_party/rust/image/src/hdr/hdr_decoder.rs
rename to third_party/rust/image/src/hdr/decoder.rs
--- a/third_party/rust/image/src/hdr/hdr_decoder.rs
+++ b/third_party/rust/image/src/hdr/decoder.rs
@@ -1,17 +1,18 @@
-use super::scoped_threadpool::Pool;
+use scoped_threadpool::Pool;
 use num_traits::cast::NumCast;
 use num_traits::identities::Zero;
 use std::mem;
 #[cfg(test)]
 use std::borrow::Cow;
 use std::error::Error;
-use std::io::{self, BufRead, Cursor, Seek};
+use std::io::{self, BufRead, Cursor, Read, Seek};
 use std::iter::Iterator;
+use std::marker::PhantomData;
 use std::path::Path;
 use Primitive;
 
 use color::{ColorType, Rgb};
 use image::{self, ImageDecoder, ImageDecoderExt, ImageError, ImageResult, Progress};
 
 /// Adapter to conform to ```ImageDecoder``` trait
 #[derive(Debug)]
@@ -19,28 +20,28 @@ pub struct HDRAdapter<R: BufRead> {
     inner: Option<HDRDecoder<R>>,
     data: Option<Vec<u8>>,
     meta: HDRMetadata,
 }
 
 impl<R: BufRead> HDRAdapter<R> {
     /// Creates adapter
     pub fn new(r: R) -> ImageResult<HDRAdapter<R>> {
-        let decoder = try!(HDRDecoder::new(r));
+        let decoder = HDRDecoder::new(r)?;
         let meta = decoder.metadata();
         Ok(HDRAdapter {
             inner: Some(decoder),
             data: None,
             meta,
         })
     }
 
     /// Allows reading old Radiance HDR images
     pub fn new_nonstrict(r: R) -> ImageResult<HDRAdapter<R>> {
-        let decoder = try!(HDRDecoder::with_strictness(r, false));
+        let decoder = HDRDecoder::with_strictness(r, false)?;
         let meta = decoder.metadata();
         Ok(HDRAdapter {
             inner: Some(decoder),
             data: None,
             meta,
         })
     }
 
@@ -49,54 +50,70 @@ impl<R: BufRead> HDRAdapter<R> {
         match self.inner.take() {
             Some(decoder) => {
                 let img: Vec<Rgb<u8>> = decoder.read_image_ldr()?;
 
                 let len = img.len() * mem::size_of::<Rgb<u8>>(); // length in bytes
                 let target = self.data.get_or_insert_with(|| Vec::with_capacity(len));
                 target.clear();
 
-                for Rgb { data } in img {
+                for Rgb(data) in img {
                     target.extend_from_slice(&data);
                 }
 
                 Ok(())
             }
             None => Err(ImageError::ImageEnd),
         }
     }
 
 }
 
-impl<R: BufRead> ImageDecoder for HDRAdapter<R> {
-    type Reader = Cursor<Vec<u8>>;
+/// Wrapper struct around a `Cursor<Vec<u8>>`
+pub struct HdrReader<R>(Cursor<Vec<u8>>, PhantomData<R>);
+impl<R> Read for HdrReader<R> {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        self.0.read(buf)
+    }
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
+        if self.0.position() == 0 && buf.is_empty() {
+            mem::swap(buf, self.0.get_mut());
+            Ok(buf.len())
+        } else {
+            self.0.read_to_end(buf)
+        }
+    }
+}
+
+impl<'a, R: 'a + BufRead> ImageDecoder<'a> for HDRAdapter<R> {
+    type Reader = HdrReader<R>;
 
     fn dimensions(&self) -> (u64, u64) {
         (self.meta.width as u64, self.meta.height as u64)
     }
 
     fn colortype(&self) -> ColorType {
         ColorType::RGB(8)
     }
 
     fn into_reader(self) -> ImageResult<Self::Reader> {
-        Ok(Cursor::new(self.read_image()?))
+        Ok(HdrReader(Cursor::new(self.read_image()?), PhantomData))
     }
 
     fn read_image(mut self) -> ImageResult<Vec<u8>> {
         if let Some(data) = self.data {
             return Ok(data);
         }
 
         self.read_image_data()?;
         Ok(self.data.unwrap())
     }
 }
 
-impl<R: BufRead + Seek> ImageDecoderExt for HDRAdapter<R> {
+impl<'a, R: 'a + BufRead + Seek> ImageDecoderExt<'a> for HDRAdapter<R> {
     fn read_rect_with_progress<F: Fn(Progress)>(
         &mut self,
         x: u64,
         y: u64,
         width: u64,
         height: u64,
         buf: &mut [u8],
         progress_callback: F,
@@ -123,17 +140,17 @@ pub struct HDRDecoder<R> {
     r: R,
     width: u32,
     height: u32,
     meta: HDRMetadata,
 }
 
 /// Refer to [wikipedia](https://en.wikipedia.org/wiki/RGBE_image_format)
 #[repr(C)]
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
 pub struct RGBE8Pixel {
     /// Color components
     pub c: [u8; 3],
     /// Exponent
     pub e: u8,
 }
 
 /// Creates ```RGBE8Pixel``` from components
@@ -175,17 +192,17 @@ impl RGBE8Pixel {
     /// color_ldr = (color_hdr*scale)<sup>gamma</sup>
     ///
     /// # Panic
     ///
     /// Panics when T::max_value() cannot be represented as f32.
     /// Panics when scale or gamma is NaN
     #[inline]
     pub fn to_ldr_scale_gamma<T: Primitive + Zero>(self, scale: f32, gamma: f32) -> Rgb<T> {
-        let Rgb { data } = self.to_hdr();
+        let Rgb(data) = self.to_hdr();
         let (r, g, b) = (data[0], data[1], data[2]);
         #[inline]
         fn sg<T: Primitive + Zero>(v: f32, scale: f32, gamma: f32) -> T {
             let t_max = T::max_value();
             // Disassembly shows that t_max_f32 is compiled into constant
             let t_max_f32: f32 = NumCast::from(t_max)
                 .expect("to_ldr_scale_gamma: maximum value of type is not representable as f32");
             let fv = f32::powf(v * scale, gamma) * t_max_f32 + 0.5;
@@ -224,60 +241,60 @@ impl<R: BufRead> HDRDecoder<R> {
     pub fn with_strictness(mut reader: R, strict: bool) -> ImageResult<HDRDecoder<R>> {
         let mut attributes = HDRMetadata::new();
 
         {
             // scope to make borrowck happy
             let r = &mut reader;
             if strict {
                 let mut signature = [0; SIGNATURE_LENGTH];
-                try!(r.read_exact(&mut signature));
+                r.read_exact(&mut signature)?;
                 if signature != SIGNATURE {
                     return Err(ImageError::FormatError(
                         "Radiance HDR signature not found".to_string(),
                     ));
                 } // no else
                   // skip signature line ending
-                try!(read_line_u8(r));
+                read_line_u8(r)?;
             } else {
                 // Old Radiance HDR files (*.pic) don't use signature
                 // Let them be parsed in non-strict mode
             }
             // read header data until empty line
             loop {
-                match try!(read_line_u8(r)) {
+                match read_line_u8(r)? {
                     None => {
                         // EOF before end of header
                         return Err(ImageError::FormatError("EOF in header".into()));
                     }
                     Some(line) => {
                         if line.is_empty() {
                             // end of header
                             break;
                         } else if line[0] == b'#' {
                             // line[0] will not panic, line.len() == 0 is false here
                             // skip comments
                             continue;
                         } // no else
                           // process attribute line
                         let line = String::from_utf8_lossy(&line[..]);
-                        try!(attributes.update_header_info(&line, strict));
+                        attributes.update_header_info(&line, strict)?;
                     } // <= Some(line)
                 } // match read_line_u8()
             } // loop
         } // scope to end borrow of reader
           // parse dimensions
-        let (width, height) = match try!(read_line_u8(&mut reader)) {
+        let (width, height) = match read_line_u8(&mut reader)? {
             None => {
                 // EOF instead of image dimensions
                 return Err(ImageError::FormatError("EOF in dimensions line".into()));
             }
             Some(dimensions) => {
                 let dimensions = String::from_utf8_lossy(&dimensions[..]);
-                try!(parse_dimensions_line(&dimensions, strict))
+                parse_dimensions_line(&dimensions, strict)?
             }
         };
 
         Ok(HDRDecoder {
             r: reader,
 
             width,
             height,
@@ -297,101 +314,81 @@ impl<R: BufRead> HDRDecoder<R> {
     /// Consumes decoder and returns a vector of RGBE8 pixels
     pub fn read_image_native(mut self) -> ImageResult<Vec<RGBE8Pixel>> {
         // Don't read anything if image is empty
         if self.width == 0 || self.height == 0 {
             return Ok(vec![]);
         }
         // expression self.width > 0 && self.height > 0 is true from now to the end of this method
         let pixel_count = self.width as usize * self.height as usize;
-        let mut ret = Vec::<RGBE8Pixel>::with_capacity(pixel_count);
-        unsafe {
-            // RGBE8Pixel doesn't implement Drop, so it's Ok to drop half-initialized ret
-            ret.set_len(pixel_count);
-        } // ret contains uninitialized data, so now it's my responsibility to return fully initialized ret
+        let mut ret = vec![Default::default(); pixel_count];
         for chunk in ret.chunks_mut(self.width as usize) {
-            try!(read_scanline(&mut self.r, chunk));
+            read_scanline(&mut self.r, chunk)?;
         }
         Ok(ret)
     }
 
     /// Consumes decoder and returns a vector of transformed pixels
     pub fn read_image_transform<T: Send, F: Send + Sync + Fn(RGBE8Pixel) -> T>(
         mut self,
         f: F,
-    ) -> ImageResult<Vec<T>> {
+        output_slice: &mut [T],
+    ) -> ImageResult<()> {
+        assert_eq!(output_slice.len(), self.width as usize * self.height as usize);
+
         // Don't read anything if image is empty
         if self.width == 0 || self.height == 0 {
-            return Ok(vec![]);
-        }
-        // expression self.width > 0 && self.height > 0 is true from now to the end of this method
-        // scanline buffer
-        let uszwidth = self.width as usize;
-
-        let pixel_count = self.width as usize * self.height as usize;
-        let mut ret = Vec::with_capacity(pixel_count);
-        unsafe {
-            // RGBE8Pixel doesn't implement Drop, so it's Ok to drop half-initialized ret
-            ret.set_len(pixel_count);
-        } // ret contains uninitialized data, so now it's my responsibility to return fully initialized ret
-
-        {
-            let chunks_iter = ret.chunks_mut(uszwidth);
-            let mut pool = Pool::new(8); //
-
-            try!(pool.scoped(|scope| {
-                for chunk in chunks_iter {
-                    let mut buf = Vec::<RGBE8Pixel>::with_capacity(uszwidth);
-                    unsafe {
-                        buf.set_len(uszwidth);
-                    }
-                    try!(read_scanline(&mut self.r, &mut buf[..]));
-                    let f = &f;
-                    scope.execute(move || {
-                        for (dst, &pix) in chunk.iter_mut().zip(buf.iter()) {
-                            *dst = f(pix);
-                        }
-                    });
-                }
-                Ok(())
-            }) as Result<(), ImageError>);
+            return Ok(());
         }
 
-        Ok(ret)
+        let chunks_iter = output_slice.chunks_mut(self.width as usize);
+        let mut pool = Pool::new(8); //
+
+        try!(pool.scoped(|scope| {
+            for chunk in chunks_iter {
+                let mut buf = vec![Default::default(); self.width as usize];
+                read_scanline(&mut self.r, &mut buf[..])?;
+                let f = &f;
+                scope.execute(move || {
+                    for (dst, &pix) in chunk.iter_mut().zip(buf.iter()) {
+                        *dst = f(pix);
+                    }
+                });
+            }
+            Ok(())
+        }) as Result<(), ImageError>);
+        Ok(())
     }
 
     /// Consumes decoder and returns a vector of Rgb<u8> pixels.
     /// scale = 1, gamma = 2.2
     pub fn read_image_ldr(self) -> ImageResult<Vec<Rgb<u8>>> {
-        self.read_image_transform(|pix| pix.to_ldr())
+        let mut ret = vec![Rgb([0,0,0]); self.width as usize * self.height as usize];
+        self.read_image_transform(|pix| pix.to_ldr(), &mut ret[..])?;
+        Ok(ret)
     }
 
     /// Consumes decoder and returns a vector of Rgb<f32> pixels.
     ///
     pub fn read_image_hdr(self) -> ImageResult<Vec<Rgb<f32>>> {
-        self.read_image_transform(|pix| pix.to_hdr())
+        let mut ret = vec![Rgb([0.0, 0.0, 0.0]); self.width as usize * self.height as usize];
+        self.read_image_transform(|pix| pix.to_hdr(), &mut ret[..])?;
+        Ok(ret)
     }
 }
 
 impl<R: BufRead> IntoIterator for HDRDecoder<R> {
     type Item = ImageResult<RGBE8Pixel>;
     type IntoIter = HDRImageDecoderIterator<R>;
 
     fn into_iter(self) -> Self::IntoIter {
-        // scanline buffer
-        let mut buf = Vec::with_capacity(self.width as usize);
-        unsafe {
-            // dropping half-initialized vector of RGBE8Pixel is safe
-            // and I took care to hide half-initialized vector from a user
-            buf.set_len(self.width as usize);
-        }
         HDRImageDecoderIterator {
             r: self.r,
             scanline_cnt: self.height as usize,
-            buf,
+            buf: vec![Default::default(); self.width as usize],
             col: 0,
             scanline: 0,
             trouble: true, // make first call to `next()` read scanline
             error_encountered: false,
         }
     }
 }
 
@@ -470,76 +467,76 @@ impl<R: BufRead> Iterator for HDRImageDe
 
 impl<R: BufRead> ExactSizeIterator for HDRImageDecoderIterator<R> {}
 
 // Precondition: buf.len() > 0
 fn read_scanline<R: BufRead>(r: &mut R, buf: &mut [RGBE8Pixel]) -> ImageResult<()> {
     assert!(!buf.is_empty());
     let width = buf.len();
     // first 4 bytes in scanline allow to determine compression method
-    let fb = try!(read_rgbe(r));
+    let fb = read_rgbe(r)?;
     if fb.c[0] == 2 && fb.c[1] == 2 && fb.c[2] < 128 {
         // denormalized pixel value (2,2,<128,_) indicates new per component RLE method
         // decode_component guarantees that offset is within 0 .. width
         // therefore we can skip bounds checking here, but we will not
-        try!(decode_component(r, width, |offset, value| buf[offset].c[0] = value));
-        try!(decode_component(r, width, |offset, value| buf[offset].c[1] = value));
-        try!(decode_component(r, width, |offset, value| buf[offset].c[2] = value));
-        try!(decode_component(r, width, |offset, value| buf[offset].e = value));
+        decode_component(r, width, |offset, value| buf[offset].c[0] = value)?;
+        decode_component(r, width, |offset, value| buf[offset].c[1] = value)?;
+        decode_component(r, width, |offset, value| buf[offset].c[2] = value)?;
+        decode_component(r, width, |offset, value| buf[offset].e = value)?;
     } else {
         // old RLE method (it was considered old around 1991, should it be here?)
-        try!(decode_old_rle(r, fb, buf));
+        decode_old_rle(r, fb, buf)?;
     }
     Ok(())
 }
 
 #[inline(always)]
 fn read_byte<R: BufRead>(r: &mut R) -> io::Result<u8> {
     let mut buf = [0u8];
-    try!(r.read_exact(&mut buf[..]));
+    r.read_exact(&mut buf[..])?;
     Ok(buf[0])
 }
 
 // Guarantees that first parameter of set_component will be within pos .. pos+width
 #[inline]
 fn decode_component<R: BufRead, S: FnMut(usize, u8)>(
     r: &mut R,
     width: usize,
     mut set_component: S,
 ) -> ImageResult<()> {
     let mut buf = [0; 128];
     let mut pos = 0;
     while pos < width {
         // increment position by a number of decompressed values
         pos += {
-            let rl = try!(read_byte(r));
+            let rl = read_byte(r)?;
             if rl <= 128 {
                 // sanity check
                 if pos + rl as usize > width {
                     return Err(ImageError::FormatError(
                         "Wrong length of decoded scanline".into(),
                     ));
                 }
                 // read values
-                try!(r.read_exact(&mut buf[0..rl as usize]));
+                r.read_exact(&mut buf[0..rl as usize])?;
                 for (offset, &value) in buf[0..rl as usize].iter().enumerate() {
                     set_component(pos + offset, value);
                 }
                 rl as usize
             } else {
                 // run
                 let rl = rl - 128;
                 // sanity check
                 if pos + rl as usize > width {
                     return Err(ImageError::FormatError(
                         "Wrong length of decoded scanline".into(),
                     ));
                 }
                 // fill with same value
-                let value = try!(read_byte(r));
+                let value = read_byte(r)?;
                 for offset in 0..rl as usize {
                     set_component(pos + offset, value);
                 }
                 rl as usize
             }
         };
     }
     if pos != width {
@@ -578,17 +575,17 @@ fn decode_old_rle<R: BufRead>(
         ));
     }
     buf[0] = fb; // set first pixel of scanline
 
     let mut x_off = 1; // current offset from beginning of a scanline
     let mut rl_mult = 1; // current run length multiplier
     let mut prev_pixel = fb;
     while x_off < width {
-        let pix = try!(read_rgbe(r));
+        let pix = read_rgbe(r)?;
         // it's harder to forget to increase x_off if I write this this way.
         x_off += {
             if let Some(rl) = rl_marker(pix) {
                 // rl_mult takes care of consecutive RL markers
                 let rl = rl * rl_mult;
                 rl_mult *= 256;
                 if x_off + rl <= width {
                     // do run
@@ -614,17 +611,17 @@ fn decode_old_rle<R: BufRead>(
             "Wrong length of decoded scanline".into(),
         ));
     }
     Ok(())
 }
 
 fn read_rgbe<R: BufRead>(r: &mut R) -> io::Result<RGBE8Pixel> {
     let mut buf = [0u8; 4];
-    try!(r.read_exact(&mut buf[..]));
+    r.read_exact(&mut buf[..])?;
     Ok(RGBE8Pixel {c: [buf[0], buf[1], buf[2]], e: buf[3] })
 }
 
 /// Metadata for Radiance HDR image
 #[derive(Debug, Clone)]
 pub struct HDRMetadata {
     /// Width of decoded image. It could be either scanline length,
     /// or scanline count, depending on image orientation.
@@ -803,18 +800,18 @@ fn parse_dimensions_line(line: &str, str
         return Err(ImageError::FormatError(err.into()));
     } // no else
       // dimensions line is in the form "-Y 10 +X 20"
       // There are 8 possible orientations: +Y +X, +X -Y and so on
     match (c1_tag, c2_tag) {
         ("-Y", "+X") => {
             // Common orientation (left-right, top-down)
             // c1_str is height, c2_str is width
-            let height = try!(c1_str.parse::<u32>().into_image_error(err));
-            let width = try!(c2_str.parse::<u32>().into_image_error(err));
+            let height = c1_str.parse::<u32>().into_image_error(err)?;
+            let width = c2_str.parse::<u32>().into_image_error(err)?;
             Ok((width, height))
         }
         _ => Err(ImageError::FormatError(format!(
             "Unsupported orientation {} {}",
             limit_string_len(c1_tag, 4),
             limit_string_len(c2_tag, 4)
         ))),
     } // final expression. Returns value
@@ -915,23 +912,23 @@ fn read_line_u8_test() {
 }
 
 /// Helper function for reading raw 3-channel f32 images
 pub fn read_raw_file<P: AsRef<Path>>(path: P) -> ::std::io::Result<Vec<Rgb<f32>>> {
     use byteorder::{LittleEndian as LE, ReadBytesExt};
     use std::fs::File;
     use std::io::BufReader;
 
-    let mut r = BufReader::new(try!(File::open(path)));
-    let w = try!(r.read_u32::<LE>()) as usize;
-    let h = try!(r.read_u32::<LE>()) as usize;
-    let c = try!(r.read_u32::<LE>()) as usize;
+    let mut r = BufReader::new(File::open(path)?);
+    let w = r.read_u32::<LE>()? as usize;
+    let h = r.read_u32::<LE>()? as usize;
+    let c = r.read_u32::<LE>()? as usize;
     assert_eq!(c, 3);
     let cnt = w * h;
     let mut ret = Vec::with_capacity(cnt);
     for _ in 0..cnt {
-        let cr = try!(r.read_f32::<LE>());
-        let cg = try!(r.read_f32::<LE>());
-        let cb = try!(r.read_f32::<LE>());
+        let cr = r.read_f32::<LE>()?;
+        let cg = r.read_f32::<LE>()?;
+        let cb = r.read_f32::<LE>()?;
         ret.push(Rgb([cr, cg, cb]));
     }
     Ok(ret)
 }
rename from third_party/rust/image/src/hdr/hdr_encoder.rs
rename to third_party/rust/image/src/hdr/encoder.rs
--- a/third_party/rust/image/src/hdr/hdr_encoder.rs
+++ b/third_party/rust/image/src/hdr/encoder.rs
@@ -13,25 +13,25 @@ impl<W: Write> HDREncoder<W> {
         HDREncoder { w }
     }
 
     /// Encodes the image ```data```
     /// that has dimensions ```width``` and ```height```
     pub fn encode(mut self, data: &[Rgb<f32>], width: usize, height: usize) -> Result<()> {
         assert!(data.len() >= width * height);
         let w = &mut self.w;
-        try!(w.write_all(SIGNATURE));
-        try!(w.write_all(b"\n"));
-        try!(w.write_all(b"# Rust HDR encoder\n"));
-        try!(w.write_all(b"FORMAT=32-bit_rle_rgbe\n\n"));
-        try!(w.write_all(format!("-Y {} +X {}\n", height, width).as_bytes()));
+        w.write_all(SIGNATURE)?;
+        w.write_all(b"\n")?;
+        w.write_all(b"# Rust HDR encoder\n")?;
+        w.write_all(b"FORMAT=32-bit_rle_rgbe\n\n")?;
+        w.write_all(format!("-Y {} +X {}\n", height, width).as_bytes())?;
 
         if width < 8 || width > 32_768 {
             for &pix in data {
-                try!(write_rgbe8(w, to_rgbe8(pix)));
+                write_rgbe8(w, to_rgbe8(pix))?;
             }
         } else {
             // new RLE marker contains scanline width
             let marker = rgbe8(2, 2, (width / 256) as u8, (width % 256) as u8);
             // buffers for encoded pixels
             let mut bufr = Vec::with_capacity(width);
             bufr.resize(width, 0);
             let mut bufg = Vec::with_capacity(width);
@@ -49,29 +49,29 @@ impl<W: Write> HDREncoder<W> {
                     .zip(scanline.iter())
                 {
                     let cp = to_rgbe8(pix);
                     *r = cp.c[0];
                     *g = cp.c[1];
                     *b = cp.c[2];
                     *e = cp.e;
                 }
-                try!(write_rgbe8(w, marker)); // New RLE encoding marker
+                write_rgbe8(w, marker)?; // New RLE encoding marker
                 rle_buf.clear();
                 rle_compress(&bufr[..], &mut rle_buf);
-                try!(w.write_all(&rle_buf[..]));
+                w.write_all(&rle_buf[..])?;
                 rle_buf.clear();
                 rle_compress(&bufg[..], &mut rle_buf);
-                try!(w.write_all(&rle_buf[..]));
+                w.write_all(&rle_buf[..])?;
                 rle_buf.clear();
                 rle_compress(&bufb[..], &mut rle_buf);
-                try!(w.write_all(&rle_buf[..]));
+                w.write_all(&rle_buf[..])?;
                 rle_buf.clear();
                 rle_compress(&bufe[..], &mut rle_buf);
-                try!(w.write_all(&rle_buf[..]));
+                w.write_all(&rle_buf[..])?;
             }
         }
         Ok(())
     }
 }
 
 #[derive(Debug, PartialEq, Eq)]
 enum RunOrNot {
@@ -221,17 +221,17 @@ fn rle_compress(data: &[u8], rle: &mut V
 }
 
 fn write_rgbe8<W: Write>(w: &mut W, v: RGBE8Pixel) -> Result<()> {
     w.write_all(&[v.c[0], v.c[1], v.c[2], v.e])
 }
 
 /// Converts ```Rgb<f32>``` into ```RGBE8Pixel```
 pub fn to_rgbe8(pix: Rgb<f32>) -> RGBE8Pixel {
-    let pix = pix.data;
+    let pix = pix.0;
     let mx = f32::max(pix[0], f32::max(pix[1], pix[2]));
     if mx <= 0.0 {
         RGBE8Pixel { c: [0, 0, 0], e: 0 }
     } else {
         // let (frac, exp) = mx.frexp(); // unstable yet
         let exp = mx.log2().floor() as i32 + 1;
         let mul = f32::powi(2.0, exp);
         let mut conv = [0u8; 3];
@@ -269,23 +269,23 @@ fn to_rgbe8_test() {
             // exponent can be -128 (represented as 0u8), so some colors cannot be represented in normalized f32
             // Let's exclude exponent value of -128 (0u8) from testing
             let pix = rgbe8(1, mc, c, if c == 0 { 1 } else { c });
             assert_eq!(pix, to_rgbe8(pix.to_hdr()));
         }
     }
     fn relative_dist(a: Rgb<f32>, b: Rgb<f32>) -> f32 {
         // maximal difference divided by maximal value
-        let max_diff = a.data
+        let max_diff = a.0
             .iter()
-            .zip(b.data.iter())
+            .zip(b.0.iter())
             .fold(0.0, |diff, (&a, &b)| f32::max(diff, (a - b).abs()));
-        let max_val = a.data
+        let max_val = a.0
             .iter()
-            .chain(b.data.iter())
+            .chain(b.0.iter())
             .fold(0.0, |maxv, &a| f32::max(maxv, a));
         if max_val == 0.0 {
             0.0
         } else {
             max_diff / max_val
         }
     }
     let test_values = vec![
--- a/third_party/rust/image/src/hdr/mod.rs
+++ b/third_party/rust/image/src/hdr/mod.rs
@@ -3,15 +3,13 @@
 //!  A decoder for Radiance HDR images
 //!
 //!  # Related Links
 //!
 //!  * <http://radsite.lbl.gov/radiance/refer/filefmts.pdf>
 //!  * <http://www.graphics.cornell.edu/~bjw/rgbe/rgbe.c>
 //!
 
-extern crate scoped_threadpool;
+mod decoder;
+mod encoder;
 
-mod hdr_decoder;
-mod hdr_encoder;
-
-pub use self::hdr_decoder::*;
-pub use self::hdr_encoder::*;
+pub use self::decoder::*;
+pub use self::encoder::*;
--- a/third_party/rust/image/src/ico/decoder.rs
+++ b/third_party/rust/image/src/ico/decoder.rs
@@ -1,10 +1,12 @@
 use byteorder::{LittleEndian, ReadBytesExt};
-use std::io::{Cursor, Read, Seek, SeekFrom};
+use std::io::{self, Cursor, Read, Seek, SeekFrom};
+use std::marker::PhantomData;
+use std::mem;
 
 use color::ColorType;
 use image::{ImageDecoder, ImageError, ImageResult};
 
 use self::InnerDecoder::*;
 use bmp::BMPDecoder;
 use png::PNGDecoder;
 
@@ -35,70 +37,70 @@ struct DirEntry {
 
     image_length: u32,
     image_offset: u32,
 }
 
 impl<R: Read + Seek> ICODecoder<R> {
     /// Create a new decoder that decodes from the stream ```r```
     pub fn new(mut r: R) -> ImageResult<ICODecoder<R>> {
-        let entries = try!(read_entries(&mut r));
-        let entry = try!(best_entry(entries));
-        let decoder = try!(entry.decoder(r));
+        let entries = read_entries(&mut r)?;
+        let entry = best_entry(entries)?;
+        let decoder = entry.decoder(r)?;
 
         Ok(ICODecoder {
             selected_entry: entry,
             inner_decoder: decoder,
         })
     }
 }
 
 fn read_entries<R: Read>(r: &mut R) -> ImageResult<Vec<DirEntry>> {
-    let _reserved = try!(r.read_u16::<LittleEndian>());
-    let _type = try!(r.read_u16::<LittleEndian>());
-    let count = try!(r.read_u16::<LittleEndian>());
+    let _reserved = r.read_u16::<LittleEndian>()?;
+    let _type = r.read_u16::<LittleEndian>()?;
+    let count = r.read_u16::<LittleEndian>()?;
     (0..count).map(|_| read_entry(r)).collect()
 }
 
 fn read_entry<R: Read>(r: &mut R) -> ImageResult<DirEntry> {
     let mut entry = DirEntry::default();
 
-    entry.width = try!(r.read_u8());
-    entry.height = try!(r.read_u8());
-    entry.color_count = try!(r.read_u8());
+    entry.width = r.read_u8()?;
+    entry.height = r.read_u8()?;
+    entry.color_count = r.read_u8()?;
     // Reserved value (not used)
-    entry.reserved = try!(r.read_u8());
+    entry.reserved = r.read_u8()?;
 
     // This may be either the number of color planes (0 or 1), or the horizontal coordinate
     // of the hotspot for CUR files.
-    entry.num_color_planes = try!(r.read_u16::<LittleEndian>());
+    entry.num_color_planes = r.read_u16::<LittleEndian>()?;
     if entry.num_color_planes > 256 {
         return Err(ImageError::FormatError(
             "ICO image entry has a too large color planes/hotspot value".to_string(),
         ));
     }
 
     // This may be either the bit depth (may be 0 meaning unspecified),
     // or the vertical coordinate of the hotspot for CUR files.
-    entry.bits_per_pixel = try!(r.read_u16::<LittleEndian>());
+    entry.bits_per_pixel = r.read_u16::<LittleEndian>()?;
     if entry.bits_per_pixel > 256 {
         return Err(ImageError::FormatError(
             "ICO image entry has a too large bits per pixel/hotspot value".to_string(),
         ));
     }
 
-    entry.image_length = try!(r.read_u32::<LittleEndian>());
-    entry.image_offset = try!(r.read_u32::<LittleEndian>());
+    entry.image_length = r.read_u32::<LittleEndian>()?;
+    entry.image_offset = r.read_u32::<LittleEndian>()?;
 
     Ok(entry)
 }
 
 /// Find the entry with the highest (color depth, size).
 fn best_entry(mut entries: Vec<DirEntry>) -> ImageResult<DirEntry> {
-    let mut best = try!(entries.pop().ok_or(ImageError::ImageEnd));
+    let mut best = entries.pop().ok_or(ImageError::ImageEnd)?;
     let mut best_score = (
         best.bits_per_pixel,
         u32::from(best.real_width()) * u32::from(best.real_height()),
     );
 
     for entry in entries {
         let score = (
             entry.bits_per_pixel,
@@ -127,61 +129,77 @@ impl DirEntry {
         }
     }
 
     fn matches_dimensions(&self, width: u64, height: u64) -> bool {
         u64::from(self.real_width()) == width && u64::from(self.real_height()) == height
     }
 
     fn seek_to_start<R: Read + Seek>(&self, r: &mut R) -> ImageResult<()> {
-        try!(r.seek(SeekFrom::Start(u64::from(self.image_offset))));
+        r.seek(SeekFrom::Start(u64::from(self.image_offset)))?;
         Ok(())
     }
 
     fn is_png<R: Read + Seek>(&self, r: &mut R) -> ImageResult<bool> {
-        try!(self.seek_to_start(r));
+        self.seek_to_start(r)?;
 
         // Read the first 8 bytes to sniff the image.
         let mut signature = [0u8; 8];
-        try!(r.read_exact(&mut signature));
+        r.read_exact(&mut signature)?;
 
         Ok(signature == PNG_SIGNATURE)
     }
 
     fn decoder<R: Read + Seek>(&self, mut r: R) -> ImageResult<InnerDecoder<R>> {
-        let is_png = try!(self.is_png(&mut r));
-        try!(self.seek_to_start(&mut r));
+        let is_png = self.is_png(&mut r)?;
+        self.seek_to_start(&mut r)?;
 
         if is_png {
             Ok(PNG(PNGDecoder::new(r)?))
         } else {
             Ok(BMP(BMPDecoder::new_with_ico_format(r)?))
         }
     }
 }
 
-impl<R: Read + Seek> ImageDecoder for ICODecoder<R> {
-    type Reader = Cursor<Vec<u8>>;
+/// Wrapper struct around a `Cursor<Vec<u8>>`
+pub struct IcoReader<R>(Cursor<Vec<u8>>, PhantomData<R>);
+impl<R> Read for IcoReader<R> {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        self.0.read(buf)
+    }
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
+        if self.0.position() == 0 && buf.is_empty() {
+            mem::swap(buf, self.0.get_mut());
+            Ok(buf.len())
+        } else {
+            self.0.read_to_end(buf)
+        }
+    }
+}
+
+impl<'a, R: 'a + Read + Seek> ImageDecoder<'a> for ICODecoder<R> {
+    type Reader = IcoReader<R>;
 
     fn dimensions(&self) -> (u64, u64) {
         match self.inner_decoder {
             BMP(ref decoder) => decoder.dimensions(),
             PNG(ref decoder) => decoder.dimensions(),
         }
     }
 
     fn colortype(&self) -> ColorType {
         match self.inner_decoder {
             BMP(ref decoder) => decoder.colortype(),
             PNG(ref decoder) => decoder.colortype(),
         }
     }
 
     fn into_reader(self) -> ImageResult<Self::Reader> {
-        Ok(Cursor::new(self.read_image()?))
+        Ok(IcoReader(Cursor::new(self.read_image()?), PhantomData))
     }
 
     fn read_image(self) -> ImageResult<Vec<u8>> {
         match self.inner_decoder {
             PNG(decoder) => {
                 if self.selected_entry.image_length < PNG_SIGNATURE.len() as u32 {
                     return Err(ImageError::FormatError(
                         "Entry specified a length that is shorter than PNG header!".to_string(),
@@ -222,34 +240,34 @@ impl<R: Read + Seek> ImageDecoder for IC
                         "Unsupported color type".to_string(),
                     ));
                 }
 
                 let mut pixel_data = decoder.read_image_data()?;
 
                 // If there's an AND mask following the image, read and apply it.
                 let r = decoder.reader();
-                let mask_start = try!(r.seek(SeekFrom::Current(0)));
+                let mask_start = r.seek(SeekFrom::Current(0))?;
                 let mask_end =
                     u64::from(self.selected_entry.image_offset + self.selected_entry.image_length);
                 let mask_length = mask_end - mask_start;
 
                 if mask_length > 0 {
                     // A mask row contains 1 bit per pixel, padded to 4 bytes.
                     let mask_row_bytes = ((width + 31) / 32) * 4;
                     let expected_length = u64::from(mask_row_bytes * height);
                     if mask_length < expected_length {
                         return Err(ImageError::ImageEnd);
                     }
 
                     for y in 0..height {
                         let mut x = 0;
                         for _ in 0..mask_row_bytes {
                             // Apply the bits of each byte until we reach the end of the row.
-                            let mask_byte = try!(r.read_u8());
+                            let mask_byte = r.read_u8()?;
                             for bit in (0..8).rev() {
                                 if x >= width {
                                     break;
                                 }
                                 if mask_byte & (1 << bit) != 0 {
                                     // Set alpha channel to transparent.
                                     pixel_data[((height - y - 1) * width + x) as usize * 4 + 3] = 0;
                                 }
--- a/third_party/rust/image/src/ico/encoder.rs
+++ b/third_party/rust/image/src/ico/encoder.rs
@@ -29,65 +29,65 @@ impl<W: Write> ICOEncoder<W> {
     pub fn encode(
         mut self,
         data: &[u8],
         width: u32,
         height: u32,
         color: ColorType,
     ) -> io::Result<()> {
         let mut image_data: Vec<u8> = Vec::new();
-        try!(PNGEncoder::new(&mut image_data).encode(data, width, height, color));
+        PNGEncoder::new(&mut image_data).encode(data, width, height, color)?;
 
-        try!(write_icondir(&mut self.w, 1));
+        write_icondir(&mut self.w, 1)?;
         try!(write_direntry(
             &mut self.w,
             width,
             height,
             color,
             ICO_ICONDIR_SIZE + ICO_DIRENTRY_SIZE,
             image_data.len() as u32
         ));
-        try!(self.w.write_all(&image_data));
+        self.w.write_all(&image_data)?;
         Ok(())
     }
 }
 
 fn write_icondir<W: Write>(w: &mut W, num_images: u16) -> io::Result<()> {
     // Reserved field (must be zero):
-    try!(w.write_u16::<LittleEndian>(0));
+    w.write_u16::<LittleEndian>(0)?;
     // Image type (ICO or CUR):
-    try!(w.write_u16::<LittleEndian>(ICO_IMAGE_TYPE));
+    w.write_u16::<LittleEndian>(ICO_IMAGE_TYPE)?;
     // Number of images in the file:
-    try!(w.write_u16::<LittleEndian>(num_images));
+    w.write_u16::<LittleEndian>(num_images)?;
     Ok(())
 }
 
 fn write_direntry<W: Write>(
     w: &mut W,
     width: u32,
     height: u32,
     color: ColorType,
     data_start: u32,
     data_size: u32,
 ) -> io::Result<()> {
     // Image dimensions:
-    try!(write_width_or_height(w, width));
-    try!(write_width_or_height(w, height));
+    write_width_or_height(w, width)?;
+    write_width_or_height(w, height)?;
     // Number of colors in palette (or zero for no palette):
-    try!(w.write_u8(0));
+    w.write_u8(0)?;
     // Reserved field (must be zero):
-    try!(w.write_u8(0));
+    w.write_u8(0)?;
     // Color planes:
-    try!(w.write_u16::<LittleEndian>(0));
+    w.write_u16::<LittleEndian>(0)?;
     // Bits per pixel:
-    try!(w.write_u16::<LittleEndian>(bits_per_pixel(color) as u16));
+    w.write_u16::<LittleEndian>(bits_per_pixel(color) as u16)?;
     // Image data size, in bytes:
-    try!(w.write_u32::<LittleEndian>(data_size));
+    w.write_u32::<LittleEndian>(data_size)?;
     // Image data offset, in bytes:
-    try!(w.write_u32::<LittleEndian>(data_start));
+    w.write_u32::<LittleEndian>(data_start)?;
     Ok(())
 }
 
 /// Encode a width/height value as a single byte, where 0 means 256.
 fn write_width_or_height<W: Write>(w: &mut W, value: u32) -> io::Result<()> {
     if value < 1 || value > 256 {
         return Err(io::Error::new(
             io::ErrorKind::InvalidData,
--- a/third_party/rust/image/src/image.rs
+++ b/third_party/rust/image/src/image.rs
@@ -1,13 +1,12 @@
 use std::error::Error;
 use std::fmt;
 use std::io;
 use std::io::Read;
-use std::mem;
 use std::ops::{Deref, DerefMut};
 
 use buffer::{ImageBuffer, Pixel};
 use color;
 use color::ColorType;
 
 use animation::Frames;
 
@@ -85,17 +84,17 @@ impl Error for ImageError {
             ImageError::UnsupportedColor(..) => "Unsupported color",
             ImageError::NotEnoughData => "Not enough data",
             ImageError::IoError(..) => "IO error",
             ImageError::ImageEnd => "Image end",
             ImageError::InsufficientMemory => "Insufficient memory",
         }
     }
 
-    fn cause(&self) -> Option<&Error> {
+    fn cause(&self) -> Option<&dyn Error> {
         match *self {
             ImageError::IoError(ref e) => Some(e),
             _ => None,
         }
     }
 }
 
 impl From<io::Error> for ImageError {
@@ -259,22 +258,22 @@ impl ImageReadBuffer {
             self.consumed = self.buffer.len();
             Ok(bytes_buffered)
         }
     }
 }
 
 /// Decodes a specific region of the image, represented by the rectangle
 /// starting from ```x``` and ```y``` and having ```length``` and ```width```
-pub(crate) fn load_rect<D, F, F1, F2>(x: u64, y: u64, width: u64, height: u64, buf: &mut [u8],
-                                      progress_callback: F,
-                                      decoder: &mut D,
-                                      mut seek_scanline: F1,
-                                      mut read_scanline: F2) -> ImageResult<()>
-    where D: ImageDecoder,
+pub(crate) fn load_rect<'a, D, F, F1, F2>(x: u64, y: u64, width: u64, height: u64, buf: &mut [u8],
+                                          progress_callback: F,
+                                          decoder: &mut D,
+                                          mut seek_scanline: F1,
+                                          mut read_scanline: F2) -> ImageResult<()>
+    where D: ImageDecoder<'a>,
           F: Fn(Progress),
           F1: FnMut(&mut D, u64) -> io::Result<()>,
           F2: FnMut(&mut D, &mut [u8]) -> io::Result<usize>
 {
     let dimensions = decoder.dimensions();
     let row_bytes = decoder.row_bytes();
     let scanline_bytes = decoder.scanline_bytes();
     let bits_per_pixel = color::bits_per_pixel(decoder.colortype()) as u64;
@@ -354,19 +353,19 @@ pub(crate) fn load_rect<D, F, F1, F2>(x:
 /// Represents the progress of an image operation.
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 pub struct Progress {
     current: u64,
     total: u64,
 }
 
 /// The trait that all decoders implement
-pub trait ImageDecoder: Sized {
+pub trait ImageDecoder<'a>: Sized {
     /// The type of reader produced by `into_reader`.
-    type Reader: Read;
+    type Reader: Read + 'a;
 
     /// Returns a tuple containing the width and height of the image
     fn dimensions(&self) -> (u64, u64);
 
     /// Returns the color type of the image e.g. RGB(8) (8bit RGB)
     fn colortype(&self) -> ColorType;
 
     /// Returns a reader that can be used to obtain the bytes of the image. For the best
@@ -430,17 +429,17 @@ pub trait ImageDecoder: Sized {
             });
         }
 
         Ok(contents)
     }
 }
 
 /// ImageDecoderExt trait
-pub trait ImageDecoderExt: ImageDecoder + Sized {
+pub trait ImageDecoderExt<'a>: ImageDecoder<'a> + Sized {
     /// Read a rectangular section of the image.
     fn read_rect(
         &mut self,
         x: u64,
         y: u64,
         width: u64,
         height: u64,
         buf: &mut [u8],
@@ -492,58 +491,16 @@ impl<'a, I: GenericImageView> Iterator f
 
             self.x += 1;
 
             Some(p)
         }
     }
 }
 
-/// Mutable pixel iterator
-///
-/// DEPRECATED: It is currently not possible to create a safe iterator for this in Rust. You have to use an iterator over the image buffer instead.
-pub struct MutPixels<'a, I: ?Sized + 'a> {
-    image: &'a mut I,
-    x: u32,
-    y: u32,
-    width: u32,
-    height: u32,
-}
-
-impl<'a, I: GenericImage + 'a> Iterator for MutPixels<'a, I>
-where
-    I::Pixel: 'a,
-    <I::Pixel as Pixel>::Subpixel: 'a,
-{
-    type Item = (u32, u32, &'a mut I::Pixel);
-
-    fn next(&mut self) -> Option<(u32, u32, &'a mut I::Pixel)> {
-        if self.x >= self.width {
-            self.x = 0;
-            self.y += 1;
-        }
-
-        if self.y >= self.height {
-            None
-        } else {
-            let tmp = self.image.get_pixel_mut(self.x, self.y);
-
-            // NOTE: This is potentially dangerous. It would require the signature fn next(&'a mut self) to be safe.
-            // error: lifetime of `self` is too short to guarantee its contents can be safely reborrowed...
-            let ptr = unsafe { mem::transmute(tmp) };
-
-            let p = (self.x, self.y, ptr);
-
-            self.x += 1;
-
-            Some(p)
-        }
-    }
-}
-
 /// Trait to inspect an image.
 pub trait GenericImageView {
     /// The type of pixel.
     type Pixel: Pixel;
 
     /// Underlying image type. This is mainly used by SubImages in order to
     /// always have a reference to the original image. This allows for less
     /// indirections and it eases the use of nested SubImages.
@@ -580,16 +537,17 @@ pub trait GenericImageView {
     /// Panics if `(x, y)` is out of bounds.
     ///
     /// TODO: change this signature to &P
     fn get_pixel(&self, x: u32, y: u32) -> Self::Pixel;
 
     /// Returns the pixel located at (x, y)
     ///
     /// This function can be implemented in a way that ignores bounds checking.
+    #[deprecated = "Generally offers little advantage over get_pixel. If you must, prefer dedicated methods or other realizations on the specific image type instead."]
     unsafe fn unsafe_get_pixel(&self, x: u32, y: u32) -> Self::Pixel {
         self.get_pixel(x, y)
     }
 
     /// Returns an Iterator over the pixels of this image.
     /// The iterator yields the coordinates of each pixel
     /// along with their value
     fn pixels(&self) -> Pixels<Self> {
@@ -632,43 +590,26 @@ pub trait GenericImage: GenericImageView
     /// # Panics
     ///
     /// Panics if `(x, y)` is out of bounds.
     fn put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel);
 
     /// Puts a pixel at location (x, y)
     ///
     /// This function can be implemented in a way that ignores bounds checking.
+    #[deprecated = "Generally offers little advantage over put_pixel. If you must, prefer dedicated methods or other realizations on the specific image type instead."]
     unsafe fn unsafe_put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel) {
         self.put_pixel(x, y, pixel);
     }
 
     /// Put a pixel at location (x, y), taking into account alpha channels
     ///
     /// DEPRECATED: This method will be removed. Blend the pixel directly instead.
     fn blend_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel);
 
-    /// Returns an Iterator over mutable pixels of this image.
-    /// The iterator yields the coordinates of each pixel
-    /// along with a mutable reference to them.
-    #[deprecated(
-        note = "This cannot be implemented safely in Rust. Please use the image buffer directly."
-    )]
-    fn pixels_mut(&mut self) -> MutPixels<Self> {
-        let (width, height) = self.dimensions();
-
-        MutPixels {
-            image: self,
-            x: 0,
-            y: 0,
-            width,
-            height,
-        }
-    }
-
     /// Copies all of the pixels from another image into this image.
     ///
     /// The other image is copied with the top-left corner of the
     /// other image placed at (x, y).
     ///
     /// In order to copy only a piece of the other image, use `sub_image`.
     ///
     /// # Returns
@@ -681,20 +622,18 @@ pub trait GenericImage: GenericImageView
         // Do bounds checking here so we can use the non-bounds-checking
         // functions to copy pixels.
         if self.width() < other.width() + x || self.height() < other.height() + y {
             return false;
         }
 
         for i in 0..other.width() {
             for k in 0..other.height() {
-                unsafe {
-                    let p = other.unsafe_get_pixel(i, k);
-                    self.unsafe_put_pixel(i + x, k + y, p);
-                }
+                let p = other.get_pixel(i, k);
+                self.put_pixel(i + x, k + y, p);
             }
         }
         true
     }
 
     /// Returns a mutable reference to the underlying image.
     fn inner_mut(&mut self) -> &mut Self::InnerImage;
 
@@ -834,18 +773,19 @@ where
 
     fn inner_mut(&mut self) -> &mut Self::InnerImage {
         &mut self.image
     }
 }
 
 #[cfg(test)]
 mod tests {
+    use std::io;
 
-    use super::{GenericImage, GenericImageView};
+    use super::{ColorType, ImageDecoder, ImageResult, GenericImage, GenericImageView, load_rect};
     use buffer::ImageBuffer;
     use color::Rgba;
 
     #[test]
     /// Test that alpha blending works as expected
     fn test_image_alpha_blending() {
         let mut target = ImageBuffer::new(1, 1);
         target.put_pixel(0, 0, Rgba([255u8, 0, 0, 255]));
@@ -908,21 +848,19 @@ mod tests {
         assert_eq!(*source.get_pixel(1, 1), view1.get_pixel(1, 1));
 
         let view2 = view1.view(1, 1, 1, 1);
         assert_eq!(*source.get_pixel(1, 1), view2.get_pixel(0, 0));
     }
 
     #[test]
     fn test_load_rect() {
-        use super::*;
-
         struct MockDecoder {scanline_number: u64, scanline_bytes: u64}
-        impl ImageDecoder for MockDecoder {
-            type Reader = Box<::std::io::Read>;
+        impl<'a> ImageDecoder<'a> for MockDecoder {
+            type Reader = Box<dyn io::Read>;
             fn dimensions(&self) -> (u64, u64) {(5, 5)}
             fn colortype(&self) -> ColorType {  ColorType::Gray(8) }
             fn into_reader(self) -> ImageResult<Self::Reader> {unimplemented!()}
             fn scanline_bytes(&self) -> u64 { self.scanline_bytes }
         }
 
         const DATA: [u8; 25] = [0,  1,  2,  3,  4,
                                 5,  6,  7,  8,  9,
--- a/third_party/rust/image/src/imageops/affine.rs
+++ b/third_party/rust/image/src/imageops/affine.rs
@@ -1,109 +1,94 @@
 //! Functions for performing affine transformations.
 
 use buffer::{ImageBuffer, Pixel};
 use image::GenericImageView;
 
 /// Rotate an image 90 degrees clockwise.
-// TODO: Is the 'static bound on `I` really required? Can we avoid it?
-pub fn rotate90<I: GenericImageView + 'static>(
+pub fn rotate90<I: GenericImageView>(
     image: &I,
 ) -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>>
-where
-    I::Pixel: 'static,
-    <I::Pixel as Pixel>::Subpixel: 'static,
+    where I::Pixel: 'static,
 {
     let (width, height) = image.dimensions();
     let mut out = ImageBuffer::new(height, width);
 
     for y in 0..height {
         for x in 0..width {
             let p = image.get_pixel(x, y);
             out.put_pixel(height - 1 - y, x, p);
         }
     }
 
     out
 }
 
 /// Rotate an image 180 degrees clockwise.
-// TODO: Is the 'static bound on `I` really required? Can we avoid it?
-pub fn rotate180<I: GenericImageView + 'static>(
+pub fn rotate180<I: GenericImageView>(
     image: &I,
 ) -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>>
-where
-    I::Pixel: 'static,
-    <I::Pixel as Pixel>::Subpixel: 'static,
+    where I::Pixel: 'static,
 {
     let (width, height) = image.dimensions();
     let mut out = ImageBuffer::new(width, height);
 
     for y in 0..height {
         for x in 0..width {
             let p = image.get_pixel(x, y);
             out.put_pixel(width - 1 - x, height - 1 - y, p);
         }
     }
 
     out
 }
 
 /// Rotate an image 270 degrees clockwise.
-// TODO: Is the 'static bound on `I` really required? Can we avoid it?
-pub fn rotate270<I: GenericImageView + 'static>(
+pub fn rotate270<I: GenericImageView>(
     image: &I,
 ) -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>>
-where
-    I::Pixel: 'static,
-    <I::Pixel as Pixel>::Subpixel: 'static,
+    where I::Pixel: 'static,
 {
     let (width, height) = image.dimensions();
     let mut out = ImageBuffer::new(height, width);
 
     for y in 0..height {
         for x in 0..width {
             let p = image.get_pixel(x, y);
             out.put_pixel(y, width - 1 - x, p);
         }
     }
 
     out
 }
 
 /// Flip an image horizontally
-// TODO: Is the 'static bound on `I` really required? Can we avoid it?
-pub fn flip_horizontal<I: GenericImageView + 'static>(
+pub fn flip_horizontal<I: GenericImageView>(
     image: &I,
 ) -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>>
-where
-    I::Pixel: 'static,
-    <I::Pixel as Pixel>::Subpixel: 'static,
+    where I::Pixel: 'static,
 {
     let (width, height) = image.dimensions();
     let mut out = ImageBuffer::new(width, height);
 
     for y in 0..height {
         for x in 0..width {
             let p = image.get_pixel(x, y);
             out.put_pixel(width - 1 - x, y, p);
         }
     }
 
     out
 }
 
 /// Flip an image vertically
-// TODO: Is the 'static bound on `I` really required? Can we avoid it?
-pub fn flip_vertical<I: GenericImageView + 'static>(
+pub fn flip_vertical<I: GenericImageView>(
     image: &I,
 ) -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>>
-where
-    I::Pixel: 'static,
-    <I::Pixel as Pixel>::Subpixel: 'static,
+    where I::Pixel: 'static,
 {
     let (width, height) = image.dimensions();
     let mut out = ImageBuffer::new(width, height);
 
     for y in 0..height {
         for x in 0..width {
             let p = image.get_pixel(x, y);
             out.put_pixel(x, height - 1 - y, p);
--- a/third_party/rust/image/src/imageops/colorops.rs
+++ b/third_party/rust/image/src/imageops/colorops.rs
@@ -191,28 +191,28 @@ pub trait ColorMap {
 #[derive(Clone, Copy)]
 pub struct BiLevel;
 
 impl ColorMap for BiLevel {
     type Color = Luma<u8>;
 
     #[inline(always)]
     fn index_of(&self, color: &Luma<u8>) -> usize {
-        let luma = color.data;
+        let luma = color.0;
         if luma[0] > 127 {
             1
         } else {
             0
         }
     }
 
     #[inline(always)]
     fn map_color(&self, color: &mut Luma<u8>) {
         let new_color = 0xFF * self.index_of(color) as u8;
-        let luma = &mut color.data;
+        let luma = &mut color.0;
         luma[0] = new_color;
     }
 }
 
 impl ColorMap for nq::NeuQuant {
     type Color = Rgba<u8>;
 
     #[inline(always)]
--- a/third_party/rust/image/src/imageops/mod.rs
+++ b/third_party/rust/image/src/imageops/mod.rs
@@ -112,17 +112,21 @@ pub fn overlay_bounds(
         .saturating_sub(x); // Determinate length from start `x`
     let y_range = top_height.saturating_add(y)
         .min(bottom_height)
         .saturating_sub(y);
     (x_range, y_range)
 }
 
 /// Overlay an image at a given coordinate (x, y)
-pub fn overlay<I: GenericImage>(bottom: &mut I, top: &I, x: u32, y: u32) {
+pub fn overlay<I, J>(bottom: &mut I, top: &J, x: u32, y: u32)
+where
+    I: GenericImage,
+    J: GenericImageView<Pixel = I::Pixel>,
+{
     let bottom_dims = bottom.dimensions();
     let top_dims = top.dimensions();
 
     // Crop our top image if we're going out of bounds
     let (range_width, range_height) = overlay_bounds(bottom_dims, top_dims, x, y);
 
     for top_y in 0..range_height {
         for top_x in 0..range_width {
@@ -131,17 +135,21 @@ pub fn overlay<I: GenericImage>(bottom: 
             bottom_pixel.blend(&p);
 
             bottom.put_pixel(x + top_x, y + top_y, bottom_pixel);
         }
     }
 }
 
 /// Replace the contents of an image at a given coordinate (x, y)
-pub fn replace<I: GenericImage>(bottom: &mut I, top: &I, x: u32, y: u32) {
+pub fn replace<I, J>(bottom: &mut I, top: &J, x: u32, y: u32)
+where
+    I: GenericImage,
+    J: GenericImageView<Pixel = I::Pixel>,
+{
     let bottom_dims = bottom.dimensions();
     let top_dims = top.dimensions();
 
     // Crop our top image if we're going out of bounds
     let (range_width, range_height) = overlay_bounds(bottom_dims, top_dims, x, y);
 
     for top_y in 0..range_height {
         for top_x in 0..range_width {
--- a/third_party/rust/image/src/imageops/sample.rs
+++ b/third_party/rust/image/src/imageops/sample.rs
@@ -8,17 +8,17 @@ use std::f32;
 use num_traits::{NumCast, ToPrimitive, Zero};
 
 use buffer::{ImageBuffer, Pixel};
 use image::GenericImageView;
 use math::utils::clamp;
 use traits::{Enlargeable, Primitive};
 
 /// Available Sampling Filters
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 pub enum FilterType {
     /// Nearest Neighbor
     Nearest,
 
     /// Linear Filter
     Triangle,
 
     /// Cubic Filter
@@ -29,17 +29,17 @@ pub enum FilterType {
 
     /// Lanczos with window 3
     Lanczos3,
 }
 
 /// A Representation of a separable filter.
 pub struct Filter<'a> {
     /// The filter's filter function.
-    pub kernel: Box<Fn(f32) -> f32 + 'a>,
+    pub kernel: Box<dyn Fn(f32) -> f32 + 'a>,
 
     /// The window on which this filter operates.
     pub support: f32,
 }
 
 // sinc function: the ideal sampling filter.
 fn sinc(t: f32) -> f32 {
     let a = t * f32::consts::PI;
@@ -117,24 +117,23 @@ pub fn triangle_kernel(x: f32) -> f32 {
 pub fn box_kernel(_x: f32) -> f32 {
     1.0
 }
 
 // Sample the rows of the supplied image using the provided filter.
 // The height of the image remains unchanged.
 // ```new_width``` is the desired width of the new image
 // ```filter``` is the filter to use for sampling.
-// TODO: Do we really need the 'static bound on `I`? Can we avoid it?
 fn horizontal_sample<I, P, S>(
     image: &I,
     new_width: u32,
     filter: &mut Filter,
 ) -> ImageBuffer<P, Vec<S>>
 where
-    I: GenericImageView<Pixel = P> + 'static,
+    I: GenericImageView<Pixel = P>,
     P: Pixel<Subpixel = S> + 'static,
     S: Primitive + 'static,
 {
     let (width, height) = image.dimensions();
     let mut out = ImageBuffer::new(new_width, height);
     let mut ws = Vec::new();
 
     let max: f32 = NumCast::from(S::max_value()).unwrap();
@@ -209,24 +208,23 @@ where
 
     out
 }
 
 // Sample the columns of the supplied image using the provided filter.
 // The width of the image remains unchanged.
 // ```new_height``` is the desired height of the new image
 // ```filter``` is the filter to use for sampling.
-// TODO: Do we really need the 'static bound on `I`? Can we avoid it?
 fn vertical_sample<I, P, S>(
     image: &I,
     new_height: u32,
     filter: &mut Filter,
 ) -> ImageBuffer<P, Vec<S>>
 where
-    I: GenericImageView<Pixel = P> + 'static,
+    I: GenericImageView<Pixel = P>,
     P: Pixel<Subpixel = S> + 'static,
     S: Primitive + 'static,
 {
     let (width, height) = image.dimensions();
     let mut out = ImageBuffer::new(width, new_height);
     let mut ws = Vec::new();
 
     let max: f32 = NumCast::from(S::max_value()).unwrap();
@@ -561,20 +559,19 @@ where
         mix(k_br.1, k_tr.1, k_bl.1, k_tl.1),
         mix(k_br.2, k_tr.2, k_bl.2, k_tl.2),
         mix(k_br.3, k_tr.3, k_bl.3, k_tl.3),
     )
 }
 
 /// Perform a 3x3 box filter on the supplied image.
 /// ```kernel``` is an array of the filter weights of length 9.
-// TODO: Do we really need the 'static bound on `I`? Can we avoid it?
 pub fn filter3x3<I, P, S>(image: &I, kernel: &[f32]) -> ImageBuffer<P, Vec<S>>
 where
-    I: GenericImageView<Pixel = P> + 'static,
+    I: GenericImageView<Pixel = P>,
     P: Pixel<Subpixel = S> + 'static,
     S: Primitive + 'static,
 {
     // The kernel's input positions relative to the current pixel.
     let taps: &[(isize, isize)] = &[
         (-1, -1),
         (0, -1),
         (1, -1),
@@ -642,18 +639,17 @@ where
     }
 
     out
 }
 
 /// Resize the supplied image to the specified dimensions.
 /// ```nwidth``` and ```nheight``` are the new dimensions.
 /// ```filter``` is the sampling filter to use.
-// TODO: Do we really need the 'static bound on `I`? Can we avoid it?
-pub fn resize<I: GenericImageView + 'static>(
+pub fn resize<I: GenericImageView>(
     image: &I,
     nwidth: u32,
     nheight: u32,
     filter: FilterType,
 ) -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>>
 where
     I::Pixel: 'static,
     <I::Pixel as Pixel>::Subpixel: 'static,
@@ -682,24 +678,22 @@ where
     };
 
     let tmp = vertical_sample(image, nheight, &mut method);
     horizontal_sample(&tmp, nwidth, &mut method)
 }
 
 /// Performs a Gaussian blur on the supplied image.
 /// ```sigma``` is a measure of how much to blur by.
-// TODO: Do we really need the 'static bound on `I`? Can we avoid it?
-pub fn blur<I: GenericImageView + 'static>(
+pub fn blur<I: GenericImageView>(
     image: &I,
     sigma: f32,
 ) -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>>
 where
     I::Pixel: 'static,
-    <I::Pixel as Pixel>::Subpixel: 'static,
 {
     let sigma = if sigma < 0.0 { 1.0 } else { sigma };
 
     let mut method = Filter {
         kernel: Box::new(|x| gaussian(x, sigma)),
         support: 2.0 * sigma,
     };
 
@@ -711,20 +705,19 @@ where
     horizontal_sample(&tmp, width, &mut method)
 }
 
 /// Performs an unsharpen mask on the supplied image.
 /// ```sigma``` is the amount to blur the image by.
 /// ```threshold``` is the threshold for the difference between
 ///
 /// See <https://en.wikipedia.org/wiki/Unsharp_masking#Digital_unsharp_masking>
-// TODO: Do we really need the 'static bound on `I`? Can we avoid it?
 pub fn unsharpen<I, P, S>(image: &I, sigma: f32, threshold: i32) -> ImageBuffer<P, Vec<S>>
 where
-    I: GenericImageView<Pixel = P> + 'static,
+    I: GenericImageView<Pixel = P>,
     P: Pixel<Subpixel = S> + 'static,
     S: Primitive + 'static,
 {
     let mut tmp = blur(image, sigma);
 
     let max = S::max_value();
     let max: i32 = NumCast::from(max).unwrap();
     let (width, height) = image.dimensions();
--- a/third_party/rust/image/src/jpeg/decoder.rs
+++ b/third_party/rust/image/src/jpeg/decoder.rs
@@ -1,11 +1,13 @@
 extern crate jpeg_decoder;
 
-use std::io::{Cursor, Read};
+use std::io::{self, Cursor, Read};
+use std::marker::PhantomData;
+use std::mem;
 
 use color::ColorType;
 use image::{ImageDecoder, ImageError, ImageResult};
 
 /// JPEG decoder
 pub struct JPEGDecoder<R> {
     decoder: jpeg_decoder::Decoder<R>,
     metadata: jpeg_decoder::ImageInfo,
@@ -26,29 +28,45 @@ impl<R: Read> JPEGDecoder<R> {
 
         Ok(JPEGDecoder {
             decoder,
             metadata,
         })
     }
 }
 
-impl<R: Read> ImageDecoder for JPEGDecoder<R> {
-    type Reader = Cursor<Vec<u8>>;
+/// Wrapper struct around a `Cursor<Vec<u8>>`
+pub struct JpegReader<R>(Cursor<Vec<u8>>, PhantomData<R>);
+impl<R> Read for JpegReader<R> {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        self.0.read(buf)
+    }
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
+        if self.0.position() == 0 && buf.is_empty() {
+            mem::swap(buf, self.0.get_mut());
+            Ok(buf.len())
+        } else {
+            self.0.read_to_end(buf)
+        }
+    }
+}
+
+impl<'a, R: 'a + Read> ImageDecoder<'a> for JPEGDecoder<R> {
+    type Reader = JpegReader<R>;
 
     fn dimensions(&self) -> (u64, u64) {
         (self.metadata.width as u64, self.metadata.height as u64)
     }
 
     fn colortype(&self) -> ColorType {
         self.metadata.pixel_format.into()
     }
 
     fn into_reader(self) -> ImageResult<Self::Reader> {
-        Ok(Cursor::new(self.read_image()?))
+        Ok(JpegReader(Cursor::new(self.read_image()?), PhantomData))
     }
 
     fn read_image(mut self) -> ImageResult<Vec<u8>> {
         let mut data = self.decoder.decode()?;
         data = match self.decoder.info().unwrap().pixel_format {
             jpeg_decoder::PixelFormat::CMYK32 => cmyk_to_rgb(&data),
             _ => data,
         };
--- a/third_party/rust/image/src/jpeg/encoder.rs
+++ b/third_party/rust/image/src/jpeg/encoder.rs
@@ -177,20 +177,20 @@ impl<'a, W: Write + 'a> BitWriter<'a, W>
             return Ok(());
         }
 
         self.accumulator |= u32::from(bits) << (32 - (self.nbits + size)) as usize;
         self.nbits += size;
 
         while self.nbits >= 8 {
             let byte = (self.accumulator & (0xFFFF_FFFFu32 << 24)) >> 24;
-            try!(self.w.write_all(&[byte as u8]));
+            self.w.write_all(&[byte as u8])?;
 
             if byte == 0xFF {
-                try!(self.w.write_all(&[0x00]));
+                self.w.write_all(&[0x00])?;
             }
 
             self.nbits -= 8;
             self.accumulator <<= 8;
         }
 
         Ok(())
     }
@@ -216,63 +216,63 @@ impl<'a, W: Write + 'a> BitWriter<'a, W>
         dctable: &[(u8, u16)],
         actable: &[(u8, u16)],
     ) -> io::Result<i32> {
         // Differential DC encoding
         let dcval = block[0];
         let diff = dcval - prevdc;
         let (size, value) = encode_coefficient(diff);
 
-        try!(self.huffman_encode(size, dctable));
-        try!(self.write_bits(value, size));
+        self.huffman_encode(size, dctable)?;
+        self.write_bits(value, size)?;
 
         // Figure F.2
         let mut zero_run = 0;
         let mut k = 0usize;
 
         loop {
             k += 1;
 
             if block[UNZIGZAG[k] as usize] == 0 {
                 if k == 63 {
-                    try!(self.huffman_encode(0x00, actable));
+                    self.huffman_encode(0x00, actable)?;
                     break;
                 }
 
                 zero_run += 1;
             } else {
                 while zero_run > 15 {
-                    try!(self.huffman_encode(0xF0, actable));
+                    self.huffman_encode(0xF0, actable)?;
                     zero_run -= 16;
                 }
 
                 let (size, value) = encode_coefficient(block[UNZIGZAG[k] as usize]);
                 let symbol = (zero_run << 4) | size;
 
-                try!(self.huffman_encode(symbol, actable));
-                try!(self.write_bits(value, size));
+                self.huffman_encode(symbol, actable)?;
+                self.write_bits(value, size)?;
 
                 zero_run = 0;
 
                 if k == 63 {
                     break;
                 }
             }
         }
 
         Ok(dcval)
     }
 
     fn write_segment(&mut self, marker: u8, data: Option<&[u8]>) -> io::Result<()> {
-        try!(self.w.write_all(&[0xFF]));
-        try!(self.w.write_all(&[marker]));
+        self.w.write_all(&[0xFF])?;
+        self.w.write_all(&[marker])?;
 
         if let Some(b) = data {
-            try!(self.w.write_u16::<BigEndian>(b.len() as u16 + 2));
-            try!(self.w.write_all(b));
+            self.w.write_u16::<BigEndian>(b.len() as u16 + 2)?;
+            self.w.write_all(b)?;
         }
         Ok(())
     }
 }
 
 /// The representation of a JPEG encoder
 pub struct JPEGEncoder<'a, W: 'a> {
     writer: BitWriter<'a, W>,
@@ -372,107 +372,107 @@ impl<'a, W: Write> JPEGEncoder<'a, W> {
         image: &[u8],
         width: u32,
         height: u32,
         c: color::ColorType,
     ) -> io::Result<()> {
         let n = color::num_components(c);
         let num_components = if n == 1 || n == 2 { 1 } else { 3 };
 
-        try!(self.writer.write_segment(SOI, None));
+        self.writer.write_segment(SOI, None)?;
 
         let mut buf = Vec::new();
 
         build_jfif_header(&mut buf);
-        try!(self.writer.write_segment(APP0, Some(&buf)));
+        self.writer.write_segment(APP0, Some(&buf))?;
 
         build_frame_header(
             &mut buf,
             8,
             width as u16,
             height as u16,
             &self.components[..num_components],
         );
-        try!(self.writer.write_segment(SOF0, Some(&buf)));
+        self.writer.write_segment(SOF0, Some(&buf))?;
 
         assert_eq!(self.tables.len() / 64, 2);
         let numtables = if num_components == 1 { 1 } else { 2 };
 
         for (i, table) in self.tables.chunks(64).enumerate().take(numtables) {
             build_quantization_segment(&mut buf, 8, i as u8, table);
-            try!(self.writer.write_segment(DQT, Some(&buf)));
+            self.writer.write_segment(DQT, Some(&buf))?;
         }
 
         build_huffman_segment(
             &mut buf,
             DCCLASS,
             LUMADESTINATION,
             &STD_LUMA_DC_CODE_LENGTHS,
             &STD_LUMA_DC_VALUES,
         );
-        try!(self.writer.write_segment(DHT, Some(&buf)));
+        self.writer.write_segment(DHT, Some(&buf))?;
 
         build_huffman_segment(
             &mut buf,
             ACCLASS,
             LUMADESTINATION,
             &STD_LUMA_AC_CODE_LENGTHS,
             &STD_LUMA_AC_VALUES,
         );
-        try!(self.writer.write_segment(DHT, Some(&buf)));
+        self.writer.write_segment(DHT, Some(&buf))?;
 
         if num_components == 3 {
             build_huffman_segment(
                 &mut buf,
                 DCCLASS,
                 CHROMADESTINATION,
                 &STD_CHROMA_DC_CODE_LENGTHS,
                 &STD_CHROMA_DC_VALUES,
             );
-            try!(self.writer.write_segment(DHT, Some(&buf)));
+            self.writer.write_segment(DHT, Some(&buf))?;
 
             build_huffman_segment(
                 &mut buf,
                 ACCLASS,
                 CHROMADESTINATION,
                 &STD_CHROMA_AC_CODE_LENGTHS,
                 &STD_CHROMA_AC_VALUES,
             );
-            try!(self.writer.write_segment(DHT, Some(&buf)));
+            self.writer.write_segment(DHT, Some(&buf))?;
         }
 
         build_scan_header(&mut buf, &self.components[..num_components]);
-        try!(self.writer.write_segment(SOS, Some(&buf)));
+        self.writer.write_segment(SOS, Some(&buf))?;
 
         match c {
             color::ColorType::RGB(8) => {
-                try!(self.encode_rgb(image, width as usize, height as usize, 3))
+                self.encode_rgb(image, width as usize, height as usize, 3)?
             }
             color::ColorType::RGBA(8) => {
-                try!(self.encode_rgb(image, width as usize, height as usize, 4))
+                self.encode_rgb(image, width as usize, height as usize, 4)?
             }
             color::ColorType::Gray(8) => {
-                try!(self.encode_gray(image, width as usize, height as usize, 1))
+                self.encode_gray(image, width as usize, height as usize, 1)?
             }
             color::ColorType::GrayA(8) => {
-                try!(self.encode_gray(image, width as usize, height as usize, 2))
+                self.encode_gray(image, width as usize, height as usize, 2)?
             }
             _ => {
                 return Err(io::Error::new(
                     io::ErrorKind::InvalidInput,
                     &format!(
                     "Unsupported color type {:?}. Use 8 bit per channel RGB(A) or Gray(A) instead.",
                     c
                 )[..],
                 ))
             }
         };
 
-        try!(self.writer.pad_byte());
-        try!(self.writer.write_segment(EOI, None));
+        self.writer.pad_byte()?;
+        self.writer.write_segment(EOI, None)?;
         Ok(())
     }
 
     fn encode_gray(
         &mut self,
         image: &[u8],
         width: usize,
         height: usize,
@@ -494,17 +494,17 @@ impl<'a, W: Write> JPEGEncoder<'a, W> {
                 // Quantization
                 for (i, dct) in dct_yblock.iter_mut().enumerate().take(64) {
                     *dct = ((*dct / 8) as f32 / f32::from(self.tables[i])).round() as i32;
                 }
 
                 let la = &*self.luma_actable;
                 let ld = &*self.luma_dctable;
 
-                y_dcprev = try!(self.writer.write_block(&dct_yblock, y_dcprev, ld, la));
+                y_dcprev = self.writer.write_block(&dct_yblock, y_dcprev, ld, la)?;
             }
         }
 
         Ok(())
     }
 
     fn encode_rgb(
         &mut self,
@@ -557,19 +557,19 @@ impl<'a, W: Write> JPEGEncoder<'a, W> {
                         .round() as i32;
                 }
 
                 let la = &*self.luma_actable;
                 let ld = &*self.luma_dctable;
                 let cd = &*self.chroma_dctable;
                 let ca = &*self.chroma_actable;
 
-                y_dcprev = try!(self.writer.write_block(&dct_yblock, y_dcprev, ld, la));
-                cb_dcprev = try!(self.writer.write_block(&dct_cb_block, cb_dcprev, cd, ca));
-                cr_dcprev = try!(self.writer.write_block(&dct_cr_block, cr_dcprev, cd, ca));
+                y_dcprev = self.writer.write_block(&dct_yblock, y_dcprev, ld, la)?;
+                cb_dcprev = self.writer.write_block(&dct_cb_block, cb_dcprev, cd, ca)?;
+                cr_dcprev = self.writer.write_block(&dct_cr_block, cr_dcprev, cd, ca)?;
             }
         }
 
         Ok(())
     }
 }
 
 fn build_jfif_header(m: &mut Vec<u8>) {
--- a/third_party/rust/image/src/lib.rs
+++ b/third_party/rust/image/src/lib.rs
@@ -9,16 +9,18 @@
 // it's a bit of a pain otherwise
 #![cfg_attr(feature = "cargo-clippy", allow(many_single_char_names))]
 
 extern crate byteorder;
 extern crate lzw;
 extern crate num_iter;
 extern crate num_rational;
 extern crate num_traits;
+#[cfg(feature = "hdr")]
+extern crate scoped_threadpool;
 #[cfg(all(test, feature = "benchmarks"))]
 extern crate test;
 
 #[cfg(test)]
 #[macro_use]
 extern crate quickcheck;
 
 use std::io::Write;
@@ -29,17 +31,16 @@ pub use color::{Luma, LumaA, Rgb, Rgba, 
 
 pub use image::{AnimationDecoder,
                 GenericImage,
                 GenericImageView,
                 ImageDecoder,
                 ImageDecoderExt,
                 ImageError,
                 ImageResult,
-                MutPixels,
                 // Iterators
                 Pixels,
                 SubImage};
 
 pub use imageops::FilterType::{self, CatmullRom, Gaussian, Lanczos3, Nearest, Triangle};
 
 pub use image::ImageFormat::{self, BMP, GIF, ICO, JPEG, PNG, PNM, WEBP};
 
@@ -56,17 +57,17 @@ pub use buffer::{ConvertBuffer,
 
 pub use flat::{FlatSamples};
 
 // Traits
 pub use traits::Primitive;
 
 // Opening and loading images
 pub use dynimage::{guess_format, load, load_from_memory, load_from_memory_with_format, open,
-                   save_buffer};
+                   save_buffer, save_buffer_with_format, image_dimensions};
 
 pub use dynimage::DynamicImage::{self, ImageLuma8, ImageLumaA8, ImageRgb8, ImageRgba8, ImageBgr8, ImageBgra8};
 
 pub use animation::{Frame, Frames};
 
 // Math utils
 pub mod math;
 
@@ -103,16 +104,34 @@ pub mod webp;
 mod animation;
 mod buffer;
 mod color;
 mod dynimage;
 mod image;
 mod traits;
 mod utils;
 
+// Can't use the macro-call itself within the `doc` attribute. So force it to eval it as part of
+// the macro invocation.
+// 
+// The inspiration for the macro and implementation is from
+// <https://github.com/GuillaumeGomez/doc-comment>
+//
+// MIT License
+//
+// Copyright (c) 2018 Guillaume Gomez
+macro_rules! insert_as_doc {
+    { $content:expr } => {
+        #[doc = $content] extern { }
+    }
+}
+
+// Provides the README.md as doc, to ensure the example works!
+insert_as_doc!(include_str!("../README.md"));
+
 // Copies data from `src` to `dst`
 //
 // Panics if the length of `dst` is less than the length of `src`.
 #[inline]
 fn copy_memory(src: &[u8], mut dst: &mut [u8]) {
     let len_src = src.len();
     assert!(dst.len() >= len_src);
     dst.write_all(src).unwrap();
--- a/third_party/rust/image/src/math/nq.rs
+++ b/third_party/rust/image/src/math/nq.rs
@@ -1,24 +1,24 @@
 //! NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994.
 //! See "Kohonen neural networks for optimal colour quantization"
 //! in "Network: Computation in Neural Systems" Vol. 5 (1994) pp 351-367.
 //! for a discussion of the algorithm.
-//! See also <http://www.acm.org/~dekker/NEUQUANT.HTML>
+//! See also <https://scientificgems.wordpress.com/stuff/neuquant-fast-high-quality-image-quantization/>
 
 /* NeuQuant Neural-Net Quantization Algorithm
  * ------------------------------------------
  *
  * Copyright (c) 1994 Anthony Dekker
  *
  * NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994.
  * See "Kohonen neural networks for optimal colour quantization"
  * in "Network: Computation in Neural Systems" Vol. 5 (1994) pp 351-367.
  * for a discussion of the algorithm.
- * See also  http://www.acm.org/~dekker/NEUQUANT.HTML
+ * See also https://scientificgems.wordpress.com/stuff/neuquant-fast-high-quality-image-quantization/
  *
  * Any party obtaining a copy of these files from the author, directly or
  * indirectly, is granted, free of charge, a full and unrestricted irrevocable,
  * world-wide, paid up, royalty-free, nonexclusive right and license to deal
  * in this software and documentation files (the "Software"), including without
  * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons who receive
  * copies from any such party to do so, with the only requirement being
--- a/third_party/rust/image/src/png.rs
+++ b/third_party/rust/image/src/png.rs
@@ -3,61 +3,143 @@
 //! PNG (Portable Network Graphics) is an image format that supports lossless compression.
 //!
 //! # Related Links
 //! * <http://www.w3.org/TR/PNG/> - The PNG Specification
 //!
 
 extern crate png;
 
-use self::png::HasParameters;
-
-use std::io::{self, Cursor, Read, Write};
+use std::io::{self, Read, Write};
 
 use color::ColorType;
 use image::{ImageDecoder, ImageError, ImageResult};
 
+/// PNG Reader
+///
+/// This reader will try to read the png one row at a time,
+/// however for interlaced png files this is not posible and
+/// these are therefore readed at once.
+pub struct PNGReader<R: Read> {
+    reader: png::Reader<R>,
+    buffer: Vec<u8>,
+    index: usize,
+}
+
+impl<R: Read> PNGReader<R> {
+    fn new(mut reader: png::Reader<R>) -> ImageResult<PNGReader<R>> {
+        let len = reader.output_buffer_size();
+        // Since interlaced images do not come in 
+        // scanline order it is almost impossible to
+        // read them in a streaming fashion, however
+        // this shouldn't be a too big of a problem
+        // as most interlaced images should fit in memory.
+        let buffer = if reader.info().interlaced {
+            let mut buffer = vec![0; len];
+            reader.next_frame(&mut buffer)?;
+            buffer
+        } else {
+            Vec::new()
+        };
+
+        Ok(PNGReader {
+            reader,
+            buffer,
+            index: 0,
+        })
+    }
+}
+
+impl<R: Read> Read for PNGReader<R> {
+    fn read(&mut self, mut buf: &mut [u8]) -> io::Result<usize> {
+        // io::Write::write for slice cannot fail
+        let readed = buf.write(&self.buffer[self.index..]).unwrap();
+
+        let mut bytes = readed;
+        self.index += readed;
+    
+        while self.index + 1 >= self.buffer.len() {
+            match self.reader.next_row()? {
+                Some(row) => {
+                    // Faster to copy directly to external buffer
+                    let readed  = buf.write(row).unwrap();
+                    bytes += readed;
+
+                    self.buffer = (&row[readed..]).to_owned();
+                    self.index = 0;
+                }
+                None => return Ok(bytes)
+            }
+        }
+
+        Ok(bytes)
+    }
+
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
+        let mut bytes = self.buffer.len();
+        buf.extend_from_slice(&self.buffer);
+        self.buffer = Vec::new();
+        self.index = 0;
+    
+        while let Some(row) = self.reader.next_row()? {
+            buf.extend_from_slice(row);
+            bytes += row.len();
+        }
+
+        Ok(bytes)
+    }
+}
+
 /// PNG decoder
 pub struct PNGDecoder<R: Read> {
     colortype: ColorType,
     reader: png::Reader<R>,
 }
 
 impl<R: Read> PNGDecoder<R> {
     /// Creates a new decoder that decodes from the stream ```r```
     pub fn new(r: R) -> ImageResult<PNGDecoder<R>> {
-        let decoder = png::Decoder::new(r);
+        let limits = png::Limits {
+            bytes: usize::max_value(),
+        };
+        let decoder = png::Decoder::new_with_limits(r, limits);
         let (_, mut reader) = decoder.read_info()?;
         let colortype = reader.output_color_type().into();
 
         Ok(PNGDecoder { colortype, reader })
     }
 }
 
-impl<R: Read> ImageDecoder for PNGDecoder<R> {
-    type Reader = Cursor<Vec<u8>>;
+impl<'a, R: 'a + Read> ImageDecoder<'a> for PNGDecoder<R> {
+    type Reader = PNGReader<R>;
 
     fn dimensions(&self) -> (u64, u64) {
         let (w, h) = self.reader.info().size();
         (w as u64, h as u64)
     }
 
     fn colortype(&self) -> ColorType {
         self.colortype
     }
 
     fn into_reader(self) -> ImageResult<Self::Reader> {
-        Ok(Cursor::new(self.read_image()?))
+        PNGReader::new(self.reader)
     }
 
     fn read_image(mut self) -> ImageResult<Vec<u8>> {
+        // This should be slightly faster than the default implementation
         let mut data = vec![0; self.reader.output_buffer_size()];
         self.reader.next_frame(&mut data)?;
         Ok(data)
     }
+
+    fn scanline_bytes(&self) -> u64 {
+        let width = self.reader.info().width;
+        self.reader.output_line_size(width) as u64
+    }
 }
 
 /// PNG encoder
 pub struct PNGEncoder<W: Write> {
     w: W,
 }
 
 impl<W: Write> PNGEncoder<W> {
@@ -67,18 +149,19 @@ impl<W: Write> PNGEncoder<W> {
     }
 
     /// Encodes the image ```image```
     /// that has dimensions ```width``` and ```height```
     /// and ```ColorType``` ```c```
     pub fn encode(self, data: &[u8], width: u32, height: u32, color: ColorType) -> io::Result<()> {
         let (ct, bits) = color.into();
         let mut encoder = png::Encoder::new(self.w, width, height);
-        encoder.set(ct).set(bits);
-        let mut writer = try!(encoder.write_header());
+        encoder.set_color(ct);
+        encoder.set_depth(bits);
+        let mut writer = encoder.write_header()?;
         writer.write_image_data(data).map_err(|e| e.into())
     }
 }
 
 impl From<(png::ColorType, png::BitDepth)> for ColorType {
     fn from((ct, bits): (png::ColorType, png::BitDepth)) -> ColorType {
         use self::png::ColorType::*;
         let bits = bits as u8;
@@ -115,11 +198,12 @@ impl From<png::DecodingError> for ImageE
             IoError(err) => ImageError::IoError(err),
             Format(desc) => ImageError::FormatError(desc.into_owned()),
             InvalidSignature => ImageError::FormatError("invalid signature".into()),
             CrcMismatch { .. } => ImageError::FormatError("CRC error".into()),
             Other(desc) => ImageError::FormatError(desc.into_owned()),
             CorruptFlateStream => {
                 ImageError::FormatError("compressed data stream corrupted".into())
             }
+            LimitsExceeded => ImageError::InsufficientMemory,
         }
     }
 }
--- a/third_party/rust/image/src/pnm/decoder.rs
+++ b/third_party/rust/image/src/pnm/decoder.rs
@@ -1,11 +1,13 @@
 use std::io::{self, BufRead, BufReader, Cursor, Read};
 use std::str::{self, FromStr};
 use std::fmt::Display;
+use std::marker::PhantomData;
+use std::mem;
 
 use super::{ArbitraryHeader, ArbitraryTuplType, BitmapHeader, GraymapHeader, PixmapHeader};
 use super::{HeaderRecord, PNMHeader, PNMSubtype, SampleEncoding};
 use color::ColorType;
 use image::{ImageDecoder, ImageError, ImageResult};
 
 use byteorder::{BigEndian, ByteOrder, NativeEndian};
 
@@ -22,17 +24,17 @@ enum TupleType {
 
 trait Sample {
     fn bytelen(width: u32, height: u32, samples: u32) -> ImageResult<usize>;
 
     /// It is guaranteed that `bytes.len() == bytelen(width, height, samples)`
     fn from_bytes(bytes: &[u8], width: u32, height: u32, samples: u32)
         -> ImageResult<Vec<u8>>;
 
-    fn from_ascii(reader: &mut Read, width: u32, height: u32, samples: u32)
+    fn from_ascii(reader: &mut dyn Read, width: u32, height: u32, samples: u32)
         -> ImageResult<Vec<u8>>;
 }
 
 struct U8;
 struct U16;
 struct PbmBit;
 struct BWBit;
 
@@ -401,29 +403,45 @@ trait HeaderReader: BufRead {
             maxval: m,
             tupltype,
         })
     }
 }
 
 impl<R: Read> HeaderReader for BufReader<R> {}
 
-impl<R: Read> ImageDecoder for PNMDecoder<R> {
-    type Reader = Cursor<Vec<u8>>;
+/// Wrapper struct around a `Cursor<Vec<u8>>`
+pub struct PnmReader<R>(Cursor<Vec<u8>>, PhantomData<R>);
+impl<R> Read for PnmReader<R> {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        self.0.read(buf)
+    }
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
+        if self.0.position() == 0 && buf.is_empty() {
+            mem::swap(buf, self.0.get_mut());
+            Ok(buf.len())
+        } else {
+            self.0.read_to_end(buf)
+        }
+    }
+}
+
+impl<'a, R: 'a + Read> ImageDecoder<'a> for PNMDecoder<R> {
+    type Reader = PnmReader<R>;
 
     fn dimensions(&self) -> (u64, u64) {
         (self.header.width() as u64, self.header.height() as u64)
     }
 
     fn colortype(&self) -> ColorType {
         self.tuple.color()
     }
 
     fn into_reader(self) -> ImageResult<Self::Reader> {
-        Ok(Cursor::new(self.read_image()?))
+        Ok(PnmReader(Cursor::new(self.read_image()?), PhantomData))
     }
 
     fn read_image(mut self) -> ImageResult<Vec<u8>> {
         self.read()
     }
 }
 
 impl<R: Read> PNMDecoder<R> {
@@ -477,17 +495,17 @@ impl TupleType {
             GrayU8 => ColorType::Gray(8),
             GrayU16 => ColorType::Gray(16),
             RGBU8 => ColorType::RGB(8),
             RGBU16 => ColorType::GrayA(16),
         }
     }
 }
 
-fn read_separated_ascii<T: FromStr>(reader: &mut Read) -> ImageResult<T>
+fn read_separated_ascii<T: FromStr>(reader: &mut dyn Read) -> ImageResult<T>
     where T::Err: Display
 {
     let is_separator = |v: &u8| match *v {
         b'\t' | b'\n' | b'\x0b' | b'\x0c' | b'\r' | b' ' => true,
         _ => false,
     };
 
     let token = reader
@@ -524,17 +542,17 @@ impl Sample for U8 {
     ) -> ImageResult<Vec<u8>> {
         let mut buffer = Vec::new();
         buffer.resize(bytes.len(), 0 as u8);
         buffer.copy_from_slice(bytes);
         Ok(buffer)
     }
 
     fn from_ascii(
-        reader: &mut Read,
+        reader: &mut dyn Read,
         width: u32,
         height: u32,
         samples: u32,
     ) -> ImageResult<Vec<u8>> {
         (0..width*height*samples)
             .map(|_| read_separated_ascii(reader))
             .collect()
     }
@@ -557,17 +575,17 @@ impl Sample for U16 {
         for chunk in buffer.chunks_mut(2) {
             let v = BigEndian::read_u16(chunk);
             NativeEndian::write_u16(chunk, v);
         }
         Ok(buffer)
     }
 
     fn from_ascii(
-        reader: &mut Read,
+        reader: &mut dyn Read,
         width: u32,
         height: u32,
         samples: u32,
     ) -> ImageResult<Vec<u8>> {
         let mut buffer = vec![0; (width * height * samples * 2) as usize];
         for i in 0..(width*height*samples) as usize {
             let v = read_separated_ascii::<u16>(reader)?;
             NativeEndian::write_u16(&mut buffer[2*i..][..2], v);
@@ -591,17 +609,17 @@ impl Sample for PbmBit {
         _width: u32,
         _height: u32,
         _samples: u32,
     ) -> ImageResult<Vec<u8>> {
         Ok(bytes.iter().map(|pixel| !pixel).collect())
     }
 
     fn from_ascii(
-        reader: &mut Read,
+        reader: &mut dyn Read,
         width: u32,
         height: u32,
         samples: u32,
     ) -> ImageResult<Vec<u8>> {
         let count = (width*height*samples) as usize;
         let raw_samples = reader.bytes()
             .filter_map(|ascii| match ascii {
                 Ok(b'0') => Some(Ok(1)),
@@ -645,17 +663,17 @@ impl Sample for BWBit {
             return Err(ImageError::FormatError(
                 format!("Sample value {} outside of bounds", val),
             ));
         };
         Ok(values)
     }
 
     fn from_ascii(
-        _reader: &mut Read,
+        _reader: &mut dyn Read,
         _width: u32,
         _height: u32,
         _samples: u32,
     ) -> ImageResult<Vec<u8>> {
         unreachable!("BW bits from anymaps are never encoded as ascii")
     }
 }
 
--- a/third_party/rust/image/src/pnm/encoder.rs
+++ b/third_party/rust/image/src/pnm/encoder.rs
@@ -165,20 +165,20 @@ impl<W: Write> PNMEncoder<W> {
         width: u32,
         height: u32,
         color: ColorType,
     ) -> io::Result<()> {
         let depth = num_components(color) as u32;
         let (maxval, tupltype) = match color {
             ColorType::Gray(1) => (1, ArbitraryTuplType::BlackAndWhite),
             ColorType::GrayA(1) => (1, ArbitraryTuplType::BlackAndWhiteAlpha),
-            ColorType::Gray(n @ 1...16) => ((1 << n) - 1, ArbitraryTuplType::Grayscale),
-            ColorType::GrayA(n @ 1...16) => ((1 << n) - 1, ArbitraryTuplType::GrayscaleAlpha),
-            ColorType::RGB(n @ 1...16) => ((1 << n) - 1, ArbitraryTuplType::RGB),
-            ColorType::RGBA(n @ 1...16) => ((1 << n) - 1, ArbitraryTuplType::RGBAlpha),
+            ColorType::Gray(n @ 1..=16) => ((1 << n) - 1, ArbitraryTuplType::Grayscale),
+            ColorType::GrayA(n @ 1..=16) => ((1 << n) - 1, ArbitraryTuplType::GrayscaleAlpha),
+            ColorType::RGB(n @ 1..=16) => ((1 << n) - 1, ArbitraryTuplType::RGB),
+            ColorType::RGBA(n @ 1..=16) => ((1 << n) - 1, ArbitraryTuplType::RGBAlpha),
             _ => {
                 return Err(io::Error::new(
                     io::ErrorKind::InvalidInput,
                     &format!("Encoding colour type {:?} is not supported", color)[..],
                 ))
             }
         };
 
@@ -246,17 +246,17 @@ impl<W: Write> PNMEncoder<W> {
 
         Self::write_with_header(&mut self.writer, &header, image, width, height, color)
     }
 
     /// Try to encode the image with the chosen header, checking if values are correct.
     ///
     /// Returns how the body should be written if successful.
     fn write_with_header(
-        writer: &mut Write,
+        writer: &mut dyn Write,
         header: &PNMHeader,
         image: FlatSamples,
         width: u32,
         height: u32,
         color: ColorType,
     ) -> io::Result<()> {
         let unchecked = UncheckedHeader { header };
 
@@ -467,27 +467,27 @@ impl<'a> CheckedHeaderColor<'a> {
             color: self,
             encoding,
             _image: image,
         })
     }
 }
 
 impl<'a> CheckedHeader<'a> {
-    fn write_header(self, writer: &mut Write) -> io::Result<TupleEncoding<'a>> {
+    fn write_header(self, writer: &mut dyn Write) -> io::Result<TupleEncoding<'a>> {
         self.header().write(writer)?;
         Ok(self.encoding)
     }
 
     fn header(&self) -> &PNMHeader {
         self.color.dimensions.unchecked.header
     }
 }
 
-struct SampleWriter<'a>(&'a mut Write);
+struct SampleWriter<'a>(&'a mut dyn Write);
 
 impl<'a> SampleWriter<'a> {
     fn write_samples_ascii<V>(self, samples: V) -> io::Result<()>
     where
         V: Iterator,
         V::Item: fmt::Display,
     {
         let mut auto_break_writer = AutoBreak::new(self.0, 70);
@@ -591,17 +591,17 @@ impl<'a> From<&'a [u8]> for FlatSamples<
 
 impl<'a> From<&'a [u16]> for FlatSamples<'a> {
     fn from(samples: &'a [u16]) -> Self {
         FlatSamples::U16(samples)
     }
 }
 
 impl<'a> TupleEncoding<'a> {
-    fn write_image(&self, writer: &mut Write) -> io::Result<()> {
+    fn write_image(&self, writer: &mut dyn Write) -> io::Result<()> {
         match *self {
             TupleEncoding::PbmBits {
                 samples: FlatSamples::U8(samples),
                 width,
             } => SampleWriter(writer).write_pbm_bits(samples, width),
             TupleEncoding::PbmBits {
                 samples: FlatSamples::U16(samples),
                 width,
--- a/third_party/rust/image/src/pnm/header.rs
+++ b/third_party/rust/image/src/pnm/header.rs
@@ -227,17 +227,17 @@ impl PNMHeader {
     pub fn as_arbitrary(&self) -> Option<&ArbitraryHeader> {
         match self.decoded {
             HeaderRecord::Arbitrary(ref arbitrary) => Some(arbitrary),
             _ => None,
         }
     }
 
     /// Write the header back into a binary stream
-    pub fn write(&self, writer: &mut io::Write) -> io::Result<()> {
+    pub fn write(&self, writer: &mut dyn io::Write) -> io::Result<()> {
         writer.write_all(self.subtype().magic_constant())?;
         match *self {
             PNMHeader {
                 encoded: Some(ref content),
                 ..
             } => writer.write_all(content),
             PNMHeader {
                 decoded:
--- a/third_party/rust/image/src/pnm/mod.rs
+++ b/third_party/rust/image/src/pnm/mod.rs
@@ -29,17 +29,17 @@ mod tests {
         {
             let mut encoder = PNMEncoder::new(&mut encoded_buffer);
             encoder
                 .encode(buffer, width, height, color)
                 .expect("Failed to encode the image buffer");
         }
 
         let (header, loaded_color, loaded_image) = {
-            let mut decoder = PNMDecoder::new(&encoded_buffer[..]).unwrap();
+            let decoder = PNMDecoder::new(&encoded_buffer[..]).unwrap();
             let colortype = decoder.colortype();
             let image = decoder.read_image().expect("Failed to decode the image");
             let (_, header) = PNMDecoder::new(&encoded_buffer[..]).unwrap().into_inner();
             (header, colortype, image)
         };
 
         assert_eq!(header.width(), width);
         assert_eq!(header.height(), height);
@@ -59,17 +59,17 @@ mod tests {
         {
             let mut encoder = PNMEncoder::new(&mut encoded_buffer).with_subtype(subtype);
             encoder
                 .encode(buffer, width, height, color)
                 .expect("Failed to encode the image buffer");
         }
 
         let (header, loaded_color, loaded_image) = {
-            let mut decoder = PNMDecoder::new(&encoded_buffer[..]).unwrap();
+            let decoder = PNMDecoder::new(&encoded_buffer[..]).unwrap();
             let colortype = decoder.colortype();
             let image = decoder.read_image().expect("Failed to decode the image");
             let (_, header) = PNMDecoder::new(&encoded_buffer[..]).unwrap().into_inner();
             (header, colortype, image)
         };
 
         assert_eq!(header.width(), width);
         assert_eq!(header.height(), height);
@@ -84,17 +84,17 @@ mod tests {
         {
             let mut encoder = PNMEncoder::new(&mut encoded_buffer);
             encoder
                 .encode(buffer, width, height, color)
                 .expect("Failed to encode the image buffer");
         }
 
         let (header, loaded_color, loaded_image) = {
-            let mut decoder = PNMDecoder::new(&encoded_buffer[..]).unwrap();
+            let decoder = PNMDecoder::new(&encoded_buffer[..]).unwrap();
             let colortype = decoder.colortype();
             let image = decoder.read_image().expect("Failed to decode the image");
             let (_, header) = PNMDecoder::new(&encoded_buffer[..]).unwrap().into_inner();
             (header, colortype, image)
         };
 
         let mut buffer_u8 = vec![0; buffer.len() * 2];
         NativeEndian::write_u16_into(buffer, &mut buffer_u8[..]);
--- a/third_party/rust/image/src/tga/decoder.rs
+++ b/third_party/rust/image/src/tga/decoder.rs
@@ -96,52 +96,52 @@ impl Header {
             image_width: 0,
             image_height: 0,
             pixel_depth: 0,
             image_desc: 0,
         }
     }
 
     /// Load the header with values from the reader
-    fn from_reader(r: &mut Read) -> ImageResult<Header> {
+    fn from_reader(r: &mut dyn Read) -> ImageResult<Header> {
         Ok(Header {
-            id_length: try!(r.read_u8()),
-            map_type: try!(r.read_u8()),
-            image_type: try!(r.read_u8()),
-            map_origin: try!(r.read_u16::<LittleEndian>()),
-            map_length: try!(r.read_u16::<LittleEndian>()),
-            map_entry_size: try!(r.read_u8()),
-            x_origin: try!(r.read_u16::<LittleEndian>()),
-            y_origin: try!(r.read_u16::<LittleEndian>()),
-            image_width: try!(r.read_u16::<LittleEndian>()),
-            image_height: try!(r.read_u16::<LittleEndian>()),
-            pixel_depth: try!(r.read_u8()),
-            image_desc: try!(r.read_u8()),
+            id_length: r.read_u8()?,
+            map_type: r.read_u8()?,
+            image_type: r.read_u8()?,
+            map_origin: r.read_u16::<LittleEndian>()?,
+            map_length: r.read_u16::<LittleEndian>()?,
+            map_entry_size: r.read_u8()?,
+            x_origin: r.read_u16::<LittleEndian>()?,
+            y_origin: r.read_u16::<LittleEndian>()?,
+            image_width: r.read_u16::<LittleEndian>()?,
+            image_height: r.read_u16::<LittleEndian>()?,
+            pixel_depth: r.read_u8()?,
+            image_desc: r.read_u8()?,
         })
     }
 }
 
 struct ColorMap {
     /// sizes in bytes
     start_offset: usize,
     entry_size: usize,
     bytes: Vec<u8>,
 }
 
 impl ColorMap {
     pub fn from_reader(
-        r: &mut Read,
+        r: &mut dyn Read,
         start_offset: u16,
         num_entries: u16,
         bits_per_entry: u8,
     ) -> ImageResult<ColorMap> {
         let bytes_per_entry = (bits_per_entry as usize + 7) / 8;
 
         let mut bytes = vec![0; bytes_per_entry * num_entries as usize];
-        try!(r.read_exact(&mut bytes));
+        r.read_exact(&mut bytes)?;
 
         Ok(ColorMap {
             entry_size: bytes_per_entry,
             start_offset: start_offset as usize,
             bytes,
         })
     }
 
@@ -192,30 +192,30 @@ impl<R: Read + Seek> TGADecoder<R> {
             line_read: None,
             line_remain_buff: Vec::new(),
         };
         decoder.read_metadata()?;
         Ok(decoder)
     }
 
     fn read_header(&mut self) -> ImageResult<()> {
-        self.header = try!(Header::from_reader(&mut self.r));
+        self.header = Header::from_reader(&mut self.r)?;
         self.image_type = ImageType::new(self.header.image_type);
         self.width = self.header.image_width as usize;
         self.height = self.header.image_height as usize;
         self.bytes_per_pixel = (self.header.pixel_depth as usize + 7) / 8;
         Ok(())
     }
 
     fn read_metadata(&mut self) -> ImageResult<()> {
         if !self.has_loaded_metadata {
-            try!(self.read_header());
-            try!(self.read_image_id());
-            try!(self.read_color_map());
-            try!(self.read_color_information());
+            self.read_header()?;
+            self.read_image_id()?;
+            self.read_color_map()?;
+            self.read_color_information()?;
             self.has_loaded_metadata = true;
         }
         Ok(())
     }
 
     /// Loads the color information for the decoder
     ///
     /// To keep things simple, we won't handle bit depths that aren't divisible
@@ -321,17 +321,17 @@ impl<R: Read + Seek> TGADecoder<R> {
 
     fn read_image_data(&mut self) -> ImageResult<Vec<u8>> {
         // read the pixels from the data region
         let mut pixel_data = if self.image_type.is_encoded() {
             try!(self.read_all_encoded_data())
         } else {
             let num_raw_bytes = self.width * self.height * self.bytes_per_pixel;
             let mut buf = vec![0; num_raw_bytes];
-            try!(self.r.by_ref().read_exact(&mut buf));
+            self.r.by_ref().read_exact(&mut buf)?;
             buf
         };
 
         // expand the indices using the color map if necessary
         if self.image_type.is_color_mapped() {
             pixel_data = self.expand_color_map(&pixel_data)
         }
 
@@ -342,17 +342,17 @@ impl<R: Read + Seek> TGADecoder<R> {
         Ok(pixel_data)
     }
 
     /// Reads a run length encoded data for given number of bytes
     fn read_encoded_data(&mut self, num_bytes: usize) -> io::Result<Vec<u8>> {
         let mut pixel_data = Vec::with_capacity(num_bytes);
 
         while pixel_data.len() < num_bytes {
-            let run_packet = try!(self.r.read_u8());
+            let run_packet = self.r.read_u8()?;
             // If the highest bit in `run_packet` is set, then we repeat pixels
             //
             // Note: the TGA format adds 1 to both counts because having a count
             // of 0 would be pointless.
             if (run_packet & 0x80) != 0 {
                 // high bit set, so we will repeat the data
                 let repeat_count = ((run_packet & !0x80) + 1) as usize;
                 let mut data = Vec::with_capacity(self.bytes_per_pixel);
@@ -493,17 +493,17 @@ impl<R: Read + Seek> TGADecoder<R> {
         buf[..pixel_data.len()].copy_from_slice(&pixel_data);
 
         self.line_read = Some(self.line_read.unwrap_or(0) + 1);
 
         Ok(pixel_data.len())
     }
 }
 
-impl<R: Read + Seek> ImageDecoder for TGADecoder<R> {
+impl<'a, R: 'a + Read + Seek> ImageDecoder<'a> for TGADecoder<R> {
     type Reader = TGAReader<R>;
 
     fn dimensions(&self) -> (u64, u64) {
         (self.width as u64, self.height as u64)
     }
 
     fn colortype(&self) -> ColorType {
         self.color_type
--- a/third_party/rust/image/src/tiff.rs
+++ b/third_party/rust/image/src/tiff.rs
@@ -3,17 +3,19 @@
 //! TIFF (Tagged Image File Format) is a versatile image format that supports
 //! lossless and lossy compression.
 //!
 //! # Related Links
 //! * <http://partners.adobe.com/public/developer/tiff/index.html> - The TIFF specification
 
 extern crate tiff;
 
-use std::io::{Cursor, Read, Seek};
+use std::io::{self, Cursor, Read, Write, Seek};
+use std::marker::PhantomData;
+use std::mem;
 
 use color::ColorType;
 use image::{ImageDecoder, ImageResult, ImageError};
 use utils::vec_u16_into_u8;
 
 /// Decoder for TIFF images.
 pub struct TIFFDecoder<R>
     where R: Read + Seek
@@ -41,16 +43,17 @@ impl<R> TIFFDecoder<R>
 }
 
 impl From<tiff::TiffError> for ImageError {
     fn from(err: tiff::TiffError) -> ImageError {
         match err {
             tiff::TiffError::IoError(err) => ImageError::IoError(err),
             tiff::TiffError::FormatError(desc) => ImageError::FormatError(desc.to_string()),
             tiff::TiffError::UnsupportedError(desc) => ImageError::UnsupportedError(desc.to_string()),
+            tiff::TiffError::LimitsExceeded => ImageError::InsufficientMemory,
         }
     }
 }
 
 impl From<tiff::ColorType> for ColorType {
     fn from(ct: tiff::ColorType) -> ColorType {
         match ct {
             tiff::ColorType::Gray(depth) => ColorType::Gray(depth),
@@ -58,30 +61,76 @@ impl From<tiff::ColorType> for ColorType
             tiff::ColorType::Palette(depth) => ColorType::Palette(depth),
             tiff::ColorType::GrayA(depth) => ColorType::GrayA(depth),
             tiff::ColorType::RGBA(depth) => ColorType::RGBA(depth),
             tiff::ColorType::CMYK(_) => unimplemented!()
         }
     }
 }
 
-impl<R: Read + Seek> ImageDecoder for TIFFDecoder<R> {
-    type Reader = Cursor<Vec<u8>>;
+/// Wrapper struct around a `Cursor<Vec<u8>>`
+pub struct TiffReader<R>(Cursor<Vec<u8>>, PhantomData<R>);
+impl<R> Read for TiffReader<R> {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        self.0.read(buf)
+    }
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
+        if self.0.position() == 0 && buf.is_empty() {
+            mem::swap(buf, self.0.get_mut());
+            Ok(buf.len())
+        } else {
+            self.0.read_to_end(buf)
+        }
+    }
+}
+
+impl<'a, R: 'a + Read + Seek> ImageDecoder<'a> for TIFFDecoder<R> {
+    type Reader = TiffReader<R>;
 
     fn dimensions(&self) -> (u64, u64) {
         (self.dimensions.0 as u64, self.dimensions.1 as u64)
     }
 
     fn colortype(&self) -> ColorType {
         self.colortype
     }
 
     fn into_reader(self) -> ImageResult<Self::Reader> {
-        Ok(Cursor::new(self.read_image()?))
+        Ok(TiffReader(Cursor::new(self.read_image()?), PhantomData))
     }
 
     fn read_image(mut self) -> ImageResult<Vec<u8>> {
         match self.inner.read_image()? {
             tiff::decoder::DecodingResult::U8(v) => Ok(v),
             tiff::decoder::DecodingResult::U16(v) => Ok(vec_u16_into_u8(v)),
         }
     }
 }
+
+/// Encoder for tiff images
+pub struct TiffEncoder<W> {
+    w: W,
+}
+
+impl<W: Write + Seek> TiffEncoder<W> {
+    /// Create a new encoder that writes its output to `w`
+    pub fn new(w: W) -> TiffEncoder<W> {
+        TiffEncoder { w }
+    }
+
+    /// Encodes the image `image`
+    /// that has dimensions `width` and `height`
+    /// and `ColorType` `c`.
+    ///
+    /// 16-bit colortypes are not yet supported.
+    pub fn encode(self, data: &[u8], width: u32, height: u32, color: ColorType) -> ImageResult<()> {
+        // TODO: 16bit support
+        let mut encoder = tiff::encoder::TiffEncoder::new(self.w)?;
+        match color {
+            ColorType::Gray(8) => encoder.write_image::<tiff::encoder::colortype::Gray8>(width, height, data)?,
+            ColorType::RGB(8) => encoder.write_image::<tiff::encoder::colortype::RGB8>(width, height, data)?,
+            ColorType::RGBA(8) => encoder.write_image::<tiff::encoder::colortype::RGBA8>(width, height, data)?,
+            _ => return Err(ImageError::UnsupportedColor(color))
+        }
+
+        Ok(())
+    }
+}
--- a/third_party/rust/image/src/utils/mod.rs
+++ b/third_party/rust/image/src/utils/mod.rs
@@ -1,12 +1,13 @@
 //!  Utilities
 
+use byteorder::{NativeEndian, ByteOrder};
 use num_iter::range_step;
-use std::{mem, slice};
+use std::mem;
 use std::iter::repeat;
 
 #[inline(always)]
 pub fn expand_packed<F>(buf: &mut [u8], channels: usize, bit_depth: u8, mut func: F)
 where
     F: FnMut(u8, &mut [u8]),
 {
     let pixels = buf.len() / channels * bit_depth as usize;
@@ -34,20 +35,12 @@ where
 }
 
 pub fn vec_u16_into_u8(vec: Vec<u16>) -> Vec<u8> {
     // Do this way until we find a way to not alloc/dealloc but get llvm to realloc instead.
     vec_u16_copy_u8(&vec)
 }
 
 pub fn vec_u16_copy_u8(vec: &Vec<u16>) -> Vec<u8> {
-    let original_slice = vec.as_slice();
-    let ptr = original_slice.as_ptr() as *const u8;
-    let len = original_slice.len() * mem::size_of::<u16>();
-
-    // Note: The original pointer points to `len` bytes and all bytes are initialized thus it is
-    // valid for this slice and for the lifetime of the method. Also, the alignment of `u8` is
-    // smaller than that of `u16` as per the assert. The `ptr` is non-null because it originates
-    // from a slice itself.
-    assert!(mem::align_of::<u8>() <= mem::align_of::<u16>());
-    let byte_slice = unsafe { slice::from_raw_parts(ptr, len) };
-    byte_slice.to_owned()
+    let mut new = vec![0; vec.len() * mem::size_of::<u16>()];
+    NativeEndian::write_u16_into(&vec[..], &mut new[..]);
+    new
 }
--- a/third_party/rust/image/src/webp/decoder.rs
+++ b/third_party/rust/image/src/webp/decoder.rs
@@ -1,23 +1,25 @@
 use byteorder::{LittleEndian, ReadBytesExt};
 use std::default::Default;
-use std::io;
-use std::io::{Cursor, Read};
+use std::io::{self, Cursor, Read};
+use std::marker::PhantomData;
+use std::mem;
 
 use image;
 use image::ImageDecoder;
 use image::ImageResult;
 
 use color;
 
 use super::vp8::Frame;
 use super::vp8::VP8Decoder;
 
-/// A Representation of a Webp Image format decoder.
+/// Webp Image format decoder. Currently only supportes the luma channel (meaning that decoded
+/// images will be grayscale).
 pub struct WebpDecoder<R> {
     r: R,
     frame: Frame,
     have_frame: bool,
 }
 
 impl<R: Read> WebpDecoder<R> {
     /// Create a new WebpDecoder from the Reader ```r```.
@@ -31,20 +33,20 @@ impl<R: Read> WebpDecoder<R> {
             frame: f,
         };
         decoder.read_metadata()?;
         Ok(decoder)
     }
 
     fn read_riff_header(&mut self) -> ImageResult<u32> {
         let mut riff = Vec::with_capacity(4);
-        try!(self.r.by_ref().take(4).read_to_end(&mut riff));
-        let size = try!(self.r.read_u32::<LittleEndian>());
+        self.r.by_ref().take(4).read_to_end(&mut riff)?;
+        let size = self.r.read_u32::<LittleEndian>()?;
         let mut webp = Vec::with_capacity(4);
-        try!(self.r.by_ref().take(4).read_to_end(&mut webp));
+        self.r.by_ref().take(4).read_to_end(&mut webp)?;
 
         if &*riff != b"RIFF" {
             return Err(image::ImageError::FormatError(
                 "Invalid RIFF signature.".to_string(),
             ));
         }
 
         if &*webp != b"WEBP" {
@@ -53,66 +55,82 @@ impl<R: Read> WebpDecoder<R> {
             ));
         }
 
         Ok(size)
     }
 
     fn read_vp8_header(&mut self) -> ImageResult<()> {
         let mut vp8 = Vec::with_capacity(4);
-        try!(self.r.by_ref().take(4).read_to_end(&mut vp8));
+        self.r.by_ref().take(4).read_to_end(&mut vp8)?;
 
         if &*vp8 != b"VP8 " {
             return Err(image::ImageError::FormatError(
                 "Invalid VP8 signature.".to_string(),
             ));
         }
 
-        let _len = try!(self.r.read_u32::<LittleEndian>());
+        let _len = self.r.read_u32::<LittleEndian>()?;
 
         Ok(())
     }
 
     fn read_frame(&mut self) -> ImageResult<()> {
         let mut framedata = Vec::new();
-        try!(self.r.read_to_end(&mut framedata));
+        self.r.read_to_end(&mut framedata)?;
         let m = io::Cursor::new(framedata);
 
         let mut v = VP8Decoder::new(m);
-        let frame = try!(v.decode_frame());
+        let frame = v.decode_frame()?;
 
         self.frame = frame.clone();
 
         Ok(())
     }
 
     fn read_metadata(&mut self) -> ImageResult<()> {
         if !self.have_frame {
-            try!(self.read_riff_header());
-            try!(self.read_vp8_header());
-            try!(self.read_frame());
+            self.read_riff_header()?;
+            self.read_vp8_header()?;
+            self.read_frame()?;
 
             self.have_frame = true;
         }
 
         Ok(())
     }
 }
 
-impl<R: Read> ImageDecoder for WebpDecoder<R> {
-    type Reader = Cursor<Vec<u8>>;
+/// Wrapper struct around a `Cursor<Vec<u8>>`
+pub struct WebpReader<R>(Cursor<Vec<u8>>, PhantomData<R>);
+impl<R> Read for WebpReader<R> {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        self.0.read(buf)
+    }
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
+        if self.0.position() == 0 && buf.is_empty() {
+            mem::swap(buf, self.0.get_mut());
+            Ok(buf.len())
+        } else {
+            self.0.read_to_end(buf)
+        }
+    }
+}
+
+impl<'a, R: 'a + Read> ImageDecoder<'a> for WebpDecoder<R> {
+    type Reader = WebpReader<R>;
 
     fn dimensions(&self) -> (u64, u64) {
         (self.frame.width as u64, self.frame.height as u64)
     }
 
     fn colortype(&self) -> color::ColorType {
         color::ColorType::Gray(8)
     }
 
     fn into_reader(self) -> ImageResult<Self::Reader> {
-        Ok(Cursor::new(self.frame.ybuf))
+        Ok(WebpReader(Cursor::new(self.frame.ybuf), PhantomData))
     }
 
     fn read_image(self) -> ImageResult<Vec<u8>> {
         Ok(self.frame.ybuf)
     }
 }
--- a/third_party/rust/image/src/webp/transform.rs
+++ b/third_party/rust/image/src/webp/transform.rs
@@ -1,46 +1,51 @@
-static CONST1: i32 = 20091;
-static CONST2: i32 = 35468;
+static CONST1: i64 = 20091;
+static CONST2: i64 = 35468;
 
 pub fn idct4x4(block: &mut [i32]) {
-    for i in 0usize..4 {
-        let a1 = block[i] + block[8 + i];
-        let b1 = block[i] - block[8 + i];
-
-        let t1 = (block[4 + i] * CONST2) >> 16;
-        let t2 = block[12 + i] + ((block[12 + i] * CONST1) >> 16);
-        let c1 = t1 - t2;
-
-        let t1 = block[4 + i] + ((block[4 + i] * CONST1) >> 16);
-        let t2 = (block[12 + i] * CONST2) >> 16;
-        let d1 = t1 + t2;
-
-        block[i] = a1 + d1;
-        block[4 + i] = b1 + c1;
-        block[4 * 3 + i] = a1 - d1;
-        block[4 * 2 + i] = b1 - c1;
+    // The intermediate results may overflow the types, so we stretch the type.
+    fn fetch(block: &mut [i32], idx: usize) -> i64 {
+        i64::from(block[idx])
     }
 
     for i in 0usize..4 {
-        let a1 = block[4 * i] + block[4 * i + 2];
-        let b1 = block[4 * i] - block[4 * i + 2];
+        let a1 = fetch(block, i) + fetch(block, 8 + i);
+        let b1 = fetch(block, i) - fetch(block, 8 + i);
 
-        let t1 = (block[4 * i + 1] * CONST2) >> 16;
-        let t2 = block[4 * i + 3] + ((block[4 * i + 3] * CONST1) >> 16);
+        let t1 = (fetch(block, 4 + i) * CONST2) >> 16;
+        let t2 = fetch(block, 12 + i) + ((fetch(block, 12 + i) * CONST1) >> 16);
         let c1 = t1 - t2;
 
-        let t1 = block[4 * i + 1] + ((block[4 * i + 1] * CONST1) >> 16);
-        let t2 = (block[4 * i + 3] * CONST2) >> 16;
+        let t1 = fetch(block, 4 + i) + ((fetch(block, 4 + i) * CONST1) >> 16);
+        let t2 = (fetch(block, 12 + i) * CONST2) >> 16;
         let d1 = t1 + t2;
 
-        block[4 * i] = (a1 + d1 + 4) >> 3;
-        block[4 * i + 3] = (a1 - d1 + 4) >> 3;
-        block[4 * i + 1] = (b1 + c1 + 4) >> 3;
-        block[4 * i + 2] = (b1 - c1 + 4) >> 3;
+        block[i] = (a1 + d1) as i32;
+        block[4 + i] = (b1 + c1) as i32;
+        block[4 * 3 + i] = (a1 - d1) as i32;
+        block[4 * 2 + i] = (b1 - c1) as i32;
+    }
+
+    for i in 0usize..4 {
+        let a1 = fetch(block, 4 * i) + fetch(block, 4 * i + 2);
+        let b1 = fetch(block, 4 * i) - fetch(block, 4 * i + 2);
+
+        let t1 = (fetch(block, 4 * i + 1) * CONST2) >> 16;
+        let t2 = fetch(block, 4 * i + 3) + ((fetch(block, 4 * i + 3) * CONST1) >> 16);
+        let c1 = t1 - t2;
+
+        let t1 = fetch(block, 4 * i + 1) + ((fetch(block, 4 * i + 1) * CONST1) >> 16);
+        let t2 = (fetch(block, 4 * i + 3) * CONST2) >> 16;
+        let d1 = t1 + t2;
+
+        block[4 * i] = ((a1 + d1 + 4) >> 3) as i32;
+        block[4 * i + 3] = ((a1 - d1 + 4) >> 3) as i32;
+        block[4 * i + 1] = ((b1 + c1 + 4) >> 3) as i32;
+        block[4 * i + 2] = ((b1 - c1 + 4) >> 3) as i32;
     }
 }
 
 // 14.3
 pub fn iwht4x4(block: &mut [i32]) {
     for i in 0usize..4 {
         let a1 = block[i] + block[12 + i];
         let b1 = block[4 + i] + block[8 + i];
--- a/third_party/rust/image/src/webp/vp8.rs
+++ b/third_party/rust/image/src/webp/vp8.rs
@@ -9,20 +9,21 @@
 //! # Related Links
 //! * [rfc-6386](http://tools.ietf.org/html/rfc6386) - The VP8 Data Format and Decoding Guide
 //! * [VP8.pdf](http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/37073.pdf) - An overview of
 //! of the VP8 format
 //!
 
 use byteorder::{LittleEndian, ReadBytesExt};
 use std::default::Default;
-use std::io;
+use std::cmp;
 use std::io::Read;
 
 use super::transform;
+use ::{ImageError, ImageResult};
 
 use math::utils::clamp;
 
 const MAX_SEGMENTS: usize = 4;
 const NUM_DCT_TOKENS: usize = 12;
 
 // Prediction modes
 const DC_PRED: i8 = 0;
@@ -37,16 +38,67 @@ const B_VE_PRED: i8 = 2;
 const B_HE_PRED: i8 = 3;
 const B_LD_PRED: i8 = 4;
 const B_RD_PRED: i8 = 5;
 const B_VR_PRED: i8 = 6;
 const B_VL_PRED: i8 = 7;
 const B_HD_PRED: i8 = 8;
 const B_HU_PRED: i8 = 9;
 
+// Prediction mode enum
+#[repr(i8)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+enum LumaMode {
+    /// Predict DC using row above and column to the left.
+    DC = DC_PRED,
+
+    /// Predict rows using row above.
+    V = V_PRED,
+
+    /// Predict columns using column to the left.
+    H = H_PRED,
+
+    /// Propagate second differences.
+    TM = TM_PRED,
+
+    /// Each Y subblock is independently predicted.
+    B = B_PRED,
+}
+
+#[repr(i8)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+enum ChromaMode {
+    /// Predict DC using row above and column to the left.
+    DC = DC_PRED,
+
+    /// Predict rows using row above.
+    V = V_PRED,
+
+    /// Predict columns using column to the left.
+    H = H_PRED,
+
+    /// Propagate second differences.
+    TM = TM_PRED,
+}
+
+#[repr(i8)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+enum IntraMode {
+    DC = B_DC_PRED,
+    TM = B_TM_PRED,
+    VE = B_VE_PRED,
+    HE = B_HE_PRED,
+    LD = B_LD_PRED,
+    RD = B_RD_PRED,
+    VR = B_VR_PRED,
+    VL = B_VL_PRED,
+    HD = B_HD_PRED,
+    HU = B_HU_PRED,
+}
+
 type Prob = u8;
 
 static SEGMENT_ID_TREE: [i8; 6] = [2, 4, -0, -1, -2, -3];
 
 // Section 11.2
 // Tree for determining the keyframe luma intra prediction modes:
 static KEYFRAME_YMODE_TREE: [i8; 8] = [-B_PRED, 2, 4, 6, -DC_PRED, -V_PRED, -H_PRED, -TM_PRED];
 
@@ -625,63 +677,71 @@ impl BoolReader {
             buf: Vec::new(),
             range: 0,
             value: 0,
             bit_count: 0,
             index: 0,
         }
     }
 
-    pub fn init(&mut self, buf: Vec<u8>) {
-        self.buf = buf;
-        self.value = 0;
-
-        for _ in 0usize..2 {
-            self.value = (self.value << 8) | u32::from(self.buf[self.index]);
-            self.index += 1;
+    pub fn init(&mut self, buf: Vec<u8>) -> ImageResult<()> {
+        if buf.len() < 2 {
+            return Err(ImageError::FormatError(
+                "Expected at least 2 bytes of decoder initialization data".into()));
         }
 
+        self.buf = buf;
+        // Direct access safe, since length has just been validated.
+        self.value = (u32::from(self.buf[0]) << 8) | u32::from(self.buf[1]);
+        self.index = 2;
         self.range = 255;
         self.bit_count = 0;
+
+        Ok(())
     }
 
-    pub fn read_bool(&mut self, probability: u8) -> u8 {
+    pub fn read_bool(&mut self, probability: u8) -> bool {
         let split = 1 + (((self.range - 1) * u32::from(probability)) >> 8);
         let bigsplit = split << 8;
 
         let retval = if self.value >= bigsplit {
             self.range -= split;
             self.value -= bigsplit;
-            1
+            true
         } else {
             self.range = split;
-            0
+            false
         };
 
         while self.range < 128 {
             self.value <<= 1;
             self.range <<= 1;
             self.bit_count += 1;
 
             if self.bit_count == 8 {
                 self.bit_count = 0;
-                self.value |= u32::from(self.buf[self.index]);
-                self.index += 1;
+
+                // If no more bits are available, just don't do anything.
+                // This strategy is suggested in the reference implementation of RFC6386 (p.135)
+                if self.index < self.buf.len() {
+                    self.value |= u32::from(self.buf[self.index]);
+                    self.index += 1;
+                }
             }
         }
 
         retval
     }
 
     pub fn read_literal(&mut self, n: u8) -> u8 {
         let mut v = 0u8;
         let mut n = n;
 
         while n != 0 {
-            v = (v << 1) + self.read_bool(128u8);
+            v = (v << 1) + self.read_bool(128u8) as u8;
             n -= 1;
         }
 
         v
     }
 
     pub fn read_magnitude_and_sign(&mut self, n: u8) -> i32 {
         let magnitude = self.read_literal(n);
@@ -710,37 +770,25 @@ impl BoolReader {
         -index as i8
     }
 
     pub fn read_flag(&mut self) -> bool {
         0 != self.read_literal(1)
     }
 }
 
-#[derive(Clone, Copy)]
+#[derive(Default, Clone, Copy)]
 struct MacroBlock {
-    bpred: [i8; 16],
+    bpred: [IntraMode; 16],
     complexity: [u8; 9],
-    luma_mode: i8,
-    chroma_mode: i8,
+    luma_mode: LumaMode,
+    chroma_mode: ChromaMode,
     segmentid: u8,
 }
 
-impl MacroBlock {
-    fn new() -> MacroBlock {
-        MacroBlock {
-            bpred: [0i8; 16],
-            complexity: [0u8; 9],
-            luma_mode: 0,
-            chroma_mode: 0,
-            segmentid: 0,
-        }
-    }
-}
-
 /// A Representation of the last decoded video frame
 #[derive(Default, Debug, Clone)]
 pub struct Frame {
     /// The width of the luma plane
     pub width: u16,
 
     /// The height of the luma plane
     pub height: u16,
@@ -818,19 +866,19 @@ pub struct VP8Decoder<R> {
     top_border: Vec<u8>,
     left_border: Vec<u8>,
 }
 
 impl<R: Read> VP8Decoder<R> {
     /// Create a new decoder.
     /// The reader must present a raw vp8 bitstream to the decoder
     pub fn new(r: R) -> VP8Decoder<R> {
-        let f: Frame = Default::default();
-        let s: Segment = Default::default();
-        let m = MacroBlock::new();
+        let f = Frame::default();
+        let s = Segment::default();
+        let m = MacroBlock::default();
 
         VP8Decoder {
             r,
             b: BoolReader::new(),
 
             mbwidth: 0,
             mbheight: 0,
 
@@ -869,53 +917,58 @@ impl<R: Read> VP8Decoder<R> {
         }
     }
 
     fn update_token_probabilities(&mut self) {
         for (i, is) in COEFF_UPDATE_PROBS.iter().enumerate() {
             for (j, js) in is.iter().enumerate() {
                 for (k, ks) in js.iter().enumerate() {
                     for (t, prob) in ks.iter().enumerate().take(NUM_DCT_TOKENS - 1) {
-                        if self.b.read_bool(*prob) != 0 {
+                        if self.b.read_bool(*prob) {
                             let v = self.b.read_literal(8);
                             self.token_probs[i][j][k][t] = v;
                         }
                     }
                 }
             }
         }
     }
 
-    fn init_partitions(&mut self, n: usize) -> io::Result<()> {
+    fn init_partitions(&mut self, n: usize) -> ImageResult<()> {
         if n > 1 {
-            let mut sizes = Vec::with_capacity(3 * n - 3);
-            try!(
-                self.r
-                    .by_ref()
-                    .take(3 * n as u64 - 3)
-                    .read_to_end(&mut sizes)
-            );
+            let mut sizes = vec![0; 3 * n - 3];
+            self.r.read_exact(sizes.as_mut_slice())?;
 
             for (i, s) in sizes.chunks(3).enumerate() {
-                let size = u32::from(s[0]) + ((u32::from(s[1])) << 8) + ((u32::from(s[2])) << 8);
-                let mut buf = Vec::with_capacity(size as usize);
-                try!(self.r.by_ref().take(u64::from(size)).read_to_end(&mut buf));
+                let size = {s}.read_u24::<LittleEndian>()
+                    .expect("Reading from &[u8] can't fail and the chunk is complete");
 
-                self.partitions[i].init(buf);
+                let mut buf = vec![0; size as usize];
+                self.r.read_exact(buf.as_mut_slice())?;
+
+                self.partitions[i].init(buf)?;
             }
         }
 
         let mut buf = Vec::new();
-        try!(self.r.read_to_end(&mut buf));
-        self.partitions[n - 1].init(buf);
+        self.r.read_to_end(&mut buf)?;
+        self.partitions[n - 1].init(buf)?;
 
         Ok(())
     }
 
     fn read_quantization_indices(&mut self) {
+        fn dc_quant(index: i32) -> i16 {
+            DC_QUANT[clamp(index, 0, 127) as usize]
+        }
+
+        fn ac_quant(index: i32) -> i16 {
+            AC_QUANT[clamp(index, 0, 127) as usize]
+        }
+
         let yac_abs = self.b.read_literal(7);
         let ydc_delta = if self.b.read_flag() {
             self.b.read_magnitude_and_sign(4)
         } else {
             0
         };
 
         let y2dc_delta = if self.b.read_flag() {
@@ -949,24 +1002,25 @@ impl<R: Read> VP8Decoder<R> {
         };
         for i in 0usize..n {
             let base = i32::from(if !self.segment[i].delta_values {
                 i16::from(self.segment[i].quantizer_level)
             } else {
                 i16::from(self.segment[i].quantizer_level) + i16::from(yac_abs)
             });
 
-            self.segment[i].ydc = DC_QUANT[clamp(base + ydc_delta, 0, 127) as usize];
-            self.segment[i].yac = AC_QUANT[clamp(base, 0, 127) as usize];
+            self.segment[i].ydc = dc_quant(base + ydc_delta);
+            self.segment[i].yac = ac_quant(base);
 
-            self.segment[i].y2dc = DC_QUANT[clamp(base + y2dc_delta, 0, 127) as usize] * 2;
-            self.segment[i].y2ac = AC_QUANT[clamp(base + y2ac_delta, 0, 127) as usize] * 155 / 100;
+            self.segment[i].y2dc = dc_quant(base + y2dc_delta) * 2;
+            // The intermediate result (max`284*155`) can be larger than the `i16` range.
+            self.segment[i].y2ac = (i32::from(ac_quant(base + y2ac_delta)) * 155 / 100) as i16;
 
-            self.segment[i].uvdc = DC_QUANT[clamp(base + uvdc_delta, 0, 127) as usize];
-            self.segment[i].uvac = AC_QUANT[clamp(base + uvac_delta, 0, 127) as usize];
+            self.segment[i].uvdc = dc_quant(base + uvdc_delta);
+            self.segment[i].uvac = ac_quant(base + uvac_delta);
 
             if self.segment[i].y2ac < 8 {
                 self.segment[i].y2ac = 8;
             }
 
             if self.segment[i].uvdc > 132 {
                 self.segment[i].uvdc = 132;
             }
@@ -1034,63 +1088,68 @@ impl<R: Read> VP8Decoder<R> {
             for i in 0usize..3 {
                 let update = self.b.read_flag();
 
                 self.segment_tree_probs[i] = if update { self.b.read_literal(8) } else { 255 };
             }
         }
     }
 
-    fn read_frame_header(&mut self) -> io::Result<()> {
-        let mut tag = [0u8; 3];
-        try!(self.r.read_exact(&mut tag));
+    fn read_frame_header(&mut self) -> ImageResult<()> {
+        let tag = self.r.read_u24::<LittleEndian>()?;
 
-        self.frame.keyframe = tag[0] & 1 == 0;
-        self.frame.version = (tag[0] >> 1) & 7;
-        self.frame.for_display = (tag[0] >> 4) & 1 != 0;
+        self.frame.keyframe = tag & 1 == 0;
+        self.frame.version = ((tag >> 1) & 7) as u8;
+        self.frame.for_display = (tag >> 4) & 1 != 0;
 
-        let first_partition_size =
-            ((u32::from(tag[2]) << 16) | (u32::from(tag[1]) << 8) | u32::from(tag[0])) >> 5;
+        let first_partition_size = tag >> 5;
 
         if self.frame.keyframe {
-            try!(self.r.read_exact(&mut tag));
-            assert_eq!(tag, [0x9d, 0x01, 0x2a]);
+            let mut tag = [0u8; 3];
+            self.r.read_exact(&mut tag)?;
 
-            let w = try!(self.r.read_u16::<LittleEndian>());
-            let h = try!(self.r.read_u16::<LittleEndian>());
+            if tag != [0x9d, 0x01, 0x2a] {
+                return Err(ImageError::FormatError(
+                    format!("Invalid magic bytes {:?} for vp8", tag)))
+            }
+
+            let w = self.r.read_u16::<LittleEndian>()?;
+            let h = self.r.read_u16::<LittleEndian>()?;
 
             self.frame.width = w & 0x3FFF;
             self.frame.height = h & 0x3FFF;
 
             self.top = init_top_macroblocks(self.frame.width as usize);
-            self.left = MacroBlock { ..self.top[0] };
+            // Almost always the first macro block, except when non exists (i.e. `width == 0`)
+            self.left = self.top.get(0).cloned()
+                .unwrap_or_else(MacroBlock::default);
 
             self.mbwidth = (self.frame.width + 15) / 16;
             self.mbheight = (self.frame.height + 15) / 16;
 
             self.frame.ybuf = vec![0u8; self.frame.width as usize * self.frame.height as usize];
 
             self.top_border = vec![127u8; self.frame.width as usize + 4 + 16];
             self.left_border = vec![129u8; 1 + 16];
         }
 
-        let mut buf = Vec::with_capacity(first_partition_size as usize);
-        try!(
-            self.r
-                .by_ref()
-                .take(u64::from(first_partition_size))
-                .read_to_end(&mut buf)
-        );
+        let mut buf = vec![0; first_partition_size as usize];
+        self.r.read_exact(&mut buf)?;
+
         // initialise binary decoder
-        self.b.init(buf);
+        self.b.init(buf)?;
 
         if self.frame.keyframe {
             let color_space = self.b.read_literal(1);
             self.frame.pixel_type = self.b.read_literal(1);
-            assert_eq!(color_space, 0);
+
+            if color_space != 0 {
+                return Err(ImageError::FormatError(
+                    format!("Only YUV color space is specified.")))
+            }
         }
 
         self.segments_enabled = self.b.read_flag();
         if self.segments_enabled {
             self.read_segment_updates();
         }
 
         self.frame.filter = self.b.read_literal(1);
@@ -1099,23 +1158,25 @@ impl<R: Read> VP8Decoder<R> {
 
         let lf_adjust_enable = self.b.read_flag();
         if lf_adjust_enable {
             self.read_loop_filter_adjustments();
         }
 
         self.num_partitions = (1usize << self.b.read_literal(2) as usize) as u8;
         let num_partitions = self.num_partitions as usize;
-        try!(self.init_partitions(num_partitions));
+        self.init_partitions(num_partitions)?;
 
         self.read_quantization_indices();
 
         if !self.frame.keyframe {
             // 9.7 refresh golden frame and altref frame
-            panic!("unimplemented")
+            return Err(ImageError::UnsupportedError(
+                "Frames that are not keyframes are not supported".into()))
+            // FIXME: support this?
         } else {
             // Refresh entropy probs ?????
             let _ = self.b.read_literal(1);
         }
 
         self.update_token_probabilities();
 
         let mb_no_skip_coeff = self.b.read_literal(1);
@@ -1124,114 +1185,123 @@ impl<R: Read> VP8Decoder<R> {
         } else {
             None
         };
 
         if !self.frame.keyframe {
             // 9.10 remaining frame data
             self.prob_intra = 0;
 
-            panic!("unimplemented")
+            return Err(ImageError::UnsupportedError(
+                "Frames that are not keyframes are not supported".into()))
+            // FIXME: support this?
         } else {
             // Reset motion vectors
         }
 
         Ok(())
     }
 
-    fn read_macroblock_header(&mut self, mbx: usize) -> (bool, MacroBlock) {
-        let mut mb = MacroBlock::new();
+    fn read_macroblock_header(&mut self, mbx: usize) -> ImageResult<(bool, MacroBlock)> {
+        let mut mb = MacroBlock::default();
 
         mb.segmentid = if self.segments_enabled && self.segments_update_map {
             self.b
                 .read_with_tree(&SEGMENT_ID_TREE, &self.segment_tree_probs, 0) as u8
         } else {
             0
         };
 
         let skip_coeff = if self.prob_skip_false.is_some() {
-            1 == self.b.read_bool(*self.prob_skip_false.as_ref().unwrap())
+            self.b.read_bool(*self.prob_skip_false.as_ref().unwrap())
         } else {
             false
         };
 
         let inter_predicted = if !self.frame.keyframe {
-            1 == self.b.read_bool(self.prob_intra)
+            self.b.read_bool(self.prob_intra)
         } else {
             false
         };
 
         if inter_predicted {
-            panic!("inter prediction not implemented");
+            return Err(ImageError::UnsupportedError(
+                "VP8 inter prediction is not implemented yet".into()));
         }
 
         if self.frame.keyframe {
             // intra prediction
-            mb.luma_mode = self.b
+            let luma = self.b
                 .read_with_tree(&KEYFRAME_YMODE_TREE, &KEYFRAME_YMODE_PROBS, 0);
-
-            if mb.luma_mode == B_PRED {
-                for y in 0usize..4 {
-                    for x in 0usize..4 {
-                        let top = self.top[mbx].bpred[12 + x];
-                        let left = self.left.bpred[y];
-                        let bmode = self.b.read_with_tree(
-                            &KEYFRAME_BPRED_MODE_TREE,
-                            &KEYFRAME_BPRED_MODE_PROBS[top as usize][left as usize],
-                            0,
-                        );
-                        mb.bpred[x + y * 4] = bmode;
+            mb.luma_mode = LumaMode::from_i8(luma)
+                .ok_or_else(|| ImageError::FormatError(
+                    format!("Invalid luma prediction mode {}", luma))
+                )?;
 
-                        self.top[mbx].bpred[12 + x] = bmode;
-                        self.left.bpred[y] = bmode;
+            match mb.luma_mode.into_intra() {
+                // `LumaMode::B` - This is predicted individually
+                None => {
+                    for y in 0usize..4 {
+                        for x in 0usize..4 {
+                            let top = self.top[mbx].bpred[12 + x];
+                            let left = self.left.bpred[y];
+                            let intra = self.b.read_with_tree(
+                                &KEYFRAME_BPRED_MODE_TREE,
+                                &KEYFRAME_BPRED_MODE_PROBS[top as usize][left as usize],
+                                0,
+                            );
+                            let bmode = IntraMode::from_i8(intra)
+                                .ok_or_else(|| ImageError::FormatError(
+                                    format!("Invalid intra prediction mode {}", intra))
+                                )?;
+                            mb.bpred[x + y * 4] = bmode;
+
+                            self.top[mbx].bpred[12 + x] = bmode;
+                            self.left.bpred[y] = bmode;
+                        }
                     }
-                }
-            } else {
-                for i in 0usize..4 {
-                    let mode = match mb.luma_mode {
-                        DC_PRED => B_DC_PRED,
-                        V_PRED => B_VE_PRED,
-                        H_PRED => B_HE_PRED,
-                        TM_PRED => B_TM_PRED,
-                        _ => panic!("unreachable"),
-                    };
-
-                    mb.bpred[12 + i] = mode;
-                    self.left.bpred[i] = mode;
+                },
+                Some(mode) =>  {
+                    for i in 0usize..4 {
+                        mb.bpred[12 + i] = mode;
+                        self.left.bpred[i] = mode;
+                    }
                 }
             }
 
-            mb.chroma_mode =
-                self.b
-                    .read_with_tree(&KEYFRAME_UV_MODE_TREE, &KEYFRAME_UV_MODE_PROBS, 0);
+            let chroma = self.b
+                .read_with_tree(&KEYFRAME_UV_MODE_TREE, &KEYFRAME_UV_MODE_PROBS, 0);
+            mb.chroma_mode = ChromaMode::from_i8(chroma)
+                .ok_or_else(|| ImageError::FormatError(
+                    format!("Invalid chroma prediction mode {}", chroma))
+                )?;
         }
 
         self.top[mbx].chroma_mode = mb.chroma_mode;
         self.top[mbx].luma_mode = mb.luma_mode;
         self.top[mbx].bpred = mb.bpred;
 
-        (skip_coeff, mb)
+        Ok((skip_coeff, mb))
     }
 
     fn intra_predict(&mut self, mbx: usize, mby: usize, mb: &MacroBlock, resdata: &[i32]) {
         let stride = 1usize + 16 + 4;
         let w = self.frame.width as usize;
         let mw = self.mbwidth as usize;
         let mut ws = create_border(mbx, mby, mw, &self.top_border, &self.left_border);
 
         match mb.luma_mode {
-            V_PRED => predict_vpred(&mut ws, 16, 1, 1, stride),
-            H_PRED => predict_hpred(&mut ws, 16, 1, 1, stride),
-            TM_PRED => predict_tmpred(&mut ws, 16, 1, 1, stride),
-            DC_PRED => predict_dcpred(&mut ws, 16, stride, mby != 0, mbx != 0),
-            B_PRED => predict_4x4(&mut ws, stride, &mb.bpred, resdata),
-            _ => panic!("unknown luma intra prediction mode"),
+            LumaMode::V => predict_vpred(&mut ws, 16, 1, 1, stride),
+            LumaMode::H => predict_hpred(&mut ws, 16, 1, 1, stride),
+            LumaMode::TM => predict_tmpred(&mut ws, 16, 1, 1, stride),
+            LumaMode::DC => predict_dcpred(&mut ws, 16, stride, mby != 0, mbx != 0),
+            LumaMode::B => predict_4x4(&mut ws, stride, &mb.bpred, resdata),
         }
 
-        if mb.luma_mode != B_PRED {
+        if mb.luma_mode != LumaMode::B {
             for y in 0usize..4 {
                 for x in 0usize..4 {
                     let i = x + y * 4;
                     let rb = &resdata[i * 16..i * 16 + 16];
                     let y0 = 1 + y * 4;
                     let x0 = 1 + x * 4;
 
                     add_residue(&mut ws, rb, y0, x0, stride);
@@ -1241,27 +1311,19 @@ impl<R: Read> VP8Decoder<R> {
 
         self.left_border[0] = ws[16];
 
         for i in 0usize..16 {
             self.top_border[mbx * 16 + i] = ws[16 * stride + 1 + i];
             self.left_border[i + 1] = ws[(i + 1) * stride + 16];
         }
 
-        let ylength = if mby < self.mbheight as usize - 1 || self.frame.height % 16 == 0 {
-            16usize
-        } else {
-            (16 - (self.frame.height as usize & 15)) % 16
-        };
-
-        let xlength = if mbx < self.mbwidth as usize - 1 || self.frame.width % 16 == 0 {
-            16usize
-        } else {
-            (16 - (self.frame.width as usize & 15)) % 16
-        };
+        // Length is the remainder to the border, but maximally the current chunk.
+        let ylength = cmp::min(self.frame.height as usize - mby*16, 16);
+        let xlength = cmp::min(self.frame.width as usize - mbx*16, 16);
 
         for y in 0usize..ylength {
             for x in 0usize..xlength {
                 self.frame.ybuf[(mby * 16 + y) * w + mbx * 16 + x] = ws[(1 + y) * stride + 1 + x];
             }
         }
     }
 
@@ -1296,26 +1358,26 @@ impl<R: Read> VP8Decoder<R> {
 
                 DCT_0 => {
                     skip = true;
                     has_coefficients = true;
                     complexity = 0;
                     continue;
                 }
 
-                literal @ DCT_1...DCT_4 => i16::from(literal),
+                literal @ DCT_1..=DCT_4 => i16::from(literal),
 
-                category @ DCT_CAT1...DCT_CAT6 => {
+                category @ DCT_CAT1..=DCT_CAT6 => {
                     let t = PROB_DCT_CAT[(category - DCT_CAT1) as usize];
 
                     let mut extra = 0i16;
                     let mut j = 0;
 
                     while t[j] > 0 {
-                        extra = extra + extra + i16::from(self.partitions[p].read_bool(t[j]));
+                        extra = extra + extra + self.partitions[p].read_bool(t[j]) as i16;
                         j += 1;
                     }
 
                     i16::from(DCT_CAT_BASE[(category - DCT_CAT1) as usize]) + extra
                 }
 
                 c => panic!(format!("unknown token: {}", c)),
             });
@@ -1325,33 +1387,33 @@ impl<R: Read> VP8Decoder<R> {
             complexity = if abs_value == 0 {
                 0
             } else if abs_value == 1 {
                 1
             } else {
                 2
             };
 
-            if self.partitions[p].read_bool(128) == 1 {
+            if self.partitions[p].read_bool(128) {
                 abs_value = -abs_value;
             }
 
             block[ZIGZAG[i] as usize] =
                 abs_value * i32::from(if ZIGZAG[i] > 0 { acq } else { dcq });
 
             has_coefficients = true;
         }
 
         has_coefficients
     }
 
     fn read_residual_data(&mut self, mb: &MacroBlock, mbx: usize, p: usize) -> [i32; 384] {
         let sindex = mb.segmentid as usize;
         let mut blocks = [0i32; 384];
-        let mut plane = if mb.luma_mode == B_PRED { 3 } else { 1 };
+        let mut plane = if mb.luma_mode == LumaMode::B { 3 } else { 1 };
 
         if plane == 1 {
             let complexity = self.top[mbx].complexity[0] + self.left.complexity[0];
             let mut block = [0i32; 16];
             let dcq = self.segment[sindex].y2dc;
             let acq = self.segment[sindex].y2ac;
             let n = self.read_coefficients(&mut block, p, plane, complexity as usize, dcq, acq);
 
@@ -1416,29 +1478,29 @@ impl<R: Read> VP8Decoder<R> {
                 self.left.complexity[y + j] = left;
             }
         }
 
         blocks
     }
 
     /// Decodes the current frame and returns a reference to it
-    pub fn decode_frame(&mut self) -> io::Result<&Frame> {
-        try!(self.read_frame_header());
+    pub fn decode_frame(&mut self) -> ImageResult<&Frame> {
+        self.read_frame_header()?;
 
         for mby in 0..self.mbheight as usize {
             let p = mby % self.num_partitions as usize;
-            self.left = MacroBlock::new();
+            self.left = MacroBlock::default();
 
             for mbx in 0..self.mbwidth as usize {
-                let (skip, mb) = self.read_macroblock_header(mbx);
+                let (skip, mb) = self.read_macroblock_header(mbx)?;
                 let blocks = if !skip {
                     self.read_residual_data(&mb, mbx, p)
                 } else {
-                    if mb.luma_mode != B_PRED {
+                    if mb.luma_mode != LumaMode::B {
                         self.left.complexity[0] = 0;
                         self.top[mbx].complexity[0] = 0;
                     }
 
                     for i in 1usize..9 {
                         self.left.complexity[i] = 0;
                         self.top[mbx].complexity[i] = 0;
                     }
@@ -1451,27 +1513,98 @@ impl<R: Read> VP8Decoder<R> {
 
             self.left_border = vec![129u8; 1 + 16];
         }
 
         Ok(&self.frame)
     }
 }
 
+impl LumaMode {
+    fn from_i8(val: i8) -> Option<Self> {
+        Some(match val {
+            DC_PRED => LumaMode::DC,
+            V_PRED => LumaMode::V,
+            H_PRED => LumaMode::H,
+            TM_PRED => LumaMode::TM,
+            B_PRED => LumaMode::B,
+            _ => return None,
+        })
+    }
+
+    fn into_intra(self) -> Option<IntraMode> {
+        Some(match self {
+            LumaMode::DC => IntraMode::DC,
+            LumaMode::V => IntraMode::VE,
+            LumaMode::H => IntraMode::HE,
+            LumaMode::TM => IntraMode::TM,
+            LumaMode::B => return None,
+        })
+    }
+}
+
+impl Default for LumaMode {
+    fn default() -> Self {
+        LumaMode::DC
+    }
+}
+
+impl ChromaMode {
+    fn from_i8(val: i8) -> Option<Self> {
+        Some(match val {
+            DC_PRED => ChromaMode::DC,
+            V_PRED => ChromaMode::V,
+            H_PRED => ChromaMode::H,
+            TM_PRED => ChromaMode::TM,
+            _ => return None,
+        })
+    }
+}
+
+impl Default for ChromaMode {
+    fn default() -> Self {
+        ChromaMode::DC
+    }
+}
+
+impl IntraMode {
+    fn from_i8(val: i8) -> Option<Self> {
+        Some(match val {
+            B_DC_PRED => IntraMode::DC,
+            B_TM_PRED => IntraMode::TM,
+            B_VE_PRED => IntraMode::VE,
+            B_HE_PRED => IntraMode::HE,
+            B_LD_PRED => IntraMode::LD,
+            B_RD_PRED => IntraMode::RD,
+            B_VR_PRED => IntraMode::VR,
+            B_VL_PRED => IntraMode::VL,
+            B_HD_PRED => IntraMode::HD,
+            B_HU_PRED => IntraMode::HU,
+            _ => return None,
+        })
+    }
+}
+
+impl Default for IntraMode {
+    fn default() -> Self {
+        IntraMode::DC
+    }
+}
+
 fn init_top_macroblocks(width: usize) -> Vec<MacroBlock> {
     let mb_width = (width + 15) / 16;
 
     let mb = MacroBlock {
         // Section 11.3 #3
-        bpred: [B_DC_PRED; 16],
-        luma_mode: DC_PRED,
-        ..MacroBlock::new()
+        bpred: [IntraMode::DC; 16],
+        luma_mode: LumaMode::DC,
+        .. MacroBlock::default()
     };
 
-    (0..mb_width).map(|_| mb).collect()
+    vec![mb; mb_width]
 }
 
 fn create_border(mbx: usize, mby: usize, mbw: usize, top: &[u8], left: &[u8]) -> [u8; 357] {
     let stride = 1usize + 16 + 4;
     let mut ws = [0u8; (1 + 16) * (1 + 16 + 4)];
 
     // A
     {
@@ -1542,36 +1675,35 @@ fn add_residue(pblock: &mut [u8], rblock
             let a = rblock[x + y * 4];
             let b = pblock[(y0 + y) * stride + x0 + x];
             let c = clamp(a + i32::from(b), 0, 255) as u8;
             pblock[(y0 + y) * stride + x0 + x] = c;
         }
     }
 }
 
-fn predict_4x4(ws: &mut [u8], stride: usize, modes: &[i8], resdata: &[i32]) {
+fn predict_4x4(ws: &mut [u8], stride: usize, modes: &[IntraMode], resdata: &[i32]) {
     for sby in 0usize..4 {
         for sbx in 0usize..4 {
             let i = sbx + sby * 4;
             let y0 = sby * 4 + 1;
             let x0 = sbx * 4 + 1;
             let rb = &resdata[i * 16..i * 16 + 16];
 
             match modes[i] {
-                B_TM_PRED => predict_tmpred(ws, 4, x0, y0, stride),
-                B_VE_PRED => predict_bvepred(ws, x0, y0, stride),
-                B_HE_PRED => predict_bhepred(ws, x0, y0, stride),
-                B_DC_PRED => predict_bdcpred(ws, x0, y0, stride),
-                B_LD_PRED => predict_bldpred(ws, x0, y0, stride),
-                B_RD_PRED => predict_brdpred(ws, x0, y0, stride),
-                B_VR_PRED => predict_bvrpred(ws, x0, y0, stride),
-                B_VL_PRED => predict_bvlpred(ws, x0, y0, stride),
-                B_HD_PRED => predict_bhdpred(ws, x0, y0, stride),
-                B_HU_PRED => predict_bhupred(ws, x0, y0, stride),
-                _ => panic!("unknown intra bmode"),
+                IntraMode::TM => predict_tmpred(ws, 4, x0, y0, stride),
+                IntraMode::VE => predict_bvepred(ws, x0, y0, stride),
+                IntraMode::HE => predict_bhepred(ws, x0, y0, stride),
+                IntraMode::DC => predict_bdcpred(ws, x0, y0, stride),
+                IntraMode::LD => predict_bldpred(ws, x0, y0, stride),
+                IntraMode::RD => predict_brdpred(ws, x0, y0, stride),
+                IntraMode::VR => predict_bvrpred(ws, x0, y0, stride),
+                IntraMode::VL => predict_bvlpred(ws, x0, y0, stride),
+                IntraMode::HD => predict_bhdpred(ws, x0, y0, stride),
+                IntraMode::HU => predict_bhupred(ws, x0, y0, stride),
             }
 
             add_residue(ws, rb, y0, x0, stride);
         }
     }
 }
 
 fn predict_vpred(a: &mut [u8], size: usize, x0: usize, y0: usize, stride: usize) {
--- a/third_party/rust/png/.cargo-checksum.json
+++ b/third_party/rust/png/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"8cc6eb1d08623955951841761c9757e67a43048d6cb40197ebabf2de1f6c46d4","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"eaf40297c75da471f7cda1f3458e8d91b4b2ec866e609527a13acfa93b638652","README.md":"4556c29a1c1dd656eb7a85bb1929f4112c7d8525216fc508e616bef4036ef023","examples/pngcheck.rs":"9eea856ab45e0daf3f470f7f86d0c3521cf3de7e06f0fcc8764800fa57ffd86d","examples/show.rs":"0cf8a74a1b8a0c350fee5eacfee082607e8adcd51968a1460ee6305d83041d19","src/chunk.rs":"f8aa01e68683b5cd41ac2580ac11f2d6a6190c52007e3f115dc5b7c3b0354e63","src/common.rs":"4f80198a5131de872a19e0b443d88def80d1688f4f1317cfd05a6b773564a48e","src/crc.rs":"7136e3ae5564db1aadfd45c3c4d65d1d41ede797b2e8be7ca1e731bd567d04bc","src/decoder/mod.rs":"e4d7e58c5f80ccccd445d22278ce46a77c9f64db8d0a8c20530917fcd6df3a1a","src/decoder/stream.rs":"917285c321e3de1b07b6aa5943bfef315e9b7bdc8035dca65b5c8c4b605b4796","src/encoder.rs":"ff0582366827a84a9a742d1781fcc41c005d34b422edeef9e063804f4b9a86c2","src/filter.rs":"74015c3e328bc0b5c03826f971ffb48f16903488f54ce16b0245b5a1467c0c08","src/lib.rs":"be7360d6f5c278f78da90e578b14bae6a4fc1e249538ff5e6aaf1d75d1bdea34","src/traits.rs":"f326ebcba17b87b609b564ff2aa4aaf1f5de4dcff991aa4d21f3d9b0ba39affc","src/utils.rs":"c5b45039c9903962842544d8ef5203a1ce820cb8010bd1bf8cc1f517d45ef160"},"package":"9adebf7fb91ccf5eac9da1a8e00e83cb8ae882c3e8d8e4ad59da73cb8c82a2c9"}
\ No newline at end of file
+{"files":{"Cargo.toml":"cbabe74b9508336598dee4e2736e644607fbaa05b1aa7b03cf324c14c02c747e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"eaf40297c75da471f7cda1f3458e8d91b4b2ec866e609527a13acfa93b638652","README.md":"a29453dab1a440374ed18881bfbb73651e2b84c35eabc0a7b293ab553ef345f4","benches/README.md":"0c60c3d497abdf6c032863aa47da41bc6bb4f5ff696d45dec0e6eb33459b14b0","benches/decoder.rs":"81a13f5c731f674cc21a6aa472bcf4cc6c3581a41b1e002fa3996fc9a6e0dfe5","examples/pngcheck.rs":"191ff0b61734a75befd0d3ecd3f39226e9f3ef89a5d7a16870808f5ebf0e054d","examples/show.rs":"22be41150fa02d42500c48920cf3b7277090680e336ab8744aac0cece8bccc68","src/chunk.rs":"f8aa01e68683b5cd41ac2580ac11f2d6a6190c52007e3f115dc5b7c3b0354e63","src/common.rs":"a0bc64f16cfdf511925a2869d9fda70ed07272a8278c1d2db142821babd4c931","src/decoder/mod.rs":"ec173948f4cd09837b5e59b30ba209a0b96d2cc23570152c4850891058632eff","src/decoder/stream.rs":"28ef3d00fc65463019f22e95b568b9776d6249de388d2af2af116017330a6bdd","src/encoder.rs":"8bc2f8a5f6f45a59de4933d230f3340f11c934d2c5f5493dbc202505d398319f","src/filter.rs":"7de56800200b15b7a6bf79eefb8771ae29c37accce8a1044f37620153060f8ba","src/lib.rs":"1d56a30f6283bbeaeb2cf7c03061b2081e8f85284b206104d08865a801b944e9","src/traits.rs":"3afe302164f1d5ffdc0482489332c6fc78120ce19c0a7db5a1f4bda0326d8f62","src/utils.rs":"03af618a3d2fe6d49828a7afc876d4561472588f542bb49191735b93f533c921"},"package":"8422b27bb2c013dd97b9aef69e161ce262236f49aaf46a0489011c8ff0264602"}
\ No newline at end of file
--- a/third_party/rust/png/Cargo.toml
+++ b/third_party/rust/png/Cargo.toml
@@ -1,53 +1,56 @@
 # 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
+# to registry (e.g., crates.io) dependencies
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
+edition = "2018"
 name = "png"
-version = "0.14.0"
+version = "0.15.0"
 authors = ["nwin <nwin@users.noreply.github.com>"]
 exclude = ["tests/*"]
 description = "PNG decoding and encoding library in pure Rust"
-license = "MIT/Apache-2.0"
-repository = "https://github.com/PistonDevelopers/image-png.git"
+categories = ["multimedia::images"]
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/image-rs/image-png.git"
 [dependencies.bitflags]
 version = "1.0"
 
+[dependencies.crc32fast]
+version = "1.2.0"
+
 [dependencies.deflate]
-version = "0.7.2"
+version = "0.7.12"
 optional = true
 
 [dependencies.inflate]
 version = "0.4.2"
-
-[dependencies.num-iter]
-version = "0.1.32"
 [dev-dependencies.getopts]
 version = "0.2.14"
 
 [dev-dependencies.glium]
 version = "0.22"
 features = ["glutin"]
 default-features = false
 
 [dev-dependencies.glob]
-version = "0.2.11"
+version = "0.3"
 
 [dev-dependencies.rand]
 version = "0.5.5"
 
 [dev-dependencies.term]
 version = "0.4"
 
 [features]
+benchmarks = []
 default = ["png-encoding"]
 png-encoding = ["deflate"]
 unstable = []
--- a/third_party/rust/png/README.md
+++ b/third_party/rust/png/README.md
@@ -1,16 +1,31 @@
 # PNG Decoder/Encoder
-[![Build Status](https://travis-ci.org/PistonDevelopers/image-png.svg?branch=master)](https://travis-ci.org/PistonDevelopers/image-png)
-[![Crates.io](https://docs.rs/png/badge.svg)](https://docs.rs/png)
+[![Build Status](https://travis-ci.org/image-rs/image-png.svg?branch=master)](https://travis-ci.org/image-rs/image-png)
+[![Documentation](https://docs.rs/png/badge.svg)](https://docs.rs/png)
 [![Crates.io](https://img.shields.io/crates/v/png.svg)](https://crates.io/crates/png)
-![Lines of Code](https://tokei.rs/b1/github/PistonDevelopers/image-png)
-[![License](https://img.shields.io/crates/l/png.svg)](https://github.com/PistonDevelopers/image-png)
+![Lines of Code](https://tokei.rs/b1/github/image-rs/image-png)
+[![License](https://img.shields.io/crates/l/png.svg)](https://github.com/image-rs/image-png)
+
+PNG decoder/encoder in pure Rust.
+
+It contains all features required to handle the entirety of [the PngSuite by
+Willem van Schack][PngSuite].
+
+[PngSuite]: http://www.schaik.com/pngsuite2011/pngsuite.html
 
-PNG decoder/encoder in pure Rust. Currently `pngcheck` is the most usable part. Build with `cargo build --release --example pngcheck`.
+## pngcheck
+
+The `pngcheck` utility is a small demonstration binary that checks and prints
+metadata on every `.png` image provided via parameter. You can run it (for
+example on the test directories) with
+
+```bash
+cargo run --release --example pngcheck ./tests/pngsuite/*
+```
 
 ## License
 
 Licensed under either of
 
  * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
  * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
 
new file mode 100644
--- /dev/null
+++ b/third_party/rust/png/benches/README.md
@@ -0,0 +1,6 @@
+# Getting started with benchmarking
+
+To run the benchmarks you need a nightly rust toolchain.
+Then you launch it with
+
+    rustup run nightly cargo bench --features=benchmarks
new file mode 100644
--- /dev/null
+++ b/third_party/rust/png/benches/decoder.rs
@@ -0,0 +1,25 @@
+#![cfg(feature = "benchmarks")]
+#![feature(test)]
+
+extern crate png;
+extern crate test;
+
+use std::fs::File;
+use std::io::Read;
+
+use png::Decoder;
+
+#[bench]
+fn bench_big(b: &mut test::Bencher) {
+    let mut data = Vec::new();
+    File::open("tests/pngsuite/PngSuite.png").unwrap().read_to_end(&mut data).unwrap();
+    let decoder = Decoder::new(&*data);
+    let (info, _) = decoder.read_info().unwrap();
+    let mut image = vec![0; info.buffer_size()];
+    b.iter(|| {
+        let decoder = Decoder::new(&*data);
+        let (_, mut decoder) = decoder.read_info().unwrap();
+        test::black_box(decoder.next_frame(&mut image)).unwrap();
+    });
+    b.bytes = info.buffer_size() as u64
+}
--- a/third_party/rust/png/examples/pngcheck.rs
+++ b/third_party/rust/png/examples/pngcheck.rs
@@ -9,32 +9,32 @@ use std::io;
 use std::io::prelude::*;
 use std::path::Path;
 use std::fs::File;
 use std::env;
 
 use getopts::{Matches, Options, ParsingStyle};
 use term::{color, Attr};
 
-fn parse_args() -> Option<Matches> {
+fn parse_args() -> Matches {
     let args: Vec<String> = env::args().collect();
     let mut opts = Options::new();
     opts.optflag("c", "", "colorize output (for ANSI terminals)")
         .optflag("q", "", "test quietly (output only errors)")
         //.optflag("t", "", "print contents of tEXt chunks (can be used with -q)");
         .optflag("v", "", "test verbosely (print most chunk data)")
         .parsing_style(ParsingStyle::StopAtFirstFree);
     if args.len() > 1 {
         match opts.parse(&args[1..]) {
-            Ok(matches) => return Some(matches),
+            Ok(matches) => return matches,
             Err(err) => println!("{}", err)
         }
     }
     println!("{}", opts.usage(&format!("Usage: pngcheck [-cpt] [file ...]")));
-    None
+    std::process::exit(0);
 }
 
 #[derive(Clone, Copy)]
 struct Config {
     quiet: bool,
     verbose: bool,
     color: bool
 }
@@ -70,25 +70,25 @@ fn final_channels(c: png::ColorType, trn
         Indexed => 3 + if trns { 1 } else { 0 },
         GrayscaleAlpha => 2,
         RGBA => 4
     }
 }
 fn check_image<P: AsRef<Path>>(c: Config, fname: P) -> io::Result<()> {
     // TODO improve performance by resusing allocations from decoder
     use png::Decoded::*;
-    let mut t = try!(term::stdout().ok_or(io::Error::new(
+    let mut t = term::stdout().ok_or(io::Error::new(
         io::ErrorKind::Other,
         "could not open terminal"
-    )));
+    ))?;
     let mut data = vec![0; 10*1024];
     let data_p = data.as_mut_ptr();
-    let mut reader = io::BufReader::new(try!(File::open(&fname)));
+    let mut reader = io::BufReader::new(File::open(&fname)?);
     let fname = fname.as_ref().to_string_lossy();
-    let n = try!(reader.read(&mut data));
+    let n = reader.read(&mut data)?;
     let mut buf = &data[..n];
     let mut pos = 0;
     let mut decoder = png::StreamingDecoder::new();
     // Image data
     let mut width = 0;
     let mut height = 0;
     let mut color = png::ColorType::Grayscale;
     let mut bits = 0;
@@ -102,114 +102,121 @@ fn check_image<P: AsRef<Path>>(c: Config
         () => ({
             compressed_size as f32/(
                 height as u64 *
                 (width as u64 * final_channels(color, trns) as u64 * bits as u64 + 7)>>3
             ) as f32
         });
     );
     let display_error = |err| -> Result<_, io::Error> {
-        let mut t = try!(term::stdout().ok_or(io::Error::new(
+        let mut t = term::stdout().ok_or(io::Error::new(
             io::ErrorKind::Other,
             "could not open terminal"
-        )));
+        ))?;
         if c.verbose {
             if c.color {
                 print!(": ");
-                try!(t.fg(color::RED));
-                try!(writeln!(t, "{}", err));
-                try!(t.attr(Attr::Bold));
-                try!(write!(t, "ERRORS DETECTED"));
-                try!(t.reset());
+                t.fg(color::RED)?;
+                writeln!(t, "{}", err)?;
+                t.attr(Attr::Bold)?;
+                write!(t, "ERRORS DETECTED")?;
+                t.reset()?;
             } else {
                 println!(": {}", err);
                 print!("ERRORS DETECTED")
             }
             println!(" in {}", fname);
         } else {
             if !c.quiet { if c.color {
-                try!(t.fg(color::RED));
-                try!(t.attr(Attr::Bold));
-                try!(write!(t, "ERROR"));
-                try!(t.reset());
-                try!(write!(t, ": "));
-                try!(t.fg(color::YELLOW));
-                try!(writeln!(t, "{}", fname));
-                try!(t.reset());
+                t.fg(color::RED)?;
+                t.attr(Attr::Bold)?;
+                write!(t, "ERROR")?;
+                t.reset()?;
+                write!(t, ": ")?;
+                t.fg(color::YELLOW)?;
+                writeln!(t, "{}", fname)?;
+                t.reset()?;
             } else {
                 println!("ERROR: {}", fname)
             }}
             print!("{}: ", fname);
             if c.color {
-                try!(t.fg(color::RED));
-                try!(writeln!(t, "{}", err));
-                try!(t.reset());
+                t.fg(color::RED)?;
+                writeln!(t, "{}", err)?;
+                t.reset()?;
             } else {
                 println!("{}", err);
             }
             
         }
         Ok(())
     };
     
     if c.verbose {
         print!("File: ");
         if c.color {
-            try!(t.attr(Attr::Bold));
-            try!(write!(t, "{}", fname));
-            try!(t.reset());
+            t.attr(Attr::Bold)?;
+            write!(t, "{}", fname)?;
+            t.reset()?;
         } else {
             print!("{}", fname);
         }
         print!(" ({}) bytes", data.len())
             
     }
     loop {
         if buf.len() == 0 {
             // circumvent borrow checker
-            let n = try!(reader.read(unsafe {
+            assert!(!data.is_empty());
+            let n = reader.read(unsafe {
                 ::std::slice::from_raw_parts_mut(data_p, data.len())
-            }));
+            })?;
+
+            // EOF
+            if n == 0 {
+                println!("ERROR: premature end of file {}", fname);
+                break;
+            }
             buf = &data[..n];
         }
         match decoder.update(buf, &mut Vec::new()) {
             Ok((_, ImageEnd)) => {
                 if !have_idat {
-                    try!(display_error(png::DecodingError::Format("IDAT chunk missing".into())));
+                    display_error(png::DecodingError::Format("IDAT chunk missing".into()))?;
                     break;
                 }
                 if !c.verbose && !c.quiet {
                     if c.color {
-                        try!(t.fg(color::GREEN));
-                        try!(t.attr(Attr::Bold));
-                        try!(write!(t, "OK"));
-                        try!(t.reset());
-                        try!(write!(t, ": "));
-                        try!(t.fg(color::YELLOW));
-                        try!(write!(t, "{}", fname));
-                        try!(t.reset());
+                        t.fg(color::GREEN)?;
+                        t.attr(Attr::Bold)?;
+                        write!(t, "OK")?;
+                        t.reset()?;
+                        write!(t, ": ")?;
+                        t.fg(color::YELLOW)?;
+                        write!(t, "{}", fname)?;
+                        t.reset()?;
                     } else {
                         print!("OK: {}", fname)
                     }
                     println!(
                         " ({}x{}, {}{}, {}, {:.1}%)",
                         width,
                         height,
                         display_image_type(bits, color),
                         (if trns { "+trns" } else { "" }),
                         display_interlaced(interlaced),
                         100.0*(1.0-c_ratio!())