Bug 1515351 - Update encoding_rs to 0.8.14. r=m_kato
authorHenri Sivonen <hsivonen@hsivonen.fi>
Thu, 10 Jan 2019 09:42:39 +0000
changeset 453233 876faba9c48f5bee522dae19d91acde4b60efc86
parent 453232 524ec48474fdb5fad28a0e3e393b3762657ab98b
child 453234 849f81f21979e1eceec29e2b3f7dd769d64496e4
push id35349
push userbtara@mozilla.com
push dateThu, 10 Jan 2019 17:19:27 +0000
treeherdermozilla-central@a51746f37520 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1515351
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 1515351 - Update encoding_rs to 0.8.14. r=m_kato Differential Revision: https://phabricator.services.mozilla.com/D15934
Cargo.lock
dom/encoding/TextEncoder.cpp
third_party/rust/encoding_rs/.cargo-checksum.json
third_party/rust/encoding_rs/Cargo.toml
third_party/rust/encoding_rs/README.md
third_party/rust/encoding_rs/generate-encoding-data.py
third_party/rust/encoding_rs/src/ascii.rs
third_party/rust/encoding_rs/src/data.rs
third_party/rust/encoding_rs/src/handles.rs
third_party/rust/encoding_rs/src/iso_2022_jp.rs
third_party/rust/encoding_rs/src/lib.rs
third_party/rust/encoding_rs/src/mem.rs
third_party/rust/encoding_rs/src/utf_8.rs
third_party/rust/encoding_rs/src/x_user_defined.rs
xpcom/rust/nsstring/src/conversions.rs
xpcom/string/nsReadableUtils.cpp
xpcom/string/nsReadableUtils.h
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -832,31 +832,31 @@ dependencies = [
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "encoding_c"
 version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "encoding_rs 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "encoding_rs 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "encoding_glue"
 version = "0.1.0"
 dependencies = [
- "encoding_rs 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "encoding_rs 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "nserror 0.1.0",
  "nsstring 0.1.0",
 ]
 
 [[package]]
 name = "encoding_rs"
-version = "0.8.13"
+version = "0.8.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "simd 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "env_logger"
@@ -1745,17 +1745,17 @@ dependencies = [
  "nsstring 0.1.0",
 ]
 
 [[package]]
 name = "nsstring"
 version = "0.1.0"
 dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "encoding_rs 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "encoding_rs 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "nsstring-gtest"
 version = "0.1.0"
 dependencies = [
  "nsstring 0.1.0",
 ]
@@ -3251,17 +3251,17 @@ dependencies = [
 "checksum dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "88972de891f6118092b643d85a0b28e0678e0f948d7f879aa32f2d5aafe97d2a"
 "checksum docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d8acd393692c503b168471874953a2531df0e9ab77d0b6bbc582395743300a4a"
 "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
 "checksum dtoa-short 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "068d4026697c1a18f0b0bb8cfcad1b0c151b90d8edb9bf4c235ad68128920d1d"
 "checksum dwrote 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2ea0fd88d96838ce5ed30326338cc04a0eb4cff10e3e15d188d74112777103"
 "checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a"
 "checksum ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "88dc8393b3c7352f94092497f6b52019643e493b6b890eb417cdb7c46117e621"
 "checksum encoding_c 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "769ecb8b33323998e482b218c0d13cd64c267609023b4b7ec3ee740714c318ee"
-"checksum encoding_rs 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1a8fa54e6689eb2549c4efed8d00d7f3b2b994a064555b0e8df4ae3764bcc4be"
+"checksum encoding_rs 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)" = "a69d152eaa438a291636c1971b0a370212165ca8a75759eb66818c5ce9b538f7"
 "checksum env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0561146661ae44c579e993456bc76d11ce1e0c7d745e57b2fa7146b6e49fa2ad"
 "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
 "checksum euclid 0.19.4 (registry+https://github.com/rust-lang/crates.io-index)" = "dbbf962bb6f877239a34491f2e0a12c6b824f389bc789eb90f1d70d4780b0727"
 "checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7"
 "checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596"
 "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
 "checksum fixedbitset 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "85cb8fec437468d86dc7c83ca7cfc933341d561873275f22dd5eedefa63a6478"
 "checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909"
--- a/dom/encoding/TextEncoder.cpp
+++ b/dom/encoding/TextEncoder.cpp
@@ -19,18 +19,17 @@ void TextEncoder::Encode(JSContext* aCx,
                          JS::MutableHandle<JSObject*> aRetval,
                          ErrorResult& aRv) {
   // Given nsTSubstring<char16_t>::kMaxCapacity, it should be
   // impossible for the length computation to overflow, but
   // let's use checked math in case someone changes something
   // in the future.
   // Uint8Array::Create takes uint32_t as the length.
   CheckedInt<uint32_t> bufLen(aString.Length());
-  bufLen *= 3;
-  bufLen += 1;  // plus one is part of the contract for ConvertUTF16toUTF8
+  bufLen *= 3;  // from the contract for ConvertUTF16toUTF8
   if (!bufLen.isValid()) {
     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
     return;
   }
 
   auto data = mozilla::MakeUniqueFallible<uint8_t[]>(bufLen.value());
   if (!data) {
     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
--- a/third_party/rust/encoding_rs/.cargo-checksum.json
+++ b/third_party/rust/encoding_rs/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"CONTRIBUTING.md":"06c26277e8dbd3f57be2eb51b5e3285dc1cbbf8c11326df413868ae702e6a61c","COPYRIGHT":"8b98376eb373dcf81950474efe34b5576a8171460dff500cc58a1ed8d160cd57","Cargo.toml":"e5b9b399e5735753af58e4931032c869e59b7a13a8c36cfc9c20bd068fbdf0a4","Ideas.md":"b7452893f500163868d8de52c09addaf91e1632454ed02e892c467ed7ec39dbd","LICENSE-APACHE":"cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30","LICENSE-MIT":"f2ad48641d9c997d9ae3b95d93d1cd6e1ab12ab4c44de89937c7bfabbd076a4a","README.md":"c1e52d69d2dca1cd645d0e2782f868fb2874c3b9e8e38356f7aab8275f7f7ca7","build.rs":"f5defca2c68b73e8723f489a9279af4fbe9724abc6e9abf58d32542e8a459e26","doc/Big5.txt":"f73a2edc5cb6c2d140ba6e07f4542e1c4a234950378acde1df93480f0ca0be0b","doc/EUC-JP.txt":"ee2818b907d0137f40a9ab9fd525fc700a44dbdddb6cf0c157a656566bae4bf1","doc/EUC-KR.txt":"71d9e2ccf3b124e8bdfb433c8cf2773fd878077038d0cec3c7237a50f4a78a30","doc/GBK.txt":"c1b522b5a799884e5001da661f42c5a8f4d0acb9ef1d74b206f22b5f65365606","doc/IBM866.txt":"a5a433e804d0f83af785015179fbc1d9b0eaf1f7960efcd04093e136b51fbd0e","doc/ISO-2022-JP.txt":"af86684f5a8f0e2868d7b2c292860140c3d2e5527530ca091f1b28198e8e2fe6","doc/ISO-8859-10.txt":"6d3949ad7c81ca176895101ed81a1db7df1060d64e262880b94bd31bb344ab4d","doc/ISO-8859-13.txt":"3951dd89cf93f7729148091683cf8511f4529388b7dc8dcd0d62eaed55be93fa","doc/ISO-8859-14.txt":"3d330784a0374fd255a38b47949675cc7168c800530534b0a01cac6edc623adc","doc/ISO-8859-15.txt":"24b1084aab5127a85aab99153f86e24694d0a3615f53b5ce23683f97cf66c47a","doc/ISO-8859-16.txt":"ce0272559b92ba76d7a7e476f6424ae4a5cc72e75b183611b08392e44add4d25","doc/ISO-8859-2.txt":"18ceff88c13d1b5ba455a3919b1e3de489045c4c3d2dd7e8527c125c75d54aad","doc/ISO-8859-3.txt":"21798404c68f4f5db59223362f24999da96968c0628427321fccce7d2849a130","doc/ISO-8859-4.txt":"d27f6520c6c5bfbcc19176b71d081cdb3bccde1622bb3e420d5680e812632d53","doc/ISO-8859-5.txt":"a10ec8d6ea7a78ad15da7275f6cb1a3365118527e28f9af6d0d5830501303f3a","doc/ISO-8859-6.txt":"ccda8a2efc96115336bdd77776637b9712425e44fbcf745353b9057fbef144e7","doc/ISO-8859-7.txt":"17900fa1f27a445958f0a77d7d9056be375a6bd7ee4492aa680c7c1500bab85e","doc/ISO-8859-8-I.txt":"8357555646d54265a9b9ffa3e68b08d132312f1561c60108ff9b8b1167b6ecf2","doc/ISO-8859-8.txt":"72cd6f3afb7b4a9c16a66a362473315770b7755d72c86c870e52fc3eba86c8af","doc/KOI8-R.txt":"839cf19a38da994488004ed7814b1f6151640156a9a2af02bf2efca745fb5966","doc/KOI8-U.txt":"0cc76624ed1f024183e2298b7e019957da2c70c8ca06e0fc4e6f353f50a5054f","doc/Shift_JIS.txt":"34c49141818cb9ddbcf59cc858f78a79be8ad148d563f26415108ae1f148443f","doc/UTF-16BE.txt":"e2e280d8acbaa6d2a6b3569d60e17500a285f2baa0df3363dd85537cd5a1ef8f","doc/UTF-16LE.txt":"70bdc170e3fc5298ba68f10125fb5eeb8b077036cc96bb4416c4de396f6d76c1","doc/UTF-8.txt":"ea7bae742e613010ced002cf4b601a737d2203fad65e115611451bc4428f548a","doc/gb18030.txt":"dc71378a8f07a2d8659f69ee81fb8791fef56ba86f124b429978285237bb4a7b","doc/macintosh.txt":"57491e53866711b4672d9b9ff35380b9dac9e0d8e3d6c20bdd6140603687c023","doc/replacement.txt":"4b6c3bbd7999d9d4108a281594bd02d13607e334a95465afff8c2c08d395f0e4","doc/windows-1250.txt":"61296bb6a21cdab602300d32ecfba434cb82de5ac3bc88d58710d2f125e28d39","doc/windows-1251.txt":"7deea1c61dea1485c8ff02db2c7d578db7a9aab63ab1cfd02ec04b515864689e","doc/windows-1252.txt":"933ef3bdddfce5ee132b9f1a1aa8b47423d2587bbe475b19028d0a6d38e180b6","doc/windows-1253.txt":"1a38748b88e99071a5c7b3d5456ead4caedeabab50d50d658be105bc113714de","doc/windows-1254.txt":"f8372f86c6f8d642563cd6ddc025260553292a39423df1683a98670bd7bf2b47","doc/windows-1255.txt":"4e5852494730054e2da258a74e1b9d780abbcdd8ce22ebc218ca2efe9e90493d","doc/windows-1256.txt":"c0879c5172abedead302a406e8f60d9cd9598694a0ffa4fd288ffe4fef7b8ea1","doc/windows-1257.txt":"c28a0c9f964fcb2b46d21f537c402446501a2800670481d6abf9fd9e9018d523","doc/windows-1258.txt":"5019ae4d61805c79aacbf17c93793342dbb098d65a1837783bc3e2c6d6a23602","doc/windows-874.txt":"4ef0e4501c5feba8b17aee1818602ed44b36ca8475db771ce2fc16d392cabecc","doc/x-mac-cyrillic.txt":"58be154d8a888ca3d484b83b44f749823ef339ab27f14d90ca9a856f5050a8bd","doc/x-user-defined.txt":"f9cd07c4321bf5cfb0be4bdddd251072999b04a6cf7a6f5bc63709a84e2c1ffc","generate-encoding-data.py":"11f92c0df48ce12919b5b71cbd03bd5e14a34dcdcdfbb20e6c7b327d203a9659","rustfmt.toml":"85c1a3b4382fd89e991cbb81b70fb52780472edc064c963943cdaaa56e0a2030","src/ascii.rs":"72ba111e4d4a0f81d11be7c8597f904006f45a33adace3b0d36b29cf54d51c06","src/big5.rs":"1c94b35813314775c3fa1b10923cf8e8f8eba8c465d9833ad4293594e16c17f2","src/data.rs":"664e87f88c4558458b09d6c600f48bac287c5db29a98a47ac097281573608dcf","src/euc_jp.rs":"0842e4f564a36051c6b85c47bbb652efae2f2926e91491daf77e4ceeecb18163","src/euc_kr.rs":"8e68590efa65485583bf57cae44ebf6de535bac1d37232e7f0307a38425fb992","src/gb18030.rs":"d269efb5e5d175f9d2ecf01d5606955a284b6f00749bb0ee23d3412c83aa3d59","src/handles.rs":"a3d953b0bc88bfd07f9c12d1b5cd85904d0d8f0fe3bee19e7fad74d4f3d3b4fa","src/iso_2022_jp.rs":"9db1cc612787ab0a874f904306d4c516bc82440183f9a6a045f601aab070ed18","src/lib.rs":"a59e12a4b71ef7dadee4fa3792ca9d0d66e5c89226365cec3265c912432c75d8","src/macros.rs":"c7a019fd81d31de77569036ac36fd4e404b3f20144bbf79747faf4ea21538d09","src/mem.rs":"4791afe98b47321f8a5dcfca114aabb3f4b60bb9b7efd89d749880d3e95be704","src/replacement.rs":"182c2093a6edb162183ca5990554fd7b199d3011924a8d80d894ba98ee7c479e","src/shift_jis.rs":"1c0c69ba6c123fcf720276646074660193bf9e6fa4327fe0d739a3e67874e081","src/simd_funcs.rs":"565ceeffe81173b85700c55c396ab72068751ef809bea8e1cb1e6c7919f5a905","src/single_byte.rs":"383d325dedbf3295acd50d880db1cecc29b69efe332ae2a37367cf40bf138ac4","src/test_data/big5_in.txt":"4c5a8691f8dc717311889c63894026d2fb62725a86c4208ca274a9cc8d42a503","src/test_data/big5_in_ref.txt":"99d399e17750cf9c7cf30bb253dbfe35b81c4fcbdead93cfa48b1429213473c7","src/test_data/big5_out.txt":"6193ca97c297aa20e09396038d18e938bb7ea331c26f0f2454097296723a0b13","src/test_data/big5_out_ref.txt":"36567691f557df144f6cc520015a87038dfa156f296fcf103b56ae9a718be1fc","src/test_data/euc_kr_in.txt":"c86a7224f3215fa0d04e685622a752fdc72763e8ae076230c7fd62de57ec4074","src/test_data/euc_kr_in_ref.txt":"1f419f4ca47d708b54c73c461545a022ae2e20498fdbf8005a483d752a204883","src/test_data/euc_kr_out.txt":"e7f32e026f70be1e1b58e0047baf7d3d2c520269c4f9b9992e158b4decb0a1a3","src/test_data/euc_kr_out_ref.txt":"c9907857980b20b8e9e3b584482ed6567a2be6185d72237b6322f0404944924e","src/test_data/gb18030_in.txt":"ab7231b2d3e9afacdbd7d7f3b9e5361a7ff9f7e1cfdb4f3bd905b9362b309e53","src/test_data/gb18030_in_ref.txt":"dc5069421adca2043c55f5012b55a76fdff651d22e6e699fd0978f8d5706815c","src/test_data/gb18030_out.txt":"f0208d527f5ca63de7d9a0323be8d5cf12d8a104b2943d92c2701f0c3364dac1","src/test_data/gb18030_out_ref.txt":"6819fe47627e4ea01027003fc514b9f21a1322e732d7f1fb92cc6c5455bc6c07","src/test_data/iso_2022_jp_in.txt":"cd24bbdcb1834e25db54646fbf4c41560a13dc7540f6be3dba4f5d97d44513af","src/test_data/iso_2022_jp_in_ref.txt":"3dc4e6a5e06471942d086b16c9440945e78415f6f3f47e43717e4bc2eac2cdf5","src/test_data/iso_2022_jp_out.txt":"9b6f015329dda6c3f9ee5ce6dbd6fa9c89acc21283e886836c78b8d833480c21","src/test_data/iso_2022_jp_out_ref.txt":"78cb260093a20116ad9a42f43b05d1848c5ab100b6b9a850749809e943884b35","src/test_data/jis0208_in.txt":"6df3030553ffb0a6615bb33dc8ea9dca6d9623a9028e2ffec754ce3c3da824cc","src/test_data/jis0208_in_ref.txt":"3dc4e6a5e06471942d086b16c9440945e78415f6f3f47e43717e4bc2eac2cdf5","src/test_data/jis0208_out.txt":"4ec24477e1675ce750733bdc3c5add1cd27b6bd4ce1f09289564646e9654e857","src/test_data/jis0208_out_ref.txt":"c3e1cef5032b2b1d93a406f31ff940c4e2dfe8859b8b17ca2761fee7a75a0e48","src/test_data/jis0212_in.txt":"c011f0dd72bd7c8cd922df9374ef8d2769a77190514c77f6c62b415852eeb9fe","src/test_data/jis0212_in_ref.txt":"7d9458b3d2f73e7092a7f505c08ce1d233dde18aa679fbcf9889256239cc9e06","src/test_data/shift_jis_in.txt":"02e389ccef0dd2122e63f503899402cb7f797912c2444cc80ab93131116c5524","src/test_data/shift_jis_in_ref.txt":"512f985950ca902e643c88682dba9708b7c38d3c5ec2925168ab00ac94ab19f9","src/test_data/shift_jis_out.txt":"5fbc44da7bf639bf6cfe0fa1fd3eba7102b88f81919c9ea991302712f69426fb","src/test_data/shift_jis_out_ref.txt":"466322c6fed8286c64582731755290c2296508efdd258826e6279686649b481f","src/test_labels_names.rs":"c962c7aeac3d9ef2aca70c9e21983b231d4cf998cb06879374b0401e5149d1da","src/testing.rs":"b299d27055f3b068de66cc10a75c024b881c48bc093627c01e0b1f8bd7d94666","src/utf_16.rs":"1ec4e1c8ed7e42e4de401c6d0f64c2835bd80c2a306f358959957d30e6ff1501","src/utf_8.rs":"3839b19071bed07efc70c837f07c78600ff3c9eaef5c81c03672e0c17874ec30","src/variant.rs":"619a8e604d2febe6a874e3ad73cddf3ef9e6011480aecf86f23708b313415251","src/x_user_defined.rs":"3f1956b698eb27bc7b323f853b188726bb5f62d15d899a7b08590ba5c26d9d45"},"package":"1a8fa54e6689eb2549c4efed8d00d7f3b2b994a064555b0e8df4ae3764bcc4be"}
\ No newline at end of file
+{"files":{"CONTRIBUTING.md":"06c26277e8dbd3f57be2eb51b5e3285dc1cbbf8c11326df413868ae702e6a61c","COPYRIGHT":"8b98376eb373dcf81950474efe34b5576a8171460dff500cc58a1ed8d160cd57","Cargo.toml":"f4c9b33981fe222ef322d640f5ef680828d75dcd534b8aa2bfdd576598deea64","Ideas.md":"b7452893f500163868d8de52c09addaf91e1632454ed02e892c467ed7ec39dbd","LICENSE-APACHE":"cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30","LICENSE-MIT":"f2ad48641d9c997d9ae3b95d93d1cd6e1ab12ab4c44de89937c7bfabbd076a4a","README.md":"ad140c9178067c8bdba8ae43ddffd0506d70d49474731247a050ff99a3ff7832","build.rs":"f5defca2c68b73e8723f489a9279af4fbe9724abc6e9abf58d32542e8a459e26","doc/Big5.txt":"f73a2edc5cb6c2d140ba6e07f4542e1c4a234950378acde1df93480f0ca0be0b","doc/EUC-JP.txt":"ee2818b907d0137f40a9ab9fd525fc700a44dbdddb6cf0c157a656566bae4bf1","doc/EUC-KR.txt":"71d9e2ccf3b124e8bdfb433c8cf2773fd878077038d0cec3c7237a50f4a78a30","doc/GBK.txt":"c1b522b5a799884e5001da661f42c5a8f4d0acb9ef1d74b206f22b5f65365606","doc/IBM866.txt":"a5a433e804d0f83af785015179fbc1d9b0eaf1f7960efcd04093e136b51fbd0e","doc/ISO-2022-JP.txt":"af86684f5a8f0e2868d7b2c292860140c3d2e5527530ca091f1b28198e8e2fe6","doc/ISO-8859-10.txt":"6d3949ad7c81ca176895101ed81a1db7df1060d64e262880b94bd31bb344ab4d","doc/ISO-8859-13.txt":"3951dd89cf93f7729148091683cf8511f4529388b7dc8dcd0d62eaed55be93fa","doc/ISO-8859-14.txt":"3d330784a0374fd255a38b47949675cc7168c800530534b0a01cac6edc623adc","doc/ISO-8859-15.txt":"24b1084aab5127a85aab99153f86e24694d0a3615f53b5ce23683f97cf66c47a","doc/ISO-8859-16.txt":"ce0272559b92ba76d7a7e476f6424ae4a5cc72e75b183611b08392e44add4d25","doc/ISO-8859-2.txt":"18ceff88c13d1b5ba455a3919b1e3de489045c4c3d2dd7e8527c125c75d54aad","doc/ISO-8859-3.txt":"21798404c68f4f5db59223362f24999da96968c0628427321fccce7d2849a130","doc/ISO-8859-4.txt":"d27f6520c6c5bfbcc19176b71d081cdb3bccde1622bb3e420d5680e812632d53","doc/ISO-8859-5.txt":"a10ec8d6ea7a78ad15da7275f6cb1a3365118527e28f9af6d0d5830501303f3a","doc/ISO-8859-6.txt":"ccda8a2efc96115336bdd77776637b9712425e44fbcf745353b9057fbef144e7","doc/ISO-8859-7.txt":"17900fa1f27a445958f0a77d7d9056be375a6bd7ee4492aa680c7c1500bab85e","doc/ISO-8859-8-I.txt":"8357555646d54265a9b9ffa3e68b08d132312f1561c60108ff9b8b1167b6ecf2","doc/ISO-8859-8.txt":"72cd6f3afb7b4a9c16a66a362473315770b7755d72c86c870e52fc3eba86c8af","doc/KOI8-R.txt":"839cf19a38da994488004ed7814b1f6151640156a9a2af02bf2efca745fb5966","doc/KOI8-U.txt":"0cc76624ed1f024183e2298b7e019957da2c70c8ca06e0fc4e6f353f50a5054f","doc/Shift_JIS.txt":"34c49141818cb9ddbcf59cc858f78a79be8ad148d563f26415108ae1f148443f","doc/UTF-16BE.txt":"e2e280d8acbaa6d2a6b3569d60e17500a285f2baa0df3363dd85537cd5a1ef8f","doc/UTF-16LE.txt":"70bdc170e3fc5298ba68f10125fb5eeb8b077036cc96bb4416c4de396f6d76c1","doc/UTF-8.txt":"ea7bae742e613010ced002cf4b601a737d2203fad65e115611451bc4428f548a","doc/gb18030.txt":"dc71378a8f07a2d8659f69ee81fb8791fef56ba86f124b429978285237bb4a7b","doc/macintosh.txt":"57491e53866711b4672d9b9ff35380b9dac9e0d8e3d6c20bdd6140603687c023","doc/replacement.txt":"4b6c3bbd7999d9d4108a281594bd02d13607e334a95465afff8c2c08d395f0e4","doc/windows-1250.txt":"61296bb6a21cdab602300d32ecfba434cb82de5ac3bc88d58710d2f125e28d39","doc/windows-1251.txt":"7deea1c61dea1485c8ff02db2c7d578db7a9aab63ab1cfd02ec04b515864689e","doc/windows-1252.txt":"933ef3bdddfce5ee132b9f1a1aa8b47423d2587bbe475b19028d0a6d38e180b6","doc/windows-1253.txt":"1a38748b88e99071a5c7b3d5456ead4caedeabab50d50d658be105bc113714de","doc/windows-1254.txt":"f8372f86c6f8d642563cd6ddc025260553292a39423df1683a98670bd7bf2b47","doc/windows-1255.txt":"4e5852494730054e2da258a74e1b9d780abbcdd8ce22ebc218ca2efe9e90493d","doc/windows-1256.txt":"c0879c5172abedead302a406e8f60d9cd9598694a0ffa4fd288ffe4fef7b8ea1","doc/windows-1257.txt":"c28a0c9f964fcb2b46d21f537c402446501a2800670481d6abf9fd9e9018d523","doc/windows-1258.txt":"5019ae4d61805c79aacbf17c93793342dbb098d65a1837783bc3e2c6d6a23602","doc/windows-874.txt":"4ef0e4501c5feba8b17aee1818602ed44b36ca8475db771ce2fc16d392cabecc","doc/x-mac-cyrillic.txt":"58be154d8a888ca3d484b83b44f749823ef339ab27f14d90ca9a856f5050a8bd","doc/x-user-defined.txt":"f9cd07c4321bf5cfb0be4bdddd251072999b04a6cf7a6f5bc63709a84e2c1ffc","generate-encoding-data.py":"92ddec35a834b6bc815fffffe6d07d9938a90d3c4526298637d8624410d83078","rustfmt.toml":"85c1a3b4382fd89e991cbb81b70fb52780472edc064c963943cdaaa56e0a2030","src/ascii.rs":"800cfbe3036d0c97ce27e07a4fd05edbcb7354ebec20903d81c76136d734931c","src/big5.rs":"1c94b35813314775c3fa1b10923cf8e8f8eba8c465d9833ad4293594e16c17f2","src/data.rs":"9544c019c7360a669bd3adaa90b70331124abd1df59841db66e74912bcdb96a5","src/euc_jp.rs":"0842e4f564a36051c6b85c47bbb652efae2f2926e91491daf77e4ceeecb18163","src/euc_kr.rs":"8e68590efa65485583bf57cae44ebf6de535bac1d37232e7f0307a38425fb992","src/gb18030.rs":"d269efb5e5d175f9d2ecf01d5606955a284b6f00749bb0ee23d3412c83aa3d59","src/handles.rs":"71aa7de1c5236a34ea0a8bb85332987751d2466b756fca6b3f6ac0da765cf91e","src/iso_2022_jp.rs":"3adc380736f24a5de36bc1cf81049bbe64473de10e6f12774195e6213c27c322","src/lib.rs":"e786de9e92e5652bc200266cf318753eea869e8971857cc0caa65a3cfe687545","src/macros.rs":"c7a019fd81d31de77569036ac36fd4e404b3f20144bbf79747faf4ea21538d09","src/mem.rs":"f412f60f2d4afb7e32ffba94dc5f93716e6ae9f065799ca17bb1f1b2145f6ee4","src/replacement.rs":"182c2093a6edb162183ca5990554fd7b199d3011924a8d80d894ba98ee7c479e","src/shift_jis.rs":"1c0c69ba6c123fcf720276646074660193bf9e6fa4327fe0d739a3e67874e081","src/simd_funcs.rs":"565ceeffe81173b85700c55c396ab72068751ef809bea8e1cb1e6c7919f5a905","src/single_byte.rs":"383d325dedbf3295acd50d880db1cecc29b69efe332ae2a37367cf40bf138ac4","src/test_data/big5_in.txt":"4c5a8691f8dc717311889c63894026d2fb62725a86c4208ca274a9cc8d42a503","src/test_data/big5_in_ref.txt":"99d399e17750cf9c7cf30bb253dbfe35b81c4fcbdead93cfa48b1429213473c7","src/test_data/big5_out.txt":"6193ca97c297aa20e09396038d18e938bb7ea331c26f0f2454097296723a0b13","src/test_data/big5_out_ref.txt":"36567691f557df144f6cc520015a87038dfa156f296fcf103b56ae9a718be1fc","src/test_data/euc_kr_in.txt":"c86a7224f3215fa0d04e685622a752fdc72763e8ae076230c7fd62de57ec4074","src/test_data/euc_kr_in_ref.txt":"1f419f4ca47d708b54c73c461545a022ae2e20498fdbf8005a483d752a204883","src/test_data/euc_kr_out.txt":"e7f32e026f70be1e1b58e0047baf7d3d2c520269c4f9b9992e158b4decb0a1a3","src/test_data/euc_kr_out_ref.txt":"c9907857980b20b8e9e3b584482ed6567a2be6185d72237b6322f0404944924e","src/test_data/gb18030_in.txt":"ab7231b2d3e9afacdbd7d7f3b9e5361a7ff9f7e1cfdb4f3bd905b9362b309e53","src/test_data/gb18030_in_ref.txt":"dc5069421adca2043c55f5012b55a76fdff651d22e6e699fd0978f8d5706815c","src/test_data/gb18030_out.txt":"f0208d527f5ca63de7d9a0323be8d5cf12d8a104b2943d92c2701f0c3364dac1","src/test_data/gb18030_out_ref.txt":"6819fe47627e4ea01027003fc514b9f21a1322e732d7f1fb92cc6c5455bc6c07","src/test_data/iso_2022_jp_in.txt":"cd24bbdcb1834e25db54646fbf4c41560a13dc7540f6be3dba4f5d97d44513af","src/test_data/iso_2022_jp_in_ref.txt":"3dc4e6a5e06471942d086b16c9440945e78415f6f3f47e43717e4bc2eac2cdf5","src/test_data/iso_2022_jp_out.txt":"9b6f015329dda6c3f9ee5ce6dbd6fa9c89acc21283e886836c78b8d833480c21","src/test_data/iso_2022_jp_out_ref.txt":"78cb260093a20116ad9a42f43b05d1848c5ab100b6b9a850749809e943884b35","src/test_data/jis0208_in.txt":"6df3030553ffb0a6615bb33dc8ea9dca6d9623a9028e2ffec754ce3c3da824cc","src/test_data/jis0208_in_ref.txt":"3dc4e6a5e06471942d086b16c9440945e78415f6f3f47e43717e4bc2eac2cdf5","src/test_data/jis0208_out.txt":"4ec24477e1675ce750733bdc3c5add1cd27b6bd4ce1f09289564646e9654e857","src/test_data/jis0208_out_ref.txt":"c3e1cef5032b2b1d93a406f31ff940c4e2dfe8859b8b17ca2761fee7a75a0e48","src/test_data/jis0212_in.txt":"c011f0dd72bd7c8cd922df9374ef8d2769a77190514c77f6c62b415852eeb9fe","src/test_data/jis0212_in_ref.txt":"7d9458b3d2f73e7092a7f505c08ce1d233dde18aa679fbcf9889256239cc9e06","src/test_data/shift_jis_in.txt":"02e389ccef0dd2122e63f503899402cb7f797912c2444cc80ab93131116c5524","src/test_data/shift_jis_in_ref.txt":"512f985950ca902e643c88682dba9708b7c38d3c5ec2925168ab00ac94ab19f9","src/test_data/shift_jis_out.txt":"5fbc44da7bf639bf6cfe0fa1fd3eba7102b88f81919c9ea991302712f69426fb","src/test_data/shift_jis_out_ref.txt":"466322c6fed8286c64582731755290c2296508efdd258826e6279686649b481f","src/test_labels_names.rs":"c962c7aeac3d9ef2aca70c9e21983b231d4cf998cb06879374b0401e5149d1da","src/testing.rs":"b299d27055f3b068de66cc10a75c024b881c48bc093627c01e0b1f8bd7d94666","src/utf_16.rs":"1ec4e1c8ed7e42e4de401c6d0f64c2835bd80c2a306f358959957d30e6ff1501","src/utf_8.rs":"f639fc5dccd5dcc2458936baa942237d0fd58ac398c83ea3f48e51dceb5b6a81","src/variant.rs":"619a8e604d2febe6a874e3ad73cddf3ef9e6011480aecf86f23708b313415251","src/x_user_defined.rs":"ab26ea900c8f7b7a4d1172872b7ca4bc573bc60b7b1979c93aafdfb86b2c2235"},"package":"a69d152eaa438a291636c1971b0a370212165ca8a75759eb66818c5ce9b538f7"}
\ No newline at end of file
--- a/third_party/rust/encoding_rs/Cargo.toml
+++ b/third_party/rust/encoding_rs/Cargo.toml
@@ -7,17 +7,17 @@
 #
 # 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 = "encoding_rs"
-version = "0.8.13"
+version = "0.8.14"
 authors = ["Henri Sivonen <hsivonen@hsivonen.fi>"]
 description = "A Gecko-oriented implementation of the Encoding Standard"
 homepage = "https://docs.rs/encoding_rs/"
 documentation = "https://docs.rs/encoding_rs/"
 readme = "README.md"
 keywords = ["encoding", "web", "unicode", "charset"]
 categories = ["text-processing", "encoding", "web-programming", "internationalization"]
 license = "MIT/Apache-2.0"
--- a/third_party/rust/encoding_rs/README.md
+++ b/third_party/rust/encoding_rs/README.md
@@ -76,38 +76,49 @@ a `std::io::Read`, decode it into UTF-8 
 crate provides that capability.
 
 ## Decoding Email
 
 For decoding character encodings that occur in email, use the
 [`charset`](https://crates.io/crates/charset) crate instead of using this
 one directly. (It wraps this crate and adds UTF-7 decoding.)
 
+## Windows Code Page Identifier Mappings
+
+For mappings to and from Windows code page identifiers, use the
+[`codepage`](https://crates.io/crates/codepage) crate.
+
 ## Licensing
 
 Please see the file named
 [COPYRIGHT](https://github.com/hsivonen/encoding_rs/blob/master/COPYRIGHT).
 
-## API Documentation
+## Documentation
 
 Generated [API documentation](https://docs.rs/encoding_rs/) is available
 online.
 
+There is a [long-form write-up](https://hsivonen.fi/encoding_rs/) about the
+design and internals of the crate.
+
 ## C and C++ bindings
 
 An FFI layer for encoding_rs is available as a
 [separate crate](https://github.com/hsivonen/encoding_c). The crate comes
 with a [demo C++ wrapper](https://github.com/hsivonen/encoding_c/blob/master/include/encoding_rs_cpp.h)
 using the C++ standard library and [GSL](https://github.com/Microsoft/GSL/) types.
 
 For the Gecko context, there's a
 [C++ wrapper using the MFBT/XPCOM types](https://searchfox.org/mozilla-central/source/intl/Encoding.h#100).
 
 These bindings do not cover the `mem` module.
 
+There's a [write-up](https://hsivonen.fi/modern-cpp-in-rust/) about the C++
+wrappers.
+
 ## Sample programs
 
 * [Rust](https://github.com/hsivonen/recode_rs)
 * [C](https://github.com/hsivonen/recode_c)
 * [C++](https://github.com/hsivonen/recode_cpp)
 
 ## Optional features
 
@@ -321,16 +332,18 @@ used in Firefox.
 
 ## Regenerating Generated Code
 
 To regenerate the generated code:
 
  * Have Python 2 installed.
  * Clone [`https://github.com/hsivonen/encoding_c`](https://github.com/hsivonen/encoding_c)
    next to the `encoding_rs` directory.
+ * Clone [`https://github.com/hsivonen/codepage`](https://github.com/hsivonen/codepage)
+   next to the `encoding_rs` directory.
  * Clone [`https://github.com/whatwg/encoding`](https://github.com/whatwg/encoding)
    next to the `encoding_rs` directory.
  * Checkout revision `f381389` of the `encoding` repo.
  * With the `encoding_rs` directory as the working directory, run
    `python generate-encoding-data.py`.
 
 ## Roadmap
 
@@ -360,25 +373,30 @@ To regenerate the generated code:
       range per encoding.
 - [x] Replace uconv with encoding_rs in Gecko.
 - [x] Implement the rust-encoding API in terms of encoding_rs.
 - [x] Add SIMD acceleration for Aarch64.
 - [x] Investigate the use of NEON on 32-bit ARM.
 - [ ] ~Investigate Björn Höhrmann's lookup table acceleration for UTF-8 as
       adapted to Rust in rust-encoding.~
 - [x] Add actually fast CJK encode options.
-- [ ] Investigate [Bob Steagall's lookup table acceleration for UTF-8](https://github.com/BobSteagall/CppNow2018/blob/master/FastConversionFromUTF-8/Fast%20Conversion%20From%20UTF-8%20with%20C%2B%2B%2C%20DFAs%2C%20and%20SSE%20Intrinsics%20-%20Bob%20Steagall%20-%20C%2B%2BNow%202018.pdf).
+- [ ] ~Investigate [Bob Steagall's lookup table acceleration for UTF-8](https://github.com/BobSteagall/CppNow2018/blob/master/FastConversionFromUTF-8/Fast%20Conversion%20From%20UTF-8%20with%20C%2B%2B%2C%20DFAs%2C%20and%20SSE%20Intrinsics%20-%20Bob%20Steagall%20-%20C%2B%2BNow%202018.pdf).~
 
 ## Release Notes
 
+### 0.8.14
+
+* Made UTF-16 to UTF-8 encode conversion fill the output buffer as
+  closely as possible.
+
 ### 0.8.13
 
-* Made the UTF-8 to UTF-16 compare the number of code units written with the
-  length of the right slice (the output slice) to fix a panic introduced in
-  0.8.11.
+* Made the UTF-8 to UTF-16 decoder compare the number of code units written
+  with the length of the right slice (the output slice) to fix a panic
+  introduced in 0.8.11.
 
 ### 0.8.12
 
 * Removed the `clippy::` prefix from clippy lint names.
 
 ### 0.8.11
 
 * Changed minimum Rust requirement to 1.29.0 (for the ability to refer
--- a/third_party/rust/encoding_rs/generate-encoding-data.py
+++ b/third_party/rust/encoding_rs/generate-encoding-data.py
@@ -17,16 +17,20 @@ import os.path
 if (not os.path.isfile("../encoding/encodings.json")) or (not os.path.isfile("../encoding/indexes.json")):
   sys.stderr.write("This script needs a clone of https://github.com/whatwg/encoding/ (preferably at revision f381389) next to the encoding_rs directory.\n");
   sys.exit(-1)
 
 if not os.path.isfile("../encoding_c/src/lib.rs"):
   sys.stderr.write("This script also writes the generated parts of the encoding_c crate and needs a clone of https://github.com/hsivonen/encoding_c next to the encoding_rs directory.\n");
   sys.exit(-1)
 
+if not os.path.isfile("../codepage/src/lib.rs"):
+  sys.stderr.write("This script also writes the generated parts of the codepage crate and needs a clone of https://github.com/hsivonen/codepage next to the encoding_rs directory.\n");
+  sys.exit(-1)
+
 def cmp_from_end(one, other):
   c = cmp(len(one), len(other))
   if c != 0:
     return c
   i = len(one) - 1
   while i >= 0:
     c = cmp(one[i], other[i])
     if c != 0:
@@ -114,34 +118,78 @@ labels = []
 data = json.load(open("../encoding/encodings.json", "r"))
 
 indexes = json.load(open("../encoding/indexes.json", "r"))
 
 single_byte = []
 
 multi_byte = []
 
-code_pages = []
-
 def to_camel_name(name):
   if name == u"iso-8859-8-i":
     return u"Iso8I"
   if name.startswith(u"iso-8859-"):
     return name.replace(u"iso-8859-", u"Iso")
   return name.title().replace(u"X-", u"").replace(u"-", u"").replace(u"_", u"")
 
 def to_constant_name(name):
   return name.replace(u"-", u"_").upper()
 
 def to_snake_name(name):
   return name.replace(u"-", u"_").lower()
 
 def to_dom_name(name):
   return name
 
+# Guestimate based on
+# https://w3techs.com/technologies/overview/character_encoding/all
+# whose methodology is known to be bogus, but the results are credible for
+# this purpose. UTF-16LE lifted up due to prevalence on Windows and
+# "ANSI codepages" prioritized.
+encodings_by_code_page_frequency = [
+  "UTF-8",    
+  "UTF-16LE",
+  "windows-1252",
+  "windows-1251",
+  "GBK",
+  "Shift_JIS",
+  "EUC-KR",
+  "windows-1250",
+  "windows-1256",
+  "windows-1254",
+  "Big5",
+  "windows-874",
+  "windows-1255",
+  "windows-1253",
+  "windows-1257",
+  "windows-1258",
+  "EUC-JP",
+  "ISO-8859-2",
+  "ISO-8859-15",
+  "ISO-8859-7",
+  "KOI8-R",
+  "gb18030",
+  "ISO-8859-5",
+  "ISO-8859-8-I",
+  "ISO-8859-4",
+  "ISO-8859-6",
+  "ISO-2022-JP",
+  "KOI8-U",
+  "ISO-8859-13",
+  "ISO-8859-3",
+  "UTF-16BE",
+  "IBM866",
+  "ISO-8859-10",
+  "ISO-8859-8",
+  "macintosh",
+  "x-mac-cyrillic",
+  "ISO-8859-14",
+  "ISO-8859-16",
+]
+
 encodings_by_code_page = {
   932: "Shift_JIS",
   936: "GBK",
   949: "EUC-KR",
   950: "Big5",
   866: "IBM866",
   874: "windows-874",
   1200: "UTF-16LE",
@@ -180,28 +228,46 @@ encodings_by_code_page = {
 
 code_pages_by_encoding = {}
 
 for code_page, encoding in encodings_by_code_page.iteritems():
   code_pages_by_encoding[encoding] = code_page
 
 encoding_by_alias_code_page = {
   951: "Big5",
+  10007: "x-mac-cyrillic",
   20936: "GBK",
   20949: "EUC-KR",
+  21010: "UTF-16LE", # Undocumented; needed by calamine for Excel compat
   28591: "windows-1252",
   28599: "windows-1254",
-  28601: "windows-847",
+  28601: "windows-874",
   50220: "ISO-2022-JP",
   50222: "ISO-2022-JP",
+  50225: "replacement", # ISO-2022-KR
+  50227: "replacement", # ISO-2022-CN
   51949: "EUC-JP",
   51936: "GBK",
   51949: "EUC-KR",
+  52936: "replacement", # HZ
 }
 
+code_pages = []
+
+for name in encodings_by_code_page_frequency:
+  code_pages.append(code_pages_by_encoding[name])
+
+encodings_by_code_page.update(encoding_by_alias_code_page)
+
+temp_keys = encodings_by_code_page.keys()
+temp_keys.sort()
+for code_page in temp_keys:
+  if not code_page in code_pages:
+    code_pages.append(code_page)
+
 # The position in the index (0 is the first index entry,
 # i.e. byte value 0x80) that starts the longest run of
 # consecutive code points. Must not be in the first
 # quadrant. If the character to be encoded is not in this
 # run, the part of the index after the run is searched
 # forward. Then the part of the index from 32 to the start
 # of the run. The first quadrant is searched last.
 #
@@ -1801,9 +1867,76 @@ jis0212_in_ref_file.write(TEST_HEADER)
 for pointer in range(0, len(index)):
   code_point = index[pointer]
   if code_point:
     jis0212_in_ref_file.write((u"%s\n" % unichr(code_point)).encode("utf-8"))
   else:
     jis0212_in_ref_file.write(u"\uFFFD\n".encode("utf-8"))
 jis0212_in_ref_file.close()
 
+(codepage_begin, codepage_end) = read_non_generated("../codepage/src/lib.rs")
+
+codepage_file = open("../codepage/src/lib.rs", "w")
+
+codepage_file.write(codepage_begin)
+codepage_file.write("""
+// Instead, please regenerate using generate-encoding-data.py
+
+/// Supported code page numbers in estimated order of usage frequency
+static CODE_PAGES: [u16; %d] = [
+""" % len(code_pages))
+
+for code_page in code_pages:
+  codepage_file.write("    %d,\n" % code_page)
+
+codepage_file.write("""];
+
+/// Encodings corresponding to the code page numbers in the same order
+static ENCODINGS: [&'static Encoding; %d] = [
+""" % len(code_pages))
+
+for code_page in code_pages:
+  name = encodings_by_code_page[code_page]
+  codepage_file.write("    &%s_INIT,\n" % to_constant_name(name))
+
+codepage_file.write("""];
+
+""")
+
+codepage_file.write(codepage_end)
+codepage_file.close()
+
+(codepage_test_begin, codepage_test_end) = read_non_generated("../codepage/src/tests.rs")
+
+codepage_test_file = open("../codepage/src/tests.rs", "w")
+
+codepage_test_file.write(codepage_test_begin)
+codepage_test_file.write("""
+// Instead, please regenerate using generate-encoding-data.py
+
+#[test]
+fn test_to_encoding() {
+    assert_eq!(to_encoding(0), None);
+
+""")
+
+for code_page in code_pages:
+  codepage_test_file.write("    assert_eq!(to_encoding(%d), Some(%s));\n" % (code_page, to_constant_name(encodings_by_code_page[code_page])))  
+
+codepage_test_file.write("""}
+
+#[test]
+fn test_from_encoding() {
+""")
+
+for name in preferred:
+  if code_pages_by_encoding.has_key(name):
+    codepage_test_file.write("    assert_eq!(from_encoding(%s), Some(%d));\n" % (to_constant_name(name), code_pages_by_encoding[name]))
+  else:
+    codepage_test_file.write("    assert_eq!(from_encoding(%s), None);\n" % to_constant_name(name))
+
+codepage_test_file.write("""}
+""")
+
+codepage_test_file.write(codepage_test_end)
+codepage_test_file.close()
+
 subprocess.call(["cargo", "fmt"])
--- a/third_party/rust/encoding_rs/src/ascii.rs
+++ b/third_party/rust/encoding_rs/src/ascii.rs
@@ -26,17 +26,17 @@
     any(
         target_feature = "sse2",
         all(target_endian = "little", target_arch = "aarch64"),
         all(target_endian = "little", target_feature = "neon")
     )
 ))]
 use simd_funcs::*;
 
-cfg_if!{
+cfg_if! {
     if #[cfg(feature = "simd-accel")] {
         #[allow(unused_imports)]
         use ::std::intrinsics::unlikely;
         #[allow(unused_imports)]
         use ::std::intrinsics::likely;
     } else {
         #[allow(dead_code)]
         #[inline(always)]
@@ -85,20 +85,17 @@ macro_rules! ascii_naive {
 }
 
 #[allow(unused_macros)]
 macro_rules! ascii_alu {
     ($name:ident,
      $src_unit:ty,
      $dst_unit:ty,
      $stride_fn:ident) => {
-        #[cfg_attr(
-            feature = "cargo-clippy",
-            allow(never_loop, cast_ptr_alignment)
-        )]
+        #[cfg_attr(feature = "cargo-clippy", allow(never_loop, cast_ptr_alignment))]
         #[inline(always)]
         pub unsafe fn $name(
             src: *const $src_unit,
             dst: *mut $dst_unit,
             len: usize,
         ) -> Option<($src_unit, usize)> {
             let mut offset = 0usize;
             // This loop is only broken out of as a `goto` forward
@@ -181,21 +178,17 @@ macro_rules! ascii_alu {
 #[allow(unused_macros)]
 macro_rules! basic_latin_alu {
     ($name:ident,
      $src_unit:ty,
      $dst_unit:ty,
      $stride_fn:ident) => {
         #[cfg_attr(
             feature = "cargo-clippy",
-            allow(
-                never_loop,
-                cast_ptr_alignment,
-                cast_lossless
-            )
+            allow(never_loop, cast_ptr_alignment, cast_lossless)
         )]
         #[inline(always)]
         pub unsafe fn $name(
             src: *const $src_unit,
             dst: *mut $dst_unit,
             len: usize,
         ) -> Option<($src_unit, usize)> {
             let mut offset = 0usize;
@@ -280,21 +273,17 @@ macro_rules! basic_latin_alu {
     };
 }
 
 #[allow(unused_macros)]
 macro_rules! latin1_alu {
     ($name:ident, $src_unit:ty, $dst_unit:ty, $stride_fn:ident) => {
         #[cfg_attr(
             feature = "cargo-clippy",
-            allow(
-                never_loop,
-                cast_ptr_alignment,
-                cast_lossless
-            )
+            allow(never_loop, cast_ptr_alignment, cast_lossless)
         )]
         #[inline(always)]
         pub unsafe fn $name(src: *const $src_unit, dst: *mut $dst_unit, len: usize) {
             let mut offset = 0usize;
             // This loop is only broken out of as a `goto` forward
             loop {
                 let mut until_alignment = {
                     if ::std::mem::size_of::<$src_unit>() < ::std::mem::size_of::<$dst_unit>() {
--- a/third_party/rust/encoding_rs/src/data.rs
+++ b/third_party/rust/encoding_rs/src/data.rs
@@ -29493,20 +29493,17 @@ const IBM_SYMBOL_POINTER_START: usize = 
 pub static JIS0208_RANGE_TRIPLES: [u16; 54] = [
     0x00CB, 0x000A, 0xFF10, 0x00DC, 0x001A, 0xFF21, 0x00FC, 0x001A, 0xFF41, 0x01D6, 0x0011, 0x0391,
     0x01E7, 0x0007, 0x03A3, 0x01F6, 0x0011, 0x03B1, 0x0207, 0x0007, 0x03C3, 0x0234, 0x0006, 0x0410,
     0x023A, 0x0001, 0x0401, 0x023B, 0x001A, 0x0416, 0x0264, 0x0006, 0x0430, 0x026A, 0x0001, 0x0451,
     0x026B, 0x001A, 0x0436, 0x0468, 0x0014, 0x2460, 0x047C, 0x000A, 0x2160, 0x21BA, 0x000A, 0x2170,
     0x29DC, 0x000A, 0x2170, 0x29E6, 0x000A, 0x2160,
 ];
 
-#[cfg(all(
-    feature = "less-slow-kanji-encode",
-    not(feature = "fast-kanji-encode")
-))]
+#[cfg(all(feature = "less-slow-kanji-encode", not(feature = "fast-kanji-encode")))]
 static JIS0208_LEVEL1_KANJI_CODE_POINTS: [u16; 2965] = [
     0x4E00, 0x4E01, 0x4E03, 0x4E07, 0x4E08, 0x4E09, 0x4E0A, 0x4E0B, 0x4E0D, 0x4E0E, 0x4E11, 0x4E14,
     0x4E16, 0x4E18, 0x4E19, 0x4E1E, 0x4E21, 0x4E26, 0x4E2D, 0x4E32, 0x4E38, 0x4E39, 0x4E3B, 0x4E43,
     0x4E45, 0x4E4B, 0x4E4D, 0x4E4E, 0x4E4F, 0x4E57, 0x4E59, 0x4E5D, 0x4E5E, 0x4E5F, 0x4E71, 0x4E73,
     0x4E7E, 0x4E80, 0x4E86, 0x4E88, 0x4E89, 0x4E8B, 0x4E8C, 0x4E91, 0x4E92, 0x4E94, 0x4E95, 0x4E98,
     0x4E99, 0x4E9B, 0x4E9C, 0x4EA1, 0x4EA4, 0x4EA5, 0x4EA6, 0x4EA8, 0x4EAB, 0x4EAC, 0x4EAD, 0x4EAE,
     0x4EBA, 0x4EC0, 0x4EC1, 0x4EC7, 0x4ECA, 0x4ECB, 0x4ECF, 0x4ED4, 0x4ED5, 0x4ED6, 0x4ED8, 0x4ED9,
     0x4EE3, 0x4EE4, 0x4EE5, 0x4EEE, 0x4EF0, 0x4EF2, 0x4EF6, 0x4EFB, 0x4F01, 0x4F0A, 0x4F0D, 0x4F0E,
@@ -29748,20 +29745,17 @@ static JIS0208_LEVEL1_KANJI_CODE_POINTS:
     0x9B92, 0x9BAA, 0x9BAB, 0x9BAD, 0x9BAE, 0x9BC9, 0x9BD6, 0x9BDB, 0x9BE8, 0x9BF5, 0x9C0D, 0x9C10,
     0x9C2D, 0x9C2F, 0x9C39, 0x9C3B, 0x9C48, 0x9C52, 0x9C57, 0x9CE5, 0x9CE9, 0x9CF3, 0x9CF4, 0x9CF6,
     0x9D07, 0x9D0E, 0x9D1B, 0x9D28, 0x9D2B, 0x9D2C, 0x9D3B, 0x9D5C, 0x9D60, 0x9D61, 0x9D6C, 0x9D8F,
     0x9DB4, 0x9DF2, 0x9DF9, 0x9DFA, 0x9E78, 0x9E7F, 0x9E93, 0x9E97, 0x9E9F, 0x9EA6, 0x9EB9, 0x9EBA,
     0x9EBB, 0x9EBF, 0x9EC4, 0x9ECD, 0x9ED2, 0x9ED9, 0x9EDB, 0x9F0E, 0x9F13, 0x9F20, 0x9F3B, 0x9F62,
     0x9F8D,
 ];
 
-#[cfg(all(
-    feature = "less-slow-kanji-encode",
-    not(feature = "fast-kanji-encode")
-))]
+#[cfg(all(feature = "less-slow-kanji-encode", not(feature = "fast-kanji-encode")))]
 static JIS0208_LEVEL1_KANJI_SHIFT_JIS_BYTES: [[u8; 2]; 2965] = [
     [0x88, 0xEA],
     [0x92, 0x9A],
     [0x8E, 0xB5],
     [0x96, 0x9C],
     [0x8F, 0xE4],
     [0x8E, 0x4F],
     [0x8F, 0xE3],
@@ -113962,20 +113956,17 @@ pub fn jis0208_kanji_shift_jis_encode(bm
     let trail = pair[1];
     if lead == 0 && trail == 0 {
         return None;
     }
     // Always set the high bit on lead. (It's zero for IBM Kanji.)
     Some((lead | 0x80, trail))
 }
 
-#[cfg(any(
-    feature = "less-slow-kanji-encode",
-    feature = "fast-kanji-encode"
-))]
+#[cfg(any(feature = "less-slow-kanji-encode", feature = "fast-kanji-encode"))]
 #[inline(always)]
 fn shift_jis_to_euc_jp(tuple: (u8, u8)) -> (u8, u8) {
     let (shift_jis_lead, shift_jis_trail) = tuple;
     let mut lead = shift_jis_lead as usize;
     if shift_jis_lead >= 0xA0 {
         lead -= 0xC1 - 0x81;
     }
     // The next line would overflow u8. Letting it go over allows us to
@@ -114007,20 +113998,17 @@ pub fn jis0208_kanji_euc_jp_encode(bmp: 
         let pos = position(&IBM_KANJI[..], bmp).unwrap();
         let lead = (pos / 94) + 0xF9;
         let trail = (pos % 94) + 0xA1;
         return Some((lead as u8, trail as u8));
     }
     Some(shift_jis_to_euc_jp((lead, trail)))
 }
 
-#[cfg(any(
-    feature = "less-slow-kanji-encode",
-    feature = "fast-kanji-encode"
-))]
+#[cfg(any(feature = "less-slow-kanji-encode", feature = "fast-kanji-encode"))]
 #[inline(always)]
 fn shift_jis_to_iso_2022_jp(tuple: (u8, u8)) -> (u8, u8) {
     let (shift_jis_lead, shift_jis_trail) = tuple;
     let mut lead = shift_jis_lead as usize;
     if shift_jis_lead >= 0xA0 {
         lead -= 0xC1 - 0x81;
     }
     // The next line would overflow u8. Letting it go over allows us to
@@ -114052,86 +114040,68 @@ pub fn jis0208_kanji_iso_2022_jp_encode(
         let pos = position(&IBM_KANJI[..], bmp).unwrap();
         let lead = (pos / 94) + (0xF9 - 0x80);
         let trail = (pos % 94) + 0x21;
         return Some((lead as u8, trail as u8));
     }
     Some(shift_jis_to_iso_2022_jp((lead, trail)))
 }
 
-#[cfg(not(any(
-    feature = "less-slow-kanji-encode",
-    feature = "fast-kanji-encode"
-)))]
+#[cfg(not(any(feature = "less-slow-kanji-encode", feature = "fast-kanji-encode")))]
 #[inline(always)]
 pub fn jis0208_level1_kanji_shift_jis_encode(bmp: u16) -> Option<(u8, u8)> {
     position(&JIS0208_LEVEL1_KANJI[..], bmp).map(|kanji_pointer| {
         let pointer = 1410 + kanji_pointer;
         let lead = pointer / 188;
         let lead_offset = if lead < 0x1F { 0x81 } else { 0xC1 };
         let trail = pointer % 188;
         let trail_offset = if trail < 0x3F { 0x40 } else { 0x41 };
         ((lead + lead_offset) as u8, (trail + trail_offset) as u8)
     })
 }
 
-#[cfg(all(
-    feature = "less-slow-kanji-encode",
-    not(feature = "fast-kanji-encode")
-))]
+#[cfg(all(feature = "less-slow-kanji-encode", not(feature = "fast-kanji-encode")))]
 #[inline(always)]
 pub fn jis0208_level1_kanji_shift_jis_encode(bmp: u16) -> Option<(u8, u8)> {
     match JIS0208_LEVEL1_KANJI_CODE_POINTS.binary_search(&bmp) {
         Ok(i) => {
             let pair = &JIS0208_LEVEL1_KANJI_SHIFT_JIS_BYTES[i];
             Some((pair[0], pair[1]))
         }
         Err(_) => None,
     }
 }
 
-#[cfg(not(any(
-    feature = "less-slow-kanji-encode",
-    feature = "fast-kanji-encode"
-)))]
+#[cfg(not(any(feature = "less-slow-kanji-encode", feature = "fast-kanji-encode")))]
 #[inline(always)]
 pub fn jis0208_level1_kanji_euc_jp_encode(bmp: u16) -> Option<(u8, u8)> {
     position(&JIS0208_LEVEL1_KANJI[..], bmp).map(|kanji_pointer| {
         let lead = (kanji_pointer / 94) + 0xB0;
         let trail = (kanji_pointer % 94) + 0xA1;
         (lead as u8, trail as u8)
     })
 }
 
-#[cfg(all(
-    feature = "less-slow-kanji-encode",
-    not(feature = "fast-kanji-encode")
-))]
+#[cfg(all(feature = "less-slow-kanji-encode", not(feature = "fast-kanji-encode")))]
 #[inline(always)]
 pub fn jis0208_level1_kanji_euc_jp_encode(bmp: u16) -> Option<(u8, u8)> {
     jis0208_level1_kanji_shift_jis_encode(bmp).map(shift_jis_to_euc_jp)
 }
 
-#[cfg(not(any(
-    feature = "less-slow-kanji-encode",
-    feature = "fast-kanji-encode"
-)))]
+#[cfg(not(any(feature = "less-slow-kanji-encode", feature = "fast-kanji-encode")))]
 #[inline(always)]
 pub fn jis0208_level1_kanji_iso_2022_jp_encode(bmp: u16) -> Option<(u8, u8)> {
     position(&JIS0208_LEVEL1_KANJI[..], bmp).map(|kanji_pointer| {
         let lead = (kanji_pointer / 94) + (0xB0 - 0x80);
         let trail = (kanji_pointer % 94) + 0x21;
         (lead as u8, trail as u8)
     })
 }
 
