Bug 1516262 - Part 2: Revendor rust dependencies; r=ato
authorBastien Orivel <eijebong@bananium.fr>
Wed, 02 Jan 2019 12:05:32 +0000
changeset 509394 cc0d70030c48dc3ded933124d3b2a0eee55f7189
parent 509393 87f621d0475355fda0e3aa04e1ec83f443ae75d8
child 509395 c6d3c8a25d9ef97b7004b6981f3574e5dcddd636
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersato
bugs1516262
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1516262 - Part 2: Revendor rust dependencies; r=ato
third_party/rust/base64/.cargo-checksum.json
third_party/rust/base64/Cargo.toml
third_party/rust/base64/README.md
third_party/rust/base64/RELEASE-NOTES.md
third_party/rust/base64/benches/benchmarks.rs
third_party/rust/base64/src/chunked_encoder.rs
third_party/rust/base64/src/decode.rs
third_party/rust/base64/src/display.rs
third_party/rust/base64/src/encode.rs
third_party/rust/base64/src/lib.rs
third_party/rust/base64/src/line_wrap.rs
third_party/rust/base64/src/tests.rs
third_party/rust/base64/src/write/encoder.rs
third_party/rust/base64/src/write/encoder_tests.rs
third_party/rust/base64/src/write/mod.rs
third_party/rust/base64/tests/decode.rs
third_party/rust/base64/tests/encode.rs
third_party/rust/base64/tests/tests.rs
third_party/rust/byteorder/.cargo-checksum.json
third_party/rust/byteorder/CHANGELOG.md
third_party/rust/byteorder/Cargo.toml
third_party/rust/byteorder/benches/bench.rs
third_party/rust/byteorder/src/io.rs
third_party/rust/byteorder/src/lib.rs
third_party/rust/safemem/.cargo-checksum.json
third_party/rust/safemem/Cargo.toml
third_party/rust/safemem/LICENSE-APACHE
third_party/rust/safemem/LICENSE-MIT
third_party/rust/safemem/README.md
third_party/rust/safemem/src/lib.rs
--- a/third_party/rust/base64/.cargo-checksum.json
+++ b/third_party/rust/base64/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"e6e873cf85b808ef7df811221f90dec19bfc9efc9b40237f325dfda8fc64fbfc","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0dd882e53de11566d50f8e8e2d5a651bcf3fabee4987d70f306233cf39094ba7","README.md":"9941b171f4885557b0dfaac9e6bba9d0d18df6143f9501cf4605ddb7d2fdffe4","RELEASE-NOTES.md":"d9a4dfe7499c69247f3216f681df0dca7cc217b6f7d38816f3b943f66544e220","benches/benchmarks.rs":"bfc990dfa1716acf5bbd7189b3d7438145a9441833d6e4a796d2ce4428e55e14","examples/make_tables.rs":"e7c3e665874faa10ff1906420eb5182d1b725bcd30ff0d6da719bb368683e197","src/chunked_encoder.rs":"3d92a8241ed6d1a402ad1c1a8c7aa9c736b62cecc4071f44bc29b1b7cc70488c","src/decode.rs":"968c9c13746338ea307d3ff0b528df7a4fa20c7a1071c6adc1fb23c573741b57","src/display.rs":"d8ec9fa3f2b03640b026bbdfd817cd76454e1bb9b6ae53bd793334cd0a4ac62e","src/encode.rs":"c38c64582105ea698c5d1ec1596f5f1d99cfc1fb894226b79c5c8e96f73e6541","src/lib.rs":"4aeed1db6057b03532b20c34dbb822c1edcb0b5a2c21cdd50e7ac6b06858843a","src/line_wrap.rs":"fd136457629b803417bd25eb191fd3665bb57b8726fc4d74e7325e499e4e88af","src/tables.rs":"10b09997ed9765dc46c2d1f0df21b915d88c4f47a292b5c7df5c1851e724fb03","src/tests.rs":"cf0ddeb01b2149041b7ea99a881b6f149b1630110c5c2eedee6b1f44e873ea6c","tests/decode.rs":"c06a7595a0ac708961a180d4a8393f6d377b56028f75b29e6e34fd8451d84226","tests/encode.rs":"2eb3c8f81a4f807be69d1dfb0857625130017b0fa7037f7168f434c886cc851b","tests/helpers.rs":"a76015e4a4e8f98213bdbaa592cd9574ccdc95a28e1b1f835a2753e09fa6037f","tests/tests.rs":"13929406ba13504ff49d1a16a2578a87c560834fba0eaad78edecf0793261b0e"},"package":"85415d2594767338a74a30c1d370b2f3262ec1b4ed2d7bba5b3faf4de40467d9"}
\ No newline at end of file
+{"files":{"Cargo.toml":"89131475d69542cea57da56ce5ba4a782188f969a1d1dc399eb254b93284a278","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0dd882e53de11566d50f8e8e2d5a651bcf3fabee4987d70f306233cf39094ba7","README.md":"7269a723029fe3254ee94efd2967ccf3521c17978d32d064b93e693271323c43","RELEASE-NOTES.md":"405f7c5f06c7e81b232d78111ddac6bc63878528bea4781645866d5f62a9f2bf","benches/benchmarks.rs":"dbdb26bea4d0d214e39176fb7ab5af5afb78863fb345d11bf6e743344ffd36d3","examples/make_tables.rs":"e7c3e665874faa10ff1906420eb5182d1b725bcd30ff0d6da719bb368683e197","src/chunked_encoder.rs":"fe2d6d65d0c5e30f8f5d0ec7a95bf5a5028c47ae338ee8c5ef8d0d7c1d968031","src/decode.rs":"f08cdf315ba7ebad7fbd06ec3b6cb3612a52d9ce16662ce0d7f3d191862f7b17","src/display.rs":"59a9ca41f5fe42be0db700a9180e58e33eaff7a08fcbfd7b24f0286544613915","src/encode.rs":"7f6413ad27bf135f1fe38866a661a7300610905d8c858aff52eff2fd9e02a441","src/lib.rs":"893155d20c55525ebcf0b46de76c4cbdf1e0e43518f911d52e2de357ec7e29a6","src/tables.rs":"10b09997ed9765dc46c2d1f0df21b915d88c4f47a292b5c7df5c1851e724fb03","src/tests.rs":"4c72499a5b13f9ed793f275445bf9d1d631530bb7c39494de96d08e5c0602430","src/write/encoder.rs":"58ded8c942b0b96e8466f9ff667fcb96c262a492c67d76414521baa1e6f32b24","src/write/encoder_tests.rs":"9e7f165650bde35858d05bdb1655ae009f4e44014e296dab6cf6e789f5271de4","src/write/mod.rs":"124b223f3effcb1d85671a4173a635cdfae480341b032217c77876647344176b","tests/decode.rs":"dc7167f8127a3ece7234f3631664e5a0987a0e2b7333f2d93bfc7e88db2f9ad6","tests/encode.rs":"5efb6904c36c6f899a05078e5c9be756fc58af1ee9940edfa8dea1ee53675364","tests/helpers.rs":"a76015e4a4e8f98213bdbaa592cd9574ccdc95a28e1b1f835a2753e09fa6037f","tests/tests.rs":"eec857210322f4ea1531f67afe1aeacfc5626ec50781ee39f91c0b2a677b9846"},"package":"621fc7ecb8008f86d7fb9b95356cd692ce9514b80a86d85b397f32a22da7b9e2"}
\ No newline at end of file
--- a/third_party/rust/base64/Cargo.toml
+++ b/third_party/rust/base64/Cargo.toml
@@ -7,26 +7,23 @@
 #
 # 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 = "base64"
-version = "0.9.2"
+version = "0.10.0"
 authors = ["Alice Maz <alice@alicemaz.com>", "Marshall Pierce <marshall@mpierce.org>"]
 description = "encodes and decodes base64 as bytes or utf8"
 documentation = "https://github.com/alicemaz/rust-base64/blob/master/README.md"
 readme = "README.md"
 keywords = ["base64", "utf8", "encode", "decode"]
 categories = ["encoding"]
 license = "MIT/Apache-2.0"
 repository = "https://github.com/alicemaz/rust-base64"
 [profile.bench]
 debug = true
 [dependencies.byteorder]
-version = "1.1.0"
-
-[dependencies.safemem]
-version = "0.2.0"
+version = "1.2.6"
 [dev-dependencies.rand]