-#[cfg(all(
-    feature = "less-slow-kanji-encode",
-    not(feature = "fast-kanji-encode")
-))]
+#[cfg(all(feature = "less-slow-kanji-encode", not(feature = "fast-kanji-encode")))]
 #[inline(always)]
 pub fn jis0208_level1_kanji_iso_2022_jp_encode(bmp: u16) -> Option<(u8, u8)> {
     jis0208_level1_kanji_shift_jis_encode(bmp).map(shift_jis_to_iso_2022_jp)
 }
 
 #[cfg(not(feature = "fast-kanji-encode"))]
 #[inline(always)]
 pub fn jis0208_level2_and_additional_kanji_encode(bmp: u16) -> Option<usize> {
--- a/third_party/rust/encoding_rs/src/handles.rs
+++ b/third_party/rust/encoding_rs/src/handles.rs
@@ -277,17 +277,17 @@ fn convert_unaligned_utf16_to_utf8<E: En
             &mut dst[dst_pos..],
         ) {
             CopyAsciiResult::GoOn((unit, read_written)) => {
                 src_pos += read_written;
                 dst_pos += read_written;
                 unit
             }
             CopyAsciiResult::Stop(read_written) => {
-                return (src_pos + read_written, dst_pos + read_written, false)
+                return (src_pos + read_written, dst_pos + read_written, false);
             }
         };
         if dst_pos >= dst_len_minus_three {
             break 'outer;
         }
         // We have enough destination space to commit to
         // having read `non_ascii`.
         src_pos += 1;
--- a/third_party/rust/encoding_rs/src/iso_2022_jp.rs
+++ b/third_party/rust/encoding_rs/src/iso_2022_jp.rs
@@ -362,20 +362,17 @@ fn is_kanji_mapped(bmp: u16) -> bool {
     // Use the shift_jis variant, because we don't care about the
     // byte values here.
     jis0208_kanji_shift_jis_encode(bmp).is_some()
 }
 
 #[cfg(not(feature = "fast-kanji-encode"))]
 #[cfg_attr(
     feature = "cargo-clippy",
-    allow(
-        if_let_redundant_pattern_matching,
-        if_same_then_else
-    )
+    allow(if_let_redundant_pattern_matching, if_same_then_else)
 )]
 #[inline(always)]
 fn is_kanji_mapped(bmp: u16) -> bool {
     if 0x4EDD == bmp {
         true
     } else if let Some(_) = jis0208_level1_kanji_shift_jis_encode(bmp) {
         // Use the shift_jis variant, because we don't care about the
         // byte values here.
@@ -386,20 +383,17 @@ fn is_kanji_mapped(bmp: u16) -> bool {
         true
     } else {
         false
     }
 }
 
 #[cfg_attr(
     feature = "cargo-clippy",
-    allow(
-        if_let_redundant_pattern_matching,
-        if_same_then_else
-    )
+    allow(if_let_redundant_pattern_matching, if_same_then_else)
 )]
 fn is_mapped_for_two_byte_encode(bmp: u16) -> bool {
     // The code below uses else after return to
     // keep the same structure as in EUC-JP.
     // Lunde says 60% Hiragana, 30% Kanji, 10% Katakana
     let bmp_minus_hiragana = bmp.wrapping_sub(0x3041);
     if bmp_minus_hiragana < 0x53 {
         true
--- a/third_party/rust/encoding_rs/src/lib.rs
+++ b/third_party/rust/encoding_rs/src/lib.rs
@@ -4,39 +4,38 @@
 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
 // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
 #![cfg_attr(
     feature = "cargo-clippy",
-    allow(
-        doc_markdown,
-        inline_always,
-        new_ret_no_self
-    )
+    allow(doc_markdown, inline_always, new_ret_no_self)
 )]