-version = "0.4"
+version = "0.5.5"
--- a/third_party/rust/base64/README.md
+++ b/third_party/rust/base64/README.md
@@ -1,19 +1,18 @@
 [base64](https://crates.io/crates/base64)
 ===
-[![Docs](https://docs.rs/base64/badge.svg)](https://docs.rs/base64)
+
+[![](https://img.shields.io/crates/v/base64.svg)](https://crates.io/crates/base64) [![Docs](https://docs.rs/base64/badge.svg)](https://docs.rs/base64) [![Build](https://travis-ci.org/alicemaz/rust-base64.svg?branch=master)](https://travis-ci.org/alicemaz/rust-base64) [![codecov](https://codecov.io/gh/alicemaz/rust-base64/branch/master/graph/badge.svg)](https://codecov.io/gh/alicemaz/rust-base64)
 
 It's base64. What more could anyone want?
 
 Example
 ---
 
-In Cargo.toml: `base64 = "~0.6.0"`
-
 ```rust
 extern crate base64;
 
 use base64::{encode, decode};
 
 fn main() {
     let a = b"hello world";
     let b = "aGVsbG8gd29ybGQ=";
@@ -88,17 +87,16 @@ You'll see a bunch of interleaved rust s
 Fuzzing
 ---
 
 This uses [cargo-fuzz](https://github.com/rust-fuzz/cargo-fuzz). See `fuzz/fuzzers` for the available fuzzing scripts. To run, use an invocation like these:
 
 ```
 cargo +nightly fuzz run roundtrip
 cargo +nightly fuzz run roundtrip_no_pad
-cargo +nightly fuzz run roundtrip_mime -- -max_len=10240
 cargo +nightly fuzz run roundtrip_random_config -- -max_len=10240
 ```
 
 
 License
 ---
 
 This project is dual-licensed under MIT and Apache 2.0.
--- a/third_party/rust/base64/RELEASE-NOTES.md
+++ b/third_party/rust/base64/RELEASE-NOTES.md
@@ -1,8 +1,22 @@
+# 0.10.0
+
+- Remove line wrapping. Line wrapping was never a great conceptual fit in this library, and other features (streaming encoding, etc) either couldn't support it or could support only special cases of it with a great increase in complexity. Line wrapping has been pulled out into a [line-wrap](https://crates.io/crates/line-wrap) crate, so it's still available if you need it.
+  - `Base64Display` creation no longer uses a `Result` because it can't fail, which means its helper methods for common
+  configs that `unwrap()` for you are no longer needed
+- Add a streaming encoder `Write` impl to transparently base64 as you write.
+- Remove the remaining `unsafe` code.
+- Remove whitespace stripping to simplify `no_std` support. No out of the box configs use it, and it's trivial to do yourself if needed: `filter(|b| !b" \n\t\r\x0b\x0c".contains(b)`.
+- Detect invalid trailing symbols when decoding and return an error rather than silently ignoring them.
+
+# 0.9.3
+
+- Update safemem
+
 # 0.9.2
 
 - Derive `Clone` for `DecodeError`.
 
 # 0.9.1
 
 - Add support for `crypt(3)`'s base64 variant.
 
--- a/third_party/rust/base64/benches/benchmarks.rs
+++ b/third_party/rust/base64/benches/benchmarks.rs
@@ -1,19 +1,20 @@
 #![feature(test)]
 
 extern crate base64;
 extern crate rand;
 extern crate test;
 
 use base64::display;
 use base64::{decode, decode_config_buf, decode_config_slice, encode, encode_config_buf,
-             encode_config_slice, Config, MIME, STANDARD};
+             encode_config_slice, write, Config, STANDARD};
 
-use rand::Rng;
+use rand::{Rng, FromEntropy};
+use std::io::Write;
 use test::Bencher;
 
 #[bench]
 fn encode_3b(b: &mut Bencher) {
     do_encode_bench(b, 3)
 }
 
 #[bench]
@@ -62,21 +63,16 @@ fn encode_500b(b: &mut Bencher) {
 }
 
 #[bench]
 fn encode_500b_reuse_buf(b: &mut Bencher) {
     do_encode_bench_reuse_buf(b, 500, STANDARD)
 }
 
 #[bench]
-fn encode_500b_reuse_buf_mime(b: &mut Bencher) {
-    do_encode_bench_reuse_buf(b, 500, MIME)
-}
-
-#[bench]
 fn encode_3kib(b: &mut Bencher) {
     do_encode_bench(b, 3 * 1024)
 }
 
 #[bench]
 fn encode_3kib_display(b: &mut Bencher) {
     do_encode_bench_display(b, 3 * 1024)
 }
@@ -87,18 +83,18 @@ fn encode_3kib_reuse_buf(b: &mut Bencher
 }
 
 #[bench]
 fn encode_3kib_slice(b: &mut Bencher) {
     do_encode_bench_slice(b, 3 * 1024, STANDARD)
 }
 
 #[bench]
-fn encode_3kib_reuse_buf_mime(b: &mut Bencher) {
-    do_encode_bench_reuse_buf(b, 3 * 1024, MIME)
+fn encode_3kib_reuse_buf_stream(b: &mut Bencher) {
+    do_encode_bench_stream(b, 3 * 1024, STANDARD)
 }
 
 #[bench]
 fn encode_3mib(b: &mut Bencher) {
     do_encode_bench(b, 3 * 1024 * 1024)
 }
 
 #[bench]
@@ -298,17 +294,17 @@ fn do_encode_bench(b: &mut Bencher, size
 }
 
 fn do_encode_bench_display(b: &mut Bencher, size: usize) {
     let mut v: Vec<u8> = Vec::with_capacity(size);
     fill(&mut v);
 
     b.bytes = v.len() as u64;
     b.iter(|| {
-        let e = format!("{}", display::Base64Display::standard(&v));
+        let e = format!("{}", display::Base64Display::with_config(&v, STANDARD));
         test::black_box(&e);
     });
 }
 
 fn do_encode_bench_reuse_buf(b: &mut Bencher, size: usize, config: Config) {
     let mut v: Vec<u8> = Vec::with_capacity(size);
     fill(&mut v);
 
@@ -330,16 +326,33 @@ fn do_encode_bench_slice(b: &mut Bencher
     b.bytes = v.len() as u64;
     // conservative estimate of encoded size
     buf.resize(size * 2, 0);
     b.iter(|| {
         encode_config_slice(&v, config, &mut buf);
     });
 }
 
+fn do_encode_bench_stream(b: &mut Bencher, size: usize, config: Config) {
+    let mut v: Vec<u8> = Vec::with_capacity(size);
+    fill(&mut v);
+
+    let mut buf = Vec::new();
+
+    b.bytes = v.len() as u64;
+
+    buf.reserve(size * 2);
+    b.iter(|| {
+        buf.clear();
+        let mut stream_enc = write::EncoderWriter::new(&mut buf, config);
+        stream_enc.write_all(&v).unwrap();
+        stream_enc.flush().unwrap();
+    });
+}
+
 fn fill(v: &mut Vec<u8>) {
     let cap = v.capacity();
     // weak randomness is plenty; we just want to not be completely friendly to the branch predictor
-    let mut r = rand::weak_rng();
+    let mut r = rand::rngs::SmallRng::from_entropy();
     while v.len() < cap {
         v.push(r.gen::<u8>());
     }
 }
--- a/third_party/rust/base64/src/chunked_encoder.rs
+++ b/third_party/rust/base64/src/chunked_encoder.rs
@@ -1,42 +1,34 @@
 use encode::{add_padding, encode_to_slice};
-use line_wrap::line_wrap;
-use std::cmp;
-use {Config, LineEnding, LineWrap};
+use std::{cmp, str};
+use Config;
 
 /// The output mechanism for ChunkedEncoder's encoded bytes.
 pub trait Sink {
     type Error;
 
     /// Handle a chunk of encoded base64 data (as UTF-8 bytes)
     fn write_encoded_bytes(&mut self, encoded: &[u8]) -> Result<(), Self::Error>;
 }
 
-#[derive(Debug, PartialEq)]
-pub enum ChunkedEncoderError {
-    /// If wrapping is configured, the line length must be a multiple of 4, and must not be absurdly
-    /// large (see BUF_SIZE).
-    InvalidLineLength,
-}
-
 const BUF_SIZE: usize = 1024;
 
 /// A base64 encoder that emits encoded bytes in chunks without heap allocation.
 pub struct ChunkedEncoder {
     config: Config,
     max_input_chunk_len: usize,
 }
 
 impl ChunkedEncoder {
-    pub fn new(config: Config) -> Result<ChunkedEncoder, ChunkedEncoderError> {
-        Ok(ChunkedEncoder {
+    pub fn new(config: Config) -> ChunkedEncoder {
+        ChunkedEncoder {
             config,
-            max_input_chunk_len: max_input_length(BUF_SIZE, &config)?,
-        })
+            max_input_chunk_len: max_input_length(BUF_SIZE, &config),
+        }
     }
 
     pub fn encode<S: Sink>(&self, bytes: &[u8], sink: &mut S) -> Result<(), S::Error> {
         let mut encode_buf: [u8; BUF_SIZE] = [0; BUF_SIZE];
         let encode_table = self.config.char_set.encode_table();
 
         let mut input_index = 0;
 
@@ -52,134 +44,78 @@ impl ChunkedEncoder {
             let more_input_left = input_index < bytes.len();
 
             if self.config.pad && !more_input_left {
                 // no more input, add padding if needed. Buffer will have room because
                 // max_input_length leaves room for it.
                 b64_bytes_written += add_padding(bytes.len(), &mut encode_buf[b64_bytes_written..]);
             }
 
-            let line_ending_bytes = match self.config.line_wrap {
-                LineWrap::NoWrap => 0,
-                LineWrap::Wrap(line_len, line_ending) => {
-                    let initial_line_ending_bytes =
-                        line_wrap(&mut encode_buf, b64_bytes_written, line_len, line_ending);
-
-                    if more_input_left {
-                        assert_eq!(input_chunk_len, self.max_input_chunk_len);
-                        // If there are more bytes of input, then we know we didn't just do the
-                        // last chunk. line_wrap() doesn't put an ending after the last line, so we
-                        // append one more line ending here. Since the chunk just encoded was not
-                        // the last one, it was multiple of the line length (max_input_chunk_len),
-                        // and therefore we can just put the line ending bytes at the end of the
-                        // contents of the buffer.
-                        match line_ending {
-                            LineEnding::LF => {
-                                encode_buf[b64_bytes_written + initial_line_ending_bytes] = b'\n';
-                                initial_line_ending_bytes + 1
-                            }
-                            LineEnding::CRLF => {
-                                encode_buf[b64_bytes_written + initial_line_ending_bytes] = b'\r';
-                                encode_buf[b64_bytes_written + initial_line_ending_bytes + 1] =
-                                    b'\n';
-                                initial_line_ending_bytes + 2
-                            }
-                        }
-                    } else {
-                        initial_line_ending_bytes
-                    }
-                }
-            };
-
-            let total_bytes_written = b64_bytes_written + line_ending_bytes;
-
-            sink.write_encoded_bytes(&encode_buf[0..total_bytes_written])?;
+            sink.write_encoded_bytes(&encode_buf[0..b64_bytes_written])?;
         }
 
         Ok(())
     }
 }
 
 /// Calculate the longest input that can be encoded for the given output buffer size.
 ///
-/// If config requires line wrap, the calculated input length will be the maximum number of input
-/// lines that can fit in the output buffer after each line has had its line ending appended.
-///
 /// If the config requires padding, two bytes of buffer space will be set aside so that the last
 /// chunk of input can be encoded safely.
 ///
 /// The input length will always be a multiple of 3 so that no encoding state has to be carried over
 /// between chunks.
-///
-/// If the configured line length is not divisible by 4 (and therefore would require carrying
-/// encoder state between chunks), or if the line length is too big for the buffer, an error will be
-/// returned.
-///
-/// Note that the last overall line of input should *not* have an ending appended, but this will
-/// conservatively calculate space as if it should because encoding is done in chunks, and all the
-/// chunks before the last one will need a line ending after the last encoded line in that chunk.
-fn max_input_length(encoded_buf_len: usize, config: &Config) -> Result<usize, ChunkedEncoderError> {
+fn max_input_length(encoded_buf_len: usize, config: &Config) -> usize {
     let effective_buf_len = if config.pad {
         // make room for padding
         encoded_buf_len
             .checked_sub(2)
             .expect("Don't use a tiny buffer")
     } else {
         encoded_buf_len
     };
 
-    match config.line_wrap {
-        // No wrapping, no padding, so just normal base64 expansion.
-        LineWrap::NoWrap => Ok((effective_buf_len / 4) * 3),
-        LineWrap::Wrap(line_len, line_ending) => {
-            // To avoid complicated encode buffer shuffling, only allow line lengths that are
-            // multiples of 4 (which map to input lengths that are multiples of 3).
-            // line_len is never 0.
-            if line_len % 4 != 0 {
-                return Err(ChunkedEncoderError::InvalidLineLength);
-            }
+    // No padding, so just normal base64 expansion.
+    (effective_buf_len / 4) * 3
+}
+
 
-            let single_encoded_full_line_with_ending_len = line_len
-                .checked_add(line_ending.len())
-                .expect("Encoded line length with ending exceeds usize");
+// A really simple sink that just appends to a string
+pub(crate) struct StringSink<'a> {
+    string: &'a mut String,
+}
 
-            // max number of complete lines with endings that will fit in buffer
-            let num_encoded_wrapped_lines_in_buffer =
-                effective_buf_len / single_encoded_full_line_with_ending_len;
-
-            if num_encoded_wrapped_lines_in_buffer == 0 {
-                // line + ending is longer than can fit into encode buffer; give up
-                Err(ChunkedEncoderError::InvalidLineLength)
-            } else {
-                let input_len_for_line_len = (line_len / 4) * 3;
+impl<'a> StringSink<'a> {
+    pub(crate) fn new(s: &mut String) -> StringSink {
+        StringSink {
+            string: s,
+        }
+    }
+}
 
-                let input_len = input_len_for_line_len
-                    .checked_mul(num_encoded_wrapped_lines_in_buffer)
-                    .expect("Max input size exceeds usize");
+impl<'a> Sink for StringSink<'a> {
+    type Error = ();
 
-                assert!(input_len % 3 == 0 && input_len > 1);
+    fn write_encoded_bytes(&mut self, s: &[u8]) -> Result<(), Self::Error> {
+        self.string.push_str(str::from_utf8(s).unwrap());
 
-                Ok(input_len)
-            }
-        }
+        Ok(())
     }
 }
 
 #[cfg(test)]
 pub mod tests {
     extern crate rand;
 
     use super::*;
     use tests::random_config;
     use *;
 
-    use std::str;
-
-    use self::rand::distributions::{IndependentSample, Range};
-    use self::rand::Rng;
+    use self::rand::distributions::{Distribution, Range};
+    use self::rand::{Rng, FromEntropy};
 
     #[test]
     fn chunked_encode_empty() {
         assert_eq!("", chunked_encode_str(&[], STANDARD));
     }
 
     #[test]
     fn chunked_encode_intermediate_fast_loop() {
@@ -201,309 +137,110 @@ pub mod tests {
 
     #[test]
     fn chunked_encode_slow_loop_only() {
         // < 8 bytes input, slow loop only
         assert_eq!("Zm9vYmFy", chunked_encode_str(b"foobar", STANDARD));
     }
 
     #[test]
-    fn chunked_encode_line_wrap_padding() {
-        // < 8 bytes input, slow loop only
-        let config = config_wrap(true, 4, LineEnding::LF);
-        assert_eq!(
-            "Zm9v\nYmFy\nZm9v\nYmFy\nZg==",
-            chunked_encode_str(b"foobarfoobarf", config)
-        );
-    }
-
-    #[test]
-    fn chunked_encode_longer_than_one_buffer_adds_final_line_wrap_lf() {
-        // longest line len possible
-        let config = config_wrap(false, 1020, LineEnding::LF);
-        let input = vec![0xFF; 768];
-        let encoded = chunked_encode_str(&input, config);
-        // got a line wrap
-        assert_eq!(1024 + 1, encoded.len());
-
-        for &b in encoded.as_bytes()[0..1020].iter() {
-            // ascii /
-            assert_eq!(47, b);
-        }
-
-        assert_eq!(10, encoded.as_bytes()[1020]);
-
-        for &b in encoded.as_bytes()[1021..].iter() {
-            // ascii /
-            assert_eq!(47, b);
-        }
-    }
-
-    #[test]
-    fn chunked_encode_longer_than_one_buffer_adds_final_line_wrap_crlf() {
-        // longest line len possible
-        let config = config_wrap(false, 1020, LineEnding::CRLF);
-        let input = vec![0xFF; 768];
-        let encoded = chunked_encode_str(&input, config);
-        // got a line wrap
-        assert_eq!(1024 + 2, encoded.len());
-
-        for &b in encoded.as_bytes()[0..1020].iter() {
-            // ascii /
-            assert_eq!(47, b);
-        }
-
-        assert_eq!(13, encoded.as_bytes()[1020]);
-        assert_eq!(10, encoded.as_bytes()[1021]);
-
-        for &b in encoded.as_bytes()[1022..].iter() {
-            // ascii /
-            assert_eq!(47, b);
-        }
-    }
-
-    #[test]
     fn chunked_encode_matches_normal_encode_random_string_sink() {
         let helper = StringSinkTestHelper;
         chunked_encode_matches_normal_encode_random(&helper);
     }
 
     #[test]
-    fn max_input_length_no_wrap_no_pad() {
-        let config = config_no_wrap(false);
-        assert_eq!(768, max_input_length(1024, &config).unwrap());
-    }
-
-    #[test]
-    fn max_input_length_no_wrap_with_pad_decrements_one_triple() {
-        let config = config_no_wrap(true);
-        assert_eq!(765, max_input_length(1024, &config).unwrap());
-    }
-
-    #[test]
-    fn max_input_length_no_wrap_with_pad_one_byte_short() {
-        let config = config_no_wrap(true);
-        assert_eq!(765, max_input_length(1025, &config).unwrap());
-    }
-
-    #[test]
-    fn max_input_length_no_wrap_with_pad_fits_exactly() {
-        let config = config_no_wrap(true);
-        assert_eq!(768, max_input_length(1026, &config).unwrap());
+    fn max_input_length_no_pad() {
+        let config = config_with_pad(false);
+        assert_eq!(768, max_input_length(1024, &config));
     }
 
     #[test]
-    fn max_input_length_wrap_with_lf_fits_exactly_no_pad() {
-        // 10 * (72 + 1) = 730. 54 input bytes = 72 encoded bytes, + 1 for LF.
-        let config = config_wrap(false, 72, LineEnding::LF);
-        assert_eq!(540, max_input_length(730, &config).unwrap());
-    }
-
-    #[test]
-    fn max_input_length_wrap_with_lf_fits_one_spare_byte_no_pad() {
-        // 10 * (72 + 1) = 730. 54 input bytes = 72 encoded bytes, + 1 for LF.
-        let config = config_wrap(false, 72, LineEnding::LF);
-        assert_eq!(540, max_input_length(731, &config).unwrap());
-    }
-
-    #[test]
-    fn max_input_length_wrap_with_lf_size_one_byte_short_of_another_line_no_pad() {
-        // 10 * (72 + 1) = 730. 54 input bytes = 72 encoded bytes, + 1 for LF.
-        // 73 * 11 = 803
-        let config = config_wrap(false, 72, LineEnding::LF);
-        assert_eq!(540, max_input_length(802, &config).unwrap());
-    }
-
-    #[test]
-    fn max_input_length_wrap_with_lf_size_another_line_no_pad() {
-        // 10 * (72 + 1) = 730. 54 input bytes = 72 encoded bytes, + 1 for LF.
-        // 73 * 11 = 803
-        let config = config_wrap(false, 72, LineEnding::LF);
-        assert_eq!(594, max_input_length(803, &config).unwrap());
-    }
-
-    #[test]
-    fn max_input_length_wrap_with_lf_one_byte_short_with_pad() {
-        // one fewer input line
-        let config = config_wrap(true, 72, LineEnding::LF);
-        assert_eq!(486, max_input_length(731, &config).unwrap());
+    fn max_input_length_with_pad_decrements_one_triple() {
+        let config = config_with_pad(true);
+        assert_eq!(765, max_input_length(1024, &config));
     }
 
     #[test]
-    fn max_input_length_wrap_with_lf_fits_exactly_with_pad() {
-        // 10 * (72 + 1) = 730. 54 input bytes = 72 encoded bytes, + 1 for LF.
-        let config = config_wrap(true, 72, LineEnding::LF);
-        assert_eq!(540, max_input_length(732, &config).unwrap());
-    }
-
-    #[test]
-    fn max_input_length_wrap_line_len_wont_fit_one_line_lf() {
-        // 300 bytes is 400 encoded, + 1 for LF
-        let config = config_wrap(false, 400, LineEnding::LF);
-        assert_eq!(
-            ChunkedEncoderError::InvalidLineLength,
-            max_input_length(400, &config).unwrap_err()
-        );
-    }
-
-    #[test]
-    fn max_input_length_wrap_line_len_just_fits_one_line_lf() {
-        // 300 bytes is 400 encoded, + 1 for LF
-        let config = Config::new(
-            CharacterSet::Standard,
-            false,
-            false,
-            LineWrap::Wrap(400, LineEnding::LF),
-        );
-        assert_eq!(300, max_input_length(401, &config).unwrap());
+    fn max_input_length_with_pad_one_byte_short() {
+        let config = config_with_pad(true);
+        assert_eq!(765, max_input_length(1025, &config));
     }
 
     #[test]
-    fn max_input_length_wrap_with_crlf_fits_exactly_no_pad() {
-        // 10 * (72 + 2) = 740. 54 input bytes = 72 encoded bytes, + 2 for CRLF.
-        let config = config_wrap(false, 72, LineEnding::CRLF);
-        assert_eq!(540, max_input_length(740, &config).unwrap());
-    }
-
-    #[test]
-    fn max_input_length_wrap_with_crlf_fits_one_spare_byte_no_pad() {
-        // 10 * (72 + 2) = 740. 54 input bytes = 72 encoded bytes, + 2 for CRLF.
-        let config = config_wrap(false, 72, LineEnding::CRLF);
-        assert_eq!(540, max_input_length(741, &config).unwrap());
+    fn max_input_length_with_pad_fits_exactly() {
+        let config = config_with_pad(true);
+        assert_eq!(768, max_input_length(1026, &config));
     }
 
     #[test]
-    fn max_input_length_wrap_with_crlf_size_one_byte_short_of_another_line_no_pad() {
-        // 10 * (72 + 2) = 740. 54 input bytes = 72 encoded bytes, + 2 for CRLF.
-        // 74 * 11 = 814
-        let config = config_wrap(false, 72, LineEnding::CRLF);
-        assert_eq!(540, max_input_length(813, &config).unwrap());
-    }
-
-    #[test]
-    fn max_input_length_wrap_with_crlf_size_another_line_no_pad() {
-        // 10 * (72 + 2) = 740. 54 input bytes = 72 encoded bytes, + 2 for CRLF.
-        // 74 * 11 = 814
-        let config = config_wrap(false, 72, LineEnding::CRLF);
-        assert_eq!(594, max_input_length(814, &config).unwrap());
-    }
-
-    #[test]
-    fn max_input_length_wrap_line_len_not_multiple_of_4_rejected() {
-        let config = config_wrap(false, 41, LineEnding::LF);
-        assert_eq!(
-            ChunkedEncoderError::InvalidLineLength,
-            max_input_length(400, &config).unwrap_err()
+    fn max_input_length_cant_use_extra_single_encoded_byte() {
+        let config = Config::new(
+            CharacterSet::Standard,
+            false,
         );
+        assert_eq!(300, max_input_length(401, &config));
     }
 
     pub fn chunked_encode_matches_normal_encode_random<S: SinkTestHelper>(sink_test_helper: &S) {
         let mut input_buf: Vec<u8> = Vec::new();
         let mut output_buf = String::new();
-        let mut rng = rand::weak_rng();
-        let line_len_range = Range::new(1, 1020);
+        let mut rng = rand::rngs::SmallRng::from_entropy();
         let input_len_range = Range::new(1, 10_000);
 
         for _ in 0..5_000 {
             input_buf.clear();
             output_buf.clear();
 
-            let buf_len = input_len_range.ind_sample(&mut rng);
+            let buf_len = input_len_range.sample(&mut rng);
             for _ in 0..buf_len {
                 input_buf.push(rng.gen());
             }
 
-            let config = random_config_for_chunked_encoder(&mut rng, &line_len_range);
+            let config = random_config(&mut rng);
 
             let chunk_encoded_string = sink_test_helper.encode_to_string(config, &input_buf);
             encode_config_buf(&input_buf, config, &mut output_buf);
 
             assert_eq!(
                 output_buf, chunk_encoded_string,
-                "input len={}, config: pad={}, wrap={:?}",
-                buf_len, config.pad, config.line_wrap
+                "input len={}, config: pad={}",
+                buf_len, config.pad
             );
         }
     }
 
     fn chunked_encode_str(bytes: &[u8], config: Config) -> String {
-        let mut sink = StringSink::new();
-
+        let mut s = String::new();
         {
-            let encoder = ChunkedEncoder::new(config).unwrap();
+            let mut sink = StringSink::new(&mut s);
+            let encoder = ChunkedEncoder::new(config);
             encoder.encode(bytes, &mut sink).unwrap();
         }
 
-        return sink.string;
+        return s;
     }
 
-    fn random_config_for_chunked_encoder<R: Rng>(
-        rng: &mut R,
-        line_len_range: &Range<usize>,
-    ) -> Config {
-        loop {
-            let config = random_config(rng, line_len_range);
-
-            // only use a config with line_len that is divisible by 4
-            match config.line_wrap {
-                LineWrap::NoWrap => return config,
-                LineWrap::Wrap(line_len, _) => if line_len % 4 == 0 {
-                    return config;
-                },
-            }
-        }
-    }
-
-    fn config_no_wrap(pad: bool) -> Config {
-        Config::new(CharacterSet::Standard, pad, false, LineWrap::NoWrap)
-    }
-
-    fn config_wrap(pad: bool, line_len: usize, line_ending: LineEnding) -> Config {
-        Config::new(
-            CharacterSet::Standard,
-            pad,
-            false,
-            LineWrap::Wrap(line_len, line_ending),
-        )
+    fn config_with_pad(pad: bool) -> Config {
+        Config::new(CharacterSet::Standard, pad)
     }
 
     // An abstraction around sinks so that we can have tests that easily to any sink implementation
     pub trait SinkTestHelper {
         fn encode_to_string(&self, config: Config, bytes: &[u8]) -> String;
     }
 
-    // A really simple sink that just appends to a string for testing
-    struct StringSink {
-        string: String,
-    }
-
-    impl StringSink {
-        fn new() -> StringSink {
-            StringSink {
-                string: String::new(),
-            }
-        }
-    }
-
-    impl Sink for StringSink {
-        type Error = ();
-
-        fn write_encoded_bytes(&mut self, s: &[u8]) -> Result<(), Self::Error> {
-            self.string.push_str(str::from_utf8(s).unwrap());
-
-            Ok(())
-        }
-    }
-
     struct StringSinkTestHelper;
 
     impl SinkTestHelper for StringSinkTestHelper {
         fn encode_to_string(&self, config: Config, bytes: &[u8]) -> String {
-            let encoder = ChunkedEncoder::new(config).unwrap();
-            let mut sink = StringSink::new();
+            let encoder = ChunkedEncoder::new(config);
+            let mut s = String::new();
+            {
+                let mut sink = StringSink::new(&mut s);
+                encoder.encode(bytes, &mut sink).unwrap();
+            }
 
-            encoder.encode(bytes, &mut sink).unwrap();
-
-            sink.string
+            s
         }
     }
 
 }
--- a/third_party/rust/base64/src/decode.rs
+++ b/third_party/rust/base64/src/decode.rs
@@ -20,34 +20,43 @@ const DECODED_BLOCK_LEN: usize =
 
 /// Errors that can occur while decoding.
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub enum DecodeError {
     /// An invalid byte was found in the input. The offset and offending byte are provided.
     InvalidByte(usize, u8),
     /// The length of the input is invalid.
     InvalidLength,
+    /// The last non-padding input symbol's encoded 6 bits have nonzero bits that will be discarded.
+    /// This is indicative of corrupted or truncated Base64.
+    /// Unlike InvalidByte, which reports symbols that aren't in the alphabet, this error is for
+    /// symbols that are in the alphabet but represent nonsensical encodings.
+    InvalidLastSymbol(usize, u8),
 }
 
 impl fmt::Display for DecodeError {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
             DecodeError::InvalidByte(index, byte) => {
                 write!(f, "Invalid byte {}, offset {}.", byte, index)
             }
             DecodeError::InvalidLength => write!(f, "Encoded text cannot have a 6-bit remainder."),
+            DecodeError::InvalidLastSymbol(index, byte) => {
+                write!(f, "Invalid last symbol {}, offset {}.", byte, index)
+            }
         }
     }
 }
 
 impl error::Error for DecodeError {
     fn description(&self) -> &str {
         match *self {
             DecodeError::InvalidByte(_, _) => "invalid byte",
             DecodeError::InvalidLength => "invalid length",
+            DecodeError::InvalidLastSymbol(_, _) => "invalid last symbol",
         }
     }
 
     fn cause(&self) -> Option<&error::Error> {
         None
     }
 }
 
@@ -115,23 +124,17 @@ pub fn decode_config<T: ?Sized + AsRef<[
 ///    println!("{:?}", buffer);
 ///}
 ///```
 pub fn decode_config_buf<T: ?Sized + AsRef<[u8]>>(
     input: &T,
     config: Config,
     buffer: &mut Vec<u8>,
 ) -> Result<(), DecodeError> {
-    let input_copy;
-    let input_bytes = if config.strip_whitespace {
-        input_copy = copy_without_whitespace(input.as_ref());
-        input_copy.as_ref()
-    } else {
-        input.as_ref()
-    };
+    let input_bytes = input.as_ref();
 
     let starting_output_len = buffer.len();
 
     let num_chunks = num_chunks(input_bytes);
     let decoded_len_estimate = num_chunks
         .checked_mul(DECODED_CHUNK_LEN)
         .and_then(|p| p.checked_add(starting_output_len))
         .expect("Overflow when calculating output buffer length");
@@ -157,23 +160,17 @@ pub fn decode_config_buf<T: ?Sized + AsR
 /// input, rounded up, or in other words `(input_len + 3) / 4 * 3`.
 ///
 /// If the slice is not large enough, this will panic.
 pub fn decode_config_slice<T: ?Sized + AsRef<[u8]>>(
     input: &T,
     config: Config,
     output: &mut [u8],
 ) -> Result<usize, DecodeError> {
-    let input_copy;
-    let input_bytes = if config.strip_whitespace {
-        input_copy = copy_without_whitespace(input.as_ref());
-        input_copy.as_ref()
-    } else {
-        input.as_ref()
-    };
+    let input_bytes = input.as_ref();
 
     decode_helper(
         input_bytes,
         num_chunks(input_bytes),
         &config.char_set,
         output,
     )
 }
@@ -181,23 +178,16 @@ pub fn decode_config_slice<T: ?Sized + A
 /// Return the number of input chunks (including a possibly partial final chunk) in the input
 fn num_chunks(input: &[u8]) -> usize {
     input
         .len()
         .checked_add(INPUT_CHUNK_LEN - 1)
         .expect("Overflow when calculating number of chunks in input") / INPUT_CHUNK_LEN
 }
 
-fn copy_without_whitespace(input: &[u8]) -> Vec<u8> {
-    let mut input_copy = Vec::<u8>::with_capacity(input.len());
-    input_copy.extend(input.iter().filter(|b| !b" \n\t\r\x0b\x0c".contains(b)));
-
-    input_copy
-}
-
 /// Helper to avoid duplicating num_chunks calculation, which is costly on short inputs.
 /// Returns the number of bytes written, or an error.
 // We're on the fragile edge of compiler heuristics here. If this is not inlined, slow. If this is
 // inlined(always), a different slow. plain ol' inline makes the benchmarks happiest at the moment,
 // but this is fragile and the best setting changes with only minor code modifications.
 #[inline]
 fn decode_helper(
     input: &[u8],
@@ -316,23 +306,28 @@ fn decode_helper(
             decode_table,
             &mut output[output_index..(output_index + DECODED_CHUNK_LEN)],
         )?;
 
         input_index += INPUT_CHUNK_LEN;
         output_index += DECODED_CHUNK_LEN;
     }
 
+    // always have one more (possibly partial) block of 8 input
+    debug_assert!(input.len() - input_index > 1 || input.len() == 0);
+    debug_assert!(input.len() - input_index <= 8);
+
     // Stage 4
     // Finally, decode any leftovers that aren't a complete input block of 8 bytes.
     // Use a u64 as a stack-resident 8 byte buffer.
     let mut leftover_bits: u64 = 0;
     let mut morsels_in_leftover = 0;
     let mut padding_bytes = 0;
     let mut first_padding_index: usize = 0;
+    let mut last_symbol = 0_u8;
     let start_of_leftovers = input_index;
     for (i, b) in input[start_of_leftovers..].iter().enumerate() {
         // '=' padding
         if *b == 0x3D {
             // There can be bad padding in a few ways:
             // 1 - Padding with non-padding characters after it
             // 2 - Padding after zero or one non-padding characters before it
             //     in the current quad.
@@ -369,16 +364,17 @@ fn decode_helper(
         // non-suffix '=' in trailing chunk either. Report error as first
         // erroneous padding.
         if padding_bytes > 0 {
             return Err(DecodeError::InvalidByte(
                 start_of_leftovers + first_padding_index,
                 0x3D,
             ));
         }
+        last_symbol = *b;
 
         // can use up to 8 * 6 = 48 bits of the u64, if last chunk has no padding.
         // To minimize shifts, pack the leftovers from left to right.
         let shift = 64 - (morsels_in_leftover + 1) * 6;
         // tables are all 256 elements, lookup with a u8 index always succeeds
         let morsel = decode_table[*b as usize];
         if morsel == tables::INVALID_VALUE {
             return Err(DecodeError::InvalidByte(start_of_leftovers + i, *b));
@@ -396,16 +392,24 @@ fn decode_helper(
         6 => 32,
         7 => 40,
         8 => 48,
         _ => unreachable!(
             "Impossible: must only have 0 to 8 input bytes in last chunk, with no invalid lengths"
         ),
     };
 
+    // if there are bits set outside the bits we care about, last symbol encodes trailing bits that
+    // will not be included in the output
+    let mask = !0 >> leftover_bits_ready_to_append;
+    if (leftover_bits & mask) != 0 {
+        // last morsel is at `morsels_in_leftover` - 1
+        return Err(DecodeError::InvalidLastSymbol(start_of_leftovers + morsels_in_leftover - 1, last_symbol));
+    }
+
     let mut leftover_bits_appended_to_buf = 0;
     while leftover_bits_appended_to_buf < leftover_bits_ready_to_append {
         // `as` simply truncates the higher bits, which is what we want here
         let selected_bits = (leftover_bits >> (56 - leftover_bits_appended_to_buf)) as u8;
         output[output_index] = selected_bits;
         output_index += 1;
 
         leftover_bits_appended_to_buf += 8;
@@ -533,18 +537,19 @@ fn decode_chunk_precise(
 #[cfg(test)]
 mod tests {
     extern crate rand;
 
     use super::*;
     use encode::encode_config_buf;
     use tests::{assert_encode_sanity, random_config};
 
-    use self::rand::distributions::{IndependentSample, Range};
-    use self::rand::Rng;
+    use self::rand::distributions::{Distribution, Range};
+    use self::rand::{Rng, FromEntropy};
+
 
     #[test]
     fn decode_chunk_precise_writes_only_6_bytes() {
         let input = b"Zm9vYmFy"; // "foobar"
         let mut output = [0_u8, 1, 2, 3, 4, 5, 6, 7];
         decode_chunk_precise(&input[..], 0, tables::STANDARD_DECODE, &mut output).unwrap();
         assert_eq!(&vec![b'f', b'o', b'o', b'b', b'a', b'r', 6, 7], &output);
     }
@@ -562,38 +567,37 @@ mod tests {
         let mut orig_data = Vec::new();
         let mut encoded_data = String::new();
         let mut decoded_with_prefix = Vec::new();
         let mut decoded_without_prefix = Vec::new();
         let mut prefix = Vec::new();
 
         let prefix_len_range = Range::new(0, 1000);
         let input_len_range = Range::new(0, 1000);
-        let line_len_range = Range::new(1, 1000);
 
-        let mut rng = rand::weak_rng();
+        let mut rng = rand::rngs::SmallRng::from_entropy();
 
         for _ in 0..10_000 {
             orig_data.clear();
             encoded_data.clear();
             decoded_with_prefix.clear();
             decoded_without_prefix.clear();
             prefix.clear();
 
-            let input_len = input_len_range.ind_sample(&mut rng);
+            let input_len = input_len_range.sample(&mut rng);
 
             for _ in 0..input_len {
                 orig_data.push(rng.gen());
             }
 
-            let config = random_config(&mut rng, &line_len_range);
+            let config = random_config(&mut rng);
             encode_config_buf(&orig_data, config, &mut encoded_data);
             assert_encode_sanity(&encoded_data, &config, input_len);
 
-            let prefix_len = prefix_len_range.ind_sample(&mut rng);
+            let prefix_len = prefix_len_range.sample(&mut rng);
 
             // fill the buf with a prefix
             for _ in 0..prefix_len {
                 prefix.push(rng.gen());
             }
 
             decoded_with_prefix.resize(prefix_len, 0);
             decoded_with_prefix.copy_from_slice(&prefix);
@@ -619,33 +623,32 @@ mod tests {
     #[test]
     fn decode_into_slice_doesnt_clobber_existing_prefix_or_suffix() {
         let mut orig_data = Vec::new();
         let mut encoded_data = String::new();
         let mut decode_buf = Vec::new();
         let mut decode_buf_copy: Vec<u8> = Vec::new();
 
         let input_len_range = Range::new(0, 1000);
-        let line_len_range = Range::new(1, 1000);
 
-        let mut rng = rand::weak_rng();
+        let mut rng = rand::rngs::SmallRng::from_entropy();
 
         for _ in 0..10_000 {
             orig_data.clear();
             encoded_data.clear();
             decode_buf.clear();
             decode_buf_copy.clear();
 
-            let input_len = input_len_range.ind_sample(&mut rng);
+            let input_len = input_len_range.sample(&mut rng);
 
             for _ in 0..input_len {
                 orig_data.push(rng.gen());
             }
 
-            let config = random_config(&mut rng, &line_len_range);
+            let config = random_config(&mut rng);
             encode_config_buf(&orig_data, config, &mut encoded_data);
             assert_encode_sanity(&encoded_data, &config, input_len);
 
             // fill the buffer with random garbage, long enough to have some room before and after
             for _ in 0..5000 {
                 decode_buf.push(rng.gen());
             }
 
@@ -673,38 +676,140 @@ mod tests {
 
     #[test]
     fn decode_into_slice_fits_in_precisely_sized_slice() {
         let mut orig_data = Vec::new();
         let mut encoded_data = String::new();
         let mut decode_buf = Vec::new();
 
         let input_len_range = Range::new(0, 1000);
-        let line_len_range = Range::new(1, 1000);
 
-        let mut rng = rand::weak_rng();
+        let mut rng = rand::rngs::SmallRng::from_entropy();
 
         for _ in 0..10_000 {
             orig_data.clear();
             encoded_data.clear();
             decode_buf.clear();
 
-            let input_len = input_len_range.ind_sample(&mut rng);
+            let input_len = input_len_range.sample(&mut rng);
 
             for _ in 0..input_len {
                 orig_data.push(rng.gen());
             }
 
-            let config = random_config(&mut rng, &line_len_range);
+            let config = random_config(&mut rng);
             encode_config_buf(&orig_data, config, &mut encoded_data);
             assert_encode_sanity(&encoded_data, &config, input_len);
 
             decode_buf.resize(input_len, 0);
 
             // decode into the non-empty buf
             let decode_bytes_written =
                 decode_config_slice(&encoded_data, config, &mut decode_buf[..]).unwrap();
 
             assert_eq!(orig_data.len(), decode_bytes_written);
             assert_eq!(orig_data, decode_buf);
         }
     }
+
+    #[test]
+    fn detect_invalid_last_symbol_two_bytes() {
+        // example from https://github.com/alicemaz/rust-base64/issues/75
+        assert!(decode("iYU=").is_ok());
+        // trailing 01
+        assert_eq!(Err(DecodeError::InvalidLastSymbol(2, b'V')), decode("iYV="));
+        // trailing 10
+        assert_eq!(Err(DecodeError::InvalidLastSymbol(2, b'W')), decode("iYW="));
+        // trailing 11
+        assert_eq!(Err(DecodeError::InvalidLastSymbol(2, b'X')), decode("iYX="));
+
+        // also works when there are 2 quads in the last block
+        assert_eq!(Err(DecodeError::InvalidLastSymbol(6, b'X')), decode("AAAAiYX="));
+    }
+
+    #[test]
+    fn detect_invalid_last_symbol_one_byte() {
+        // 0xFF -> "/w==", so all letters > w, 0-9, and '+', '/' should get InvalidLastSymbol
+
+        assert!(decode("/w==").is_ok());
+        // trailing 01
+        assert_eq!(Err(DecodeError::InvalidLastSymbol(1, b'x')), decode("/x=="));
+        assert_eq!(Err(DecodeError::InvalidLastSymbol(1, b'z')), decode("/z=="));
+        assert_eq!(Err(DecodeError::InvalidLastSymbol(1, b'0')), decode("/0=="));
+        assert_eq!(Err(DecodeError::InvalidLastSymbol(1, b'9')), decode("/9=="));
+        assert_eq!(Err(DecodeError::InvalidLastSymbol(1, b'+')), decode("/+=="));
+        assert_eq!(Err(DecodeError::InvalidLastSymbol(1, b'/')), decode("//=="));
+
+        // also works when there are 2 quads in the last block
+        assert_eq!(Err(DecodeError::InvalidLastSymbol(5, b'x')), decode("AAAA/x=="));
+    }
+
+    #[test]
+    fn detect_invalid_last_symbol_every_possible_three_symbols() {
+        let mut base64_to_bytes = ::std::collections::HashMap::new();
+
+        let mut bytes = [0_u8; 2];
+        for b1 in 0_u16..256 {
+            bytes[0] = b1 as u8;
+            for b2 in 0_u16..256 {
+                bytes[1] = b2 as u8;
+                let mut b64 = vec![0_u8; 4];
+                assert_eq!(4, ::encode_config_slice(&bytes, STANDARD, &mut b64[..]));
+                let mut v = ::std::vec::Vec::with_capacity(2);
+                v.extend_from_slice(&bytes[..]);
+
+                assert!(base64_to_bytes.insert(b64, v).is_none());
+            };
+        }
+
+        // every possible combination of symbols must either decode to 2 bytes or get InvalidLastSymbol
+
+        let mut symbols = [0_u8; 4];
+        for &s1 in STANDARD.char_set.encode_table().iter() {
+            symbols[0] = s1;
+            for &s2 in STANDARD.char_set.encode_table().iter() {
+                symbols[1] = s2;
+                for &s3 in STANDARD.char_set.encode_table().iter() {
+                    symbols[2] = s3;
+                    symbols[3] = b'=';
+
+                    match base64_to_bytes.get(&symbols[..]) {
+                        Some(bytes) => assert_eq!(Ok(bytes.to_vec()), decode_config(&symbols, STANDARD)),
+                        None => assert_eq!(Err(DecodeError::InvalidLastSymbol(2, s3)),
+                                           decode_config(&symbols[..], STANDARD))
+                    }
+                }
+            }
+        }
+    }
+
+    #[test]
+    fn detect_invalid_last_symbol_every_possible_two_symbols() {
+        let mut base64_to_bytes = ::std::collections::HashMap::new();
+
+        for b in 0_u16..256 {
+            let mut b64 = vec![0_u8; 4];
+            assert_eq!(4, ::encode_config_slice(&[b as u8], STANDARD, &mut b64[..]));
+            let mut v = ::std::vec::Vec::with_capacity(1);
+            v.push(b as u8);
+
+            assert!(base64_to_bytes.insert(b64, v).is_none());
+        };
+
+        // every possible combination of symbols must either decode to 1 byte or get InvalidLastSymbol
+
+        let mut symbols = [0_u8; 4];
+        for &s1 in STANDARD.char_set.encode_table().iter() {
+            symbols[0] = s1;
+            for &s2 in STANDARD.char_set.encode_table().iter() {
+                symbols[1] = s2;
+                symbols[2] = b'=';
+                symbols[3] = b'=';
+
+                match base64_to_bytes.get(&symbols[..]) {
+                    Some(bytes) => assert_eq!(Ok(bytes.to_vec()), decode_config(&symbols, STANDARD)),
+                    None => assert_eq!(Err(DecodeError::InvalidLastSymbol(1, s2)),
+                                       decode_config(&symbols[..], STANDARD))
+                }
+            }
+        }
+    }
 }
--- a/third_party/rust/base64/src/display.rs
+++ b/third_party/rust/base64/src/display.rs
@@ -1,61 +1,37 @@
 //! Enables base64'd output anywhere you might use a `Display` implementation, like a format string.
 //!
 //! ```
 //! use base64::display::Base64Display;
 //!
 //! let data = vec![0x0, 0x1, 0x2, 0x3];
-//! let wrapper = Base64Display::standard(&data);
+//! let wrapper = Base64Display::with_config(&data, base64::STANDARD);
 //!
 //! assert_eq!("base64: AAECAw==", format!("base64: {}", wrapper));
 //! ```
 
-use super::chunked_encoder::{ChunkedEncoder, ChunkedEncoderError};
+use super::chunked_encoder::ChunkedEncoder;
 use super::Config;
 use std::fmt::{Display, Formatter};
 use std::{fmt, str};
 
-// I'm not convinced that we should expose ChunkedEncoder or its error type since it's just an
-// implementation detail, so use a different error type.
-/// Errors that can occur initializing a Base64Display.
-#[derive(Debug, PartialEq)]
-pub enum DisplayError {
-    /// If wrapping is configured, the line length must be a multiple of 4, and must not be absurdly
-    /// large (currently capped at 1024, subject to change).
-    InvalidLineLength,
-}
-
 /// A convenience wrapper for base64'ing bytes into a format string without heap allocation.
 pub struct Base64Display<'a> {
     bytes: &'a [u8],
     chunked_encoder: ChunkedEncoder,
 }
 
 impl<'a> Base64Display<'a> {
     /// Create a `Base64Display` with the provided config.
-    pub fn with_config(bytes: &[u8], config: Config) -> Result<Base64Display, DisplayError> {
-        ChunkedEncoder::new(config)
-            .map(|c| Base64Display {
-                bytes,
-                chunked_encoder: c,
-            })
-            .map_err(|e| match e {
-                ChunkedEncoderError::InvalidLineLength => DisplayError::InvalidLineLength,
-            })
-    }
-
-    /// Convenience method for creating a `Base64Display` with the `STANDARD` configuration.
-    pub fn standard(bytes: &[u8]) -> Base64Display {
-        Base64Display::with_config(bytes, super::STANDARD).expect("STANDARD is valid")
-    }
-
-    /// Convenience method for creating a `Base64Display` with the `URL_SAFE` configuration.
-    pub fn url_safe(bytes: &[u8]) -> Base64Display {
-        Base64Display::with_config(bytes, super::URL_SAFE).expect("URL_SAFE is valid")
+    pub fn with_config(bytes: &[u8], config: Config) -> Base64Display {
+        Base64Display {
+            bytes,
+            chunked_encoder: ChunkedEncoder::new(config),
+        }
     }
 }
 
 impl<'a> Display for Base64Display<'a> {
     fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> {
         let mut sink = FormatterSink { f: formatter };
         self.chunked_encoder.encode(self.bytes, &mut sink)
     }
@@ -82,31 +58,30 @@ mod tests {
                                                SinkTestHelper};
     use super::super::*;
     use super::*;
 
     #[test]
     fn basic_display() {
         assert_eq!(
             "~$Zm9vYmFy#*",
-            format!("~${}#*", Base64Display::standard("foobar".as_bytes()))
+            format!("~${}#*", Base64Display::with_config(b"foobar", STANDARD))
         );
         assert_eq!(
             "~$Zm9vYmFyZg==#*",
-            format!("~${}#*", Base64Display::standard("foobarf".as_bytes()))
+            format!("~${}#*", Base64Display::with_config(b"foobarf", STANDARD))
         );
     }
 
     #[test]
     fn display_encode_matches_normal_encode() {
         let helper = DisplaySinkTestHelper;
         chunked_encode_matches_normal_encode_random(&helper);
     }
 
     struct DisplaySinkTestHelper;
 
     impl SinkTestHelper for DisplaySinkTestHelper {
         fn encode_to_string(&self, config: Config, bytes: &[u8]) -> String {
-            format!("{}", Base64Display::with_config(bytes, config).unwrap())
+            format!("{}", Base64Display::with_config(bytes, config))
         }
     }
-
 }
--- a/third_party/rust/base64/src/encode.rs
+++ b/third_party/rust/base64/src/encode.rs
@@ -1,10 +1,10 @@
 use byteorder::{BigEndian, ByteOrder};
-use {line_wrap, line_wrap_parameters, Config, LineWrap, STANDARD};
+use {Config, STANDARD};
 
 ///Encode arbitrary octets as base64.
 ///Returns a String.
 ///Convenience for `encode_config(input, base64::STANDARD);`.
 ///
 ///# Example
 ///
 ///```rust
@@ -32,23 +32,24 @@ pub fn encode<T: ?Sized + AsRef<[u8]>>(i
 ///    println!("{}", b64);
 ///
 ///    let b64_url = base64::encode_config(b"hello internet~", base64::URL_SAFE);
 ///    println!("{}", b64_url);
 ///}
 ///```
 pub fn encode_config<T: ?Sized + AsRef<[u8]>>(input: &T, config: Config) -> String {
     let mut buf = match encoded_size(input.as_ref().len(), &config) {
-        Some(n) => String::with_capacity(n),
+        Some(n) => vec![0; n],
         None => panic!("integer overflow when calculating buffer size"),
     };
 
-    encode_config_buf(input, config, &mut buf);
+    let encoded_len = encode_config_slice(input.as_ref(), config, &mut buf[..]);
+    debug_assert_eq!(encoded_len, buf.len());
 
-    buf
+    return String::from_utf8(buf).expect("Invalid UTF8");
 }
 
 ///Encode arbitrary octets as base64.
 ///Writes into the supplied output buffer, which will grow the buffer if needed.
 ///
 ///# Example
 ///
 ///```rust
@@ -62,37 +63,23 @@ pub fn encode_config<T: ?Sized + AsRef<[
 ///    buf.clear();
 ///    base64::encode_config_buf(b"hello internet~", base64::URL_SAFE, &mut buf);
 ///    println!("{}", buf);
 ///}
 ///```
 pub fn encode_config_buf<T: ?Sized + AsRef<[u8]>>(input: &T, config: Config, buf: &mut String) {
     let input_bytes = input.as_ref();
 
-    let encoded_size = encoded_size(input_bytes.len(), &config)
-        .expect("usize overflow when calculating buffer size");
-
-    let orig_buf_len = buf.len();
+    {
+        let mut sink = ::chunked_encoder::StringSink::new(buf);
+        let encoder = ::chunked_encoder::ChunkedEncoder::new(config);
 
-    // we're only going to insert valid utf8
-    let buf_bytes;
-    unsafe {
-        buf_bytes = buf.as_mut_vec();
+        encoder.encode(input_bytes, &mut sink).expect("Writing to a String shouldn't fail")
     }
 
-    buf_bytes.resize(
-        orig_buf_len
-            .checked_add(encoded_size)
-            .expect("usize overflow when calculating expanded buffer size"),
-        0,
-    );
-
-    let mut b64_output = &mut buf_bytes[orig_buf_len..];
-
-    encode_with_padding_line_wrap(&input_bytes, &config, encoded_size, &mut b64_output);
 }
 
 /// Encode arbitrary octets as base64.
 /// Writes into the supplied output buffer.
 ///
 /// This is useful if you wish to avoid allocation entirely (e.g. encoding into a stack-resident
 /// or statically-allocated buffer).
 ///
@@ -127,32 +114,32 @@ pub fn encode_config_slice<T: ?Sized + A
 ) -> usize {
     let input_bytes = input.as_ref();
 
     let encoded_size = encoded_size(input_bytes.len(), &config)
         .expect("usize overflow when calculating buffer size");
 
     let mut b64_output = &mut output[0..encoded_size];
 
-    encode_with_padding_line_wrap(&input_bytes, &config, encoded_size, &mut b64_output);
+    encode_with_padding(&input_bytes, &config, encoded_size, &mut b64_output);
 
     encoded_size
 }
 
-/// B64-encode, pad, and line wrap (if configured).
+/// B64-encode and pad (if configured).
 ///
 /// This helper exists to avoid recalculating encoded_size, which is relatively expensive on short
 /// inputs.
 ///
 /// `encoded_size` is the encoded size calculated for `input`.
 ///
 /// `output` must be of size `encoded_size`.
 ///
 /// All bytes in `output` will be written to since it is exactly the size of the output.
-pub fn encode_with_padding_line_wrap(
+fn encode_with_padding(
     input: &[u8],
     config: &Config,
     encoded_size: usize,
     output: &mut [u8],
 ) {
     debug_assert_eq!(encoded_size, output.len());
 
     let b64_bytes_written = encode_to_slice(input, output, config.char_set.encode_table());
@@ -162,27 +149,21 @@ pub fn encode_with_padding_line_wrap(
     } else {
         0
     };
 
     let encoded_bytes = b64_bytes_written
         .checked_add(padding_bytes)
         .expect("usize overflow when calculating b64 length");
 
-    let line_ending_bytes = if let LineWrap::Wrap(line_len, line_end) = config.line_wrap {
-        line_wrap(output, encoded_bytes, line_len, line_end)
-    } else {
-        0
-    };
-
-    debug_assert_eq!(encoded_size, encoded_bytes + line_ending_bytes);
+    debug_assert_eq!(encoded_size, encoded_bytes);
 }
 
-/// Encode input bytes to utf8 base64 bytes. Does not pad or line wrap.
-/// `output` must be long enough to hold the encoded `input` without padding or line wrapping.
+/// Encode input bytes to utf8 base64 bytes. Does not pad.
+/// `output` must be long enough to hold the encoded `input` without padding.
 /// Returns the number of bytes written.
 #[inline]
 pub fn encode_to_slice(input: &[u8], output: &mut [u8], encode_table: &[u8; 64]) -> usize {
     let mut input_index: usize = 0;
 
     const BLOCKS_PER_FAST_LOOP: usize = 4;
     const LOW_SIX_BITS: u64 = 0x3F;
 
@@ -292,44 +273,37 @@ pub fn encode_to_slice(input: &[u8], out
         output[output_index + 1] =
             encode_table[((input[start_of_rem] << 4) & LOW_SIX_BITS_U8) as usize];
         output_index += 2;
     }
 
     output_index
 }
 
-/// calculate the base64 encoded string size, including padding and line wraps if appropriate
+/// calculate the base64 encoded string size, including padding if appropriate
 pub fn encoded_size(bytes_len: usize, config: &Config) -> Option<usize> {
     let rem = bytes_len % 3;
 
     let complete_input_chunks = bytes_len / 3;
     let complete_chunk_output = complete_input_chunks.checked_mul(4);
 
-    let encoded_len_no_wrap = if rem > 0 {
+    if rem > 0 {
         if config.pad {
             complete_chunk_output.and_then(|c| c.checked_add(4))
         } else {
             let encoded_rem = match rem {
                 1 => 2,
                 2 => 3,
                 _ => unreachable!("Impossible remainder"),
             };
             complete_chunk_output.and_then(|c| c.checked_add(encoded_rem))
         }
     } else {
         complete_chunk_output
-    };
-
-    encoded_len_no_wrap.map(|e| match config.line_wrap {
-        LineWrap::NoWrap => e,
-        LineWrap::Wrap(line_len, line_ending) => {
-            line_wrap_parameters(e, line_len, line_ending).total_len
-        }
-    })
+    }
 }
 
 /// Write padding characters.
 /// `output` is the slice where padding should be written, of length at least 2.
 ///
 /// Returns the number of padding bytes written.
 pub fn add_padding(input_len: usize, output: &mut [u8]) -> usize {
     let rem = input_len % 3;
@@ -344,20 +318,20 @@ pub fn add_padding(input_len: usize, out
 
 #[cfg(test)]
 mod tests {
     extern crate rand;
 
     use super::*;
     use decode::decode_config_buf;
     use tests::{assert_encode_sanity, random_config};
-    use {CharacterSet, Config, LineEnding, LineWrap, MIME, STANDARD, URL_SAFE_NO_PAD};
+    use {Config, STANDARD, URL_SAFE_NO_PAD};
 
-    use self::rand::distributions::{IndependentSample, Range};
-    use self::rand::Rng;
+    use self::rand::distributions::{Distribution, Range};
+    use self::rand::{Rng, FromEntropy};
     use std;
     use std::str;
 
     #[test]
     fn encoded_size_correct_standard() {
         assert_encoded_length(0, 0, STANDARD);
 
         assert_encoded_length(1, 4, STANDARD);
@@ -377,17 +351,17 @@ mod tests {
         assert_encoded_length(55, 76, STANDARD);
         assert_encoded_length(56, 76, STANDARD);
         assert_encoded_length(57, 76, STANDARD);
 
         assert_encoded_length(58, 80, STANDARD);
     }
 
     #[test]
-    fn encoded_size_correct_no_pad_no_wrap() {
+    fn encoded_size_correct_no_pad() {
         assert_encoded_length(0, 0, URL_SAFE_NO_PAD);
 
         assert_encoded_length(1, 2, URL_SAFE_NO_PAD);
         assert_encoded_length(2, 3, URL_SAFE_NO_PAD);
         assert_encoded_length(3, 4, URL_SAFE_NO_PAD);
 
         assert_encoded_length(4, 6, URL_SAFE_NO_PAD);
         assert_encoded_length(5, 7, URL_SAFE_NO_PAD);
@@ -402,118 +376,55 @@ mod tests {
         assert_encoded_length(55, 74, URL_SAFE_NO_PAD);
         assert_encoded_length(56, 75, URL_SAFE_NO_PAD);
         assert_encoded_length(57, 76, URL_SAFE_NO_PAD);
 
         assert_encoded_length(58, 78, URL_SAFE_NO_PAD);
     }
 
     #[test]
-    fn encoded_size_correct_mime() {
-        assert_encoded_length(0, 0, MIME);
-
-        assert_encoded_length(1, 4, MIME);
-        assert_encoded_length(2, 4, MIME);
-        assert_encoded_length(3, 4, MIME);
-
-        assert_encoded_length(4, 8, MIME);
-        assert_encoded_length(5, 8, MIME);
-        assert_encoded_length(6, 8, MIME);
-
-        assert_encoded_length(7, 12, MIME);
-        assert_encoded_length(8, 12, MIME);
-        assert_encoded_length(9, 12, MIME);
-
-        assert_encoded_length(54, 72, MIME);
-
-        assert_encoded_length(55, 76, MIME);
-        assert_encoded_length(56, 76, MIME);
-        assert_encoded_length(57, 76, MIME);
-
-        assert_encoded_length(58, 82, MIME);
-        assert_encoded_length(59, 82, MIME);
-        assert_encoded_length(60, 82, MIME);
-    }
-
-    #[test]
-    fn encoded_size_correct_lf_pad() {
-        let config = Config::new(
-            CharacterSet::Standard,
-            true,
-            false,
-            LineWrap::Wrap(76, LineEnding::LF),
-        );
-
-        assert_encoded_length(0, 0, config);
-
-        assert_encoded_length(1, 4, config);
-        assert_encoded_length(2, 4, config);
-        assert_encoded_length(3, 4, config);
-
-        assert_encoded_length(4, 8, config);
-        assert_encoded_length(5, 8, config);
-        assert_encoded_length(6, 8, config);
-
-        assert_encoded_length(7, 12, config);
-        assert_encoded_length(8, 12, config);
-        assert_encoded_length(9, 12, config);
-
-        assert_encoded_length(54, 72, config);
-
-        assert_encoded_length(55, 76, config);
-        assert_encoded_length(56, 76, config);
-        assert_encoded_length(57, 76, config);
-
-        // one fewer than MIME
-        assert_encoded_length(58, 81, config);
-        assert_encoded_length(59, 81, config);
-        assert_encoded_length(60, 81, config);
-    }
-
-    #[test]
     fn encoded_size_overflow() {
         assert_eq!(None, encoded_size(std::usize::MAX, &STANDARD));
     }
 
     #[test]
     fn encode_config_buf_into_nonempty_buffer_doesnt_clobber_prefix() {
         let mut orig_data = Vec::new();
         let mut prefix = String::new();
         let mut encoded_data_no_prefix = String::new();
         let mut encoded_data_with_prefix = String::new();
         let mut decoded = Vec::new();
 
         let prefix_len_range = Range::new(0, 1000);
         let input_len_range = Range::new(0, 1000);
-        let line_len_range = Range::new(1, 1000);
 
-        let mut rng = rand::weak_rng();
+        let mut rng = rand::rngs::SmallRng::from_entropy();
 
         for _ in 0..10_000 {
             orig_data.clear();
             prefix.clear();
             encoded_data_no_prefix.clear();
             encoded_data_with_prefix.clear();
             decoded.clear();
 
-            let input_len = input_len_range.ind_sample(&mut rng);
+            let input_len = input_len_range.sample(&mut rng);
 
             for _ in 0..input_len {
                 orig_data.push(rng.gen());
             }
 
-            let prefix_len = prefix_len_range.ind_sample(&mut rng);
+            let prefix_len = prefix_len_range.sample(&mut rng);
             for _ in 0..prefix_len {
                 // getting convenient random single-byte printable chars that aren't base64 is
                 // annoying
                 prefix.push('#');
             }
             encoded_data_with_prefix.push_str(&prefix);
 
-            let config = random_config(&mut rng, &line_len_range);
+            let config = random_config(&mut rng);
             encode_config_buf(&orig_data, config, &mut encoded_data_no_prefix);
             encode_config_buf(&orig_data, config, &mut encoded_data_with_prefix);
 
             assert_eq!(
                 encoded_data_no_prefix.len() + prefix_len,
                 encoded_data_with_prefix.len()
             );
             assert_encode_sanity(&encoded_data_no_prefix, &config, input_len);
@@ -532,40 +443,39 @@ mod tests {
     #[test]
     fn encode_config_slice_into_nonempty_buffer_doesnt_clobber_suffix() {
         let mut orig_data = Vec::new();
         let mut encoded_data = Vec::new();
         let mut encoded_data_original_state = Vec::new();
         let mut decoded = Vec::new();
 
         let input_len_range = Range::new(0, 1000);
-        let line_len_range = Range::new(1, 1000);
 
-        let mut rng = rand::weak_rng();
+        let mut rng = rand::rngs::SmallRng::from_entropy();
 
         for _ in 0..10_000 {
             orig_data.clear();
             encoded_data.clear();
             encoded_data_original_state.clear();
             decoded.clear();
 
-            let input_len = input_len_range.ind_sample(&mut rng);
+            let input_len = input_len_range.sample(&mut rng);
 
             for _ in 0..input_len {
                 orig_data.push(rng.gen());
             }
 
             // plenty of existing garbage in the encoded buffer
             for _ in 0..10 * input_len {
                 encoded_data.push(rng.gen());
             }
 
             encoded_data_original_state.extend_from_slice(&encoded_data);
 
-            let config = random_config(&mut rng, &line_len_range);
+            let config = random_config(&mut rng);
 
             let encoded_size = encoded_size(input_len, &config).unwrap();
 
             assert_eq!(
                 encoded_size,
                 encode_config_slice(&orig_data, config, &mut encoded_data)
             );
 
@@ -587,32 +497,31 @@ mod tests {
 
     #[test]
     fn encode_config_slice_fits_into_precisely_sized_slice() {
         let mut orig_data = Vec::new();
         let mut encoded_data = Vec::new();
         let mut decoded = Vec::new();
 
         let input_len_range = Range::new(0, 1000);
-        let line_len_range = Range::new(1, 1000);
 
-        let mut rng = rand::weak_rng();
+        let mut rng = rand::rngs::SmallRng::from_entropy();
 
         for _ in 0..10_000 {
             orig_data.clear();
             encoded_data.clear();
             decoded.clear();
 
-            let input_len = input_len_range.ind_sample(&mut rng);
+            let input_len = input_len_range.sample(&mut rng);
 
             for _ in 0..input_len {
                 orig_data.push(rng.gen());
             }
 
-            let config = random_config(&mut rng, &line_len_range);
+            let config = random_config(&mut rng);
 
             let encoded_size = encoded_size(input_len, &config).unwrap();
 
             encoded_data.resize(encoded_size, 0);
 
             assert_eq!(
                 encoded_size,
                 encode_config_slice(&orig_data, config, &mut encoded_data)
@@ -630,31 +539,30 @@ mod tests {
     }
 
     #[test]
     fn encode_to_slice_random_valid_utf8() {
         let mut input = Vec::new();
         let mut output = Vec::new();
 
         let input_len_range = Range::new(0, 1000);
-        let line_len_range = Range::new(1, 1000);
 
-        let mut rng = rand::weak_rng();
+        let mut rng = rand::rngs::SmallRng::from_entropy();
 
         for _ in 0..10_000 {
             input.clear();
             output.clear();
 
-            let input_len = input_len_range.ind_sample(&mut rng);
+            let input_len = input_len_range.sample(&mut rng);
 
             for _ in 0..input_len {
                 input.push(rng.gen());
             }
 
-            let config = random_config(&mut rng, &line_len_range);
+            let config = random_config(&mut rng);
 
             // fill up the output buffer with garbage
             let encoded_size = encoded_size(input_len, &config).unwrap();
             for _ in 0..encoded_size {
                 output.push(rng.gen());
             }
 
             let orig_output_buf = output.to_vec();
@@ -666,46 +574,45 @@ mod tests {
             assert_eq!(orig_output_buf[bytes_written..], output[bytes_written..]);
 
             // make sure the encoded bytes are UTF-8
             let _ = str::from_utf8(&output[0..bytes_written]).unwrap();
         }
     }
 
     #[test]
-    fn encode_with_padding_line_wrap_random_valid_utf8() {
+    fn encode_with_padding_random_valid_utf8() {
         let mut input = Vec::new();
         let mut output = Vec::new();
 
         let input_len_range = Range::new(0, 1000);
-        let line_len_range = Range::new(1, 1000);
 
-        let mut rng = rand::weak_rng();
+        let mut rng = rand::rngs::SmallRng::from_entropy();
 
         for _ in 0..10_000 {
             input.clear();
             output.clear();
 
-            let input_len = input_len_range.ind_sample(&mut rng);
+            let input_len = input_len_range.sample(&mut rng);
 
             for _ in 0..input_len {
                 input.push(rng.gen());
             }
 
-            let config = random_config(&mut rng, &line_len_range);
+            let config = random_config(&mut rng);
 
             // fill up the output buffer with garbage
             let encoded_size = encoded_size(input_len, &config).unwrap();
             for _ in 0..encoded_size + 1000 {
                 output.push(rng.gen());
             }
 
             let orig_output_buf = output.to_vec();
 
-            encode_with_padding_line_wrap(
+            encode_with_padding(
                 &input,
                 &config,
                 encoded_size,
                 &mut output[0..encoded_size],
             );
 
             // make sure the part beyond b64 is the same garbage it was before
             assert_eq!(orig_output_buf[encoded_size..], output[encoded_size..]);
@@ -714,17 +621,17 @@ mod tests {
             let _ = str::from_utf8(&output[0..encoded_size]).unwrap();
         }
     }
 
     #[test]
     fn add_padding_random_valid_utf8() {
         let mut output = Vec::new();
 
-        let mut rng = rand::weak_rng();
+        let mut rng = rand::rngs::SmallRng::from_entropy();
 
         // cover our bases for length % 3
         for input_len in 0..10 {
             output.clear();
 
             // fill output with random
             for _ in 0..10 {
                 output.push(rng.gen());
@@ -741,17 +648,17 @@ mod tests {
             let _ = str::from_utf8(&output[0..bytes_written]).unwrap();
         }
     }
 
     fn assert_encoded_length(input_len: usize, encoded_len: usize, config: Config) {
         assert_eq!(encoded_len, encoded_size(input_len, &config).unwrap());
 
         let mut bytes: Vec<u8> = Vec::new();
-        let mut rng = rand::weak_rng();
+        let mut rng = rand::rngs::SmallRng::from_entropy();
 
         for _ in 0..input_len {
             bytes.push(rng.gen());
         }
 
         let encoded = encode_config(&bytes, config);
         assert_encode_sanity(&encoded, &config, input_len);
 
--- a/third_party/rust/base64/src/lib.rs
+++ b/third_party/rust/base64/src/lib.rs
@@ -1,14 +1,14 @@
 //! # Configs
 //!
 //! There isn't just one type of Base64; that would be too simple. You need to choose a character
-//! set (standard or URL-safe), padding suffix (yes/no), and line wrap (line length, line ending).
+//! set (standard, URL-safe, etc) and padding suffix (yes/no).
 //! The `Config` struct encapsulates this info. There are some common configs included: `STANDARD`,
-//! `MIME`, etc. You can also make your own `Config` if needed.
+//! `URL_SAFE`, etc. You can also make your own `Config` if needed.
 //!
 //! The functions that don't have `config` in the name (e.g. `encode()` and `decode()`) use the
 //! `STANDARD` config .
 //!
 //! The functions that write to a slice (the ones that end in `_slice`) are generally the fastest
 //! because they don't need to resize anything. If it fits in your workflow and you care about
 //! performance, keep using the same buffer (growing as need be) and use the `_slice` methods for
 //! the best performance.
@@ -20,77 +20,75 @@
 //!
 //! | Function                | Output                       | Allocates                      |
 //! | ----------------------- | ---------------------------- | ------------------------------ |
 //! | `encode`                | Returns a new `String`       | Always                         |
 //! | `encode_config`         | Returns a new `String`       | Always                         |
 //! | `encode_config_buf`     | Appends to provided `String` | Only if `String` needs to grow |
 //! | `encode_config_slice`   | Writes to provided `&[u8]`   | Never                          |
 //!
-//! All of the encoding functions that take a `Config` will pad, line wrap, etc, as per the config.
+//! All of the encoding functions that take a `Config` will pad as per the config.
 //!
 //! # Decoding
 //!
 //! Just as for encoding, there are different decoding functions available.
 //!
-//! Note that all decode functions that take a config will allocate a copy of the input if you
-//! specify a config that requires whitespace to be stripped. If you care about speed, don't use
-//! formats that line wrap and then require whitespace stripping.
-//!
 //! | Function                | Output                        | Allocates                      |
 //! | ----------------------- | ----------------------------- | ------------------------------ |
 //! | `decode`                | Returns a new `Vec<u8>`       | Always                         |
 //! | `decode_config`         | Returns a new `Vec<u8>`       | Always                         |
 //! | `decode_config_buf`     | Appends to provided `Vec<u8>` | Only if `Vec` needs to grow    |
 //! | `decode_config_slice`   | Writes to provided `&[u8]`    | Never                          |
 //!
 //! Unlike encoding, where all possible input is valid, decoding can fail (see `DecodeError`).
 //!
 //! Input can be invalid because it has invalid characters or invalid padding. (No padding at all is
-//! valid, but excess padding is not.)
-//!
-//! Whitespace in the input is invalid unless `strip_whitespace` is enabled in the `Config` used.
+//! valid, but excess padding is not.) Whitespace in the input is invalid.
 //!
 //! # Panics
 //!
 //! If length calculations result in overflowing `usize`, a panic will result.
 //!
 //! The `_slice` flavors of encode or decode will panic if the provided output slice is too small,
 
 #![deny(
     missing_docs, trivial_casts, trivial_numeric_casts, unused_extern_crates, unused_import_braces,
-    unused_results, variant_size_differences, warnings
+    unused_results, variant_size_differences, warnings, unsafe_code
 )]
 
 extern crate byteorder;
 
 mod chunked_encoder;
 pub mod display;
-mod line_wrap;
+pub mod write;
 mod tables;
 
-use line_wrap::{line_wrap, line_wrap_parameters};
-
 mod encode;
 pub use encode::{encode, encode_config, encode_config_buf, encode_config_slice};
 
 mod decode;
 pub use decode::{decode, decode_config, decode_config_buf, decode_config_slice, DecodeError};
 
 #[cfg(test)]
 mod tests;
 
 /// Available encoding character sets
 #[derive(Clone, Copy, Debug)]
 pub enum CharacterSet {
-    /// The standard character set (uses `+` and `/`)
+    /// The standard character set (uses `+` and `/`).
+    ///
+    /// See [RFC 3548](https://tools.ietf.org/html/rfc3548#section-3).
     Standard,
-    /// The URL safe character set (uses `-` and `_`)
+    /// The URL safe character set (uses `-` and `_`).
+    ///
+    /// See [RFC 3548](https://tools.ietf.org/html/rfc3548#section-4).
     UrlSafe,
-    /// The `crypt(3)` character set (uses `./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`)
+    /// The `crypt(3)` character set (uses `./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`).
+    ///
+    /// Not standardized, but folk wisdom on the net asserts that this alphabet is what crypt uses.
     Crypt,
 }
 
 impl CharacterSet {
     fn encode_table(&self) -> &'static [u8; 64] {
         match *self {
             CharacterSet::Standard => tables::STANDARD_ENCODE,
             CharacterSet::UrlSafe => tables::URL_SAFE_ENCODE,
@@ -102,119 +100,59 @@ impl CharacterSet {
         match *self {
             CharacterSet::Standard => tables::STANDARD_DECODE,
             CharacterSet::UrlSafe => tables::URL_SAFE_DECODE,
             CharacterSet::Crypt => tables::CRYPT_DECODE,
         }
     }
 }
 
-/// Line ending used in optional line wrapping.
-#[derive(Clone, Copy, Debug)]
-pub enum LineEnding {
-    /// Unix-style \n
-    LF,
-    /// Windows-style \r\n
-    CRLF,
-}
-
-impl LineEnding {
-    fn len(&self) -> usize {
-        match *self {
-            LineEnding::LF => 1,
-            LineEnding::CRLF => 2,
-        }
-    }
-}
-
-/// Line wrap configuration.
-#[derive(Clone, Copy, Debug)]
-pub enum LineWrap {
-    /// Don't wrap.
-    NoWrap,
-    /// Wrap lines with the specified length and line ending. The length must be > 0.
-    Wrap(usize, LineEnding),
-}
-
 /// Contains configuration parameters for base64 encoding
 #[derive(Clone, Copy, Debug)]
 pub struct Config {
     /// Character set to use
     char_set: CharacterSet,
     /// True to pad output with `=` characters
     pad: bool,
-    /// Remove whitespace before decoding, at the cost of an allocation. Whitespace is defined
-    /// according to POSIX-locale `isspace`, meaning \n \r \f \t \v and space.
-    strip_whitespace: bool,
-    /// ADT signifying whether to linewrap output, and if so by how many characters and with what
-    /// ending
-    line_wrap: LineWrap,
 }
 
 impl Config {
     /// Create a new `Config`.
     pub fn new(
         char_set: CharacterSet,
         pad: bool,
-        strip_whitespace: bool,
-        input_line_wrap: LineWrap,
     ) -> Config {
-        let line_wrap = match input_line_wrap {
-            LineWrap::Wrap(0, _) => LineWrap::NoWrap,
-            _ => input_line_wrap,
-        };
-
         Config {
             char_set,
             pad,
-            strip_whitespace,
-            line_wrap,
         }
     }
 }
 
 /// Standard character set with padding.
 pub const STANDARD: Config = Config {
     char_set: CharacterSet::Standard,
     pad: true,
-    strip_whitespace: false,
-    line_wrap: LineWrap::NoWrap,
 };
 
 /// Standard character set without padding.
 pub const STANDARD_NO_PAD: Config = Config {
     char_set: CharacterSet::Standard,
     pad: false,
-    strip_whitespace: false,
-    line_wrap: LineWrap::NoWrap,
-};
-
-/// As per standards for MIME encoded messages
-pub const MIME: Config = Config {
-    char_set: CharacterSet::Standard,
-    pad: true,
-    strip_whitespace: true,
-    line_wrap: LineWrap::Wrap(76, LineEnding::CRLF),
 };
 
 /// URL-safe character set with padding
 pub const URL_SAFE: Config = Config {
     char_set: CharacterSet::UrlSafe,
     pad: true,
-    strip_whitespace: false,
-    line_wrap: LineWrap::NoWrap,
 };
 
 /// URL-safe character set without padding
 pub const URL_SAFE_NO_PAD: Config = Config {
     char_set: CharacterSet::UrlSafe,
     pad: false,
-    strip_whitespace: false,
-    line_wrap: LineWrap::NoWrap,
 };
 
 /// As per `crypt(3)` requirements
 pub const CRYPT: Config = Config {
     char_set: CharacterSet::Crypt,
     pad: false,
-    strip_whitespace: false,
-    line_wrap: LineWrap::NoWrap,
 };
deleted file mode 100644
--- a/third_party/rust/base64/src/line_wrap.rs
+++ /dev/null
@@ -1,393 +0,0 @@
-extern crate safemem;
-
-use super::*;
-
-#[derive(Debug, PartialEq)]
-pub struct LineWrapParameters {
-    // number of lines that need an ending
-    pub lines_with_endings: usize,
-    // length of last line (which never needs an ending)
-    pub last_line_len: usize,
-    // length of lines that need an ending (which are always full lines), with their endings
-    pub total_full_wrapped_lines_len: usize,
-    // length of all lines, including endings for the ones that need them
-    pub total_len: usize,
-    // length of the line endings only
-    pub total_line_endings_len: usize,
-}
-
-/// Calculations about how many lines we'll get for a given line length, line ending, etc.
-/// This assumes that the last line will not get an ending, even if it is the full line length.
-pub fn line_wrap_parameters(
-    input_len: usize,
-    line_len: usize,
-    line_ending: LineEnding,
-) -> LineWrapParameters {
-    let line_ending_len = line_ending.len();
-
-    if input_len <= line_len {
-        // no wrapping needed
-        return LineWrapParameters {
-            lines_with_endings: 0,
-            last_line_len: input_len,
-            total_full_wrapped_lines_len: 0,
-            total_len: input_len,
-            total_line_endings_len: 0,
-        };
-    };
-
-    // num_lines_with_endings > 0, last_line_length > 0
-    let (num_lines_with_endings, last_line_length) = if input_len % line_len > 0 {
-        // Every full line has an ending since there is a partial line at the end
-        (input_len / line_len, input_len % line_len)
-    } else {
-        // Every line is a full line, but no trailing ending.
-        // Subtraction will not underflow since we know input_len > line_len.
-        (input_len / line_len - 1, line_len)
-    };
-
-    // TODO should we expose exceeding usize via Result to be kind to 16-bit users? Or is that
-    // always going to be a panic anyway in practice? If we choose to use a Result we could pull
-    // line wrapping out of the normal encode path and have it be a separate step. Then only users
-    // who need line wrapping would care about the possibility for error.
-
-    let single_full_line_with_ending_len = line_len
-        .checked_add(line_ending_len)
-        .expect("Line length with ending exceeds usize");
-    // length of just the full lines with line endings
-    let total_full_wrapped_lines_len = num_lines_with_endings
-        .checked_mul(single_full_line_with_ending_len)
-        .expect("Full lines with endings length exceeds usize");
-    // all lines with appropriate endings, including the last line
-    let total_all_wrapped_len = total_full_wrapped_lines_len
-        .checked_add(last_line_length)
-        .expect("All lines with endings length exceeds usize");
-    let total_line_endings_len = num_lines_with_endings
-        .checked_mul(line_ending_len)
-        .expect("Total line endings length exceeds usize");
-
-    LineWrapParameters {
-        lines_with_endings: num_lines_with_endings,
-        last_line_len: last_line_length,
-        total_full_wrapped_lines_len: total_full_wrapped_lines_len,
-        total_len: total_all_wrapped_len,
-        total_line_endings_len: total_line_endings_len,
-    }
-}
-
-/// Insert line endings into the encoded base64 after each complete line (except the last line, even
-/// if it is complete).
-/// The provided buffer must be large enough to handle the increased size after endings are
-/// inserted.
-/// `input_len` is the length of the encoded data in `encoded_buf`.
-/// `line_len` is the width without line ending characters.
-/// Returns the number of line ending bytes added.
-pub fn line_wrap(
-    encoded_buf: &mut [u8],
-    input_len: usize,
-    line_len: usize,
-    line_ending: LineEnding,
-) -> usize {
-    let line_wrap_params = line_wrap_parameters(input_len, line_len, line_ending);
-
-    // ptr.offset() is undefined if it wraps, and there is no checked_offset(). However, because
-    // we perform this check up front to make sure we have enough capacity, we know that none of
-    // the subsequent pointer operations (assuming they implement the desired behavior of course!)
-    // will overflow.
-    assert!(
-        encoded_buf.len() >= line_wrap_params.total_len,
-        "Buffer must be able to hold encoded data after line wrapping"
-    );
-
-    // Move the last line, either partial or full, by itself as it does not have a line ending
-    // afterwards
-    let last_line_start = line_wrap_params
-        .lines_with_endings
-        .checked_mul(line_len)
-        .expect("Start of last line in input exceeds usize");
-    // last line starts immediately after all the wrapped full lines
-    let new_line_start = line_wrap_params.total_full_wrapped_lines_len;
-
-    safemem::copy_over(
-        encoded_buf,
-        last_line_start,
-        new_line_start,
-        line_wrap_params.last_line_len,
-    );
-
-    let mut line_ending_bytes = 0;
-
-    let line_ending_len = line_ending.len();
-
-    // handle the full lines
-    for line_num in 0..line_wrap_params.lines_with_endings {
-        // doesn't underflow because line_num < lines_with_endings
-        let lines_before_this_line = line_wrap_params.lines_with_endings - 1 - line_num;
-        let old_line_start = lines_before_this_line
-            .checked_mul(line_len)
-            .expect("Old line start index exceeds usize");
-        let new_line_start = lines_before_this_line
-            .checked_mul(line_ending_len)
-            .and_then(|i| i.checked_add(old_line_start))
-            .expect("New line start index exceeds usize");
-
-        safemem::copy_over(encoded_buf, old_line_start, new_line_start, line_len);
-
-        let after_new_line = new_line_start
-            .checked_add(line_len)
-            .expect("Line ending index exceeds usize");
-
-        match line_ending {
-            LineEnding::LF => {
-                encoded_buf[after_new_line] = b'\n';
-                line_ending_bytes += 1;
-            }
-            LineEnding::CRLF => {
-                encoded_buf[after_new_line] = b'\r';
-                encoded_buf[after_new_line
-                                .checked_add(1)
-                                .expect("Line ending index exceeds usize")] = b'\n';
-                line_ending_bytes += 2;
-            }
-        }
-    }
-
-    assert_eq!(line_wrap_params.total_line_endings_len, line_ending_bytes);
-
-    line_ending_bytes
-}
-
-#[cfg(test)]
-mod tests {
-    extern crate rand;
-
-    use super::*;
-
-    use self::rand::distributions::{IndependentSample, Range};
-    use self::rand::Rng;
-
-    #[test]
-    fn line_params_perfect_multiple_of_line_length_lf() {
-        let params = line_wrap_parameters(100, 20, LineEnding::LF);
-
-        assert_eq!(
-            LineWrapParameters {
-                lines_with_endings: 4,
-                last_line_len: 20,
-                total_full_wrapped_lines_len: 84,
-                total_len: 104,
-                total_line_endings_len: 4,
-            },
-            params
-        );
-    }
-
-    #[test]
-    fn line_params_partial_last_line_crlf() {
-        let params = line_wrap_parameters(103, 20, LineEnding::CRLF);
-
-        assert_eq!(
-            LineWrapParameters {
-                lines_with_endings: 5,
-                last_line_len: 3,
-                total_full_wrapped_lines_len: 110,
-                total_len: 113,
-                total_line_endings_len: 10,
-            },
-            params
-        );
-    }
-
-    #[test]
-    fn line_params_line_len_1_crlf() {
-        let params = line_wrap_parameters(100, 1, LineEnding::CRLF);
-
-        assert_eq!(
-            LineWrapParameters {
-                lines_with_endings: 99,
-                last_line_len: 1,
-                total_full_wrapped_lines_len: 99 * 3,
-                total_len: 99 * 3 + 1,
-                total_line_endings_len: 99 * 2,
-            },
-            params
-        );
-    }
-
-    #[test]
-    fn line_params_line_len_longer_than_input_crlf() {
-        let params = line_wrap_parameters(100, 200, LineEnding::CRLF);
-
-        assert_eq!(
-            LineWrapParameters {
-                lines_with_endings: 0,
-                last_line_len: 100,
-                total_full_wrapped_lines_len: 0,
-                total_len: 100,
-                total_line_endings_len: 0,
-            },
-            params
-        );
-    }
-
-    #[test]
-    fn line_params_line_len_same_as_input_crlf() {
-        let params = line_wrap_parameters(100, 100, LineEnding::CRLF);
-
-        assert_eq!(
-            LineWrapParameters {
-                lines_with_endings: 0,
-                last_line_len: 100,
-                total_full_wrapped_lines_len: 0,
-                total_len: 100,
-                total_line_endings_len: 0,
-            },
-            params
-        );
-    }
-
-    #[test]
-    fn line_wrap_length_1_lf() {
-        let mut buf = vec![0x1, 0x2, 0x3, 0x4];
-
-        assert_eq!(3, do_line_wrap(&mut buf, 1, LineEnding::LF));
-
-        assert_eq!(vec![0x1, 0xA, 0x2, 0xA, 0x3, 0xA, 0x4], buf);
-    }
-
-    #[test]
-    fn line_wrap_length_1_crlf() {
-        let mut buf = vec![0x1, 0x2, 0x3, 0x4];
-
-        assert_eq!(6, do_line_wrap(&mut buf, 1, LineEnding::CRLF));
-
-        assert_eq!(vec![0x1, 0xD, 0xA, 0x2, 0xD, 0xA, 0x3, 0xD, 0xA, 0x4], buf);
-    }
-
-    #[test]
-    fn line_wrap_length_2_lf_full_lines() {
-        let mut buf = vec![0x1, 0x2, 0x3, 0x4];
-
-        assert_eq!(1, do_line_wrap(&mut buf, 2, LineEnding::LF));
-
-        assert_eq!(vec![0x1, 0x2, 0xA, 0x3, 0x4], buf);
-    }
-
-    #[test]
-    fn line_wrap_length_2_crlf_full_lines() {
-        let mut buf = vec![0x1, 0x2, 0x3, 0x4];
-
-        assert_eq!(2, do_line_wrap(&mut buf, 2, LineEnding::CRLF));
-
-        assert_eq!(vec![0x1, 0x2, 0xD, 0xA, 0x3, 0x4], buf);
-    }
-
-    #[test]
-    fn line_wrap_length_2_lf_partial_line() {
-        let mut buf = vec![0x1, 0x2, 0x3, 0x4, 0x5];
-
-        assert_eq!(2, do_line_wrap(&mut buf, 2, LineEnding::LF));
-
-        assert_eq!(vec![0x1, 0x2, 0xA, 0x3, 0x4, 0xA, 0x5], buf);
-    }
-
-    #[test]
-    fn line_wrap_length_2_crlf_partial_line() {
-        let mut buf = vec![0x1, 0x2, 0x3, 0x4, 0x5];
-
-        assert_eq!(4, do_line_wrap(&mut buf, 2, LineEnding::CRLF));
-
-        assert_eq!(vec![0x1, 0x2, 0xD, 0xA, 0x3, 0x4, 0xD, 0xA, 0x5], buf);
-    }
-
-    #[test]
-    fn line_wrap_random() {
-        let mut buf: Vec<u8> = Vec::new();
-        let buf_range = Range::new(10, 1000);
-        let line_range = Range::new(10, 100);
-        let mut rng = rand::weak_rng();
-
-        for _ in 0..10_000 {
-            buf.clear();
-
-            let buf_len = buf_range.ind_sample(&mut rng);
-            let line_len = line_range.ind_sample(&mut rng);
-            let line_ending = if rng.gen() {
-                LineEnding::LF
-            } else {
-                LineEnding::CRLF
-            };
-            let line_ending_len = line_ending.len();
-
-            for _ in 0..buf_len {
-                buf.push(rng.gen());
-            }
-
-            let line_wrap_params = line_wrap_parameters(buf_len, line_len, line_ending);
-
-            let not_wrapped_buf = buf.to_vec();
-
-            let _ = do_line_wrap(&mut buf, line_len, line_ending);
-
-            // remove the endings
-            for line_ending_num in 0..line_wrap_params.lines_with_endings {
-                let line_ending_offset = (line_ending_num + 1) * line_len;
-
-                for _ in 0..line_ending_len {
-                    let _ = buf.remove(line_ending_offset);
-                }
-            }
-
-            assert_eq!(not_wrapped_buf, buf);
-        }
-    }
-
-    fn do_line_wrap(buf: &mut Vec<u8>, line_len: usize, line_ending: LineEnding) -> usize {
-        let mut rng = rand::weak_rng();
-
-        let orig_len = buf.len();
-
-        // A 3x inflation is enough for the worst case: line length 1, crlf ending.
-        // We add on extra bytes so we'll have un-wrapped bytes at the end that shouldn't get
-        // modified..
-        for _ in 0..(1000 + 2 * orig_len) {
-            buf.push(rng.gen());
-        }
-
-        let mut before_line_wrap = buf.to_vec();
-
-        let params = line_wrap_parameters(orig_len, line_len, line_ending);
-
-        let bytes_written = line_wrap(&mut buf[..], orig_len, line_len, line_ending);
-
-        assert_eq!(params.total_line_endings_len, bytes_written);
-        assert_eq!(params.lines_with_endings * line_ending.len(), bytes_written);
-        assert_eq!(params.total_len, orig_len + bytes_written);
-
-        // make sure line_wrap didn't touch anything beyond what it should
-        let start_of_untouched_data = orig_len + bytes_written;
-        assert_eq!(
-            before_line_wrap[start_of_untouched_data..],
-            buf[start_of_untouched_data..]
-        );
-
-        // also make sure that line wrapping will fit into a slice no bigger than what it should
-        // need
-        let bytes_written_precise_fit = line_wrap(
-            &mut before_line_wrap[0..(params.total_len)],
-            orig_len,
-            line_len,
-            line_ending,
-        );
-
-        assert_eq!(bytes_written, bytes_written_precise_fit);
-        assert_eq!(
-            &buf[0..(params.total_len)],
-            &before_line_wrap[0..(params.total_len)]
-        );
-
-        buf.truncate(orig_len + bytes_written);
-
-        bytes_written
-    }
-}
--- a/third_party/rust/base64/src/tests.rs
+++ b/third_party/rust/base64/src/tests.rs
@@ -1,114 +1,82 @@
 extern crate rand;
 
 use encode::encoded_size;
-use line_wrap::line_wrap_parameters;
 use *;
 
 use std::str;
 
-use self::rand::distributions::{IndependentSample, Range};
-use self::rand::Rng;
+use self::rand::distributions::{Distribution, Range};
+use self::rand::{Rng, FromEntropy};
 
 #[test]
 fn roundtrip_random_config_short() {
     // exercise the slower encode/decode routines that operate on shorter buffers more vigorously
-    roundtrip_random_config(Range::new(0, 50), Range::new(0, 50), 10_000);
+    roundtrip_random_config(Range::new(0, 50), 10_000);
 }
 
 #[test]
 fn roundtrip_random_config_long() {
-    roundtrip_random_config(Range::new(0, 1000), Range::new(0, 1000), 10_000);
+    roundtrip_random_config(Range::new(0, 1000), 10_000);
 }
 
 pub fn assert_encode_sanity(encoded: &str, config: &Config, input_len: usize) {
     let input_rem = input_len % 3;
-    let (expected_padding_len, last_encoded_chunk_len) = if input_rem > 0 {
+    let expected_padding_len = if input_rem > 0 {
         if config.pad {
-            (3 - input_rem, 4)
+            3 - input_rem
         } else {
-            (0, input_rem + 1)
+            0
         }
     } else {
-        (0, 0)
-    };
-
-    let b64_only_len = (input_len / 3) * 4 + last_encoded_chunk_len;
-
-    let expected_line_ending_len = match config.line_wrap {
-        LineWrap::NoWrap => 0,
-        LineWrap::Wrap(line_len, line_ending) => {
-            line_wrap_parameters(b64_only_len, line_len, line_ending).total_line_endings_len
-        }
+        0
     };
 
     let expected_encoded_len = encoded_size(input_len, &config).unwrap();
 
     assert_eq!(expected_encoded_len, encoded.len());
 
-    let line_endings_len = encoded.chars().filter(|&c| c == '\r' || c == '\n').count();
     let padding_len = encoded.chars().filter(|&c| c == '=').count();
 
     assert_eq!(expected_padding_len, padding_len);
-    assert_eq!(expected_line_ending_len, line_endings_len);
 
     let _ = str::from_utf8(encoded.as_bytes()).expect("Base64 should be valid utf8");
 }
 
 fn roundtrip_random_config(
     input_len_range: Range<usize>,
-    line_len_range: Range<usize>,
     iterations: u32,
 ) {
     let mut input_buf: Vec<u8> = Vec::new();
     let mut encoded_buf = String::new();
-    let mut rng = rand::weak_rng();
+    let mut rng = rand::rngs::SmallRng::from_entropy();
 
     for _ in 0..iterations {
         input_buf.clear();
         encoded_buf.clear();
 
-        let input_len = input_len_range.ind_sample(&mut rng);
+        let input_len = input_len_range.sample(&mut rng);
 
-        let config = random_config(&mut rng, &line_len_range);
+        let config = random_config(&mut rng);
 
         for _ in 0..input_len {
             input_buf.push(rng.gen());
         }
 
         encode_config_buf(&input_buf, config, &mut encoded_buf);
 
         assert_encode_sanity(&encoded_buf, &config, input_len);
 
         assert_eq!(input_buf, decode_config(&encoded_buf, config).unwrap());
     }
 }
 
-pub fn random_config<R: Rng>(rng: &mut R, line_len_range: &Range<usize>) -> Config {
-    let line_wrap = if rng.gen() {
-        LineWrap::NoWrap
-    } else {
-        let line_len = line_len_range.ind_sample(rng);
-
-        let line_ending = if rng.gen() {
-            LineEnding::LF
-        } else {
-            LineEnding::CRLF
-        };
-
-        LineWrap::Wrap(line_len, line_ending)
-    };
-
+pub fn random_config<R: Rng>(rng: &mut R) -> Config {
     const CHARSETS: &[CharacterSet] = &[
         CharacterSet::UrlSafe,
         CharacterSet::Standard,
         CharacterSet::Crypt,
     ];
     let charset = *rng.choose(CHARSETS).unwrap();
 
-    let strip_whitespace = match line_wrap {
-        LineWrap::NoWrap => false,
-        _ => true,
-    };
-
-    Config::new(charset, rng.gen(), strip_whitespace, line_wrap)
+    Config::new(charset, rng.gen())
 }
new file mode 100644
--- /dev/null
+++ b/third_party/rust/base64/src/write/encoder.rs
@@ -0,0 +1,252 @@
+use ::encode::encode_to_slice;
+use std::{cmp, fmt};
+use std::io::{Result, Write};
+use {encode_config_slice, Config};
+
+pub(crate) const BUF_SIZE: usize = 1024;
+/// The most bytes whose encoding will fit in `BUF_SIZE`
+const MAX_INPUT_LEN: usize = BUF_SIZE / 4 * 3;
+// 3 bytes of input = 4 bytes of base64, always (because we don't allow line wrapping)
+const MIN_ENCODE_CHUNK_SIZE: usize = 3;
+
+/// A `Write` implementation that base64 encodes data before delegating to the wrapped writer.
+///
+/// Because base64 has special handling for the end of the input data (padding, etc), there's a
+/// `finish()` method on this type that encodes any leftover input bytes and adds padding if
+/// appropriate. It's called automatically when deallocated (see the `Drop` implementation), but
+/// any error that occurs when invoking the underlying writer will be suppressed. If you want to
+/// handle such errors, call `finish()` yourself.
+///
+/// # Examples
+///
+/// ```
+/// use std::io::Write;
+///
+/// // use a vec as the simplest possible `Write` -- in real code this is probably a file, etc.
+/// let mut wrapped_writer = Vec::new();
+/// {
+///     let mut enc = base64::write::EncoderWriter::new(
+///         &mut wrapped_writer, base64::STANDARD);
+///
+///     // handle errors as you normally would
+///     enc.write_all(b"asdf").unwrap();
+///     // could leave this out to be called by Drop, if you don't care
+///     // about handling errors
+///     enc.finish().unwrap();
+///
+/// }
+///
+/// // base64 was written to the writer
+/// assert_eq!(b"YXNkZg==", &wrapped_writer[..]);
+///
+/// ```
+///
+/// # Panics
+///
+/// Calling `write()` after `finish()` is invalid and will panic.
+///
+/// # Errors
+///
+/// Base64 encoding itself does not generate errors, but errors from the wrapped writer will be
+/// returned as per the contract of `Write`.
+///
+/// # Performance
+///
+/// It has some minor performance loss compared to encoding slices (a couple percent).
+/// It does not do any heap allocation.
+pub struct EncoderWriter<'a, W: 'a + Write> {
+    config: Config,
+    /// Where encoded data is written to
+    w: &'a mut W,
+    /// Holds a partial chunk, if any, after the last `write()`, so that we may then fill the chunk
+    /// with the next `write()`, encode it, then proceed with the rest of the input normally.
+    extra: [u8; MIN_ENCODE_CHUNK_SIZE],
+    /// How much of `extra` is occupied, in `[0, MIN_ENCODE_CHUNK_SIZE]`.
+    extra_len: usize,
+    /// Buffer to encode into.
+    output: [u8; BUF_SIZE],
+    /// True iff padding / partial last chunk has been written.
+    finished: bool,
+    /// panic safety: don't write again in destructor if writer panicked while we were writing to it
+    panicked: bool
+}
+
+impl<'a, W: Write> fmt::Debug for EncoderWriter<'a, W> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "extra:{:?} extra_len:{:?} output[..5]: {:?}",
+            self.extra,
+            self.extra_len,
+            &self.output[0..5]
+        )
+    }
+}
+
+impl<'a, W: Write> EncoderWriter<'a, W> {
+    /// Create a new encoder around an existing writer.
+    pub fn new(w: &'a mut W, config: Config) -> EncoderWriter<'a, W> {
+        EncoderWriter {
+            config,
+            w,
+            extra: [0u8; MIN_ENCODE_CHUNK_SIZE],
+            extra_len: 0,
+            output: [0u8; BUF_SIZE],
+            finished: false,
+            panicked: false
+        }
+    }
+
+    /// Encode all remaining buffered data and write it, including any trailing incomplete input
+    /// triples and associated padding.
+    ///
+    /// Once this succeeds, no further writes can be performed, as that would produce invalid
+    /// base64.
+    ///
+    /// # Errors
+    ///
+    /// Assuming the wrapped writer obeys the `Write` contract, if this returns `Err`, no data was
+    /// written, and `finish()` may be retried if appropriate for the type of error, etc.
+    pub fn finish(&mut self) -> Result<()> {
+        if self.finished {
+            return Ok(());
+        };
+
+        if self.extra_len > 0 {
+            let encoded_len = encode_config_slice(
+                &self.extra[..self.extra_len],
+                self.config,
+                &mut self.output[..],
+            );
+            self.panicked = true;
+            let _ = self.w.write(&self.output[..encoded_len])?;
+            self.panicked = false;
+            // write succeeded, do not write the encoding of extra again if finish() is retried
+            self.extra_len = 0;
+        }
+
+        self.finished = true;
+        Ok(())
+    }
+}
+
+impl<'a, W: Write> Write for EncoderWriter<'a, W> {
+    fn write(&mut self, input: &[u8]) -> Result<usize> {
+        if self.finished {
+            panic!("Cannot write more after calling finish()");
+        }
+
+        if input.len() == 0 {
+            return Ok(0);
+        }
+
+        // The contract of `Write::write` places some constraints on this implementation:
+        // - a call to `write()` represents at most one call to a wrapped `Write`, so we can't
+        // iterate over the input and encode multiple chunks.
+        // - Errors mean that "no bytes were written to this writer", so we need to reset the
+        // internal state to what it was before the error occurred
+
+        // how many bytes, if any, were read into `extra` to create a triple to encode
+        let mut extra_input_read_len = 0;
+        let mut input = input;
+
+        let orig_extra_len = self.extra_len;
+
+        let mut encoded_size = 0;
+        // always a multiple of MIN_ENCODE_CHUNK_SIZE
+        let mut max_input_len = MAX_INPUT_LEN;
+
+        // process leftover stuff from last write
+        if self.extra_len > 0 {
+            debug_assert!(self.extra_len < 3);
+            if input.len() + self.extra_len >= MIN_ENCODE_CHUNK_SIZE {
+                // Fill up `extra`, encode that into `output`, and consume as much of the rest of
+                // `input` as possible.
+                // We could write just the encoding of `extra` by itself but then we'd have to
+                // return after writing only 4 bytes, which is inefficient if the underlying writer
+                // would make a syscall.
+                extra_input_read_len = MIN_ENCODE_CHUNK_SIZE - self.extra_len;
+                debug_assert!(extra_input_read_len > 0);
+                // overwrite only bytes that weren't already used. If we need to rollback extra_len
+                // (when the subsequent write errors), the old leading bytes will still be there.
+                self.extra[self.extra_len..MIN_ENCODE_CHUNK_SIZE].copy_from_slice(&input[0..extra_input_read_len]);
+
+                let len = encode_to_slice(&self.extra[0..MIN_ENCODE_CHUNK_SIZE],
+                                          &mut self.output[..],
+                                          self.config.char_set.encode_table());
+                debug_assert_eq!(4, len);
+
+                input = &input[extra_input_read_len..];
+
+                // consider extra to be used up, since we encoded it
+                self.extra_len = 0;
+                // don't clobber where we just encoded to
+                encoded_size = 4;
+                // and don't read more than can be encoded
+                max_input_len = MAX_INPUT_LEN - MIN_ENCODE_CHUNK_SIZE;
+
+                // fall through to normal encoding
+            } else {
+                // `extra` and `input` are non empty, but `|extra| + |input| < 3`, so there must be
+                // 1 byte in each.
+                debug_assert_eq!(1, input.len());
+                debug_assert_eq!(1, self.extra_len);
+
+                self.extra[self.extra_len] = input[0];
+                self.extra_len += 1;
+                return Ok(1);
+            };
+        } else if input.len() < MIN_ENCODE_CHUNK_SIZE {
+            // `extra` is empty, and `input` fits inside it
+            self.extra[0..input.len()].copy_from_slice(input);
+            self.extra_len = input.len();
+            return Ok(input.len());
+        };
+
+        // either 0 or 1 complete chunks encoded from extra
+        debug_assert!(encoded_size == 0 || encoded_size == 4);
+        debug_assert!(MAX_INPUT_LEN - max_input_len == 0
+            || MAX_INPUT_LEN - max_input_len == MIN_ENCODE_CHUNK_SIZE);
+
+        // handle complete triples
+        let input_complete_chunks_len = input.len() - (input.len() % MIN_ENCODE_CHUNK_SIZE);
+        let input_chunks_to_encode_len = cmp::min(input_complete_chunks_len, max_input_len);
+        debug_assert_eq!(0, max_input_len % MIN_ENCODE_CHUNK_SIZE);
+        debug_assert_eq!(0, input_chunks_to_encode_len % MIN_ENCODE_CHUNK_SIZE);
+
+        encoded_size += encode_to_slice(
+            &input[..(input_chunks_to_encode_len)],
+            &mut self.output[encoded_size..],
+            self.config.char_set.encode_table(),
+        );
+        self.panicked = true;
+        let r = self.w.write(&self.output[..encoded_size]);
+        self.panicked = false;
+        match r {
+            Ok(_) => return Ok(extra_input_read_len + input_chunks_to_encode_len),
+            Err(_) => {
+                // in case we filled and encoded `extra`, reset extra_len
+                self.extra_len = orig_extra_len;
+                return r;
+            }
+        }
+
+        // we could hypothetically copy a few more bytes into `extra` but the extra 1-2 bytes
+        // are not worth all the complexity (and branches)
+    }
+
+    /// Because this is usually treated as OK to call multiple times, it will *not* flush any
+    /// incomplete chunks of input or write padding.
+    fn flush(&mut self) -> Result<()> {
+        self.w.flush()
+    }
+}
+
+impl<'a, W: Write> Drop for EncoderWriter<'a, W> {
+    fn drop(&mut self) {
+        if !self.panicked {
+            // like `BufWriter`, ignore errors during drop
+            let _ = self.finish();
+        }
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/base64/src/write/encoder_tests.rs
@@ -0,0 +1,479 @@
+extern crate rand;
+
+use super::EncoderWriter;
+use tests::random_config;
+use {encode_config, encode_config_buf, URL_SAFE, STANDARD_NO_PAD};
+
+use std::io::{Cursor, Write};
+use std::{cmp, str, io};
+
+use self::rand::Rng;
+
+#[test]
+fn encode_three_bytes() {
+    let mut c = Cursor::new(Vec::new());
+    {
+        let mut enc = EncoderWriter::new(&mut c, URL_SAFE);
+
+        let sz = enc.write(b"abc").unwrap();
+        assert_eq!(sz, 3);
+    }
+    assert_eq!(&c.get_ref()[..], encode_config("abc", URL_SAFE).as_bytes());
+}
+
+#[test]
+fn encode_nine_bytes_two_writes() {
+    let mut c = Cursor::new(Vec::new());
+    {
+        let mut enc = EncoderWriter::new(&mut c, URL_SAFE);
+
+        let sz = enc.write(b"abcdef").unwrap();
+        assert_eq!(sz, 6);
+        let sz = enc.write(b"ghi").unwrap();
+        assert_eq!(sz, 3);
+    }
+    assert_eq!(
+        &c.get_ref()[..],
+        encode_config("abcdefghi", URL_SAFE).as_bytes()
+    );
+}
+
+#[test]
+fn encode_one_then_two_bytes() {
+    let mut c = Cursor::new(Vec::new());
+    {
+        let mut enc = EncoderWriter::new(&mut c, URL_SAFE);
+
+        let sz = enc.write(b"a").unwrap();
+        assert_eq!(sz, 1);
+        let sz = enc.write(b"bc").unwrap();
+        assert_eq!(sz, 2);
+    }
+    assert_eq!(&c.get_ref()[..], encode_config("abc", URL_SAFE).as_bytes());
+}
+
+#[test]
+fn encode_one_then_five_bytes() {
+    let mut c = Cursor::new(Vec::new());
+    {
+        let mut enc = EncoderWriter::new(&mut c, URL_SAFE);
+
+        let sz = enc.write(b"a").unwrap();
+        assert_eq!(sz, 1);
+        let sz = enc.write(b"bcdef").unwrap();
+        assert_eq!(sz, 5);
+    }
+    assert_eq!(
+        &c.get_ref()[..],
+        encode_config("abcdef", URL_SAFE).as_bytes()
+    );
+}
+
+#[test]
+fn encode_1_2_3_bytes() {
+    let mut c = Cursor::new(Vec::new());
+    {
+        let mut enc = EncoderWriter::new(&mut c, URL_SAFE);
+
+        let sz = enc.write(b"a").unwrap();
+        assert_eq!(sz, 1);
+        let sz = enc.write(b"bc").unwrap();
+        assert_eq!(sz, 2);
+        let sz = enc.write(b"def").unwrap();
+        assert_eq!(sz, 3);
+    }
+    assert_eq!(
+        &c.get_ref()[..],
+        encode_config("abcdef", URL_SAFE).as_bytes()
+    );
+}
+
+#[test]
+fn encode_with_padding() {
+    let mut c = Cursor::new(Vec::new());
+    {
+        let mut enc = EncoderWriter::new(&mut c, URL_SAFE);
+
+        enc.write_all(b"abcd").unwrap();
+
+        enc.flush().unwrap();
+    }
+    assert_eq!(&c.get_ref()[..], encode_config("abcd", URL_SAFE).as_bytes());
+}
+
+#[test]
+fn encode_with_padding_multiple_writes() {
+    let mut c = Cursor::new(Vec::new());
+    {
+        let mut enc = EncoderWriter::new(&mut c, URL_SAFE);
+
+        assert_eq!(1, enc.write(b"a").unwrap());
+        assert_eq!(2, enc.write(b"bc").unwrap());
+        assert_eq!(3, enc.write(b"def").unwrap());
+        assert_eq!(1, enc.write(b"g").unwrap());
+
+        enc.flush().unwrap();
+    }
+    assert_eq!(
+        &c.get_ref()[..],
+        encode_config("abcdefg", URL_SAFE).as_bytes()
+    );
+}
+
+#[test]
+fn finish_writes_extra_byte() {
+    let mut c = Cursor::new(Vec::new());
+    {
+        let mut enc = EncoderWriter::new(&mut c, URL_SAFE);
+
+        assert_eq!(6, enc.write(b"abcdef").unwrap());
+
+        // will be in extra
+        assert_eq!(1, enc.write(b"g").unwrap());
+
+        // 1 trailing byte = 2 encoded chars
+        let _ = enc.finish().unwrap();
+    }
+    assert_eq!(
+        &c.get_ref()[..],
+        encode_config("abcdefg", URL_SAFE).as_bytes()
+    );
+}
+
+#[test]
+fn write_partial_chunk_encodes_partial_chunk() {
+    let mut c = Cursor::new(Vec::new());
+    {
+        let mut enc = EncoderWriter::new(&mut c, STANDARD_NO_PAD);
+
+        // nothing encoded yet
+        assert_eq!(2, enc.write(b"ab").unwrap());
+        // encoded here
+        let _ = enc.finish().unwrap();
+    }
+    assert_eq!(
+        &c.get_ref()[..],
+        encode_config("ab", STANDARD_NO_PAD).as_bytes()
+    );
+    assert_eq!(3, c.get_ref().len());
+}
+
+#[test]
+fn write_1_chunk_encodes_complete_chunk() {
+    let mut c = Cursor::new(Vec::new());
+    {
+        let mut enc = EncoderWriter::new(&mut c, STANDARD_NO_PAD);
+
+        assert_eq!(3, enc.write(b"abc").unwrap());
+        let _ = enc.finish().unwrap();
+    }
+    assert_eq!(
+        &c.get_ref()[..],
+        encode_config("abc", STANDARD_NO_PAD).as_bytes()
+    );
+    assert_eq!(4, c.get_ref().len());
+}
+
+#[test]
+fn write_1_chunk_and_partial_encodes_only_complete_chunk() {
+    let mut c = Cursor::new(Vec::new());
+    {
+        let mut enc = EncoderWriter::new(&mut c, STANDARD_NO_PAD);
+
+        // "d" not written
+        assert_eq!(3, enc.write(b"abcd").unwrap());
+        let _ = enc.finish().unwrap();
+    }
+    assert_eq!(
+        &c.get_ref()[..],
+        encode_config("abc", STANDARD_NO_PAD).as_bytes()
+    );
+    assert_eq!(4, c.get_ref().len());
+}
+
+#[test]
+fn write_2_partials_to_exactly_complete_chunk_encodes_complete_chunk() {
+    let mut c = Cursor::new(Vec::new());
+    {
+        let mut enc = EncoderWriter::new(&mut c, STANDARD_NO_PAD);
+
+        assert_eq!(1, enc.write(b"a").unwrap());
+        assert_eq!(2, enc.write(b"bc").unwrap());
+        let _ = enc.finish().unwrap();
+    }
+    assert_eq!(
+        &c.get_ref()[..],
+        encode_config("abc", STANDARD_NO_PAD).as_bytes()
+    );
+    assert_eq!(4, c.get_ref().len());
+}
+
+#[test]
+fn write_partial_then_enough_to_complete_chunk_but_not_complete_another_chunk_encodes_complete_chunk_without_consuming_remaining() {
+    let mut c = Cursor::new(Vec::new());
+    {
+        let mut enc = EncoderWriter::new(&mut c, STANDARD_NO_PAD);
+
+        assert_eq!(1, enc.write(b"a").unwrap());
+        // doesn't consume "d"
+        assert_eq!(2, enc.write(b"bcd").unwrap());
+        let _ = enc.finish().unwrap();
+    }
+    assert_eq!(
+        &c.get_ref()[..],
+        encode_config("abc", STANDARD_NO_PAD).as_bytes()
+    );
+    assert_eq!(4, c.get_ref().len());
+}
+
+#[test]
+fn write_partial_then_enough_to_complete_chunk_and_another_chunk_encodes_complete_chunks() {
+    let mut c = Cursor::new(Vec::new());
+    {
+        let mut enc = EncoderWriter::new(&mut c, STANDARD_NO_PAD);
+
+        assert_eq!(1, enc.write(b"a").unwrap());
+        // completes partial chunk, and another chunk
+        assert_eq!(5, enc.write(b"bcdef").unwrap());
+        let _ = enc.finish().unwrap();
+    }
+    assert_eq!(
+        &c.get_ref()[..],
+        encode_config("abcdef", STANDARD_NO_PAD).as_bytes()
+    );
+    assert_eq!(8, c.get_ref().len());
+}
+
+#[test]
+fn write_partial_then_enough_to_complete_chunk_and_another_chunk_and_another_partial_chunk_encodes_only_complete_chunks() {
+    let mut c = Cursor::new(Vec::new());
+    {
+        let mut enc = EncoderWriter::new(&mut c, STANDARD_NO_PAD);
+
+        assert_eq!(1, enc.write(b"a").unwrap());
+        // completes partial chunk, and another chunk, with one more partial chunk that's not
+        // consumed
+        assert_eq!(5, enc.write(b"bcdefe").unwrap());
+        let _ = enc.finish().unwrap();
+    }
+    assert_eq!(
+        &c.get_ref()[..],
+        encode_config("abcdef", STANDARD_NO_PAD).as_bytes()
+    );
+    assert_eq!(8, c.get_ref().len());
+}
+
+#[test]
+fn drop_calls_finish_for_you() {
+    let mut c = Cursor::new(Vec::new());
+    {
+        let mut enc = EncoderWriter::new(&mut c, STANDARD_NO_PAD);
+        assert_eq!(1, enc.write(b"a").unwrap());
+    }
+    assert_eq!(
+        &c.get_ref()[..],
+        encode_config("a", STANDARD_NO_PAD).as_bytes()
+    );
+    assert_eq!(2, c.get_ref().len());
+}
+
+#[test]
+fn every_possible_split_of_input() {
+    let mut rng = rand::thread_rng();
+    let mut orig_data = Vec::<u8>::new();
+    let mut stream_encoded = Vec::<u8>::new();
+    let mut normal_encoded = String::new();
+
+    let size = 5_000;
+
+    for i in 0..size {
+        orig_data.clear();
+        stream_encoded.clear();
+        normal_encoded.clear();
+
+        for _ in 0..size {
+            orig_data.push(rng.gen());
+        }
+
+        let config = random_config(&mut rng);
+        encode_config_buf(&orig_data, config, &mut normal_encoded);
+
+        {
+            let mut stream_encoder = EncoderWriter::new(&mut stream_encoded, config);
+            // Write the first i bytes, then the rest
+            stream_encoder.write_all(&orig_data[0..i]).unwrap();
+            stream_encoder.write_all(&orig_data[i..]).unwrap();
+        }
+
+        assert_eq!(normal_encoded, str::from_utf8(&stream_encoded).unwrap());
+    }
+}
+
+#[test]
+fn encode_random_config_matches_normal_encode_reasonable_input_len() {
+    // choose up to 2 * buf size, so ~half the time it'll use a full buffer
+    do_encode_random_config_matches_normal_encode(super::encoder::BUF_SIZE * 2)
+}
+
+#[test]
+fn encode_random_config_matches_normal_encode_tiny_input_len() {
+    do_encode_random_config_matches_normal_encode(10)
+}
+
+#[test]
+fn retrying_writes_that_error_with_interrupted_works() {
+    let mut rng = rand::thread_rng();
+    let mut orig_data = Vec::<u8>::new();
+    let mut stream_encoded = Vec::<u8>::new();
+    let mut normal_encoded = String::new();
+
+    for _ in 0..1_000 {
+        orig_data.clear();
+        stream_encoded.clear();
+        normal_encoded.clear();
+
+        let orig_len: usize = rng.gen_range(100, 20_000);
+        for _ in 0..orig_len {
+            orig_data.push(rng.gen());
+        }
+
+        // encode the normal way
+        let config = random_config(&mut rng);
+        encode_config_buf(&orig_data, config, &mut normal_encoded);
+
+        // encode via the stream encoder
+        {
+            let mut interrupt_rng = rand::thread_rng();
+            let mut interrupting_writer = InterruptingWriter {
+                w: &mut stream_encoded,
+                rng: &mut interrupt_rng,
+                fraction: 0.8,
+            };
+
+            let mut stream_encoder = EncoderWriter::new(&mut interrupting_writer, config);
+            let mut bytes_consumed = 0;
+            while bytes_consumed < orig_len {
+                // use short inputs since we want to use `extra` a lot as that's what needs rollback
+                // when errors occur
+                let input_len: usize = cmp::min(rng.gen_range(0, 10),
+                                                orig_len - bytes_consumed);
+
+                // write a little bit of the data
+                retry_interrupted_write_all(&mut stream_encoder,
+                                            &orig_data[bytes_consumed..bytes_consumed + input_len])
+                    .unwrap();
+
+                bytes_consumed += input_len;
+            }
+
+            loop {
+                let res = stream_encoder.finish();
+                match res {
+                    Ok(_) => break,
+                    Err(e) => match e.kind() {
+                        io::ErrorKind::Interrupted => continue,
+                        _ => Err(e).unwrap() // bail
+                    }
+                }
+            }
+
+            assert_eq!(orig_len, bytes_consumed);
+        }
+
+        assert_eq!(normal_encoded, str::from_utf8(&stream_encoded).unwrap());
+    }
+}
+
+/// Retry writes until all the data is written or an error that isn't Interrupted is returned.
+fn retry_interrupted_write_all<W: Write>(w: &mut W, buf: &[u8]) -> io::Result<()> {
+    let mut written = 0;
+
+    while written < buf.len() {
+        let res = w.write(&buf[written..]);
+
+        match res {
+            Ok(len) => written += len,
+            Err(e) => match e.kind() {
+                io::ErrorKind::Interrupted => continue,
+                _ => {
+                    println!("got kind: {:?}", e.kind());
+                    return Err(e);
+                }
+            }
+        }
+    }
+
+    Ok(())
+}
+
+fn do_encode_random_config_matches_normal_encode(max_input_len: usize) {
+    let mut rng = rand::thread_rng();
+    let mut orig_data = Vec::<u8>::new();
+    let mut stream_encoded = Vec::<u8>::new();
+    let mut normal_encoded = String::new();
+
+    for _ in 0..1_000 {
+        orig_data.clear();
+        stream_encoded.clear();
+        normal_encoded.clear();
+
+        let orig_len: usize = rng.gen_range(100, 20_000);
+        for _ in 0..orig_len {
+            orig_data.push(rng.gen());
+        }
+
+        // encode the normal way
+        let config = random_config(&mut rng);
+        encode_config_buf(&orig_data, config, &mut normal_encoded);
+
+        // encode via the stream encoder
+        {
+            let mut stream_encoder = EncoderWriter::new(&mut stream_encoded, config);
+            let mut bytes_consumed = 0;
+            while bytes_consumed < orig_len {
+                let input_len: usize = cmp::min(rng.gen_range(0, max_input_len),
+                                                orig_len - bytes_consumed);
+
+                // write a little bit of the data
+                stream_encoder
+                    .write_all(&orig_data[bytes_consumed..bytes_consumed + input_len])
+                    .unwrap();
+
+                bytes_consumed += input_len;
+            }
+
+            stream_encoder.finish().unwrap();
+
+            assert_eq!(orig_len, bytes_consumed);
+        }
+
+        assert_eq!(normal_encoded, str::from_utf8(&stream_encoded).unwrap());
+    }
+}
+
+/// A `Write` implementation that returns Interrupted some fraction of the time, randomly.
+struct InterruptingWriter<'a, W: 'a + Write, R: 'a + Rng> {
+    w: &'a mut W,
+    rng: &'a mut R,
+    /// In [0, 1]. If a random number in [0, 1] is  `<= threshold`, `Write` methods will return
+    /// an `Interrupted` error
+    fraction: f64,
+}
+
+impl<'a, W: Write, R: Rng> Write for InterruptingWriter<'a, W, R> {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        if self.rng.gen_range(0.0, 1.0) <= self.fraction {
+            return Err(io::Error::new(io::ErrorKind::Interrupted, "interrupted"));
+        }
+
+        self.w.write(buf)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        if self.rng.gen_range(0.0, 1.0) <= self.fraction {
+            return Err(io::Error::new(io::ErrorKind::Interrupted, "interrupted"));
+        }
+
+        self.w.flush()
+    }
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/third_party/rust/base64/src/write/mod.rs
@@ -0,0 +1,6 @@
+//! Implementations of `io::Write` to transparently handle base64.
+mod encoder;
+pub use self::encoder::EncoderWriter;
+
+#[cfg(test)]
+mod encoder_tests;
--- a/third_party/rust/base64/tests/decode.rs
+++ b/third_party/rust/base64/tests/decode.rs
@@ -1,23 +1,16 @@
 extern crate base64;
 
 use base64::*;
 
 mod helpers;
 
 use helpers::*;
 
-fn compare_decode_mime(expected: &str, target: &str) {
-    assert_eq!(
-        expected,
-        String::from_utf8(decode_config(target, MIME).unwrap()).unwrap()
-    );
-}
-
 #[test]
 fn decode_rfc4648_0() {
     compare_decode("", "");
 }
 
 #[test]
 fn decode_rfc4648_1() {
     compare_decode("f", "Zg==");
@@ -70,58 +63,20 @@ fn decode_rfc4648_5_no_padding() {
 }
 
 #[test]
 fn decode_rfc4648_6() {
     compare_decode("foobar", "Zm9vYmFy");
 }
 
 #[test]
-fn decode_mime_allow_space() {
-    assert!(decode_config("YWx pY2U=", MIME).is_ok());
-}
-
-#[test]
-fn decode_mime_allow_tab() {
-    assert!(decode_config("YWx\tpY2U=", MIME).is_ok());
-}
-
-#[test]
-fn decode_mime_allow_ff() {
-    assert!(decode_config("YWx\x0cpY2U=", MIME).is_ok());
-}
-
-#[test]
-fn decode_mime_allow_vtab() {
-    assert!(decode_config("YWx\x0bpY2U=", MIME).is_ok());
-}
-
-#[test]
-fn decode_mime_allow_nl() {
-    assert!(decode_config("YWx\npY2U=", MIME).is_ok());
-}
-
-#[test]
-fn decode_mime_allow_crnl() {
-    assert!(decode_config("YWx\r\npY2U=", MIME).is_ok());
-}
-
-#[test]
-fn decode_mime_reject_null() {
+fn decode_reject_null() {
     assert_eq!(
         DecodeError::InvalidByte(3, 0x0),
-        decode_config("YWx\0pY2U==", MIME).unwrap_err()
-    );
-}
-
-#[test]
-fn decode_mime_absurd_whitespace() {
-    compare_decode_mime(
-        "how could you let this happen",
-        "\n aG93I\n\nG\x0bNvd\r\nWxkI HlvdSB \tsZXQgdGh\rpcyBo\x0cYXBwZW4 =   ",
+        decode_config("YWx\0pY2U==", config_std_pad()).unwrap_err()
     );
 }
 
 #[test]
 fn decode_single_pad_byte_after_2_chars_in_trailing_quad_ok() {
     for num_quads in 0..25 {
         let mut s: String = std::iter::repeat("ABCD").take(num_quads).collect();
         s.push_str("Zg=");
@@ -344,8 +299,12 @@ fn decode_reject_invalid_bytes_with_corr
                         DecodeError::InvalidByte(index, invalid_byte),
                         decode(&input).unwrap_err()
                     );
                 }
             }
         }
     }
 }
+
+fn config_std_pad() -> Config {
+    Config::new(CharacterSet::Standard, true)
+}
\ No newline at end of file
--- a/third_party/rust/base64/tests/encode.rs
+++ b/third_party/rust/base64/tests/encode.rs
@@ -90,60 +90,16 @@ fn encode_all_bytes_url() {
          -AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq\
          -wsbKztLW2t7i5uru8vb6_wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t_g4eLj5OXm5-jp6uvs7e7v8PHy\
          8_T19vf4-fr7_P3-_w==",
         encode_config(&bytes, URL_SAFE)
     );
 }
 
 #[test]
-fn encode_line_ending_lf_partial_last_line() {
-    let config = Config::new(
-        CharacterSet::Standard,
-        true,
-        false,
-        LineWrap::Wrap(3, LineEnding::LF),
-    );
-    assert_eq!("Zm9\nvYm\nFy", encode_config(b"foobar", config));
-}
-
-#[test]
-fn encode_line_ending_crlf_partial_last_line() {
-    let config = Config::new(
-        CharacterSet::Standard,
-        true,
-        false,
-        LineWrap::Wrap(3, LineEnding::CRLF),
-    );
-    assert_eq!("Zm9\r\nvYm\r\nFy", encode_config(b"foobar", config));
-}
-
-#[test]
-fn encode_line_ending_lf_full_last_line() {
-    let config = Config::new(
-        CharacterSet::Standard,
-        true,
-        false,
-        LineWrap::Wrap(4, LineEnding::LF),
-    );
-    assert_eq!("Zm9v\nYmFy", encode_config(b"foobar", config));
-}
-
-#[test]
-fn encode_line_ending_crlf_full_last_line() {
-    let config = Config::new(
-        CharacterSet::Standard,
-        true,
-        false,
-        LineWrap::Wrap(4, LineEnding::CRLF),
-    );
-    assert_eq!("Zm9v\r\nYmFy", encode_config(b"foobar", config));
-}
-
-#[test]
 fn encode_url_safe_without_padding() {
     let encoded = encode_config(b"alice", URL_SAFE_NO_PAD);
     assert_eq!(&encoded, "YWxpY2U");
     assert_eq!(
         String::from_utf8(decode(&encoded).unwrap()).unwrap(),
         "alice"
     );
 }
--- a/third_party/rust/base64/tests/tests.rs
+++ b/third_party/rust/base64/tests/tests.rs
@@ -1,12 +1,12 @@
 extern crate base64;
 extern crate rand;
 
-use rand::Rng;
+use rand::{Rng, FromEntropy};
 
 use base64::*;
 
 mod helpers;
 use helpers::*;
 
 // generate random contents of the specified length and test encode/decode roundtrip
 fn roundtrip_random(
@@ -14,17 +14,17 @@ fn roundtrip_random(
     str_buf: &mut String,
     config: Config,
     byte_len: usize,
     approx_values_per_byte: u8,
     max_rounds: u64,
 ) {
     // let the short ones be short but don't let it get too crazy large
     let num_rounds = calculate_number_of_rounds(byte_len, approx_values_per_byte, max_rounds);
-    let mut r = rand::weak_rng();
+    let mut r = rand::rngs::SmallRng::from_entropy();
     let mut decode_buf = Vec::new();
 
     for _ in 0..num_rounds {
         byte_buf.clear();
         str_buf.clear();
         decode_buf.clear();
         while byte_buf.len() < byte_len {
             byte_buf.push(r.gen::<u8>());
@@ -48,17 +48,17 @@ fn calculate_number_of_rounds(byte_len: 
 
         prod = prod.saturating_mul(prod);
     }
 
     prod
 }
 
 fn no_pad_config() -> Config {
-    Config::new(CharacterSet::Standard, false, false, LineWrap::NoWrap)
+    Config::new(CharacterSet::Standard, false)
 }
 
 #[test]
 fn roundtrip_random_short_standard() {
     let mut byte_buf: Vec<u8> = Vec::new();
     let mut str_buf = String::new();
 
     for input_len in 0..40 {
@@ -136,34 +136,34 @@ fn display_wrapper_matches_normal_encode
 
     for i in 0..255 {
         bytes.push(i);
     }
     bytes.push(255);
 
     assert_eq!(
         encode(&bytes),
-        format!("{}", base64::display::Base64Display::standard(&bytes))
+        format!("{}", base64::display::Base64Display::with_config(&bytes, STANDARD))
     );
 }
 
 #[test]
 fn because_we_can() {
     compare_decode("alice", "YWxpY2U=");
     compare_decode("alice", &encode(b"alice"));
     compare_decode("alice", &encode(&decode(&encode(b"alice")).unwrap()));
 }
 
 #[test]
 fn encode_config_slice_can_use_inline_buffer() {
     let mut buf: [u8; 22] = [0; 22];
     let mut larger_buf: [u8; 24] = [0; 24];
     let mut input: [u8; 16] = [0; 16];
 
-    let mut rng = rand::weak_rng();
+    let mut rng = rand::rngs::SmallRng::from_entropy();
     for elt in &mut input {
         *elt = rng.gen();
     }
 
     assert_eq!(22, encode_config_slice(&input, STANDARD_NO_PAD, &mut buf));
     let decoded = decode_config(&buf, STANDARD_NO_PAD).unwrap();
 
     assert_eq!(decoded, input);
@@ -177,15 +177,15 @@ fn encode_config_slice_can_use_inline_bu
 }
 
 #[test]
 #[should_panic(expected = "index 24 out of range for slice of length 22")]
 fn encode_config_slice_panics_when_buffer_too_small() {
     let mut buf: [u8; 22] = [0; 22];
     let mut input: [u8; 16] = [0; 16];
 
-    let mut rng = rand::weak_rng();
+    let mut rng = rand::rngs::SmallRng::from_entropy();
     for elt in &mut input {
         *elt = rng.gen();
     }
 
     encode_config_slice(&input, STANDARD, &mut buf);
 }
--- a/third_party/rust/byteorder/.cargo-checksum.json
+++ b/third_party/rust/byteorder/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"CHANGELOG.md":"750ff16a714caad77a272a62b4baed5ea113ead2846f8c3968342e592a99ecd5","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"cd633b2d76dd5d57191388e7cc31340eb2d6b89e2f98f587999dc685d977c673","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"97c01a66dbff4615acd49a8c3a85d137bf29cc113fa514910195bb11aef445bc","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","benches/bench.rs":"250d46461a0529a856d76a6421fd45c499bccba2c532e05dbf438c94582a8eac","src/io.rs":"4221711399f9723ef21c5b07700b8e9319f6f665b1eaaceb49528f6e976a25a9","src/lib.rs":"07e5f53bf3b9e30f1da9f4cf37797b77ce3d16c9f2a3a3e56669dd323debd1b9"},"package":"652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"}
\ No newline at end of file
+{"files":{"CHANGELOG.md":"dc0a497d6932b874a32c1a457e344bdcd27a1767a174d163f19d66b837477a08","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"9f119d940ff1131bb71fb7c2b10c36ae91b45dbcf010975ccc555268a5b79165","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"97c01a66dbff4615acd49a8c3a85d137bf29cc113fa514910195bb11aef445bc","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","benches/bench.rs":"5dbfb724aa137efdff2cf0faeb728a3d302eda097ba5189de2d82314ce500654","src/io.rs":"d9759a25c625aa341b23bdb489144b1e9554db11bc2fa799a2a6ecfbc442ea5e","src/lib.rs":"fd18e7969a80314537ba41b3c460284975c0d4df4b72f27527506cb5bd889ae8"},"package":"94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"}
\ No newline at end of file
--- a/third_party/rust/byteorder/CHANGELOG.md
+++ b/third_party/rust/byteorder/CHANGELOG.md
@@ -1,8 +1,21 @@
+1.2.3
+=====
+This patch release removes the use of `feature(i128_type)` from byteorder,
+since it has been stabilized. We leave byteorder's `i128` feature in place
+in order to continue supporting compilation on older versions of Rust.
+
+
+1.2.2
+=====
+This patch release only consists of internal improvements and refactorings.
+Notably, this removes all uses of `transmute` and instead uses pointer casts.
+
+
 1.2.1
 =====
 This patch release removes more unnecessary uses of `unsafe` that
 were overlooked in the prior `1.2.0` release. In particular, the
 `ReadBytesExt::read_{f32,f64}_into_checked` methods have been deprecated and
 replaced by more appropriately named `read_{f32,f64}_into` methods.
 
 
--- a/third_party/rust/byteorder/Cargo.toml
+++ b/third_party/rust/byteorder/Cargo.toml
@@ -7,37 +7,38 @@
 #
 # 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 = "byteorder"
-version = "1.2.1"
+version = "1.2.7"
 authors = ["Andrew Gallant <jamslam@gmail.com>"]
+exclude = ["/ci/*"]
 description = "Library for reading/writing numbers in big-endian and little-endian."
 homepage = "https://github.com/BurntSushi/byteorder"
 documentation = "https://docs.rs/byteorder"
 readme = "README.md"
 keywords = ["byte", "endian", "big-endian", "little-endian", "binary"]
 categories = ["encoding", "parsing"]
-license = "Unlicense/MIT"
+license = "Unlicense OR MIT"
 repository = "https://github.com/BurntSushi/byteorder"
 [profile.bench]
 opt-level = 3
 
 [lib]
 name = "byteorder"
 bench = false
 [dev-dependencies.quickcheck]
-version = "0.4"
+version = "0.7"
 default-features = false
 
 [dev-dependencies.rand]
-version = "0.3"
+version = "0.5"
 
 [features]
 default = ["std"]
 i128 = []
 std = []
 [badges.travis-ci]
 repository = "BurntSushi/byteorder"
--- a/third_party/rust/byteorder/benches/bench.rs
+++ b/third_party/rust/byteorder/benches/bench.rs
@@ -1,9 +1,8 @@
-#![cfg_attr(feature = "i128", feature(i128))]
 #![feature(test)]
 
 extern crate byteorder;
 extern crate rand;
 extern crate test;
 
 macro_rules! bench_num {
     ($name:ident, $read:ident, $bytes:expr, $data:expr) => (
@@ -257,60 +256,69 @@ bench_num!(int128_16, read_int128,
 
 macro_rules! bench_slice {
     ($name:ident, $numty:ty, $read:ident, $write:ident) => {
         mod $name {
             use std::mem::size_of;
 
             use byteorder::{ByteOrder, BigEndian, LittleEndian};
             use rand::{self, Rng};
+            use rand::distributions;
             use test::Bencher;
 
             #[bench]
             fn read_big_endian(b: &mut Bencher) {
-                let mut numbers: Vec<$numty> =
-                    rand::thread_rng().gen_iter().take(100000).collect();
+                let mut numbers: Vec<$numty> = rand::thread_rng()
+                    .sample_iter(&distributions::Standard)
+                    .take(100000)
+                    .collect();
                 let mut bytes = vec![0; numbers.len() * size_of::<$numty>()];
                 BigEndian::$write(&numbers, &mut bytes);
 
                 b.bytes = bytes.len() as u64;
                 b.iter(|| {
                     BigEndian::$read(&bytes, &mut numbers);
                 });
             }
 
             #[bench]
             fn read_little_endian(b: &mut Bencher) {
-                let mut numbers: Vec<$numty> =
-                    rand::thread_rng().gen_iter().take(100000).collect();
+                let mut numbers: Vec<$numty> = rand::thread_rng()
+                    .sample_iter(&distributions::Standard)
+                    .take(100000)
+                    .collect();
                 let mut bytes = vec![0; numbers.len() * size_of::<$numty>()];
                 LittleEndian::$write(&numbers, &mut bytes);
 
                 b.bytes = bytes.len() as u64;
                 b.iter(|| {
                     LittleEndian::$read(&bytes, &mut numbers);
                 });
             }
 
             #[bench]
             fn write_big_endian(b: &mut Bencher) {
-                let numbers: Vec<$numty> =
-                    rand::thread_rng().gen_iter().take(100000).collect();
+                let numbers: Vec<$numty> = rand::thread_rng()
+                    .sample_iter(&distributions::Standard)
+                    .take(100000)
+                    .collect();
                 let mut bytes = vec![0; numbers.len() * size_of::<$numty>()];
 
                 b.bytes = bytes.len() as u64;
                 b.iter(|| {
                     BigEndian::$write(&numbers, &mut bytes);
                 });
             }
 
             #[bench]
             fn write_little_endian(b: &mut Bencher) {
-                let numbers: Vec<$numty> =
-                    rand::thread_rng().gen_iter().take(100000).collect();
+                let numbers: Vec<$numty> = rand::thread_rng()
+                    .sample_iter(&distributions::Standard)
+                    .take(100000)
+                    .collect();
                 let mut bytes = vec![0; numbers.len() * size_of::<$numty>()];
 
                 b.bytes = bytes.len() as u64;
                 b.iter(|| {
                     LittleEndian::$write(&numbers, &mut bytes);
                 });
             }
         }
--- a/third_party/rust/byteorder/src/io.rs
+++ b/third_party/rust/byteorder/src/io.rs
@@ -1,31 +1,35 @@
 use std::io::{self, Result};
 use std::slice;
 
 use ByteOrder;
 
-/// Extends `Read` with methods for reading numbers. (For `std::io`.)
+/// Extends [`Read`] with methods for reading numbers. (For `std::io`.)
 ///
 /// Most of the methods defined here have an unconstrained type parameter that
 /// must be explicitly instantiated. Typically, it is instantiated with either
-/// the `BigEndian` or `LittleEndian` types defined in this crate.
+/// the [`BigEndian`] or [`LittleEndian`] types defined in this crate.
 ///
 /// # Examples
 ///
-/// Read unsigned 16 bit big-endian integers from a `Read`:
+/// Read unsigned 16 bit big-endian integers from a [`Read`]:
 ///
 /// ```rust
 /// use std::io::Cursor;
 /// use byteorder::{BigEndian, ReadBytesExt};
 ///
 /// let mut rdr = Cursor::new(vec![2, 5, 3, 0]);
 /// assert_eq!(517, rdr.read_u16::<BigEndian>().unwrap());
 /// assert_eq!(768, rdr.read_u16::<BigEndian>().unwrap());
 /// ```
+///
+/// [`BigEndian`]: enum.BigEndian.html
+/// [`LittleEndian`]: enum.LittleEndian.html
+/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
 pub trait ReadBytesExt: io::Read {
     /// Reads an unsigned 8 bit integer from the underlying reader.
     ///
     /// Note that since this reads a single byte, no byte order conversions
     /// are used. It is included for completeness.
     ///
     /// # Errors
     ///
@@ -34,17 +38,17 @@ pub trait ReadBytesExt: io::Read {
     /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
     ///
     /// # Examples
     ///
     /// Read unsigned 8 bit integers from a `Read`:
     ///
     /// ```rust
     /// use std::io::Cursor;
-    /// use byteorder::{BigEndian, ReadBytesExt};
+    /// use byteorder::ReadBytesExt;
     ///
     /// let mut rdr = Cursor::new(vec![2, 5]);
     /// assert_eq!(2, rdr.read_u8().unwrap());
     /// assert_eq!(5, rdr.read_u8().unwrap());
     /// ```
     #[inline]
     fn read_u8(&mut self) -> Result<u8> {
         let mut buf = [0; 1];
@@ -60,21 +64,21 @@ pub trait ReadBytesExt: io::Read {
     /// # Errors
     ///
     /// This method returns the same errors as [`Read::read_exact`].
     ///
     /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
     ///
     /// # Examples
     ///
-    /// Read unsigned 8 bit integers from a `Read`:
+    /// Read signed 8 bit integers from a `Read`:
     ///
     /// ```rust
     /// use std::io::Cursor;
-    /// use byteorder::{BigEndian, ReadBytesExt};
+    /// use byteorder::ReadBytesExt;
     ///
     /// let mut rdr = Cursor::new(vec![0x02, 0xfb]);
     /// assert_eq!(2, rdr.read_i8().unwrap());
     /// assert_eq!(-5, rdr.read_i8().unwrap());
     /// ```
     #[inline]
     fn read_i8(&mut self) -> Result<i8> {
         let mut buf = [0; 1];
@@ -235,16 +239,68 @@ pub trait ReadBytesExt: io::Read {
     /// ```
     #[inline]
     fn read_i32<T: ByteOrder>(&mut self) -> Result<i32> {
         let mut buf = [0; 4];
         try!(self.read_exact(&mut buf));
         Ok(T::read_i32(&buf))
     }
 
+    /// Reads an unsigned 48 bit integer from the underlying reader.
+    ///
+    /// # Errors
+    ///
+    /// This method returns the same errors as [`Read::read_exact`].
+    ///
+    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
+    ///
+    /// # Examples
+    ///
+    /// Read unsigned 48 bit big-endian integers from a `Read`:
+    ///
+    /// ```rust
+    /// use std::io::Cursor;
+    /// use byteorder::{BigEndian, ReadBytesExt};
+    ///
+    /// let mut rdr = Cursor::new(vec![0xb6, 0x71, 0x6b, 0xdc, 0x2b, 0x31]);
+    /// assert_eq!(200598257150769, rdr.read_u48::<BigEndian>().unwrap());
+    /// ```
+    #[inline]
+    fn read_u48<T: ByteOrder>(&mut self) -> Result<u64> {
+        let mut buf = [0; 6];
+        try!(self.read_exact(&mut buf));
+        Ok(T::read_u48(&buf))
+    }
+
+    /// Reads a signed 48 bit integer from the underlying reader.
+    ///
+    /// # Errors
+    ///
+    /// This method returns the same errors as [`Read::read_exact`].
+    ///
+    /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
+    ///
+    /// # Examples
+    ///
+    /// Read signed 48 bit big-endian integers from a `Read`:
+    ///
+    /// ```rust
+    /// use std::io::Cursor;
+    /// use byteorder::{BigEndian, ReadBytesExt};
+    ///
+    /// let mut rdr = Cursor::new(vec![0x9d, 0x71, 0xab, 0xe7, 0x97, 0x8f]);
+    /// assert_eq!(-108363435763825, rdr.read_i48::<BigEndian>().unwrap());
+    /// ```
+    #[inline]
+    fn read_i48<T: ByteOrder>(&mut self) -> Result<i64> {
+        let mut buf = [0; 6];
+        try!(self.read_exact(&mut buf));
+        Ok(T::read_i48(&buf))
+    }
+
     /// Reads an unsigned 64 bit integer from the underlying reader.
     ///
     /// # Errors
     ///
     /// This method returns the same errors as [`Read::read_exact`].
     ///
     /// [`Read::read_exact`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact
     ///
@@ -618,17 +674,17 @@ pub trait ReadBytesExt: io::Read {
     /// ```
     #[cfg(feature = "i128")]
     #[inline]
     fn read_u128_into<T: ByteOrder>(
         &mut self,
         dst: &mut [u128],
     ) -> Result<()> {
         {
-            let mut buf = unsafe { slice_to_u8_mut(dst) };
+            let buf = unsafe { slice_to_u8_mut(dst) };
             try!(self.read_exact(buf));
         }
         T::from_slice_u128(dst);
         Ok(())
     }
 
     /// Reads a sequence of signed 16 bit integers from the underlying
     /// reader.
@@ -768,17 +824,17 @@ pub trait ReadBytesExt: io::Read {
     /// ```
     #[cfg(feature = "i128")]
     #[inline]
     fn read_i128_into<T: ByteOrder>(
         &mut self,
         dst: &mut [i128],
     ) -> Result<()> {
         {
-            let mut buf = unsafe { slice_to_u8_mut(dst) };
+            let buf = unsafe { slice_to_u8_mut(dst) };
             try!(self.read_exact(buf));
         }
         T::from_slice_i128(dst);
         Ok(())
     }
 
     /// Reads a sequence of IEEE754 single-precision (4 bytes) floating
     /// point numbers from the underlying reader.
@@ -855,16 +911,17 @@ pub trait ReadBytesExt: io::Read {
     ///     0x40, 0x49, 0x0f, 0xdb,
     ///     0x3f, 0x80, 0x00, 0x00,
     /// ]);
     /// let mut dst = [0.0; 2];
     /// rdr.read_f32_into_unchecked::<BigEndian>(&mut dst).unwrap();
     /// assert_eq!([f32::consts::PI, 1.0], dst);
     /// ```
     #[inline]
+    #[deprecated(since="1.2.0", note="please use `read_f32_into` instead")]
     fn read_f32_into_unchecked<T: ByteOrder>(
         &mut self,
         dst: &mut [f32],
     ) -> Result<()> {
         self.read_f32_into::<T>(dst)
     }
 
     /// Reads a sequence of IEEE754 double-precision (8 bytes) floating
@@ -948,182 +1005,371 @@ pub trait ReadBytesExt: io::Read {
     ///     0x40, 0x09, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18,
     ///     0x3f, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     /// ]);
     /// let mut dst = [0.0; 2];
     /// rdr.read_f64_into_unchecked::<BigEndian>(&mut dst).unwrap();
     /// assert_eq!([f64::consts::PI, 1.0], dst);
     /// ```
     #[inline]
+    #[deprecated(since="1.2.0", note="please use `read_f64_into` instead")]
     fn read_f64_into_unchecked<T: ByteOrder>(
         &mut self,
         dst: &mut [f64],
     ) -> Result<()> {
         self.read_f64_into::<T>(dst)
     }
 }
 
 /// All types that implement `Read` get methods defined in `ReadBytesExt`
 /// for free.
 impl<R: io::Read + ?Sized> ReadBytesExt for R {}
 
-/// Extends `Write` with methods for writing numbers. (For `std::io`.)
+/// Extends [`Write`] with methods for writing numbers. (For `std::io`.)
 ///
 /// Most of the methods defined here have an unconstrained type parameter that
 /// must be explicitly instantiated. Typically, it is instantiated with either
-/// the `BigEndian` or `LittleEndian` types defined in this crate.
+/// the [`BigEndian`] or [`LittleEndian`] types defined in this crate.
 ///
 /// # Examples
 ///
-/// Write unsigned 16 bit big-endian integers to a `Write`:
+/// Write unsigned 16 bit big-endian integers to a [`Write`]:
 ///
 /// ```rust
 /// use byteorder::{BigEndian, WriteBytesExt};
 ///
 /// let mut wtr = vec![];
 /// wtr.write_u16::<BigEndian>(517).unwrap();
 /// wtr.write_u16::<BigEndian>(768).unwrap();
 /// assert_eq!(wtr, vec![2, 5, 3, 0]);
 /// ```
+///
+/// [`BigEndian`]: enum.BigEndian.html
+/// [`LittleEndian`]: enum.LittleEndian.html
+/// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
 pub trait WriteBytesExt: io::Write {
     /// Writes an unsigned 8 bit integer to the underlying writer.
     ///
     /// Note that since this writes a single byte, no byte order conversions
     /// are used. It is included for completeness.
     ///
     /// # Errors
     ///
     /// This method returns the same errors as [`Write::write_all`].
     ///
     /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
+    ///
+    /// # Examples
+    ///
+    /// Write unsigned 8 bit integers to a `Write`:
+    ///
+    /// ```rust
+    /// use byteorder::WriteBytesExt;
+    ///
+    /// let mut wtr = Vec::new();
+    /// wtr.write_u8(2).unwrap();
+    /// wtr.write_u8(5).unwrap();
+    /// assert_eq!(wtr, b"\x02\x05");
+    /// ```
     #[inline]
     fn write_u8(&mut self, n: u8) -> Result<()> {
         self.write_all(&[n])
     }
 
     /// Writes a signed 8 bit integer to the underlying writer.
     ///
     /// Note that since this writes a single byte, no byte order conversions
     /// are used. It is included for completeness.
     ///
     /// # Errors
     ///
     /// This method returns the same errors as [`Write::write_all`].
     ///
     /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
+    ///
+    /// # Examples
+    ///
+    /// Write signed 8 bit integers to a `Write`:
+    ///
+    /// ```rust
+    /// use byteorder::WriteBytesExt;
+    ///
+    /// let mut wtr = Vec::new();
+    /// wtr.write_i8(2).unwrap();
+    /// wtr.write_i8(-5).unwrap();
+    /// assert_eq!(wtr, b"\x02\xfb");
+    /// ```
     #[inline]
     fn write_i8(&mut self, n: i8) -> Result<()> {
         self.write_all(&[n as u8])
     }
 
     /// Writes an unsigned 16 bit integer to the underlying writer.
     ///
     /// # Errors
     ///
     /// This method returns the same errors as [`Write::write_all`].
     ///
     /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
+    ///
+    /// # Examples
+    ///
+    /// Write unsigned 16 bit big-endian integers to a `Write`:
+    ///
+    /// ```rust
+    /// use byteorder::{BigEndian, WriteBytesExt};
+    ///
+    /// let mut wtr = Vec::new();
+    /// wtr.write_u16::<BigEndian>(517).unwrap();
+    /// wtr.write_u16::<BigEndian>(768).unwrap();
+    /// assert_eq!(wtr, b"\x02\x05\x03\x00");
+    /// ```
     #[inline]
     fn write_u16<T: ByteOrder>(&mut self, n: u16) -> Result<()> {
         let mut buf = [0; 2];
         T::write_u16(&mut buf, n);
         self.write_all(&buf)
     }
 
     /// Writes a signed 16 bit integer to the underlying writer.
     ///
     /// # Errors
     ///
     /// This method returns the same errors as [`Write::write_all`].
     ///
     /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
+    ///
+    /// # Examples
+    ///
+    /// Write signed 16 bit big-endian integers to a `Write`:
+    ///
+    /// ```rust
+    /// use byteorder::{BigEndian, WriteBytesExt};
+    ///
+    /// let mut wtr = Vec::new();
+    /// wtr.write_i16::<BigEndian>(193).unwrap();
+    /// wtr.write_i16::<BigEndian>(-132).unwrap();
+    /// assert_eq!(wtr, b"\x00\xc1\xff\x7c");
+    /// ```
     #[inline]
     fn write_i16<T: ByteOrder>(&mut self, n: i16) -> Result<()> {
         let mut buf = [0; 2];
         T::write_i16(&mut buf, n);
         self.write_all(&buf)
     }
 
     /// Writes an unsigned 24 bit integer to the underlying writer.
     ///
     /// # Errors
     ///
     /// This method returns the same errors as [`Write::write_all`].
     ///
     /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
+    ///
+    /// # Examples
+    ///
+    /// Write unsigned 24 bit big-endian integers to a `Write`:
+    ///
+    /// ```rust
+    /// use byteorder::{BigEndian, WriteBytesExt};
+    ///
+    /// let mut wtr = Vec::new();
+    /// wtr.write_u24::<BigEndian>(267).unwrap();
+    /// wtr.write_u24::<BigEndian>(120111).unwrap();
+    /// assert_eq!(wtr, b"\x00\x01\x0b\x01\xd5\x2f");
+    /// ```
     #[inline]
     fn write_u24<T: ByteOrder>(&mut self, n: u32) -> Result<()> {
         let mut buf = [0; 3];
         T::write_u24(&mut buf, n);
         self.write_all(&buf)
     }
 
     /// Writes a signed 24 bit integer to the underlying writer.
     ///
     /// # Errors
     ///
     /// This method returns the same errors as [`Write::write_all`].
     ///
     /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
+    ///
+    /// # Examples
+    ///
+    /// Write signed 24 bit big-endian integers to a `Write`:
+    ///
+    /// ```rust
+    /// use byteorder::{BigEndian, WriteBytesExt};
+    ///
+    /// let mut wtr = Vec::new();
+    /// wtr.write_i24::<BigEndian>(-34253).unwrap();
+    /// wtr.write_i24::<BigEndian>(120111).unwrap();
+    /// assert_eq!(wtr, b"\xff\x7a\x33\x01\xd5\x2f");
+    /// ```
     #[inline]
     fn write_i24<T: ByteOrder>(&mut self, n: i32) -> Result<()> {
         let mut buf = [0; 3];
         T::write_i24(&mut buf, n);
         self.write_all(&buf)
     }
 
     /// Writes an unsigned 32 bit integer to the underlying writer.
     ///
     /// # Errors
     ///
     /// This method returns the same errors as [`Write::write_all`].
     ///
     /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
+    ///
+    /// # Examples
+    ///
+    /// Write unsigned 32 bit big-endian integers to a `Write`:
+    ///
+    /// ```rust
+    /// use byteorder::{BigEndian, WriteBytesExt};
+    ///
+    /// let mut wtr = Vec::new();
+    /// wtr.write_u32::<BigEndian>(267).unwrap();
+    /// wtr.write_u32::<BigEndian>(1205419366).unwrap();
+    /// assert_eq!(wtr, b"\x00\x00\x01\x0b\x47\xd9\x3d\x66");
+    /// ```
     #[inline]
     fn write_u32<T: ByteOrder>(&mut self, n: u32) -> Result<()> {
         let mut buf = [0; 4];
         T::write_u32(&mut buf, n);
         self.write_all(&buf)
     }
 
     /// Writes a signed 32 bit integer to the underlying writer.
     ///
     /// # Errors
     ///
     /// This method returns the same errors as [`Write::write_all`].
     ///
     /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
+    ///
+    /// # Examples
+    ///
+    /// Write signed 32 bit big-endian integers to a `Write`:
+    ///
+    /// ```rust
+    /// use byteorder::{BigEndian, WriteBytesExt};
+    ///
+    /// let mut wtr = Vec::new();
+    /// wtr.write_i32::<BigEndian>(-34253).unwrap();
+    /// wtr.write_i32::<BigEndian>(1205419366).unwrap();
+    /// assert_eq!(wtr, b"\xff\xff\x7a\x33\x47\xd9\x3d\x66");
+    /// ```
     #[inline]
     fn write_i32<T: ByteOrder>(&mut self, n: i32) -> Result<()> {
         let mut buf = [0; 4];
         T::write_i32(&mut buf, n);
         self.write_all(&buf)
     }
 
+    /// Writes an unsigned 48 bit integer to the underlying writer.
+    ///
+    /// # Errors
+    ///
+    /// This method returns the same errors as [`Write::write_all`].
+    ///
+    /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
+    ///
+    /// # Examples
+    ///
+    /// Write unsigned 48 bit big-endian integers to a `Write`:
+    ///
+    /// ```rust
+    /// use byteorder::{BigEndian, WriteBytesExt};
+    ///
+    /// let mut wtr = Vec::new();
+    /// wtr.write_u48::<BigEndian>(52360336390828).unwrap();
+    /// wtr.write_u48::<BigEndian>(541).unwrap();
+    /// assert_eq!(wtr, b"\x2f\x9f\x17\x40\x3a\xac\x00\x00\x00\x00\x02\x1d");
+    /// ```
+    #[inline]
+    fn write_u48<T: ByteOrder>(&mut self, n: u64) -> Result<()> {
+        let mut buf = [0; 6];
+        T::write_u48(&mut buf, n);
+        self.write_all(&buf)
+    }
+
+    /// Writes a signed 48 bit integer to the underlying writer.
+    ///
+    /// # Errors
+    ///
+    /// This method returns the same errors as [`Write::write_all`].
+    ///
+    /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
+    ///
+    /// # Examples
+    ///
+    /// Write signed 48 bit big-endian integers to a `Write`:
+    ///
+    /// ```rust
+    /// use byteorder::{BigEndian, WriteBytesExt};
+    ///
+    /// let mut wtr = Vec::new();
+    /// wtr.write_i48::<BigEndian>(-108363435763825).unwrap();
+    /// wtr.write_i48::<BigEndian>(77).unwrap();
+    /// assert_eq!(wtr, b"\x9d\x71\xab\xe7\x97\x8f\x00\x00\x00\x00\x00\x4d");
+    /// ```
+    #[inline]
+    fn write_i48<T: ByteOrder>(&mut self, n: i64) -> Result<()> {
+        let mut buf = [0; 6];
+        T::write_i48(&mut buf, n);
+        self.write_all(&buf)
+    }
+
     /// Writes an unsigned 64 bit integer to the underlying writer.
     ///
     /// # Errors
     ///
     /// This method returns the same errors as [`Write::write_all`].
     ///
     /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
+    ///
+    /// # Examples
+    ///
+    /// Write unsigned 64 bit big-endian integers to a `Write`:
+    ///
+    /// ```rust
+    /// use byteorder::{BigEndian, WriteBytesExt};
+    ///
+    /// let mut wtr = Vec::new();
+    /// wtr.write_u64::<BigEndian>(918733457491587).unwrap();
+    /// wtr.write_u64::<BigEndian>(143).unwrap();
+    /// assert_eq!(wtr, b"\x00\x03\x43\x95\x4d\x60\x86\x83\x00\x00\x00\x00\x00\x00\x00\x8f");
+    /// ```
     #[inline]
     fn write_u64<T: ByteOrder>(&mut self, n: u64) -> Result<()> {
         let mut buf = [0; 8];
         T::write_u64(&mut buf, n);
         self.write_all(&buf)
     }
 
     /// Writes a signed 64 bit integer to the underlying writer.
     ///
     /// # Errors
     ///
     /// This method returns the same errors as [`Write::write_all`].
     ///
     /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
+    ///
+    /// # Examples
+    ///
+    /// Write signed 64 bit big-endian integers to a `Write`:
+    ///
+    /// ```rust
+    /// use byteorder::{BigEndian, WriteBytesExt};
+    ///
+    /// let mut wtr = Vec::new();
+    /// wtr.write_i64::<BigEndian>(i64::min_value()).unwrap();
+    /// wtr.write_i64::<BigEndian>(i64::max_value()).unwrap();
+    /// assert_eq!(wtr, b"\x80\x00\x00\x00\x00\x00\x00\x00\x7f\xff\xff\xff\xff\xff\xff\xff");
+    /// ```
     #[inline]
     fn write_i64<T: ByteOrder>(&mut self, n: i64) -> Result<()> {
         let mut buf = [0; 8];
         T::write_i64(&mut buf, n);
         self.write_all(&buf)
     }
 
     /// Writes an unsigned 128 bit integer to the underlying writer.
@@ -1151,16 +1397,29 @@ pub trait WriteBytesExt: io::Write {
     /// This method returns the same errors as [`Write::write_all`].
     ///
     /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
     ///
     /// # Panics
     ///
     /// If the given integer is not representable in the given number of bytes,
     /// this method panics. If `nbytes > 8`, this method panics.
+    ///
+    /// # Examples
+    ///
+    /// Write unsigned 40 bit big-endian integers to a `Write`:
+    ///
+    /// ```rust
+    /// use byteorder::{BigEndian, WriteBytesExt};
+    ///
+    /// let mut wtr = Vec::new();
+    /// wtr.write_uint::<BigEndian>(312550384361, 5).unwrap();
+    /// wtr.write_uint::<BigEndian>(43, 5).unwrap();
+    /// assert_eq!(wtr, b"\x48\xc5\x74\x62\xe9\x00\x00\x00\x00\x2b");
+    /// ```
     #[inline]
     fn write_uint<T: ByteOrder>(
         &mut self,
         n: u64,
         nbytes: usize,
     ) -> Result<()> {
         let mut buf = [0; 8];
         T::write_uint(&mut buf, n, nbytes);
@@ -1174,16 +1433,29 @@ pub trait WriteBytesExt: io::Write {
     /// This method returns the same errors as [`Write::write_all`].
     ///
     /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
     ///
     /// # Panics
     ///
     /// If the given integer is not representable in the given number of bytes,
     /// this method panics. If `nbytes > 8`, this method panics.
+    ///
+    /// # Examples
+    ///
+    /// Write signed 56 bit big-endian integers to a `Write`:
+    ///
+    /// ```rust
+    /// use byteorder::{BigEndian, WriteBytesExt};
+    ///
+    /// let mut wtr = Vec::new();
+    /// wtr.write_int::<BigEndian>(-3548172039376767, 7).unwrap();
+    /// wtr.write_int::<BigEndian>(43, 7).unwrap();
+    /// assert_eq!(wtr, b"\xf3\x64\xf4\xd1\xfd\xb0\x81\x00\x00\x00\x00\x00\x00\x2b");
+    /// ```
     #[inline]
     fn write_int<T: ByteOrder>(
         &mut self,
         n: i64,
         nbytes: usize,
     ) -> Result<()> {
         let mut buf = [0; 8];
         T::write_int(&mut buf, n, nbytes);
@@ -1225,25 +1497,59 @@ pub trait WriteBytesExt: io::Write {
     /// Writes a IEEE754 single-precision (4 bytes) floating point number to
     /// the underlying writer.
     ///
     /// # Errors
     ///
     /// This method returns the same errors as [`Write::write_all`].
     ///
     /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
+    ///
+    /// # Examples
+    ///
+    /// Write a big-endian single-precision floating point number to a `Write`:
+    ///
+    /// ```rust
+    /// use std::f32;
+    ///
+    /// use byteorder::{BigEndian, WriteBytesExt};
+    ///
+    /// let mut wtr = Vec::new();
+    /// wtr.write_f32::<BigEndian>(f32::consts::PI).unwrap();
+    /// assert_eq!(wtr, b"\x40\x49\x0f\xdb");
+    /// ```
     #[inline]
     fn write_f32<T: ByteOrder>(&mut self, n: f32) -> Result<()> {
         let mut buf = [0; 4];
         T::write_f32(&mut buf, n);
         self.write_all(&buf)
     }
 
     /// Writes a IEEE754 double-precision (8 bytes) floating point number to
     /// the underlying writer.
+    ///
+    /// # Errors
+    ///
+    /// This method returns the same errors as [`Write::write_all`].
+    ///
+    /// [`Write::write_all`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all
+    ///
+    /// # Examples
+    ///
+    /// Write a big-endian double-precision floating point number to a `Write`:
+    ///
+    /// ```rust
+    /// use std::f64;
+    ///
+    /// use byteorder::{BigEndian, WriteBytesExt};
+    ///
+    /// let mut wtr = Vec::new();
+    /// wtr.write_f64::<BigEndian>(f64::consts::PI).unwrap();
+    /// assert_eq!(wtr, b"\x40\x09\x21\xfb\x54\x44\x2d\x18");
+    /// ```
     #[inline]
     fn write_f64<T: ByteOrder>(&mut self, n: f64) -> Result<()> {
         let mut buf = [0; 8];
         T::write_f64(&mut buf, n);
         self.write_all(&buf)
     }
 }
 
--- a/third_party/rust/byteorder/src/lib.rs
+++ b/third_party/rust/byteorder/src/lib.rs
@@ -1,59 +1,81 @@
 /*!
 This crate provides convenience methods for encoding and decoding numbers
-in either big-endian or little-endian order.
+in either [big-endian or little-endian order].
 
-The organization of the crate is pretty simple. A trait, `ByteOrder`, specifies
+The organization of the crate is pretty simple. A trait, [`ByteOrder`], specifies
 byte conversion methods for each type of number in Rust (sans numbers that have
-a platform dependent size like `usize` and `isize`). Two types, `BigEndian`
-and `LittleEndian` implement these methods. Finally, `ReadBytesExt` and
-`WriteBytesExt` provide convenience methods available to all types that
-implement `Read` and `Write`.
+a platform dependent size like `usize` and `isize`). Two types, [`BigEndian`]
+and [`LittleEndian`] implement these methods. Finally, [`ReadBytesExt`] and
+[`WriteBytesExt`] provide convenience methods available to all types that
+implement [`Read`] and [`Write`].
+
+An alias, [`NetworkEndian`], for [`BigEndian`] is provided to help improve
+code clarity.
+
+An additional alias, [`NativeEndian`], is provided for the endianness of the
+local platform. This is convenient when serializing data for use and
+conversions are not desired.
 
 # Examples
 
-Read unsigned 16 bit big-endian integers from a `Read` type:
+Read unsigned 16 bit big-endian integers from a [`Read`] type:
 
 ```rust
 use std::io::Cursor;
 use byteorder::{BigEndian, ReadBytesExt};
 
 let mut rdr = Cursor::new(vec![2, 5, 3, 0]);
 // Note that we use type parameters to indicate which kind of byte order
 // we want!
 assert_eq!(517, rdr.read_u16::<BigEndian>().unwrap());
 assert_eq!(768, rdr.read_u16::<BigEndian>().unwrap());
 ```
 
-Write unsigned 16 bit little-endian integers to a `Write` type:
+Write unsigned 16 bit little-endian integers to a [`Write`] type:
 
 ```rust
 use byteorder::{LittleEndian, WriteBytesExt};
 
 let mut wtr = vec![];
 wtr.write_u16::<LittleEndian>(517).unwrap();
 wtr.write_u16::<LittleEndian>(768).unwrap();
 assert_eq!(wtr, vec![5, 2, 0, 3]);
 ```
+
+# Optional Features
+
+This crate optionally provides support for 128 bit values (`i128` and `u128`)
+when built with the `i128` feature enabled.
+
+This crate can also be used without the standard library.
+
+[big-endian or little-endian order]: https://en.wikipedia.org/wiki/Endianness
+[`ByteOrder`]: trait.ByteOrder.html
+[`BigEndian`]: enum.BigEndian.html
+[`LittleEndian`]: enum.LittleEndian.html
+[`ReadBytesExt`]: trait.ReadBytesExt.html
+[`WriteBytesExt`]: trait.WriteBytesExt.html
+[`NetworkEndian`]: type.NetworkEndian.html
+[`NativeEndian`]: type.NativeEndian.html
+[`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
+[`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
 */
 
 #![deny(missing_docs)]
 #![cfg_attr(not(feature = "std"), no_std)]
-#![cfg_attr(feature = "i128", feature(i128_type))]
-#![cfg_attr(all(feature = "i128", test), feature(i128))]
-#![doc(html_root_url = "https://docs.rs/byteorder/1.2.1")]
 
 #[cfg(feature = "std")]
 extern crate core;
 
 use core::fmt::Debug;
 use core::hash::Hash;
-use core::mem::transmute;
 use core::ptr::copy_nonoverlapping;
+use core::slice;
 
 #[cfg(feature = "std")]
 pub use io::{ReadBytesExt, WriteBytesExt};
 
 #[cfg(feature = "std")]
 mod io;
 
 #[inline]
@@ -144,24 +166,24 @@ fn pack_size128(n: u128) -> usize {
 mod private {
     /// Sealed stops crates other than byteorder from implementing any traits
     /// that use it.
     pub trait Sealed{}
     impl Sealed for super::LittleEndian {}
     impl Sealed for super::BigEndian {}
 }
 
-/// ByteOrder describes types that can serialize integers as bytes.
+/// `ByteOrder` describes types that can serialize integers as bytes.
 ///
 /// Note that `Self` does not appear anywhere in this trait's definition!
 /// Therefore, in order to use it, you'll need to use syntax like
 /// `T::read_u16(&[0, 1])` where `T` implements `ByteOrder`.
 ///
-/// This crate provides two types that implement `ByteOrder`: `BigEndian`
-/// and `LittleEndian`.
+/// This crate provides two types that implement `ByteOrder`: [`BigEndian`]
+/// and [`LittleEndian`].
 /// This trait is sealed and cannot be implemented for callers to avoid
 /// breaking backwards compatibility when adding new derived traits.
 ///
 /// # Examples
 ///
 /// Write and read `u32` numbers in little endian order:
 ///
 /// ```rust
@@ -176,16 +198,19 @@ mod private {
 ///
 /// ```rust
 /// use byteorder::{ByteOrder, BigEndian};
 ///
 /// let mut buf = [0; 2];
 /// BigEndian::write_i16(&mut buf, -50_000);
 /// assert_eq!(-50_000, BigEndian::read_i16(&buf));
 /// ```
+///
+/// [`BigEndian`]: enum.BigEndian.html
+/// [`LittleEndian`]: enum.LittleEndian.html
 pub trait ByteOrder
     : Clone + Copy + Debug + Default + Eq + Hash + Ord + PartialEq + PartialOrd
     + private::Sealed
 {
     /// Reads an unsigned 16 bit integer from `buf`.
     ///
     /// # Panics
     ///
@@ -227,16 +252,37 @@ pub trait ByteOrder
     /// use byteorder::{ByteOrder, LittleEndian};
     ///
     /// let mut buf = [0; 4];
     /// LittleEndian::write_u32(&mut buf, 1_000_000);
     /// assert_eq!(1_000_000, LittleEndian::read_u32(&buf));
     /// ```
     fn read_u32(buf: &[u8]) -> u32;
 
+    /// Reads an unsigned 48 bit integer from `buf`, stored in u64.
+    ///
+    /// # Panics
+    ///
+    /// Panics when `buf.len() < 6`.
+    ///
+    /// # Examples
+    ///
+    /// Write and read 48 bit `u64` numbers in little endian order:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, LittleEndian};
+    ///
+    /// let mut buf = [0; 6];
+    /// LittleEndian::write_u48(&mut buf, 1_000_000_000_000);
+    /// assert_eq!(1_000_000_000_000, LittleEndian::read_u48(&buf));
+    /// ```
+    fn read_u48(buf: &[u8]) -> u64 {
+        Self::read_uint(buf, 6) as u64
+    }
+
     /// Reads an unsigned 64 bit integer from `buf`.
     ///
     /// # Panics
     ///
     /// Panics when `buf.len() < 8`.
     ///
     /// # Examples
     ///
@@ -366,16 +412,37 @@ pub trait ByteOrder
     /// use byteorder::{ByteOrder, LittleEndian};
     ///
     /// let mut buf = [0; 4];
     /// LittleEndian::write_u32(&mut buf, 1_000_000);
     /// assert_eq!(1_000_000, LittleEndian::read_u32(&buf));
     /// ```
     fn write_u32(buf: &mut [u8], n: u32);
 
+    /// Writes an unsigned 48 bit integer `n` to `buf`, stored in u64.
+    ///
+    /// # Panics
+    ///
+    /// Panics when `buf.len() < 6`.
+    ///
+    /// # Examples
+    ///
+    /// Write and read 48 bit `u64` numbers in little endian order:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, LittleEndian};
+    ///
+    /// let mut buf = [0; 6];
+    /// LittleEndian::write_u48(&mut buf, 1_000_000_000_000);
+    /// assert_eq!(1_000_000_000_000, LittleEndian::read_u48(&buf));
+    /// ```
+    fn write_u48(buf: &mut [u8], n: u64) {
+        Self::write_uint(buf, n as u64, 6)
+    }
+
     /// Writes an unsigned 64 bit integer `n` to `buf`.
     ///
     /// # Panics
     ///
     /// Panics when `buf.len() < 8`.
     ///
     /// # Examples
     ///
@@ -512,16 +579,38 @@ pub trait ByteOrder
     /// LittleEndian::write_i32(&mut buf, -1_000_000);
     /// assert_eq!(-1_000_000, LittleEndian::read_i32(&buf));
     /// ```
     #[inline]
     fn read_i32(buf: &[u8]) -> i32 {
         Self::read_u32(buf) as i32
     }
 
+    /// Reads a signed 48 bit integer from `buf`, stored in i64.
+    ///
+    /// # Panics
+    ///
+    /// Panics when `buf.len() < 6`.
+    ///
+    /// # Examples
+    ///
+    /// Write and read 48 bit `i64` numbers in little endian order:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, LittleEndian};
+    ///
+    /// let mut buf = [0; 6];
+    /// LittleEndian::write_i48(&mut buf, -1_000_000_000_000);
+    /// assert_eq!(-1_000_000_000_000, LittleEndian::read_i48(&buf));
+    /// ```
+    #[inline]
+    fn read_i48(buf: &[u8]) -> i64 {
+        Self::read_int(buf, 6) as i64
+    }
+
     /// Reads a signed 64 bit integer from `buf`.
     ///
     /// # Panics
     ///
     /// Panics when `buf.len() < 8`.
     ///
     /// # Examples
     ///
@@ -624,17 +713,17 @@ pub trait ByteOrder
     ///
     /// let e = 2.71828;
     /// let mut buf = [0; 4];
     /// LittleEndian::write_f32(&mut buf, e);
     /// assert_eq!(e, LittleEndian::read_f32(&buf));
     /// ```
     #[inline]
     fn read_f32(buf: &[u8]) -> f32 {
-        unsafe { transmute(Self::read_u32(buf)) }
+        unsafe { *(&Self::read_u32(buf) as *const u32 as *const f32) }
     }
 
     /// Reads a IEEE754 double-precision (8 bytes) floating point number.
     ///
     /// # Panics
     ///
     /// Panics when `buf.len() < 8`.
     ///
@@ -647,17 +736,17 @@ pub trait ByteOrder
     ///
     /// let phi = 1.6180339887;
     /// let mut buf = [0; 8];
     /// LittleEndian::write_f64(&mut buf, phi);
     /// assert_eq!(phi, LittleEndian::read_f64(&buf));
     /// ```
     #[inline]
     fn read_f64(buf: &[u8]) -> f64 {
-        unsafe { transmute(Self::read_u64(buf)) }
+        unsafe { *(&Self::read_u64(buf) as *const u64 as *const f64) }
     }
 
     /// Writes a signed 16 bit integer `n` to `buf`.
     ///
     /// # Panics
     ///
     /// Panics when `buf.len() < 2`.
     ///
@@ -716,16 +805,38 @@ pub trait ByteOrder
     /// LittleEndian::write_i32(&mut buf, -1_000_000);
     /// assert_eq!(-1_000_000, LittleEndian::read_i32(&buf));
     /// ```
     #[inline]
     fn write_i32(buf: &mut [u8], n: i32) {
         Self::write_u32(buf, n as u32)
     }
 
+    /// Writes a signed 48 bit integer `n` to `buf`, stored in i64.
+    ///
+    /// # Panics
+    ///
+    /// Panics when `buf.len() < 6`.
+    ///
+    /// # Examples
+    ///
+    /// Write and read 48 bit `i64` numbers in little endian order:
+    ///
+    /// ```rust
+    /// use byteorder::{ByteOrder, LittleEndian};
+    ///
+    /// let mut buf = [0; 6];
+    /// LittleEndian::write_i48(&mut buf, -1_000_000_000_000);
+    /// assert_eq!(-1_000_000_000_000, LittleEndian::read_i48(&buf));
+    /// ```
+    #[inline]
+    fn write_i48(buf: &mut [u8], n: i64) {
+        Self::write_int(buf, n as i64, 6)
+    }
+
     /// Writes a signed 64 bit integer `n` to `buf`.
     ///
     /// # Panics
     ///
     /// Panics when `buf.len() < 8`.
     ///
     /// # Examples
     ///
@@ -828,17 +939,18 @@ pub trait ByteOrder
     ///
     /// let e = 2.71828;
     /// let mut buf = [0; 4];
     /// LittleEndian::write_f32(&mut buf, e);
     /// assert_eq!(e, LittleEndian::read_f32(&buf));
     /// ```
     #[inline]
     fn write_f32(buf: &mut [u8], n: f32) {
-        Self::write_u32(buf, unsafe { transmute(n) })
+        let n = unsafe { *(&n as *const f32 as *const u32) };
+        Self::write_u32(buf, n)
     }
 
     /// Writes a IEEE754 double-precision (8 bytes) floating point number.
     ///
     /// # Panics
     ///
     /// Panics when `buf.len() < 8`.
     ///
@@ -851,17 +963,18 @@ pub trait ByteOrder
     ///
     /// let phi = 1.6180339887;
     /// let mut buf = [0; 8];
     /// LittleEndian::write_f64(&mut buf, phi);
     /// assert_eq!(phi, LittleEndian::read_f64(&buf));
     /// ```
     #[inline]
     fn write_f64(buf: &mut [u8], n: f64) {
-        Self::write_u64(buf, unsafe { transmute(n) })
+        let n = unsafe { *(&n as *const f64 as *const u64) };
+        Self::write_u64(buf, n)
     }
 
     /// Reads unsigned 16 bit integers from `src` into `dst`.
     ///
     /// # Panics
     ///
     /// Panics when `src.len() != 2*dst.len()`.
     ///
@@ -970,17 +1083,20 @@ pub trait ByteOrder
     /// LittleEndian::write_i16_into(&numbers_given, &mut bytes);
     ///
     /// let mut numbers_got = [0; 4];
     /// LittleEndian::read_i16_into(&bytes, &mut numbers_got);
     /// assert_eq!(numbers_given, numbers_got);
     /// ```
     #[inline]
     fn read_i16_into(src: &[u8], dst: &mut [i16]) {
-        Self::read_u16_into(src, unsafe { transmute(dst) });
+        let dst = unsafe {
+            slice::from_raw_parts_mut(dst.as_mut_ptr() as *mut u16, dst.len())
+        };
+        Self::read_u16_into(src, dst)
     }
 
     /// Reads signed 32 bit integers from `src` into `dst`.
     ///
     /// # Panics
     ///
     /// Panics when `src.len() != 4*dst.len()`.
     ///
@@ -996,17 +1112,20 @@ pub trait ByteOrder
     /// LittleEndian::write_i32_into(&numbers_given, &mut bytes);
     ///
     /// let mut numbers_got = [0; 4];
     /// LittleEndian::read_i32_into(&bytes, &mut numbers_got);
     /// assert_eq!(numbers_given, numbers_got);
     /// ```
     #[inline]
     fn read_i32_into(src: &[u8], dst: &mut [i32]) {
-        Self::read_u32_into(src, unsafe { transmute(dst) });
+        let dst = unsafe {
+            slice::from_raw_parts_mut(dst.as_mut_ptr() as *mut u32, dst.len())
+        };
+        Self::read_u32_into(src, dst);
     }
 
     /// Reads signed 64 bit integers from `src` into `dst`.
     ///
     /// # Panics
     ///
     /// Panics when `src.len() != 8*dst.len()`.
     ///
@@ -1022,17 +1141,20 @@ pub trait ByteOrder
     /// LittleEndian::write_i64_into(&numbers_given, &mut bytes);
     ///
     /// let mut numbers_got = [0; 4];
     /// LittleEndian::read_i64_into(&bytes, &mut numbers_got);
     /// assert_eq!(numbers_given, numbers_got);
     /// ```
     #[inline]
     fn read_i64_into(src: &[u8], dst: &mut [i64]) {
-        Self::read_u64_into(src, unsafe { transmute(dst) });
+        let dst = unsafe {
+            slice::from_raw_parts_mut(dst.as_mut_ptr() as *mut u64, dst.len())
+        };
+        Self::read_u64_into(src, dst);
     }
 
     /// Reads signed 128 bit integers from `src` into `dst`.
     ///
     /// # Panics
     ///
     /// Panics when `src.len() != 16*dst.len()`.
     ///
@@ -1049,17 +1171,20 @@ pub trait ByteOrder
     ///
     /// let mut numbers_got = [0; 4];
     /// LittleEndian::read_i128_into(&bytes, &mut numbers_got);
     /// assert_eq!(numbers_given, numbers_got);
     /// ```
     #[cfg(feature = "i128")]
     #[inline]
     fn read_i128_into(src: &[u8], dst: &mut [i128]) {
-        Self::read_u128_into(src, unsafe { transmute(dst) });
+        let dst = unsafe {
+            slice::from_raw_parts_mut(dst.as_mut_ptr() as *mut u128, dst.len())
+        };
+        Self::read_u128_into(src, dst);
     }
 
     /// Reads IEEE754 single-precision (4 bytes) floating point numbers from
     /// `src` into `dst`.
     ///
     /// # Panics
     ///
     /// Panics when `src.len() != 4*dst.len()`.
@@ -1076,17 +1201,20 @@ pub trait ByteOrder
     /// LittleEndian::write_f32_into(&numbers_given, &mut bytes);
     ///
     /// let mut numbers_got = [0.0; 4];
     /// LittleEndian::read_f32_into_unchecked(&bytes, &mut numbers_got);
     /// assert_eq!(numbers_given, numbers_got);
     /// ```
     #[inline]
     fn read_f32_into_unchecked(src: &[u8], dst: &mut [f32]) {
-        Self::read_u32_into(src, unsafe { transmute(dst) });
+        let dst = unsafe {
+            slice::from_raw_parts_mut(dst.as_mut_ptr() as *mut u32, dst.len())
+        };
+        Self::read_u32_into(src, dst);
     }
 
     /// Reads IEEE754 single-precision (4 bytes) floating point numbers from
     /// `src` into `dst`.
     ///
     /// # Panics
     ///
     /// Panics when `src.len() != 8*dst.len()`.
@@ -1103,17 +1231,20 @@ pub trait ByteOrder
     /// LittleEndian::write_f64_into(&numbers_given, &mut bytes);
     ///
     /// let mut numbers_got = [0.0; 4];
     /// LittleEndian::read_f64_into_unchecked(&bytes, &mut numbers_got);
     /// assert_eq!(numbers_given, numbers_got);
     /// ```
     #[inline]
     fn read_f64_into_unchecked(src: &[u8], dst: &mut [f64]) {
-        Self::read_u64_into(src, unsafe { transmute(dst) });
+        let dst = unsafe {
+            slice::from_raw_parts_mut(dst.as_mut_ptr() as *mut u64, dst.len())
+        };
+        Self::read_u64_into(src, dst);
     }
 
     /// Writes unsigned 16 bit integers from `src` into `dst`.
     ///
     /// # Panics
     ///
     /// Panics when `dst.len() != 2*src.len()`.
     ///
@@ -1221,17 +1352,20 @@ pub trait ByteOrder
     /// let numbers_given = [1, 2, 0xf00f, 0xffee];
     /// LittleEndian::write_i16_into(&numbers_given, &mut bytes);
     ///
     /// let mut numbers_got = [0; 4];
     /// LittleEndian::read_i16_into(&bytes, &mut numbers_got);
     /// assert_eq!(numbers_given, numbers_got);
     /// ```
     fn write_i16_into(src: &[i16], dst: &mut [u8]) {
-        Self::write_u16_into(unsafe { transmute(src) }, dst);
+        let src = unsafe {
+            slice::from_raw_parts(src.as_ptr() as *const u16, src.len())
+        };
+        Self::write_u16_into(src, dst);
     }
 
     /// Writes signed 32 bit integers from `src` into `dst`.
     ///
     /// # Panics
     ///
     /// Panics when `dst.len() != 4*src.len()`.
     ///
@@ -1246,17 +1380,20 @@ pub trait ByteOrder
     /// let numbers_given = [1, 2, 0xf00f, 0xffee];
     /// LittleEndian::write_i32_into(&numbers_given, &mut bytes);
     ///
     /// let mut numbers_got = [0; 4];
     /// LittleEndian::read_i32_into(&bytes, &mut numbers_got);
     /// assert_eq!(numbers_given, numbers_got);
     /// ```
     fn write_i32_into(src: &[i32], dst: &mut [u8]) {
-        Self::write_u32_into(unsafe { transmute(src) }, dst);
+        let src = unsafe {
+            slice::from_raw_parts(src.as_ptr() as *const u32, src.len())
+        };
+        Self::write_u32_into(src, dst);
     }
 
     /// Writes signed 64 bit integers from `src` into `dst`.
     ///
     /// # Panics
     ///
     /// Panics when `dst.len() != 8*src.len()`.
     ///
@@ -1271,17 +1408,20 @@ pub trait ByteOrder
     /// let numbers_given = [1, 2, 0xf00f, 0xffee];
     /// LittleEndian::write_i64_into(&numbers_given, &mut bytes);
     ///
     /// let mut numbers_got = [0; 4];
     /// LittleEndian::read_i64_into(&bytes, &mut numbers_got);
     /// assert_eq!(numbers_given, numbers_got);
     /// ```
     fn write_i64_into(src: &[i64], dst: &mut [u8]) {
-        Self::write_u64_into(unsafe { transmute(src) }, dst);
+        let src = unsafe {
+            slice::from_raw_parts(src.as_ptr() as *const u64, src.len())
+        };
+        Self::write_u64_into(src, dst);
     }
 
     /// Writes signed 128 bit integers from `src` into `dst`.
     ///
     /// # Panics
     ///
     /// Panics when `dst.len() != 16*src.len()`.
     ///
@@ -1297,17 +1437,20 @@ pub trait ByteOrder
     /// LittleEndian::write_i128_into(&numbers_given, &mut bytes);
     ///
     /// let mut numbers_got = [0; 4];
     /// LittleEndian::read_i128_into(&bytes, &mut numbers_got);
     /// assert_eq!(numbers_given, numbers_got);
     /// ```
     #[cfg(feature = "i128")]
     fn write_i128_into(src: &[i128], dst: &mut [u8]) {
-        Self::write_u128_into(unsafe { transmute(src) }, dst);
+        let src = unsafe {
+            slice::from_raw_parts(src.as_ptr() as *const u128, src.len())
+        };
+        Self::write_u128_into(src, dst);
     }
 
     /// Writes IEEE754 single-precision (4 bytes) floating point numbers from
     /// `src` into `dst`.
     ///
     /// # Panics
     ///
     /// Panics when `src.len() != 4*dst.len()`.
@@ -1325,17 +1468,20 @@ pub trait ByteOrder
     ///
     /// let mut numbers_got = [0.0; 4];
     /// unsafe {
     ///     LittleEndian::read_f32_into_unchecked(&bytes, &mut numbers_got);
     /// }
     /// assert_eq!(numbers_given, numbers_got);
     /// ```
     fn write_f32_into(src: &[f32], dst: &mut [u8]) {
-        Self::write_u32_into(unsafe { transmute(src) }, dst);
+        let src = unsafe {
+            slice::from_raw_parts(src.as_ptr() as *const u32, src.len())
+        };
+        Self::write_u32_into(src, dst);
     }
 
     /// Writes IEEE754 double-precision (8 bytes) floating point numbers from
     /// `src` into `dst`.
     ///
     /// # Panics
     ///
     /// Panics when `src.len() != 8*dst.len()`.
@@ -1353,17 +1499,20 @@ pub trait ByteOrder
     ///
     /// let mut numbers_got = [0.0; 4];
     /// unsafe {
     ///     LittleEndian::read_f64_into_unchecked(&bytes, &mut numbers_got);
     /// }
     /// assert_eq!(numbers_given, numbers_got);
     /// ```
     fn write_f64_into(src: &[f64], dst: &mut [u8]) {
-        Self::write_u64_into(unsafe { transmute(src) }, dst);
+        let src = unsafe {
+            slice::from_raw_parts(src.as_ptr() as *const u64, src.len())
+        };
+        Self::write_u64_into(src, dst);
     }
 
     /// Converts the given slice of unsigned 16 bit integers to a particular
     /// endianness.
     ///
     /// If the endianness matches the endianness of the host platform, then
     /// this is a no-op.
     ///
@@ -1371,21 +1520,17 @@ pub trait ByteOrder
     ///
     /// Convert the host platform's endianness to big-endian:
     ///
     /// ```rust
     /// use byteorder::{ByteOrder, BigEndian};
     ///
     /// let mut numbers = [5, 65000];
     /// BigEndian::from_slice_u16(&mut numbers);
-    /// if cfg!(target_endian = "little") {
-    ///     assert_eq!(numbers, [5u16.swap_bytes(), 65000u16.swap_bytes()]);
-    /// } else {
-    ///     assert_eq!(numbers, [5, 65000]);
-    /// }
+    /// assert_eq!(numbers, [5u16.to_be(), 65000u16.to_be()]);
     /// ```
     fn from_slice_u16(numbers: &mut [u16]);
 
     /// Converts the given slice of unsigned 32 bit integers to a particular
     /// endianness.
     ///
     /// If the endianness matches the endianness of the host platform, then
     /// this is a no-op.
@@ -1394,21 +1539,17 @@ pub trait ByteOrder
     ///
     /// Convert the host platform's endianness to big-endian:
     ///
     /// ```rust
     /// use byteorder::{ByteOrder, BigEndian};
     ///
     /// let mut numbers = [5, 65000];
     /// BigEndian::from_slice_u32(&mut numbers);
-    /// if cfg!(target_endian = "little") {
-    ///     assert_eq!(numbers, [5u32.swap_bytes(), 65000u32.swap_bytes()]);
-    /// } else {
-    ///     assert_eq!(numbers, [5, 65000]);
-    /// }
+    /// assert_eq!(numbers, [5u32.to_be(), 65000u32.to_be()]);
     /// ```
     fn from_slice_u32(numbers: &mut [u32]);
 
     /// Converts the given slice of unsigned 64 bit integers to a particular
     /// endianness.
     ///
     /// If the endianness matches the endianness of the host platform, then
     /// this is a no-op.
@@ -1417,46 +1558,36 @@ pub trait ByteOrder
     ///
     /// Convert the host platform's endianness to big-endian:
     ///
     /// ```rust
     /// use byteorder::{ByteOrder, BigEndian};
     ///
     /// let mut numbers = [5, 65000];
     /// BigEndian::from_slice_u64(&mut numbers);
-    /// if cfg!(target_endian = "little") {
-    ///     assert_eq!(numbers, [5u64.swap_bytes(), 65000u64.swap_bytes()]);
-    /// } else {
-    ///     assert_eq!(numbers, [5, 65000]);
-    /// }
+    /// assert_eq!(numbers, [5u64.to_be(), 65000u64.to_be()]);
     /// ```
     fn from_slice_u64(numbers: &mut [u64]);
 
     /// Converts the given slice of unsigned 128 bit integers to a particular
     /// endianness.
     ///
     /// If the endianness matches the endianness of the host platform, then
     /// this is a no-op.
     ///
     /// # Examples
     ///
     /// Convert the host platform's endianness to big-endian:
     ///
     /// ```rust
-    /// #![feature(i128_type)]
-    ///
     /// use byteorder::{ByteOrder, BigEndian};
     ///
     /// let mut numbers = [5, 65000];
     /// BigEndian::from_slice_u128(&mut numbers);
-    /// if cfg!(target_endian = "little") {
-    ///     assert_eq!(numbers, [5u128.swap_bytes(), 65000u128.swap_bytes()]);
-    /// } else {
-    ///     assert_eq!(numbers, [5, 65000]);
-    /// }
+    /// assert_eq!(numbers, [5u128.to_be(), 65000u128.to_be()]);
     /// ```
     #[cfg(feature = "i128")]
     fn from_slice_u128(numbers: &mut [u128]);
 
     /// Converts the given slice of signed 16 bit integers to a particular
     /// endianness.
     ///
     /// If the endianness matches the endianness of the host platform, then
@@ -1466,25 +1597,24 @@ pub trait ByteOrder
     ///
     /// Convert the host platform's endianness to big-endian:
     ///
     /// ```rust
     /// use byteorder::{ByteOrder, BigEndian};
     ///
     /// let mut numbers = [5, 65000];
     /// BigEndian::from_slice_i16(&mut numbers);
-    /// if cfg!(target_endian = "little") {
-    ///     assert_eq!(numbers, [5i16.swap_bytes(), 65000i16.swap_bytes()]);
-    /// } else {
-    ///     assert_eq!(numbers, [5, 65000]);
-    /// }
+    /// assert_eq!(numbers, [5i16.to_be(), 65000i16.to_be()]);
     /// ```
     #[inline]
-    fn from_slice_i16(numbers: &mut [i16]) {
-        Self::from_slice_u16(unsafe { transmute(numbers) });
+    fn from_slice_i16(src: &mut [i16]) {
+        let src = unsafe {
+            slice::from_raw_parts_mut(src.as_ptr() as *mut u16, src.len())
+        };
+        Self::from_slice_u16(src);
     }
 
     /// Converts the given slice of signed 32 bit integers to a particular
     /// endianness.
     ///
     /// If the endianness matches the endianness of the host platform, then
     /// this is a no-op.
     ///
@@ -1492,25 +1622,24 @@ pub trait ByteOrder
     ///
     /// Convert the host platform's endianness to big-endian:
     ///
     /// ```rust
     /// use byteorder::{ByteOrder, BigEndian};
     ///
     /// let mut numbers = [5, 65000];
     /// BigEndian::from_slice_i32(&mut numbers);
-    /// if cfg!(target_endian = "little") {
-    ///     assert_eq!(numbers, [5i32.swap_bytes(), 65000i32.swap_bytes()]);
-    /// } else {
-    ///     assert_eq!(numbers, [5, 65000]);
-    /// }
+    /// assert_eq!(numbers, [5i32.to_be(), 65000i32.to_be()]);
     /// ```
     #[inline]
-    fn from_slice_i32(numbers: &mut [i32]) {
-        Self::from_slice_u32(unsafe { transmute(numbers) });
+    fn from_slice_i32(src: &mut [i32]) {
+        let src = unsafe {
+            slice::from_raw_parts_mut(src.as_ptr() as *mut u32, src.len())
+        };
+        Self::from_slice_u32(src);
     }
 
     /// Converts the given slice of signed 64 bit integers to a particular
     /// endianness.
     ///
     /// If the endianness matches the endianness of the host platform, then
     /// this is a no-op.
     ///
@@ -1518,54 +1647,50 @@ pub trait ByteOrder
     ///
     /// Convert the host platform's endianness to big-endian:
     ///
     /// ```rust
     /// use byteorder::{ByteOrder, BigEndian};
     ///
     /// let mut numbers = [5, 65000];
     /// BigEndian::from_slice_i64(&mut numbers);
-    /// if cfg!(target_endian = "little") {
-    ///     assert_eq!(numbers, [5i64.swap_bytes(), 65000i64.swap_bytes()]);
-    /// } else {
-    ///     assert_eq!(numbers, [5, 65000]);
-    /// }
+    /// assert_eq!(numbers, [5i64.to_be(), 65000i64.to_be()]);
     /// ```
     #[inline]
-    fn from_slice_i64(numbers: &mut [i64]) {
-        Self::from_slice_u64(unsafe { transmute(numbers) });
+    fn from_slice_i64(src: &mut [i64]) {
+        let src = unsafe {
+            slice::from_raw_parts_mut(src.as_ptr() as *mut u64, src.len())
+        };
+        Self::from_slice_u64(src);
     }
 
     /// Converts the given slice of signed 128 bit integers to a particular
     /// endianness.
     ///
     /// If the endianness matches the endianness of the host platform, then
     /// this is a no-op.
     ///
     /// # Examples
     ///
     /// Convert the host platform's endianness to big-endian:
     ///
     /// ```rust
-    /// #![feature(i128_type)]
-    ///
     /// use byteorder::{ByteOrder, BigEndian};
     ///
     /// let mut numbers = [5, 65000];
     /// BigEndian::from_slice_i128(&mut numbers);
-    /// if cfg!(target_endian = "little") {
-    ///     assert_eq!(numbers, [5i128.swap_bytes(), 65000i128.swap_bytes()]);
-    /// } else {
-    ///     assert_eq!(numbers, [5, 65000]);
-    /// }
+    /// assert_eq!(numbers, [5i128.to_be(), 65000i128.to_be()]);
     /// ```
     #[cfg(feature = "i128")]
     #[inline]
-    fn from_slice_i128(numbers: &mut [i128]) {
-        Self::from_slice_u128(unsafe { transmute(numbers) });
+    fn from_slice_i128(src: &mut [i128]) {
+        let src = unsafe {
+            slice::from_raw_parts_mut(src.as_ptr() as *mut u128, src.len())
+        };
+        Self::from_slice_u128(src);
     }
 
     /// Converts the given slice of IEEE754 single-precision (4 bytes) floating
     /// point numbers to a particular endianness.
     ///
     /// If the endianness matches the endianness of the host platform, then
     /// this is a no-op.
     fn from_slice_f32(numbers: &mut [f32]);
@@ -1598,17 +1723,19 @@ pub trait ByteOrder
 pub enum BigEndian {}
 
 impl Default for BigEndian {
     fn default() -> BigEndian {
         panic!("BigEndian default")
     }
 }
 
-/// A type alias for `BigEndian`.
+/// A type alias for [`BigEndian`].
+///
+/// [`BigEndian`]: enum.BigEndian.html
 pub type BE = BigEndian;
 
 /// Defines little-endian serialization.
 ///
 /// Note that this type has no value constructor. It is used purely at the
 /// type level.
 ///
 /// # Examples
@@ -1626,24 +1753,26 @@ pub type BE = BigEndian;
 pub enum LittleEndian {}
 
 impl Default for LittleEndian {
     fn default() -> LittleEndian {
         panic!("LittleEndian default")
     }
 }
 
-/// A type alias for `LittleEndian`.
+/// A type alias for [`LittleEndian`].
+///
+/// [`LittleEndian`]: enum.LittleEndian.html
 pub type LE = LittleEndian;
 
 /// Defines network byte order serialization.
 ///
 /// Network byte order is defined by [RFC 1700][1] to be big-endian, and is
 /// referred to in several protocol specifications.  This type is an alias of
-/// BigEndian.
+/// [`BigEndian`].
 ///
 /// [1]: https://tools.ietf.org/html/rfc1700
 ///
 /// Note that this type has no value constructor. It is used purely at the
 /// type level.
 ///
 /// # Examples
 ///
@@ -1651,29 +1780,39 @@ pub type LE = LittleEndian;
 ///
 /// ```rust
 /// use byteorder::{ByteOrder, NetworkEndian, BigEndian};
 ///
 /// let mut buf = [0; 2];
 /// BigEndian::write_i16(&mut buf, -50_000);
 /// assert_eq!(-50_000, NetworkEndian::read_i16(&buf));
 /// ```
+///
+/// [`BigEndian`]: enum.BigEndian.html
 pub type NetworkEndian = BigEndian;
 
 /// Defines system native-endian serialization.
 ///
 /// Note that this type has no value constructor. It is used purely at the
 /// type level.
+///
+/// On this platform, this is an alias for [`LittleEndian`].
+///
+/// [`LittleEndian`]: enum.LittleEndian.html
 #[cfg(target_endian = "little")]
 pub type NativeEndian = LittleEndian;
 
 /// Defines system native-endian serialization.
 ///
 /// Note that this type has no value constructor. It is used purely at the
 /// type level.
+///
+/// On this platform, this is an alias for [`BigEndian`].
+///
+/// [`BigEndian`]: enum.BigEndian.html
 #[cfg(target_endian = "big")]
 pub type NativeEndian = BigEndian;
 
 macro_rules! read_num_bytes {
     ($ty:ty, $size:expr, $src:expr, $which:ident) => ({
         assert!($size == ::core::mem::size_of::<$ty>());
         assert!($size <= $src.len());
         let mut data: $ty = 0;
@@ -1687,17 +1826,17 @@ macro_rules! read_num_bytes {
     });
 }
 
 macro_rules! write_num_bytes {
     ($ty:ty, $size:expr, $n:expr, $dst:expr, $which:ident) => ({
         assert!($size <= $dst.len());
         unsafe {
             // N.B. https://github.com/rust-lang/rust/issues/22776
-            let bytes = transmute::<_, [u8; $size]>($n.$which());
+            let bytes = *(&$n.$which() as *const _ as *const [u8; $size]);
             copy_nonoverlapping((&bytes).as_ptr(), $dst.as_mut_ptr(), $size);
         }
     });
 }
 
 macro_rules! read_slice {
     ($src:expr, $dst:expr, $size:expr, $which:ident) => {{
         assert_eq!($src.len(), $size * $dst.len());
@@ -1807,31 +1946,31 @@ impl ByteOrder for BigEndian {
         write_num_bytes!(u128, 16, n, buf, to_be);
     }
 
     #[inline]
     fn write_uint(buf: &mut [u8], n: u64, nbytes: usize) {
         assert!(pack_size(n) <= nbytes && nbytes <= 8);
         assert!(nbytes <= buf.len());
         unsafe {
-            let bytes: [u8; 8] = transmute(n.to_be());
+            let bytes = *(&n.to_be() as *const u64 as *const [u8; 8]);
             copy_nonoverlapping(
                 bytes.as_ptr().offset((8 - nbytes) as isize),
                 buf.as_mut_ptr(),
                 nbytes);
         }
     }
 
     #[cfg(feature = "i128")]
     #[inline]
     fn write_uint128(buf: &mut [u8], n: u128, nbytes: usize) {
         assert!(pack_size128(n) <= nbytes && nbytes <= 16);
         assert!(nbytes <= buf.len());
         unsafe {
-            let bytes: [u8; 16] = transmute(n.to_be());
+            let bytes = *(&n.to_be() as *const u128 as *const [u8; 16]);
             copy_nonoverlapping(
                 bytes.as_ptr().offset((16 - nbytes) as isize),
                 buf.as_mut_ptr(),
                 nbytes);
         }
     }
 
     #[inline]
@@ -1928,28 +2067,32 @@ impl ByteOrder for BigEndian {
             }
         }
     }
 
     #[inline]
     fn from_slice_f32(numbers: &mut [f32]) {
         if cfg!(target_endian = "little") {
             for n in numbers {
-                let int: u32 = unsafe { transmute(*n) };
-                *n = unsafe { transmute(int.to_be()) };
+                unsafe {
+                    let int = *(n as *const f32 as *const u32);
+                    *n = *(&int.to_be() as *const u32 as *const f32);
+                }
             }
         }
     }
 
     #[inline]
     fn from_slice_f64(numbers: &mut [f64]) {
         if cfg!(target_endian = "little") {
             for n in numbers {
-                let int: u64 = unsafe { transmute(*n) };
-                *n = unsafe { transmute(int.to_be()) };
+                unsafe {
+                    let int = *(n as *const f64 as *const u64);
+                    *n = *(&int.to_be() as *const u64 as *const f64);
+                }
             }
         }
     }
 }
 
 impl ByteOrder for LittleEndian {
     #[inline]
     fn read_u16(buf: &[u8]) -> u16 {
@@ -2016,28 +2159,28 @@ impl ByteOrder for LittleEndian {
         write_num_bytes!(u128, 16, n, buf, to_le);
     }
 
     #[inline]
     fn write_uint(buf: &mut [u8], n: u64, nbytes: usize) {
         assert!(pack_size(n as u64) <= nbytes && nbytes <= 8);
         assert!(nbytes <= buf.len());
         unsafe {
-            let bytes: [u8; 8] = transmute(n.to_le());
+            let bytes = *(&n.to_le() as *const u64 as *const [u8; 8]);
             copy_nonoverlapping(bytes.as_ptr(), buf.as_mut_ptr(), nbytes);
         }
     }
 
     #[cfg(feature = "i128")]
     #[inline]
     fn write_uint128(buf: &mut [u8], n: u128, nbytes: usize) {
         assert!(pack_size128(n as u128) <= nbytes && nbytes <= 16);
         assert!(nbytes <= buf.len());
         unsafe {
-            let bytes: [u8; 16] = transmute(n.to_le());
+            let bytes = *(&n.to_le() as *const u128 as *const [u8; 16]);
             copy_nonoverlapping(bytes.as_ptr(), buf.as_mut_ptr(), nbytes);
         }
     }
 
     #[inline]
     fn read_u16_into(src: &[u8], dst: &mut [u16]) {
         read_slice!(src, dst, 2, to_le);
     }
@@ -2131,44 +2274,50 @@ impl ByteOrder for LittleEndian {
             }
         }
     }
 
     #[inline]
     fn from_slice_f32(numbers: &mut [f32]) {
         if cfg!(target_endian = "big") {
             for n in numbers {
-                let int: u32 = unsafe { transmute(*n) };
-                *n = unsafe { transmute(int.to_le()) };
+                unsafe {
+                    let int = *(n as *const f32 as *const u32);
+                    *n = *(&int.to_le() as *const u32 as *const f32);
+                }
             }
         }
     }
 
     #[inline]
     fn from_slice_f64(numbers: &mut [f64]) {
         if cfg!(target_endian = "big") {
             for n in numbers {
-                let int: u64 = unsafe { transmute(*n) };
-                *n = unsafe { transmute(int.to_le()) };
+                unsafe {
+                    let int = *(n as *const f64 as *const u64);
+                    *n = *(&int.to_le() as *const u64 as *const f64);
+                }
             }
         }
     }
 }
 
 #[cfg(test)]
 mod test {
     extern crate quickcheck;
     extern crate rand;
 
     use self::quickcheck::{QuickCheck, StdGen, Testable};
-    use self::rand::thread_rng;
+    use self::rand::{Rng, thread_rng};
     #[cfg(feature = "i128")] use self::quickcheck::{Arbitrary, Gen};
 
     pub const U24_MAX: u32 = 16_777_215;
     pub const I24_MAX: i32 = 8_388_607;
+    pub const U48_MAX: u64 = 281_474_976_710_655;
+    pub const I48_MAX: i64 = 140_737_488_355_327;
 
     pub const U64_MAX: u64 = ::core::u64::MAX;
     pub const I64_MAX: u64 = ::core::i64::MAX as u64;
 
     macro_rules! calc_max {
         ($max:expr, $bytes:expr) => { calc_max!($max, $bytes, 8) };
         ($max:expr, $bytes:expr, $maxbytes:expr) => {
             ($max - 1) >> (8 * ($maxbytes - $bytes))
@@ -2303,16 +2452,18 @@ mod test {
     }
 
     qc_byte_order!(prop_u16, u16, ::core::u16::MAX as u64, read_u16, write_u16);
     qc_byte_order!(prop_i16, i16, ::core::i16::MAX as u64, read_i16, write_i16);
     qc_byte_order!(prop_u24, u32, ::test::U24_MAX as u64, read_u24, write_u24);
     qc_byte_order!(prop_i24, i32, ::test::I24_MAX as u64, read_i24, write_i24);
     qc_byte_order!(prop_u32, u32, ::core::u32::MAX as u64, read_u32, write_u32);
     qc_byte_order!(prop_i32, i32, ::core::i32::MAX as u64, read_i32, write_i32);
+    qc_byte_order!(prop_u48, u64, ::test::U48_MAX as u64, read_u48, write_u48);
+    qc_byte_order!(prop_i48, i64, ::test::I48_MAX as u64, read_i48, write_i48);
     qc_byte_order!(prop_u64, u64, ::core::u64::MAX as u64, read_u64, write_u64);
     qc_byte_order!(prop_i64, i64, ::core::i64::MAX as u64, read_i64, write_i64);
     qc_byte_order!(prop_f32, f32, ::core::u64::MAX as u64, read_f32, write_f32);
     qc_byte_order!(prop_f64, f64, ::core::i64::MAX as u64, read_f64, write_f64);
 
     #[cfg(feature = "i128")]
     qc_byte_order!(prop_u128, Wi128<u128>, 16 + 1, read_u128, write_u128);
     #[cfg(feature = "i128")]
deleted file mode 100644
--- a/third_party/rust/safemem/.cargo-checksum.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{"files":{"Cargo.toml":"94aae7f1f5f45951bc2143279ac3c61259cbd047b1ac9fc6cb820f26d0b6b392","LICENSE-APACHE":"7cfd738c53d61c79f07e348f622bf7707c9084237054d37fbe07788a75f5881c","LICENSE-MIT":"64e1c5f067ee2d8c0ee8abd751e57275d4e97e4f7c05699bc23f5005a9c53043","README.md":"2bb7c7b12f6d223514fdf7e346c9bd9950347a6a7e271dfc8eec06c6fe10ab3e","src/lib.rs":"da812d1fa45ff718510e8f32d5012efca83b0880f9ccf1ff1147dc318e3e434f"},"package":"e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f"}
\ No newline at end of file
deleted file mode 100644
--- a/third_party/rust/safemem/Cargo.toml
+++ /dev/null
@@ -1,13 +0,0 @@
-[package]
-name = "safemem"
-version = "0.2.0"
-authors = ["Austin Bonander <austin.bonander@gmail.com>"]
-
-description = "Safe wrappers for memory-accessing functions, like `std::ptr::copy()`."
-repository = "https://github.com/abonander/safemem"
-keywords = ["memset", "memmove", "copy"]
-license = "MIT OR Apache-2.0"
-
-documentation = "https://docs.rs/safemem"
-
-[dependencies]
deleted file mode 100644
--- a/third_party/rust/safemem/LICENSE-APACHE
+++ /dev/null
@@ -1,201 +0,0 @@
-                              Apache License
-                        Version 2.0, January 2004
-                     http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-   "License" shall mean the terms and conditions for use, reproduction,
-   and distribution as defined by Sections 1 through 9 of this document.
-
-   "Licensor" shall mean the copyright owner or entity authorized by
-   the copyright owner that is granting the License.
-
-   "Legal Entity" shall mean the union of the acting entity and all
-   other entities that control, are controlled by, or are under common
-   control with that entity. For the purposes of this definition,
-   "control" means (i) the power, direct or indirect, to cause the
-   direction or management of such entity, whether by contract or
-   otherwise, or (ii) ownership of fifty percent (50%) or more of the
-   outstanding shares, or (iii) beneficial ownership of such entity.
-
-   "You" (or "Your") shall mean an individual or Legal Entity
-   exercising permissions granted by this License.
-
-   "Source" form shall mean the preferred form for making modifications,
-   including but not limited to software source code, documentation
-   source, and configuration files.
-
-   "Object" form shall mean any form resulting from mechanical
-   transformation or translation of a Source form, including but
-   not limited to compiled object code, generated documentation,
-   and conversions to other media types.
-
-   "Work" shall mean the work of authorship, whether in Source or
-   Object form, made available under the License, as indicated by a
-   copyright notice that is included in or attached to the work
-   (an example is provided in the Appendix below).
-
-   "Derivative Works" shall mean any work, whether in Source or Object
-   form, that is based on (or derived from) the Work and for which the
-   editorial revisions, annotations, elaborations, or other modifications
-   represent, as a whole, an original work of authorship. For the purposes
-   of this License, Derivative Works shall not include works that remain
-   separable from, or merely link (or bind by name) to the interfaces of,
-   the Work and Derivative Works thereof.
-
-   "Contribution" shall mean any work of authorship, including
-   the original version of the Work and any modifications or additions
-   to that Work or Derivative Works thereof, that is intentionally
-   submitted to Licensor for inclusion in the Work by the copyright owner
-   or by an individual or Legal Entity authorized to submit on behalf of
-   the copyright owner. For the purposes of this definition, "submitted"
-   means any form of electronic, verbal, or written communication sent
-   to the Licensor or its representatives, including but not limited to
-   communication on electronic mailing lists, source code control systems,
-   and issue tracking systems that are managed by, or on behalf of, the
-   Licensor for the purpose of discussing and improving the Work, but
-   excluding communication that is conspicuously marked or otherwise
-   designated in writing by the copyright owner as "Not a Contribution."
-
-   "Contributor" shall mean Licensor and any individual or Legal Entity
-   on behalf of whom a Contribution has been received by Licensor and
-   subsequently incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of
-   this License, each Contributor hereby grants to You a perpetual,
-   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-   copyright license to reproduce, prepare Derivative Works of,
-   publicly display, publicly perform, sublicense, and distribute the
-   Work and such Derivative Works in Source or Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of
-   this License, each Contributor hereby grants to You a perpetual,
-   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-   (except as stated in this section) patent license to make, have made,
-   use, offer to sell, sell, import, and otherwise transfer the Work,
-   where such license applies only to those patent claims licensable
-   by such Contributor that are necessarily infringed by their
-   Contribution(s) alone or by combination of their Contribution(s)
-   with the Work to which such Contribution(s) was submitted. If You
-   institute patent litigation against any entity (including a
-   cross-claim or counterclaim in a lawsuit) alleging that the Work
-   or a Contribution incorporated within the Work constitutes direct
-   or contributory patent infringement, then any patent licenses
-   granted to You under this License for that Work shall terminate
-   as of the date such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the
-   Work or Derivative Works thereof in any medium, with or without
-   modifications, and in Source or Object form, provided that You
-   meet the following conditions:
-
-   (a) You must give any other recipients of the Work or
-       Derivative Works a copy of this License; and
-
-   (b) You must cause any modified files to carry prominent notices
-       stating that You changed the files; and
-
-   (c) You must retain, in the Source form of any Derivative Works
-       that You distribute, all copyright, patent, trademark, and
-       attribution notices from the Source form of the Work,
-       excluding those notices that do not pertain to any part of
-       the Derivative Works; and
-
-   (d) If the Work includes a "NOTICE" text file as part of its
-       distribution, then any Derivative Works that You distribute must
-       include a readable copy of the attribution notices contained
-       within such NOTICE file, excluding those notices that do not
-       pertain to any part of the Derivative Works, in at least one
-       of the following places: within a NOTICE text file distributed
-       as part of the Derivative Works; within the Source form or
-       documentation, if provided along with the Derivative Works; or,
-       within a display generated by the Derivative Works, if and
-       wherever such third-party notices normally appear. The contents
-       of the NOTICE file are for informational purposes only and
-       do not modify the License. You may add Your own attribution
-       notices within Derivative Works that You distribute, alongside
-       or as an addendum to the NOTICE text from the Work, provided
-       that such additional attribution notices cannot be construed
-       as modifying the License.
-
-   You may add Your own copyright statement to Your modifications and
-   may provide additional or different license terms and conditions
-   for use, reproduction, or distribution of Your modifications, or
-   for any such Derivative Works as a whole, provided Your use,
-   reproduction, and distribution of the Work otherwise complies with
-   the conditions stated in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise,
-   any Contribution intentionally submitted for inclusion in the Work
-   by You to the Licensor shall be under the terms and conditions of
-   this License, without any additional terms or conditions.
-   Notwithstanding the above, nothing herein shall supersede or modify
-   the terms of any separate license agreement you may have executed
-   with Licensor regarding such Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade
-   names, trademarks, service marks, or product names of the Licensor,
-   except as required for reasonable and customary use in describing the
-   origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or
-   agreed to in writing, Licensor provides the Work (and each
-   Contributor provides its Contributions) on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-   implied, including, without limitation, any warranties or conditions
-   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-   PARTICULAR PURPOSE. You are solely responsible for determining the
-   appropriateness of using or redistributing the Work and assume any
-   risks associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory,
-   whether in tort (including negligence), contract, or otherwise,
-   unless required by applicable law (such as deliberate and grossly
-   negligent acts) or agreed to in writing, shall any Contributor be
-   liable to You for damages, including any direct, indirect, special,
-   incidental, or consequential damages of any character arising as a
-   result of this License or out of the use or inability to use the
-   Work (including but not limited to damages for loss of goodwill,
-   work stoppage, computer failure or malfunction, or any and all
-   other commercial damages or losses), even if such Contributor
-   has been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing
-   the Work or Derivative Works thereof, You may choose to offer,
-   and charge a fee for, acceptance of support, warranty, indemnity,
-   or other liability obligations and/or rights consistent with this
-   License. However, in accepting such obligations, You may act only
-   on Your own behalf and on Your sole responsibility, not on behalf
-   of any other Contributor, and only if You agree to indemnify,
-   defend, and hold each Contributor harmless for any liability
-   incurred by, or claims asserted against, such Contributor by reason
-   of your accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work.
-
-   To apply the Apache License to your work, attach the following
-   boilerplate notice, with the fields enclosed by brackets "[]"
-   replaced with your own identifying information. (Don't include
-   the brackets!)  The text should be enclosed in the appropriate
-   comment syntax for the file format. We also recommend that a
-   file or class name and description of purpose be included on the
-   same "printed page" as the copyright notice for easier
-   identification within third-party archives.
-
-Copyright [yyyy] [name of copyright owner]
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-	http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
deleted file mode 100644
--- a/third_party/rust/safemem/LICENSE-MIT
+++ /dev/null
@@ -1,25 +0,0 @@
-Copyright (c) 2016 The `multipart` Crate Developers
-
-Permission is hereby granted, free of charge, to any
-person obtaining a copy of this software and associated
-documentation files (the "Software"), to deal in the
-Software without restriction, including without
-limitation the rights to use, copy, modify, merge,
-publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software
-is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice
-shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
-ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
-TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
-SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
-IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
deleted file mode 100644
--- a/third_party/rust/safemem/README.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# safemem
-Safe wrappers for `memmove`, `memset`, etc. in Rust
-
-License
--------
-
-Licensed under either of
-
- * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
-
-at your option.
-
-### Contribution
-
-Unless you explicitly state otherwise, any contribution intentionally submitted
-for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
-additional terms or conditions.
\ No newline at end of file
deleted file mode 100644
--- a/third_party/rust/safemem/src/lib.rs
+++ /dev/null
@@ -1,109 +0,0 @@
-//! Safe wrappers for memory-accessing functions like `std::ptr::copy()`.
-use std::ptr;
-
-macro_rules! idx_check (
-    ($slice:expr, $idx:expr) => {
-        assert!($idx < $slice.len(),
-            concat!("`", stringify!($idx), "` ({}) out of bounds. Length: {}"),
-            $idx, $slice.len());
-    }
-);
-
-macro_rules! len_check (
-    ($slice:expr, $start:ident, $len:ident) => {
-        assert!(
-            $start.checked_add($len)
-                .expect(concat!("Overflow evaluating ", stringify!($start + $len)))
-                <= $slice.len(),
-            "Length {} starting at {} is out of bounds (slice len {}).", $len, $start, $slice.len()
-        )
-    }
-);
-
-/// Copy `len` elements from `src_idx` to `dest_idx`. Ranges may overlap.
-///
-/// Safe wrapper for `memmove()`/`std::ptr::copy()`.
-///
-/// ###Panics
-/// * If either `src_idx` or `dest_idx` are out of bounds, or if either of these plus `len` is out of
-/// bounds.
-/// * If `src_idx + len` or `dest_idx + len` overflows.
-pub fn copy_over<T: Copy>(slice: &mut [T], src_idx: usize, dest_idx: usize, len: usize) {
-    if slice.len() == 0 { return; }
-
-    idx_check!(slice, src_idx);
-    idx_check!(slice, dest_idx);
-    len_check!(slice, src_idx, len);
-    len_check!(slice, dest_idx, len);
-
-    let src_ptr: *const T = &slice[src_idx];
-    let dest_ptr: *mut T = &mut slice[dest_idx];
-
-    unsafe {
-        ptr::copy(src_ptr, dest_ptr, len);
-    }
-}
-
-/// Safe wrapper for `std::ptr::write_bytes()`/`memset()`.
-pub fn write_bytes(slice: &mut [u8], byte: u8) {
-    unsafe {
-        ptr::write_bytes(slice.as_mut_ptr(), byte, slice.len());
-    }
-}
-
-/// Prepend `elems` to `vec`, resizing if necessary.
-///
-/// ###Panics
-/// If `vec.len() + elems.len()` overflows.
-pub fn prepend<T: Copy>(elems: &[T], vec: &mut Vec<T>) {
-    // Our overflow check occurs here, no need to do it ourselves.
-    vec.reserve(elems.len());
-
-    let old_len = vec.len();
-    let new_len = old_len + elems.len();
-
-    unsafe {
-        vec.set_len(new_len);
-    }
-
-    // Move the old elements down to the end.
-    if old_len > 0 {
-        copy_over(vec, 0, elems.len(), old_len);
-    }
-
-    vec[..elems.len()].copy_from_slice(elems);
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    #[should_panic]
-    fn bounds_check() {
-        let mut arr = [0i32, 1, 2, 3, 4, 5];
-
-        copy_over(&mut arr, 2, 1, 7);
-    }
-
-    #[test]
-    fn copy_empty() {
-        let mut arr: [i32; 0] = [];
-
-        copy_over(&mut arr, 0, 0, 0);
-    }
-
-    #[test]
-    fn prepend_empty() {
-        let mut vec: Vec<i32> = vec![];
-        prepend(&[1, 2, 3], &mut vec);
-    }
-
-    #[test]
-    fn prepend_i32() {
-        let mut vec = vec![3, 4, 5];
-        prepend(&[1, 2], &mut vec);
-        assert_eq!(vec, &[1, 2, 3, 4, 5]);
-    }
-}
-