-#![doc(html_root_url = "https://docs.rs/encoding_rs/0.8.13")]
+#![doc(html_root_url = "https://docs.rs/encoding_rs/0.8.14")]
 
 //! encoding_rs is a Gecko-oriented Free Software / Open Source implementation
 //! of the [Encoding Standard](https://encoding.spec.whatwg.org/) in Rust.
 //! Gecko-oriented means that converting to and from UTF-16 is supported in
 //! addition to converting to and from UTF-8, that the performance and
 //! streamability goals are browser-oriented, and that FFI-friendliness is a
 //! goal.
 //!
 //! Additionally, the `mem` module provides functions that are useful for
 //! applications that need to be able to deal with legacy in-memory
 //! representations of Unicode.
 //!
 //! For expectation setting, please be sure to read the sections
 //! [_UTF-16LE, UTF-16BE and Unicode Encoding Schemes_](#utf-16le-utf-16be-and-unicode-encoding-schemes),
 //! [_ISO-8859-1_](#iso-8859-1) and [_Web / Browser Focus_](#web--browser-focus) below.
 //!
+//! There is a [long-form write-up](https://hsivonen.fi/encoding_rs/) about the
+//! design and internals of the crate.
+//!
 //! # Availability
 //!
 //! The code is available under the
 //! [Apache license, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0)
 //! or the [MIT license](https://opensource.org/licenses/MIT), at your option.
 //! See the
 //! [`COPYRIGHT`](https://github.com/hsivonen/encoding_rs/blob/master/COPYRIGHT)
 //! file for details.
@@ -235,17 +234,19 @@
 //! performance, the decoder for ISO-2022-JP optimizes for ease/clarity
 //! of implementation.
 //!
 //! Despite the browser focus, the hope is that non-browser applications
 //! that wish to consume Web content or submit Web forms in a Web-compatible
 //! way will find encoding_rs useful. While encoding_rs does not try to match
 //! Windows behavior, many of the encodings are close enough to legacy
 //! encodings implemented by Windows that applications that need to consume
-//! data in legacy Windows encodins may find encoding_rs useful.
+//! data in legacy Windows encodins may find encoding_rs useful. The
+//! [codepage](https://crates.io/crates/codepage) crate maps from Windows
+//! code page identifiers onto encoding_rs `Encoding`s and vice versa.
 //!
 //! For decoding email, UTF-7 support is needed (unfortunately) in additition
 //! to the encodings defined in the Encoding Standard. The
 //! [charset](https://crates.io/crates/charset) wraps encoding_rs and adds
 //! UTF-7 decoding for email purposes.
 //!
 //! # Streaming & Non-Streaming; Rust & C/C++
 //!
@@ -659,20 +660,17 @@
 //! <tr><td>ISO-8859-9</td><td>windows-1254</td></tr>
 //! <tr><td>TIS-620</td><td>windows-874</td></tr>
 //! </tbody>
 //! </table>
 //!
 //! See the section [_UTF-16LE, UTF-16BE and Unicode Encoding Schemes_](#utf-16le-utf-16be-and-unicode-encoding-schemes)
 //! for discussion about the UTF-16 family.
 
-#![cfg_attr(
-    feature = "simd-accel",
-    feature(platform_intrinsics, core_intrinsics)
-)]
+#![cfg_attr(feature = "simd-accel", feature(platform_intrinsics, core_intrinsics))]
 
 #[macro_use]
 extern crate cfg_if;
 
 #[cfg(all(
     feature = "simd-accel",
     any(
         target_feature = "sse2",
@@ -3648,17 +3646,17 @@ impl Decoder {
     pub fn max_utf8_buffer_length(&self, byte_length: usize) -> Option<usize> {
         // Need to consider a) the decoder morphing due to the BOM and b) a partial
         // BOM getting pushed to the underlying decoder.
         match self.life_cycle {
             DecoderLifeCycle::Converting
             | DecoderLifeCycle::AtUtf8Start
             | DecoderLifeCycle::AtUtf16LeStart
             | DecoderLifeCycle::AtUtf16BeStart => {
-                return self.variant.max_utf8_buffer_length(byte_length)
+                return self.variant.max_utf8_buffer_length(byte_length);
             }
             DecoderLifeCycle::AtStart => {
                 if let Some(utf8_bom) = checked_add(3, byte_length.checked_mul(3)) {
                     if let Some(utf16_bom) = checked_add(
                         1,
                         checked_mul(3, checked_div(byte_length.checked_add(1), 2)),
                     ) {
                         let utf_bom = std::cmp::max(utf8_bom, utf16_bom);
@@ -3740,17 +3738,17 @@ impl Decoder {
         // BOM getting pushed to the underlying decoder.
         match self.life_cycle {
             DecoderLifeCycle::Converting
             | DecoderLifeCycle::AtUtf8Start
             | DecoderLifeCycle::AtUtf16LeStart
             | DecoderLifeCycle::AtUtf16BeStart => {
                 return self
                     .variant
-                    .max_utf8_buffer_length_without_replacement(byte_length)
+                    .max_utf8_buffer_length_without_replacement(byte_length);
             }
             DecoderLifeCycle::AtStart => {
                 if let Some(utf8_bom) = byte_length.checked_add(3) {
                     if let Some(utf16_bom) = checked_add(
                         1,
                         checked_mul(3, checked_div(byte_length.checked_add(1), 2)),
                     ) {
                         let utf_bom = std::cmp::max(utf8_bom, utf16_bom);
@@ -4056,17 +4054,17 @@ impl Decoder {
     pub fn max_utf16_buffer_length(&self, byte_length: usize) -> Option<usize> {
         // Need to consider a) the decoder morphing due to the BOM and b) a partial
         // BOM getting pushed to the underlying decoder.
         match self.life_cycle {
             DecoderLifeCycle::Converting
             | DecoderLifeCycle::AtUtf8Start
             | DecoderLifeCycle::AtUtf16LeStart
             | DecoderLifeCycle::AtUtf16BeStart => {
-                return self.variant.max_utf16_buffer_length(byte_length)
+                return self.variant.max_utf16_buffer_length(byte_length);
             }
             DecoderLifeCycle::AtStart => {
                 if let Some(utf8_bom) = byte_length.checked_add(1) {
                     if let Some(utf16_bom) =
                         checked_add(1, checked_div(byte_length.checked_add(1), 2))
                     {
                         let utf_bom = std::cmp::max(utf8_bom, utf16_bom);
                         let encoding = self.encoding();
@@ -5295,23 +5293,21 @@ mod tests {
                 Cow::Owned(_) => unreachable!(),
             },
             None => unreachable!(),
         }
     }
 
     #[test]
     fn test_decode_bomful_invalid_utf8_to_cow_without_bom_handling_and_without_replacement() {
-        assert!(
-            UTF_8
-                .decode_without_bom_handling_and_without_replacement(
-                    b"\xEF\xBB\xBF\xE2\x82\xAC\x80\xC3\xA4"
-                )
-                .is_none()
-        );
+        assert!(UTF_8
+            .decode_without_bom_handling_and_without_replacement(
+                b"\xEF\xBB\xBF\xE2\x82\xAC\x80\xC3\xA4"
+            )
+            .is_none());
     }
 
     #[test]
     fn test_decode_valid_windows_1257_to_cow_without_bom_handling_and_without_replacement() {
         match WINDOWS_1257.decode_without_bom_handling_and_without_replacement(b"abc\x80\xE4") {
             Some(cow) => match cow {
                 Cow::Borrowed(_) => unreachable!(),
                 Cow::Owned(s) => {
@@ -5319,21 +5315,19 @@ mod tests {
                 }
             },
             None => unreachable!(),
         }
     }
 
     #[test]
     fn test_decode_invalid_windows_1257_to_cow_without_bom_handling_and_without_replacement() {
-        assert!(
-            WINDOWS_1257
-                .decode_without_bom_handling_and_without_replacement(b"abc\x80\xA1\xE4")
-                .is_none()
-        );
+        assert!(WINDOWS_1257
+            .decode_without_bom_handling_and_without_replacement(b"abc\x80\xA1\xE4")
+            .is_none());
     }
 
     #[test]
     fn test_decode_ascii_only_windows_1257_to_cow_without_bom_handling_and_without_replacement() {
         match WINDOWS_1257.decode_without_bom_handling_and_without_replacement(b"abc") {
             Some(cow) => match cow {
                 Cow::Borrowed(s) => {
                     assert_eq!(s, "abc");
--- a/third_party/rust/encoding_rs/src/mem.rs
+++ b/third_party/rust/encoding_rs/src/mem.rs
@@ -24,30 +24,35 @@
 use std::borrow::Cow;
 
 use super::in_inclusive_range16;
 use super::in_inclusive_range32;
 use super::in_inclusive_range8;
 use super::in_range16;
 use super::in_range32;
 use super::DecoderResult;
-use super::EncoderResult;
 use ascii::*;
 use utf_8::*;
 
 macro_rules! non_fuzz_debug_assert {
     ($($arg:tt)*) => (if !cfg!(fuzzing) { debug_assert!($($arg)*); })
 }
 
-cfg_if!{
+cfg_if! {
     if #[cfg(feature = "simd-accel")] {
+        use ::std::intrinsics::likely;
         use ::std::intrinsics::unlikely;
     } else {
         #[inline(always)]
         // Unsafe to match the intrinsic, which is needlessly unsafe.
+        unsafe fn likely(b: bool) -> bool {
+            b
+        }
+        #[inline(always)]
+        // Unsafe to match the intrinsic, which is needlessly unsafe.
         unsafe fn unlikely(b: bool) -> bool {
             b
         }
     }
 }
 
 /// Classification of text as Latin1 (all code points are below U+0100),
 /// left-to-right with some non-Latin1 characters or as containing at least
@@ -215,17 +220,17 @@ macro_rules! by_unit_check_simd {
             for &unit in &buffer[offset..] {
                 accu |= unit as usize;
             }
             accu < $bound
         }
     };
 }
 
-cfg_if!{
+cfg_if! {
     if #[cfg(all(feature = "simd-accel", any(target_feature = "sse2", all(target_endian = "little", target_arch = "aarch64"), all(target_endian = "little", target_feature = "neon"))))] {
         use simd_funcs::*;
         use simd::u8x16;
         use simd::u16x8;
 
         const SIMD_ALIGNMENT: usize = 16;
 
         const SIMD_ALIGNMENT_MASK: usize = 15;
@@ -347,17 +352,17 @@ fn utf16_valid_up_to_alu(buffer: &[u16])
             }
             // Unpaired, fall through
         }
         // Unpaired surrogate
         return (offset, false);
     }
 }
 
-cfg_if!{
+cfg_if! {
     if #[cfg(all(feature = "simd-accel", any(target_feature = "sse2", all(target_endian = "little", target_arch = "aarch64"), all(target_endian = "little", target_feature = "neon"))))] {
         #[inline(always)]
         fn is_str_latin1_impl(buffer: &str) -> Option<usize> {
             let mut offset = 0usize;
             let bytes = buffer.as_bytes();
             let len = bytes.len();
             if len >= SIMD_STRIDE_SIZE {
                 let src = bytes.as_ptr();
@@ -436,17 +441,17 @@ fn is_utf8_latin1_impl(buffer: &[u8]) ->
                 return Some(total);
             }
         } else {
             return None;
         }
     }
 }
 
-cfg_if!{
+cfg_if! {
     if #[cfg(all(feature = "simd-accel", any(target_feature = "sse2", all(target_endian = "little", target_arch = "aarch64"), all(target_endian = "little", target_feature = "neon"))))] {
         #[inline(always)]
         fn is_utf16_bidi_impl(buffer: &[u16]) -> bool {
             let mut offset = 0usize;
             let len = buffer.len();
             if len >= SIMD_STRIDE_SIZE / 2 {
                 let src = buffer.as_ptr();
                 let mut until_alignment = ((SIMD_ALIGNMENT - ((src as usize) & SIMD_ALIGNMENT_MASK)) &
@@ -486,17 +491,17 @@ cfg_if!{
                     return true;
                 }
             }
             false
         }
     }
 }
 
-cfg_if!{
+cfg_if! {
     if #[cfg(all(feature = "simd-accel", any(target_feature = "sse2", all(target_endian = "little", target_arch = "aarch64"), all(target_endian = "little", target_feature = "neon"))))] {
         #[inline(always)]
         fn check_utf16_for_latin1_and_bidi_impl(buffer: &[u16]) -> Latin1Bidi {
             let mut offset = 0usize;
             let len = buffer.len();
             if len >= SIMD_STRIDE_SIZE / 2 {
                 let src = buffer.as_ptr();
                 let mut until_alignment = ((SIMD_ALIGNMENT - ((src as usize) & SIMD_ALIGNMENT_MASK)) &
@@ -682,20 +687,17 @@ pub fn is_utf16_latin1(buffer: &[u16]) -
 /// for. Control characters that are technically bidi controls but do not
 /// cause right-to-left behavior without the presence of right-to-left
 /// characters or right-to-left controls are not checked for. As a special
 /// case, U+FEFF is excluded from Arabic Presentation Forms-B.
 ///
 /// Returns `true` if the input is invalid UTF-8 or the input contains an
 /// RTL character. Returns `false` if the input is valid UTF-8 and contains
 /// no RTL characters.
-#[cfg_attr(
-    feature = "cargo-clippy",
-    allow(collapsible_if, cyclomatic_complexity)
-)]
+#[cfg_attr(feature = "cargo-clippy", allow(collapsible_if, cyclomatic_complexity))]
 #[inline]
 pub fn is_utf8_bidi(buffer: &[u8]) -> bool {
     // As of rustc 1.25.0-nightly (73ac5d6a8 2018-01-11), this is faster
     // than UTF-8 validation followed by `is_str_bidi()` for German,
     // Russian and Japanese. However, this is considerably slower for Thai.
     // Chances are that the compiler makes some branch predictions that are
     // unfortunate for Thai. Not spending the time to manually optimize
     // further at this time, since it's unclear if this variant even has
@@ -766,32 +768,36 @@ pub fn is_utf8_bidi(buffer: &[u8]) -> bo
                             }
                             read += 2;
                         }
                         // two-byte starting with 0xD7 and above is bidi
                         0xE1 | 0xE3...0xEC | 0xEE => {
                             // Three-byte normal
                             let second = unsafe { *(src.get_unchecked(read + 1)) };
                             let third = unsafe { *(src.get_unchecked(read + 2)) };
-                            if ((UTF8_DATA.table[usize::from(second)] & unsafe {
-                                *(UTF8_DATA.table.get_unchecked(byte as usize + 0x80))
-                            }) | (third >> 6))
+                            if ((UTF8_DATA.table[usize::from(second)]
+                                & unsafe {
+                                    *(UTF8_DATA.table.get_unchecked(byte as usize + 0x80))
+                                })
+                                | (third >> 6))
                                 != 2
                             {
                                 return true;
                             }
                             read += 3;
                         }
                         0xE2 => {
                             // Three-byte normal, potentially bidi
                             let second = unsafe { *(src.get_unchecked(read + 1)) };
                             let third = unsafe { *(src.get_unchecked(read + 2)) };
-                            if ((UTF8_DATA.table[usize::from(second)] & unsafe {
-                                *(UTF8_DATA.table.get_unchecked(byte as usize + 0x80))
-                            }) | (third >> 6))
+                            if ((UTF8_DATA.table[usize::from(second)]
+                                & unsafe {
+                                    *(UTF8_DATA.table.get_unchecked(byte as usize + 0x80))
+                                })
+                                | (third >> 6))
                                 != 2
                             {
                                 return true;
                             }
                             if second == 0x80 {
                                 if third == 0x8F || third == 0xAB || third == 0xAE {
                                     return true;
                                 }
@@ -801,19 +807,21 @@ pub fn is_utf8_bidi(buffer: &[u8]) -> bo
                                 }
                             }
                             read += 3;
                         }
                         0xEF => {
                             // Three-byte normal, potentially bidi
                             let second = unsafe { *(src.get_unchecked(read + 1)) };
                             let third = unsafe { *(src.get_unchecked(read + 2)) };
-                            if ((UTF8_DATA.table[usize::from(second)] & unsafe {
-                                *(UTF8_DATA.table.get_unchecked(byte as usize + 0x80))
-                            }) | (third >> 6))
+                            if ((UTF8_DATA.table[usize::from(second)]
+                                & unsafe {
+                                    *(UTF8_DATA.table.get_unchecked(byte as usize + 0x80))
+                                })
+                                | (third >> 6))
                                 != 2
                             {
                                 return true;
                             }
                             if in_inclusive_range8(second, 0xAC, 0xB7) {
                                 if second == 0xAC {
                                     if third > 0x9C {
                                         return true;
@@ -835,36 +843,40 @@ pub fn is_utf8_bidi(buffer: &[u8]) -> bo
                                 }
                             }
                             read += 3;
                         }
                         0xE0 => {
                             // Three-byte special lower bound, potentially bidi
                             let second = unsafe { *(src.get_unchecked(read + 1)) };
                             let third = unsafe { *(src.get_unchecked(read + 2)) };
-                            if ((UTF8_DATA.table[usize::from(second)] & unsafe {
-                                *(UTF8_DATA.table.get_unchecked(byte as usize + 0x80))
-                            }) | (third >> 6))
+                            if ((UTF8_DATA.table[usize::from(second)]
+                                & unsafe {
+                                    *(UTF8_DATA.table.get_unchecked(byte as usize + 0x80))
+                                })
+                                | (third >> 6))
                                 != 2
                             {
                                 return true;
                             }
                             // XXX can this be folded into the above validity check
                             if second < 0xA4 {
                                 return true;
                             }
                             read += 3;
                         }
                         0xED => {
                             // Three-byte special upper bound
                             let second = unsafe { *(src.get_unchecked(read + 1)) };
                             let third = unsafe { *(src.get_unchecked(read + 2)) };
-                            if ((UTF8_DATA.table[usize::from(second)] & unsafe {
-                                *(UTF8_DATA.table.get_unchecked(byte as usize + 0x80))
-                            }) | (third >> 6))
+                            if ((UTF8_DATA.table[usize::from(second)]
+                                & unsafe {
+                                    *(UTF8_DATA.table.get_unchecked(byte as usize + 0x80))
+                                })
+                                | (third >> 6))
                                 != 2
                             {
                                 return true;
                             }
                             read += 3;
                         }
                         0xF1...0xF4 => {
                             // Four-byte normal
@@ -1591,58 +1603,73 @@ pub fn convert_str_to_utf16(src: &str, d
 }
 
 /// Converts potentially-invalid UTF-16 to valid UTF-8 with errors replaced
 /// with the REPLACEMENT CHARACTER with potentially insufficient output
 /// space.
 ///
 /// Returns the number of code units read and the number of bytes written.
 ///
+/// Guarantees that the bytes in the destination beyond the number of
+/// bytes claimed as written by the second item of the return tuple
+/// are left unmodified.
+///
 /// Not all code units are read if there isn't enough output space.
 ///
 /// Note  that this method isn't designed for general streamability but for
 /// not allocating memory for the worst case up front. Specifically,
 /// if the input starts with or ends with an unpaired surrogate, those are
 /// replaced with the REPLACEMENT CHARACTER.
 ///
+/// Matches the semantics of `TextEncoder.encodeInto()` from the
+/// Encoding Standard.
+///
 /// # Safety
 ///
-/// Note that this function may write garbage beyond the number of bytes
-/// indicated by the return value, so using a `&mut str` interpreted as
-/// `&mut [u8]` as the destination is not safe. If you want to convert into
-/// a `&mut str`, use `convert_utf16_to_str()` instead of this function.
-#[inline]
+/// If you want to convert into a `&mut str`, use
+/// `convert_utf16_to_str_partial()` instead of using this function
+/// together with the `unsafe` method `as_bytes_mut()` on `&mut str`.
+#[inline(always)]
 pub fn convert_utf16_to_utf8_partial(src: &[u16], dst: &mut [u8]) -> (usize, usize) {
-    let mut encoder = Utf8Encoder;
-    let (result, read, written) = encoder.encode_from_utf16_raw(src, dst, true);
-    debug_assert!(result == EncoderResult::OutputFull || read == src.len());
-    (read, written)
+    // The two functions called below are marked `inline(never)` to make
+    // transitions from the hot part (first function) into the cold part
+    // (second function) go through a return and another call to discouge
+    // the CPU from speculating from the hot code into the cold code.
+    // Letting the transitions be mere intra-function jumps, even to
+    // basic blocks out-of-lined to the end of the function would wipe
+    // away a quarter of Arabic encode performance on Haswell!
+    let (read, written) = convert_utf16_to_utf16_partial_inner(src, dst);
+    if unsafe { likely(read == src.len()) } {
+        return (read, written);
+    }
+    let (tail_read, tail_written) =
+        convert_utf16_to_utf16_partial_tail(&src[read..], &mut dst[written..]);
+    (read + tail_read, written + tail_written)
 }
 
 /// Converts potentially-invalid UTF-16 to valid UTF-8 with errors replaced
 /// with the REPLACEMENT CHARACTER.
 ///
 /// The length of the destination buffer must be at least the length of the
-/// source buffer times three _plus one_.
+/// source buffer times three.
 ///
 /// Returns the number of bytes written.
 ///
 /// # Panics
 ///
 /// Panics if the destination buffer is shorter than stated above.
 ///
 /// # Safety
 ///
-/// Note that this function may write garbage beyond the number of bytes
-/// indicated by the return value, so using a `&mut str` interpreted as
-/// `&mut [u8]` as the destination is not safe. If you want to convert into
-/// a `&mut str`, use `convert_utf16_to_str()` instead of this function.
-#[inline]
+/// If you want to convert into a `&mut str`, use `convert_utf16_to_str()`
+/// instead of using this function together with the `unsafe` method
+/// `as_bytes_mut()` on `&mut str`.
+#[inline(always)]
 pub fn convert_utf16_to_utf8(src: &[u16], dst: &mut [u8]) -> usize {
-    assert!(dst.len() > src.len() * 3);
+    assert!(dst.len() >= src.len() * 3);
     let (read, written) = convert_utf16_to_utf8_partial(src, dst);
     debug_assert_eq!(read, src.len());
     written
 }
 
 /// Converts potentially-invalid UTF-16 to valid UTF-8 with errors replaced
 /// with the REPLACEMENT CHARACTER such that the validity of the output is
 /// signaled using the Rust type system with potentially insufficient output
@@ -1657,43 +1684,38 @@ pub fn convert_utf16_to_utf8(src: &[u16]
 /// if the input starts with or ends with an unpaired surrogate, those are
 /// replaced with the REPLACEMENT CHARACTER.
 #[inline]
 pub fn convert_utf16_to_str_partial(src: &[u16], dst: &mut str) -> (usize, usize) {
     let bytes: &mut [u8] = unsafe { dst.as_bytes_mut() };
     let (read, written) = convert_utf16_to_utf8_partial(src, bytes);
     let len = bytes.len();
     let mut trail = written;
-    let max = ::std::cmp::min(len, trail + MAX_STRIDE_SIZE);
-    while trail < max {
-        bytes[trail] = 0;
-        trail += 1;
-    }
     while trail < len && ((bytes[trail] & 0xC0) == 0x80) {
         bytes[trail] = 0;
         trail += 1;
     }
     (read, written)
 }
 
 /// Converts potentially-invalid UTF-16 to valid UTF-8 with errors replaced
 /// with the REPLACEMENT CHARACTER such that the validity of the output is
 /// signaled using the Rust type system.
 ///
 /// The length of the destination buffer must be at least the length of the
-/// source buffer times three _plus one_.
+/// source buffer times three.
 ///
 /// Returns the number of bytes written.
 ///
 /// # Panics
 ///
 /// Panics if the destination buffer is shorter than stated above.
-#[inline]
+#[inline(always)]
 pub fn convert_utf16_to_str(src: &[u16], dst: &mut str) -> usize {
-    assert!(dst.len() > src.len() * 3);
+    assert!(dst.len() >= src.len() * 3);
     let (read, written) = convert_utf16_to_str_partial(src, dst);
     debug_assert_eq!(read, src.len());
     written
 }
 
 /// Converts bytes whose unsigned value is interpreted as Unicode code point
 /// (i.e. U+0000 to U+00FF, inclusive) to UTF-16.
 ///
--- a/third_party/rust/encoding_rs/src/utf_8.rs
+++ b/third_party/rust/encoding_rs/src/utf_8.rs
@@ -7,19 +7,20 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
 use super::*;
 use ascii::ascii_to_basic_latin;
 use ascii::basic_latin_to_ascii;
 use ascii::validate_ascii;
 use handles::*;
+use mem::convert_utf16_to_utf8_partial;
 use variant::*;
 
-cfg_if!{
+cfg_if! {
     if #[cfg(feature = "simd-accel")] {
         use ::std::intrinsics::unlikely;
         use ::std::intrinsics::likely;
     } else {
         #[inline(always)]
         // Unsafe to match the intrinsic, which is needlessly unsafe.
         unsafe fn unlikely(b: bool) -> bool {
             b
@@ -228,20 +229,17 @@ pub fn utf8_valid_up_to(src: &[u8]) -> u
                 break 'outer;
             }
             break 'outer;
         }
     }
     read
 }
 
-#[cfg_attr(
-    feature = "cargo-clippy",
-    allow(never_loop, cyclomatic_complexity)
-)]
+#[cfg_attr(feature = "cargo-clippy", allow(never_loop, cyclomatic_complexity))]
 pub fn convert_utf8_to_utf16_up_to_invalid(src: &[u8], dst: &mut [u16]) -> (usize, usize) {
     // This algorithm differs from the UTF-8 validation algorithm, but making
     // this one consistent with that one makes this slower for reasons I don't
     // understand.
     let mut read = 0;
     let mut written = 0;
     'outer: loop {
         let mut byte = {
@@ -607,181 +605,270 @@ impl Utf8Decoder {
         source,
         b,
         destination_handle,
         unread_handle,
         check_space_astral
     );
 }
 
+#[cfg_attr(feature = "cargo-clippy", allow(never_loop))]
+#[inline(never)]
+pub fn convert_utf16_to_utf16_partial_inner(src: &[u16], dst: &mut [u8]) -> (usize, usize) {
+    let mut read = 0;
+    let mut written = 0;
+    'outer: loop {
+        let mut unit = {
+            let src_remaining = &src[read..];
+            let dst_remaining = &mut dst[written..];
+            let length = if dst_remaining.len() < src_remaining.len() {
+                dst_remaining.len()
+            } else {
+                src_remaining.len()
+            };
+            match unsafe {
+                basic_latin_to_ascii(src_remaining.as_ptr(), dst_remaining.as_mut_ptr(), length)
+            } {
+                None => {
+                    read += length;
+                    written += length;
+                    return (read, written);
+                }
+                Some((non_ascii, consumed)) => {
+                    read += consumed;
+                    written += consumed;
+                    non_ascii
+                }
+            }
+        };
+        'inner: loop {
+            // The following loop is only broken out of as a goto forward.
+            loop {
+                // Unfortunately, this check isn't enough for the compiler to elide
+                // the bound checks on writes to dst, which is why they are manually
+                // elided, which makes a measurable difference.
+                if written.checked_add(4).unwrap() > dst.len() {
+                    return (read, written);
+                }
+                read += 1;
+                if unit < 0x800 {
+                    unsafe {
+                        *(dst.get_unchecked_mut(written)) = (unit >> 6) as u8 | 0xC0u8;
+                        written += 1;
+                        *(dst.get_unchecked_mut(written)) = (unit & 0x3F) as u8 | 0x80u8;
+                        written += 1;
+                    }
+                    break;
+                }
+                let unit_minus_surrogate_start = unit.wrapping_sub(0xD800);
+                if unsafe { likely(unit_minus_surrogate_start > (0xDFFF - 0xD800)) } {
+                    unsafe {
+                        *(dst.get_unchecked_mut(written)) = (unit >> 12) as u8 | 0xE0u8;
+                        written += 1;
+                        *(dst.get_unchecked_mut(written)) = ((unit & 0xFC0) >> 6) as u8 | 0x80u8;
+                        written += 1;
+                        *(dst.get_unchecked_mut(written)) = (unit & 0x3F) as u8 | 0x80u8;
+                        written += 1;
+                    }
+                    break;
+                }
+                if unsafe { likely(unit_minus_surrogate_start <= (0xDBFF - 0xD800)) } {
+                    // high surrogate
+                    // read > src.len() is impossible, but using
+                    // >= instead of == allows the compiler to elide a bound check.
+                    if read >= src.len() {
+                        debug_assert_eq!(read, src.len());
+                        // Unpaired surrogate at the end of the buffer.
+                        unsafe {
+                            *(dst.get_unchecked_mut(written)) = 0xEFu8;
+                            written += 1;
+                            *(dst.get_unchecked_mut(written)) = 0xBFu8;
+                            written += 1;
+                            *(dst.get_unchecked_mut(written)) = 0xBDu8;
+                            written += 1;
+                        }
+                        return (read, written);
+                    }
+                    let second = src[read];
+                    let second_minus_low_surrogate_start = second.wrapping_sub(0xDC00);
+                    if unsafe { likely(second_minus_low_surrogate_start <= (0xDFFF - 0xDC00)) } {
+                        // The next code unit is a low surrogate. Advance position.
+                        read += 1;
+                        let astral = (u32::from(unit) << 10) + u32::from(second)
+                            - (((0xD800u32 << 10) - 0x10000u32) + 0xDC00u32);
+                        unsafe {
+                            *(dst.get_unchecked_mut(written)) = (astral >> 18) as u8 | 0xF0u8;
+                            written += 1;
+                            *(dst.get_unchecked_mut(written)) =
+                                ((astral & 0x3F000u32) >> 12) as u8 | 0x80u8;
+                            written += 1;
+                            *(dst.get_unchecked_mut(written)) =
+                                ((astral & 0xFC0u32) >> 6) as u8 | 0x80u8;
+                            written += 1;
+                            *(dst.get_unchecked_mut(written)) = (astral & 0x3F) as u8 | 0x80u8;
+                            written += 1;
+                        }
+                        break;
+                    }
+                    // The next code unit is not a low surrogate. Don't advance
+                    // position and treat the high surrogate as unpaired.
+                    // Fall through
+                }
+                // Unpaired low surrogate
+                unsafe {
+                    *(dst.get_unchecked_mut(written)) = 0xEFu8;
+                    written += 1;
+                    *(dst.get_unchecked_mut(written)) = 0xBFu8;
+                    written += 1;
+                    *(dst.get_unchecked_mut(written)) = 0xBDu8;
+                    written += 1;
+                }
+                break;
+            }
+            // Now see if the next unit is Basic Latin
+            // read > src.len() is impossible, but using
+            // >= instead of == allows the compiler to elide a bound check.
+            if read >= src.len() {
+                debug_assert_eq!(read, src.len());
+                return (read, written);
+            }
+            unit = src[read];
+            if unsafe { unlikely(unit < 0x80) } {
+                // written > dst.len() is impossible, but using
+                // >= instead of == allows the compiler to elide a bound check.
+                if written >= dst.len() {
+                    debug_assert_eq!(written, dst.len());
+                    return (read, written);
+                }
+                dst[written] = unit as u8;
+                read += 1;
+                written += 1;
+                // Mysteriously, adding a punctuation check here makes
+                // the expected benificiary cases *slower*!
+                continue 'outer;
+            }
+            continue 'inner;
+        }
+    }
+}
+
+#[inline(never)]
+pub fn convert_utf16_to_utf16_partial_tail(src: &[u16], dst: &mut [u8]) -> (usize, usize) {
+    // Everything below is cold code!
+    let mut read = 0;
+    let mut written = 0;
+    let mut unit = src[read];
+    // We now have up to 3 output slots, so an astral character
+    // will not fit.
+    if unit < 0x800 {
+        loop {
+            if unit < 0x80 {
+                if written >= dst.len() {
+                    return (read, written);
+                }
+                read += 1;
+                dst[written] = unit as u8;
+                written += 1;
+            } else if unit < 0x800 {
+                if written + 2 > dst.len() {
+                    return (read, written);
+                }
+                read += 1;
+                dst[written] = (unit >> 6) as u8 | 0xC0u8;
+                written += 1;
+                dst[written] = (unit & 0x3F) as u8 | 0x80u8;
+                written += 1;
+            } else {
+                return (read, written);
+            }
+            // read > src.len() is impossible, but using
+            // >= instead of == allows the compiler to elide a bound check.
+            if read >= src.len() {
+                debug_assert_eq!(read, src.len());
+                return (read, written);
+            }
+            unit = src[read];
+        }
+    }
+    // Could be an unpaired surrogate, but we'll need 3 output
+    // slots in any case.
+    if written + 3 > dst.len() {
+        return (read, written);
+    }
+    read += 1;
+    let unit_minus_surrogate_start = unit.wrapping_sub(0xD800);
+    if unit_minus_surrogate_start <= (0xDFFF - 0xD800) {
+        // Got surrogate
+        if unit_minus_surrogate_start <= (0xDBFF - 0xD800) {
+            // Got high surrogate
+            if read >= src.len() {
+                // Unpaired high surrogate
+                unit = 0xFFFD;
+            } else {
+                let second = src[read];
+                if in_inclusive_range16(second, 0xDC00, 0xDFFF) {
+                    // Valid surrogate pair, but we know it won't fit.
+                    read -= 1;
+                    return (read, written);
+                }
+                // Unpaired high
+                unit = 0xFFFD;
+            }
+        } else {
+            // Unpaired low
+            unit = 0xFFFD;
+        }
+    }
+    dst[written] = (unit >> 12) as u8 | 0xE0u8;
+    written += 1;
+    dst[written] = ((unit & 0xFC0) >> 6) as u8 | 0x80u8;
+    written += 1;
+    dst[written] = (unit & 0x3F) as u8 | 0x80u8;
+    written += 1;
+    debug_assert_eq!(written, dst.len());
+    (read, written)
+}
+
 pub struct Utf8Encoder;
 
 impl Utf8Encoder {
     pub fn new(encoding: &'static Encoding) -> Encoder {
         Encoder::new(encoding, VariantEncoder::Utf8(Utf8Encoder))
     }
 
     pub fn max_buffer_length_from_utf16_without_replacement(
         &self,
         u16_length: usize,
     ) -> Option<usize> {
-        checked_add(1, u16_length.checked_mul(3))
+        u16_length.checked_mul(3)
     }
 
     pub fn max_buffer_length_from_utf8_without_replacement(
         &self,
         byte_length: usize,
     ) -> Option<usize> {
         Some(byte_length)
     }
 
-    #[cfg_attr(feature = "cargo-clippy", allow(never_loop))]
     pub fn encode_from_utf16_raw(
         &mut self,
         src: &[u16],
         dst: &mut [u8],
         _last: bool,
     ) -> (EncoderResult, usize, usize) {
-        let mut read = 0;
-        let mut written = 0;
-        'outer: loop {
-            let mut unit = {
-                let src_remaining = &src[read..];
-                let dst_remaining = &mut dst[written..];
-                let (pending, length) = if dst_remaining.len() < src_remaining.len() {
-                    (EncoderResult::OutputFull, dst_remaining.len())
-                } else {
-                    (EncoderResult::InputEmpty, src_remaining.len())
-                };
-                match unsafe {
-                    basic_latin_to_ascii(src_remaining.as_ptr(), dst_remaining.as_mut_ptr(), length)
-                } {
-                    None => {
-                        read += length;
-                        written += length;
-                        return (pending, read, written);
-                    }
-                    Some((non_ascii, consumed)) => {
-                        read += consumed;
-                        written += consumed;
-                        non_ascii
-                    }
-                }
-            };
-            'inner: loop {
-                // The following loop is only broken out of as a goto forward.
-                loop {
-                    // Unfortunately, this check isn't enough for the compiler to elide
-                    // the bound checks on writes to dst, which is why they are manually
-                    // elided, which makes a measurable difference.
-                    if written.checked_add(4).unwrap() > dst.len() {
-                        return (EncoderResult::OutputFull, read, written);
-                    }
-                    read += 1;
-                    if unit < 0x800 {
-                        unsafe {
-                            *(dst.get_unchecked_mut(written)) = (unit >> 6) as u8 | 0xC0u8;
-                            written += 1;
-                            *(dst.get_unchecked_mut(written)) = (unit & 0x3F) as u8 | 0x80u8;
-                            written += 1;
-                        }
-                        break;
-                    }
-                    let unit_minus_surrogate_start = unit.wrapping_sub(0xD800);
-                    if unsafe { likely(unit_minus_surrogate_start > (0xDFFF - 0xD800)) } {
-                        unsafe {
-                            *(dst.get_unchecked_mut(written)) = (unit >> 12) as u8 | 0xE0u8;
-                            written += 1;
-                            *(dst.get_unchecked_mut(written)) =
-                                ((unit & 0xFC0) >> 6) as u8 | 0x80u8;
-                            written += 1;
-                            *(dst.get_unchecked_mut(written)) = (unit & 0x3F) as u8 | 0x80u8;
-                            written += 1;
-                        }
-                        break;
-                    }
-                    if unsafe { likely(unit_minus_surrogate_start <= (0xDBFF - 0xD800)) } {
-                        // high surrogate
-                        // read > src.len() is impossible, but using
-                        // >= instead of == allows the compiler to elide a bound check.
-                        if read >= src.len() {
-                            debug_assert_eq!(read, src.len());
-                            // Unpaired surrogate at the end of the buffer.
-                            unsafe {
-                                *(dst.get_unchecked_mut(written)) = 0xEFu8;
-                                written += 1;
-                                *(dst.get_unchecked_mut(written)) = 0xBFu8;
-                                written += 1;
-                                *(dst.get_unchecked_mut(written)) = 0xBDu8;
-                                written += 1;
-                            }
-                            return (EncoderResult::InputEmpty, read, written);
-                        }
-                        let second = src[read];
-                        let second_minus_low_surrogate_start = second.wrapping_sub(0xDC00);
-                        if unsafe { likely(second_minus_low_surrogate_start <= (0xDFFF - 0xDC00)) }
-                        {
-                            // The next code unit is a low surrogate. Advance position.
-                            read += 1;
-                            let astral = (u32::from(unit) << 10) + u32::from(second)
-                                - (((0xD800u32 << 10) - 0x10000u32) + 0xDC00u32);
-                            unsafe {
-                                *(dst.get_unchecked_mut(written)) = (astral >> 18) as u8 | 0xF0u8;
-                                written += 1;
-                                *(dst.get_unchecked_mut(written)) =
-                                    ((astral & 0x3F000u32) >> 12) as u8 | 0x80u8;
-                                written += 1;
-                                *(dst.get_unchecked_mut(written)) =
-                                    ((astral & 0xFC0u32) >> 6) as u8 | 0x80u8;
-                                written += 1;
-                                *(dst.get_unchecked_mut(written)) = (astral & 0x3F) as u8 | 0x80u8;
-                                written += 1;
-                            }
-                            break;
-                        }
-                        // The next code unit is not a low surrogate. Don't advance
-                        // position and treat the high surrogate as unpaired.
-                        // Fall through
-                    }
-                    // Unpaired low surrogate
-                    unsafe {
-                        *(dst.get_unchecked_mut(written)) = 0xEFu8;
-                        written += 1;
-                        *(dst.get_unchecked_mut(written)) = 0xBFu8;
-                        written += 1;
-                        *(dst.get_unchecked_mut(written)) = 0xBDu8;
-                        written += 1;
-                    }
-                    break;
-                }
-                // Now see if the next unit is Basic Latin
-                // read > src.len() is impossible, but using
-                // >= instead of == allows the compiler to elide a bound check.
-                if read >= src.len() {
-                    debug_assert_eq!(read, src.len());
-                    return (EncoderResult::InputEmpty, read, written);
-                }
-                unit = src[read];
-                if unsafe { unlikely(unit < 0x80) } {
-                    // written > dst.len() is impossible, but using
-                    // >= instead of == allows the compiler to elide a bound check.
-                    if written >= dst.len() {
-                        debug_assert_eq!(written, dst.len());
-                        return (EncoderResult::OutputFull, read, written);
-                    }
-                    dst[written] = unit as u8;
-                    read += 1;
-                    written += 1;
-                    // Mysteriously, adding a punctuation check here makes
-                    // the expected benificiary cases *slower*!
-                    continue 'outer;
-                }
-                continue 'inner;
-            }
-        }
+        let (read, written) = convert_utf16_to_utf8_partial(src, dst);
+        (
+            if read == src.len() {
+                EncoderResult::InputEmpty
+            } else {
+                EncoderResult::OutputFull
+            },
+            read,
+            written,
+        )
     }
 
     pub fn encode_from_utf8_raw(
         &mut self,
         src: &str,
         dst: &mut [u8],
         _last: bool,
     ) -> (EncoderResult, usize, usize) {
@@ -824,16 +911,49 @@ mod tests {
     fn encode_utf8_from_utf16(string: &[u16], expect: &[u8]) {
         encode_from_utf16(UTF_8, string, expect);
     }
 
     fn encode_utf8_from_utf8(string: &str, expect: &[u8]) {
         encode_from_utf8(UTF_8, string, expect);
     }
 
+    fn encode_utf8_from_utf16_with_output_limit(
+        string: &[u16],
+        expect: &str,
+        limit: usize,
+        expect_result: EncoderResult,
+    ) {
+        let mut dst = Vec::new();
+        {
+            dst.resize(limit, 0u8);
+            let mut encoder = UTF_8.new_encoder();
+            let (result, read, written) =
+                encoder.encode_from_utf16_without_replacement(string, &mut dst, false);
+            assert_eq!(result, expect_result);
+            if expect_result == EncoderResult::InputEmpty {
+                assert_eq!(read, string.len());
+            }
+            assert_eq!(&dst[..written], expect.as_bytes());
+        }
+        {
+            dst.resize(64, 0u8);
+            for (i, elem) in dst.iter_mut().enumerate() {
+                *elem = i as u8;
+            }
+            let mut encoder = UTF_8.new_encoder();
+            let (_, _, mut j) =
+                encoder.encode_from_utf16_without_replacement(string, &mut dst, false);
+            while j < dst.len() {
+                assert_eq!(usize::from(dst[j]), j);
+                j += 1;
+            }
+        }
+    }
+
     #[test]
     fn test_utf8_decode() {
         // Empty
         decode_valid_utf8("");
         // ASCII
         decode_valid_utf8("ab");
         // Low BMP
         decode_valid_utf8("a\u{E4}Z");
@@ -1009,16 +1129,414 @@ mod tests {
         encode_utf8_from_utf16(&[0xE000], "\u{E000}".as_bytes());
         encode_utf8_from_utf16(&[0xFFFF], "\u{FFFF}".as_bytes());
         encode_utf8_from_utf16(&[0xD800, 0xDC00], "\u{10000}".as_bytes());
         encode_utf8_from_utf16(&[0xDBFF, 0xDFFF], "\u{10FFFF}".as_bytes());
         encode_utf8_from_utf16(&[0xDC00, 0xDEDE], "\u{FFFD}\u{FFFD}".as_bytes());
     }
 
     #[test]
+    fn test_encode_utf8_from_utf16_with_output_limit() {
+        encode_utf8_from_utf16_with_output_limit(&[0x0062], "\u{62}", 1, EncoderResult::InputEmpty);
+        encode_utf8_from_utf16_with_output_limit(&[0x00A7], "\u{A7}", 2, EncoderResult::InputEmpty);
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x2603],
+            "\u{2603}",
+            3,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0xD83D, 0xDCA9],
+            "\u{1F4A9}",
+            4,
+            EncoderResult::InputEmpty,
+        );
+
+        encode_utf8_from_utf16_with_output_limit(&[0x00A7], "", 1, EncoderResult::OutputFull);
+        encode_utf8_from_utf16_with_output_limit(&[0x2603], "", 2, EncoderResult::OutputFull);
+        encode_utf8_from_utf16_with_output_limit(
+            &[0xD83D, 0xDCA9],
+            "",
+            3,
+            EncoderResult::OutputFull,
+        );
+
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x0063, 0x0062],
+            "\u{63}\u{62}",
+            2,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x0063, 0x00A7],
+            "\u{63}\u{A7}",
+            3,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x0063, 0x2603],
+            "\u{63}\u{2603}",
+            4,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x0063, 0xD83D, 0xDCA9],
+            "\u{63}\u{1F4A9}",
+            5,
+            EncoderResult::InputEmpty,
+        );
+
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x0063, 0x00A7],
+            "\u{63}",
+            2,
+            EncoderResult::OutputFull,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x0063, 0x2603],
+            "\u{63}",
+            3,
+            EncoderResult::OutputFull,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x0063, 0xD83D, 0xDCA9],
+            "\u{63}",
+            4,
+            EncoderResult::OutputFull,
+        );
+
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x00B6, 0x0062],
+            "\u{B6}\u{62}",
+            3,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x00B6, 0x00A7],
+            "\u{B6}\u{A7}",
+            4,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x00B6, 0x2603],
+            "\u{B6}\u{2603}",
+            5,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x00B6, 0xD83D, 0xDCA9],
+            "\u{B6}\u{1F4A9}",
+            6,
+            EncoderResult::InputEmpty,
+        );
+
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x00B6, 0x00A7],
+            "\u{B6}",
+            3,
+            EncoderResult::OutputFull,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x00B6, 0x2603],
+            "\u{B6}",
+            4,
+            EncoderResult::OutputFull,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x00B6, 0xD83D, 0xDCA9],
+            "\u{B6}",
+            5,
+            EncoderResult::OutputFull,
+        );
+
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x263A, 0x0062],
+            "\u{263A}\u{62}",
+            4,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x263A, 0x00A7],
+            "\u{263A}\u{A7}",
+            5,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x263A, 0x2603],
+            "\u{263A}\u{2603}",
+            6,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x263A, 0xD83D, 0xDCA9],
+            "\u{263A}\u{1F4A9}",
+            7,
+            EncoderResult::InputEmpty,
+        );
+
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x263A, 0x00A7],
+            "\u{263A}",
+            4,
+            EncoderResult::OutputFull,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x263A, 0x2603],
+            "\u{263A}",
+            5,
+            EncoderResult::OutputFull,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x263A, 0xD83D, 0xDCA9],
+            "\u{263A}",
+            6,
+            EncoderResult::OutputFull,
+        );
+
+        encode_utf8_from_utf16_with_output_limit(
+            &[0xD83D, 0xDE0E, 0x0062],
+            "\u{1F60E}\u{62}",
+            5,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0xD83D, 0xDE0E, 0x00A7],
+            "\u{1F60E}\u{A7}",
+            6,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0xD83D, 0xDE0E, 0x2603],
+            "\u{1F60E}\u{2603}",
+            7,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0xD83D, 0xDE0E, 0xD83D, 0xDCA9],
+            "\u{1F60E}\u{1F4A9}",
+            8,
+            EncoderResult::InputEmpty,
+        );
+
+        encode_utf8_from_utf16_with_output_limit(
+            &[0xD83D, 0xDE0E, 0x00A7],
+            "\u{1F60E}",
+            5,
+            EncoderResult::OutputFull,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0xD83D, 0xDE0E, 0x2603],
+            "\u{1F60E}",
+            6,
+            EncoderResult::OutputFull,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0xD83D, 0xDE0E, 0xD83D, 0xDCA9],
+            "\u{1F60E}",
+            7,
+            EncoderResult::OutputFull,
+        );
+
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x0063, 0x00B6, 0x0062, 0x0062],
+            "\u{63}\u{B6}\u{62}\u{62}",
+            5,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x0063, 0x00B6, 0x0062, 0x0062],
+            "\u{63}\u{B6}\u{62}",
+            4,
+            EncoderResult::OutputFull,
+        );
+
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x0063, 0x00B6, 0x0062, 0x0062, 0x0062],
+            "\u{63}\u{B6}\u{62}\u{62}\u{62}",
+            6,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x0063, 0x00B6, 0x0062, 0x0062, 0x0062],
+            "\u{63}\u{B6}\u{62}\u{62}",
+            5,
+            EncoderResult::OutputFull,
+        );
+
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x263A, 0x0062, 0x0062],
+            "\u{263A}\u{62}\u{62}",
+            5,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x263A, 0x0062, 0x0062],
+            "\u{263A}\u{62}",
+            4,
+            EncoderResult::OutputFull,
+        );
+
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x263A, 0x0062, 0x0062, 0x0062],
+            "\u{263A}\u{62}\u{62}\u{62}",
+            6,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x263A, 0x0062, 0x0062, 0x0062],
+            "\u{263A}\u{62}\u{62}",
+            5,
+            EncoderResult::OutputFull,
+        );
+
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x0063, 0x00B6, 0x00A7],
+            "\u{63}\u{B6}\u{A7}",
+            5,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x0063, 0x00B6, 0x00A7],
+            "\u{63}\u{B6}",
+            4,
+            EncoderResult::OutputFull,
+        );
+
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x0063, 0x00B6, 0x00A7, 0x0062],
+            "\u{63}\u{B6}\u{A7}\u{62}",
+            6,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x0063, 0x00B6, 0x00A7, 0x0062],
+            "\u{63}\u{B6}\u{A7}",
+            5,
+            EncoderResult::OutputFull,
+        );
+
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x263A, 0x00A7, 0x0062],
+            "\u{263A}\u{A7}\u{62}",
+            6,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x263A, 0x00A7, 0x0062],
+            "\u{263A}\u{A7}",
+            5,
+            EncoderResult::OutputFull,
+        );
+
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x0063, 0x00B6, 0x0062, 0x00A7],
+            "\u{63}\u{B6}\u{62}\u{A7}",
+            6,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x0063, 0x00B6, 0x0062, 0x00A7],
+            "\u{63}\u{B6}\u{62}",
+            5,
+            EncoderResult::OutputFull,
+        );
+
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x263A, 0x0062, 0x00A7],
+            "\u{263A}\u{62}\u{A7}",
+            6,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x263A, 0x0062, 0x00A7],
+            "\u{263A}\u{62}",
+            5,
+            EncoderResult::OutputFull,
+        );
+
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x0063, 0x00B6, 0x2603],
+            "\u{63}\u{B6}\u{2603}",
+            6,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x0063, 0x00B6, 0x2603],
+            "\u{63}\u{B6}",
+            5,
+            EncoderResult::OutputFull,
+        );
+
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x263A, 0x2603],
+            "\u{263A}\u{2603}",
+            6,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x263A, 0x2603],
+            "\u{263A}",
+            5,
+            EncoderResult::OutputFull,
+        );
+
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x0063, 0x00B6, 0xD83D],
+            "\u{63}\u{B6}\u{FFFD}",
+            6,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x0063, 0x00B6, 0xD83D],
+            "\u{63}\u{B6}",
+            5,
+            EncoderResult::OutputFull,
+        );
+
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x263A, 0xD83D],
+            "\u{263A}\u{FFFD}",
+            6,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x263A, 0xD83D],
+            "\u{263A}",
+            5,
+            EncoderResult::OutputFull,
+        );
+
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x0063, 0x00B6, 0xDCA9],
+            "\u{63}\u{B6}\u{FFFD}",
+            6,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x0063, 0x00B6, 0xDCA9],
+            "\u{63}\u{B6}",
+            5,
+            EncoderResult::OutputFull,
+        );
+
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x263A, 0xDCA9],
+            "\u{263A}\u{FFFD}",
+            6,
+            EncoderResult::InputEmpty,
+        );
+        encode_utf8_from_utf16_with_output_limit(
+            &[0x263A, 0xDCA9],
+            "\u{263A}",
+            5,
+            EncoderResult::OutputFull,
+        );
+    }
+
+    #[test]
     fn test_utf8_max_length_from_utf16() {
         let mut encoder = UTF_8.new_encoder();
         let mut output = [0u8; 13];
         let input = &[0x2C9Fu16, 0x2CA9u16, 0x2CA3u16, 0x2C9Fu16];
         let needed = encoder
             .max_buffer_length_from_utf16_without_replacement(input.len())
             .unwrap();
         let (result, _, _) =
@@ -1109,12 +1627,11 @@ mod tests {
             let (result, read, written, had_errors) =
                 decoder.decode_to_utf16("\u{E4}a".as_bytes(), &mut output[..], false);
             assert_eq!(result, CoderResult::OutputFull);
             assert_eq!(read, 2);
             assert_eq!(written, 1);
             assert!(!had_errors);
             assert_eq!(output[0], 0x00E4);
         }
-
     }
 
 }
--- a/third_party/rust/encoding_rs/src/x_user_defined.rs
+++ b/third_party/rust/encoding_rs/src/x_user_defined.rs
@@ -6,17 +6,17 @@
 // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
 use super::*;
 use handles::*;
 use variant::*;
 
-cfg_if!{
+cfg_if! {
     if #[cfg(feature = "simd-accel")] {
         use simd_funcs::*;
         use simd::u16x8;
 
         #[inline(always)]
         fn shift_upper(unpacked: u16x8) -> u16x8 {
             let highest_ascii = u16x8::splat(0x7F);
             let offset = u16x8::splat(0xF700);
--- a/xpcom/rust/nsstring/src/conversions.rs
+++ b/xpcom/rust/nsstring/src/conversions.rs
@@ -14,18 +14,18 @@ use super::Gecko_FallibleAssignCString;
 use super::Latin1StringLike;
 
 use conversions::encoding_rs::mem::*;
 use conversions::encoding_rs::Encoding;
 
 /// Required math stated in the docs of
 /// `convert_utf16_to_utf8()`.
 #[inline(always)]
-fn times_three_plus_one(a: usize) -> Option<usize> {
-    a.checked_mul(3)?.checked_add(1)
+fn times_three(a: usize) -> Option<usize> {
+    a.checked_mul(3)
 }
 
 #[inline(always)]
 fn identity(a: usize) -> Option<usize> {
     Some(a)
 }
 
 #[inline(always)]
@@ -316,17 +316,17 @@ impl nsACString {
         other: &[u16],
         old_len: usize,
     ) -> Result<BulkWriteOk, ()> {
         // We first size the buffer for ASCII if the first two cache lines are ASCII. If that turns out
         // not to be enough, we size for the worst case given the length of the remaining input at that
         // point. BUT if the worst case fits inside the inline capacity of an autostring, we skip
         // the ASCII stuff.
         let worst_case_needed = if let Some(inline_capacity) = self.inline_capacity() {
-            let worst_case = times_three_plus_one(other.len()).ok_or(())?;
+            let worst_case = times_three(other.len()).ok_or(())?;
             if worst_case <= inline_capacity {
                 Some(worst_case)
             } else {
                 None
             }
         } else {
             None
         };
@@ -335,28 +335,28 @@ impl nsACString {
             let new_len_with_ascii = old_len.checked_add(other.len()).ok_or(())?;
             let mut handle = unsafe { self.bulk_write(new_len_with_ascii, old_len, false)? };
             let (read, written) = convert_utf16_to_utf8_partial(other, &mut handle.as_mut_slice()[old_len..]);
             let left = other.len() - read;
             if left == 0 {
                 return Ok(handle.finish(old_len + written, true));
             }
             let filled = old_len + written;
-            let needed = times_three_plus_one(left).ok_or(())?;
+            let needed = times_three(left).ok_or(())?;
             let new_len = filled.checked_add(needed).ok_or(())?;
             unsafe {
                 handle.restart_bulk_write(new_len, filled, false)?;
             }
             (filled, read, handle)
         } else {
             // Started with non-ASCII. Compute worst case
             let needed = if let Some(n) = worst_case_needed {
                 n
             } else {
-                times_three_plus_one(other.len()).ok_or(())?
+                times_three(other.len()).ok_or(())?
             };
             let new_len = old_len.checked_add(needed).ok_or(())?;
             let mut handle = unsafe { self.bulk_write(new_len, old_len, false)? };
             (old_len, 0, handle)
         };
         let written =
             convert_utf16_to_utf8(&other[read..], &mut handle.as_mut_slice()[filled..]);
         Ok(handle.finish(filled + written, true))
--- a/xpcom/string/nsReadableUtils.cpp
+++ b/xpcom/string/nsReadableUtils.cpp
@@ -46,23 +46,23 @@ char* ToNewCString(const nsAString& aSou
   return dest;
 }
 
 char* ToNewUTF8String(const nsAString& aSource, uint32_t* aUTF8Count) {
   auto len = aSource.Length();
   // The uses of this function seem temporary enough that it's not
   // worthwhile to be fancy about the allocation size. Let's just use
   // the worst case.
-  // Times 3 plus 2, because ConvertUTF16toUTF8 requires times 3 plus 1 and
+  // Times 3 plus 1, because ConvertUTF16toUTF8 requires times 3 and
   // then we have the terminator.
   // Using CheckedInt<uint32_t>, because aUTF8Count is uint32_t* for
   // historical reasons.
   mozilla::CheckedInt<uint32_t> destLen(len);
   destLen *= 3;
-  destLen += 2;
+  destLen += 1;
   if (!destLen.isValid()) {
     return nullptr;
   }
   size_t destLenVal = destLen.value();
   char* dest = static_cast<char*>(moz_xmalloc(destLenVal));
 
   size_t written = ConvertUTF16toUTF8(aSource, MakeSpan(dest, destLenVal));
   dest[written] = 0;
--- a/xpcom/string/nsReadableUtils.h
+++ b/xpcom/string/nsReadableUtils.h
@@ -124,18 +124,17 @@ inline void ConvertLatin1toUTF16(mozilla
                                  mozilla::Span<char16_t> aDest) {
   encoding_mem_convert_latin1_to_utf16(aSource.Elements(), aSource.Length(),
                                        aDest.Elements(), aDest.Length());
 }
 
 /**
  * Lone surrogates are replaced with the REPLACEMENT CHARACTER.
  *
- * The length of aDest must be at least the length of aSource times three
- * _plus one_.
+ * The length of aDest must be at least the length of aSource times three.
  *
  * Returns the number of code units written.
  */
 inline size_t ConvertUTF16toUTF8(mozilla::Span<const char16_t> aSource,
                                  mozilla::Span<char> aDest) {
   return encoding_mem_convert_utf16_to_utf8(
       aSource.Elements(), aSource.Length(), aDest.Elements(), aDest.Length());
 }