Skip to main content

encoding_rs/
lib.rs

1// Copyright Mozilla Foundation. See the COPYRIGHT
2// file at the top-level directory of this distribution.
3//
4// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
7// option. This file may not be copied, modified, or distributed
8// except according to those terms.
9
10// The above license applies to code in this file. The label data in
11// this file is generated from WHATWG's encodings.json, which came under
12// the following license:
13
14// Copyright © WHATWG (Apple, Google, Mozilla, Microsoft).
15//
16// Redistribution and use in source and binary forms, with or without
17// modification, are permitted provided that the following conditions are met:
18//
19// 1. Redistributions of source code must retain the above copyright notice, this
20//    list of conditions and the following disclaimer.
21//
22// 2. Redistributions in binary form must reproduce the above copyright notice,
23//    this list of conditions and the following disclaimer in the documentation
24//    and/or other materials provided with the distribution.
25//
26// 3. Neither the name of the copyright holder nor the names of its
27//    contributors may be used to endorse or promote products derived from
28//    this software without specific prior written permission.
29//
30// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
31// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
33// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
34// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
36// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
37// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
38// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40
41#![allow(
42    clippy::doc_markdown,
43    clippy::inline_always,
44    clippy::new_ret_no_self,
45    clippy::redundant_static_lifetimes
46)]
47
48//! encoding_rs is a Gecko-oriented Free Software / Open Source implementation
49//! of the [Encoding Standard](https://encoding.spec.whatwg.org/) in Rust.
50//! Gecko-oriented means that converting to and from UTF-16 is supported in
51//! addition to converting to and from UTF-8, that the performance and
52//! streamability goals are browser-oriented, and that FFI-friendliness is a
53//! goal.
54//!
55//! Additionally, the `mem` module provides functions that are useful for
56//! applications that need to be able to deal with legacy in-memory
57//! representations of Unicode.
58//!
59//! For expectation setting, please be sure to read the sections
60//! [_UTF-16LE, UTF-16BE and Unicode Encoding Schemes_](#utf-16le-utf-16be-and-unicode-encoding-schemes),
61//! [_ISO-8859-1_](#iso-8859-1) and [_Web / Browser Focus_](#web--browser-focus) below.
62//!
63//! There is a [long-form write-up](https://hsivonen.fi/encoding_rs/) about the
64//! design and internals of the crate.
65//!
66//! # Availability
67//!
68//! The code is available under the
69//! [Apache license, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0)
70//! or the [MIT license](https://opensource.org/licenses/MIT), at your option.
71//! See the
72//! [`COPYRIGHT`](https://github.com/hsivonen/encoding_rs/blob/master/COPYRIGHT)
73//! file for details.
74//! The [repository is on GitHub](https://github.com/hsivonen/encoding_rs). The
75//! [crate is available on crates.io](https://crates.io/crates/encoding_rs).
76//!
77//! # Integration with `std::io`
78//!
79//! This crate doesn't implement traits from `std::io`. However, for the case of
80//! wrapping a `std::io::Read` in a decoder that implements `std::io::Read` and
81//! presents the data from the wrapped `std::io::Read` as UTF-8 is addressed by
82//! the [`encoding_rs_io`](https://docs.rs/encoding_rs_io/) crate.
83//!
84//! # Examples
85//!
86//! Example programs:
87//!
88//! * [Rust](https://github.com/hsivonen/recode_rs)
89//! * [C](https://github.com/hsivonen/recode_c)
90//! * [C++](https://github.com/hsivonen/recode_cpp)
91//!
92//! Decode using the non-streaming API:
93//!
94//! ```
95//! #[cfg(feature = "alloc")] {
96//! use encoding_rs::*;
97//!
98//! let expectation = "\u{30CF}\u{30ED}\u{30FC}\u{30FB}\u{30EF}\u{30FC}\u{30EB}\u{30C9}";
99//! let bytes = b"\x83n\x83\x8D\x81[\x81E\x83\x8F\x81[\x83\x8B\x83h";
100//!
101//! let (cow, encoding_used, had_errors) = SHIFT_JIS.decode(bytes);
102//! assert_eq!(&cow[..], expectation);
103//! assert_eq!(encoding_used, SHIFT_JIS);
104//! assert!(!had_errors);
105//! }
106//! ```
107//!
108//! Decode using the streaming API:
109//!
110//! ```
111//! use encoding_rs::*;
112//!
113//! let expectation = "\u{30CF}\u{30ED}\u{30FC}\u{30FB}\u{30EF}\u{30FC}\u{30EB}\u{30C9}";
114//!
115//! // Use an array of byte slices to demonstrate content arriving piece by
116//! // piece from the network.
117//! let bytes: [&'static [u8]; 4] = [b"\x83",
118//!                                  b"n\x83\x8D\x81",
119//!                                  b"[\x81E\x83\x8F\x81[\x83",
120//!                                  b"\x8B\x83h"];
121//!
122//! // Very short output buffer to demonstrate the output buffer getting full.
123//! // Normally, you'd use something like `[0u8; 2048]`.
124//! let mut buffer_bytes = [0u8; 8];
125//! let mut buffer: &mut str = std::str::from_utf8_mut(&mut buffer_bytes[..]).unwrap();
126//!
127//! // How many bytes in the buffer currently hold significant data.
128//! let mut bytes_in_buffer = 0usize;
129//!
130//! // Collect the output to a string for demonstration purposes.
131//! let mut output = String::new();
132//!
133//! // The `Decoder`
134//! let mut decoder = SHIFT_JIS.new_decoder();
135//!
136//! // Track whether we see errors.
137//! let mut total_had_errors = false;
138//!
139//! // Decode using a fixed-size intermediate buffer (for demonstrating the
140//! // use of a fixed-size buffer; normally when the output of an incremental
141//! // decode goes to a `String` one would use `Decoder.decode_to_string()` to
142//! // avoid the intermediate buffer).
143//! for input in &bytes[..] {
144//!     // The number of bytes already read from current `input` in total.
145//!     let mut total_read_from_current_input = 0usize;
146//!
147//!     loop {
148//!         let (result, read, written, had_errors) =
149//!             decoder.decode_to_str(&input[total_read_from_current_input..],
150//!                                   &mut buffer[bytes_in_buffer..],
151//!                                   false);
152//!         total_read_from_current_input += read;
153//!         bytes_in_buffer += written;
154//!         total_had_errors |= had_errors;
155//!         match result {
156//!             CoderResult::InputEmpty => {
157//!                 // We have consumed the current input buffer. Break out of
158//!                 // the inner loop to get the next input buffer from the
159//!                 // outer loop.
160//!                 break;
161//!             },
162//!             CoderResult::OutputFull => {
163//!                 // Write the current buffer out and consider the buffer
164//!                 // empty.
165//!                 output.push_str(&buffer[..bytes_in_buffer]);
166//!                 bytes_in_buffer = 0usize;
167//!                 continue;
168//!             }
169//!         }
170//!     }
171//! }
172//!
173//! // Process EOF
174//! loop {
175//!     let (result, _, written, had_errors) =
176//!         decoder.decode_to_str(b"",
177//!                               &mut buffer[bytes_in_buffer..],
178//!                               true);
179//!     bytes_in_buffer += written;
180//!     total_had_errors |= had_errors;
181//!     // Write the current buffer out and consider the buffer empty.
182//!     // Need to do this here for both `match` arms, because we exit the
183//!     // loop on `CoderResult::InputEmpty`.
184//!     output.push_str(&buffer[..bytes_in_buffer]);
185//!     bytes_in_buffer = 0usize;
186//!     match result {
187//!         CoderResult::InputEmpty => {
188//!             // Done!
189//!             break;
190//!         },
191//!         CoderResult::OutputFull => {
192//!             continue;
193//!         }
194//!     }
195//! }
196//!
197//! assert_eq!(&output[..], expectation);
198//! assert!(!total_had_errors);
199//! ```
200//!
201//! ## UTF-16LE, UTF-16BE and Unicode Encoding Schemes
202//!
203//! The Encoding Standard doesn't specify encoders for UTF-16LE and UTF-16BE,
204//! __so this crate does not provide encoders for those encodings__!
205//! Along with the replacement encoding, their _output encoding_ (i.e. the
206//! encoding used for form submission and error handling in the query string
207//! of URLs) is UTF-8, so you get an UTF-8 encoder if you request an encoder
208//! for them.
209//!
210//! Additionally, the Encoding Standard factors BOM handling into wrapper
211//! algorithms so that BOM handling isn't part of the definition of the
212//! encodings themselves. The Unicode _encoding schemes_ in the Unicode
213//! Standard define BOM handling or lack thereof as part of the encoding
214//! scheme.
215//!
216//! When used with the `_without_bom_handling` entry points, the UTF-16LE
217//! and UTF-16BE _encodings_ match the same-named _encoding schemes_ from
218//! the Unicode Standard.
219//!
220//! When used with the `_with_bom_removal` entry points, the UTF-8
221//! _encoding_ matches the UTF-8 _encoding scheme_ from the Unicode
222//! Standard.
223//!
224//! This crate does not provide a mode that matches the UTF-16 _encoding
225//! scheme_ from the Unicode Stardard. The UTF-16BE encoding used with
226//! the entry points without `_bom_` qualifiers is the closest match,
227//! but in that case, the UTF-8 BOM triggers UTF-8 decoding, which is
228//! not part of the behavior of the UTF-16 _encoding scheme_ per the
229//! Unicode Standard.
230//!
231//! The UTF-32 family of Unicode encoding schemes is not supported
232//! by this crate. The Encoding Standard doesn't define any UTF-32
233//! family encodings, since they aren't necessary for consuming Web
234//! content.
235//!
236//! While gb18030 is capable of representing U+FEFF, the Encoding
237//! Standard does not treat the gb18030 byte representation of U+FEFF
238//! as a BOM, so neither does this crate.
239//!
240//! ## ISO-8859-1
241//!
242//! ISO-8859-1 does not exist as a distinct encoding from windows-1252 in
243//! the Encoding Standard. Therefore, an encoding that maps the unsigned
244//! byte value to the same Unicode scalar value is not available via
245//! `Encoding` in this crate.
246//!
247//! However, the functions whose name starts with `convert` and contains
248//! `latin1` in the `mem` module support such conversions, which are known as
249//! [_isomorphic decode_](https://infra.spec.whatwg.org/#isomorphic-decode)
250//! and [_isomorphic encode_](https://infra.spec.whatwg.org/#isomorphic-encode)
251//! in the [Infra Standard](https://infra.spec.whatwg.org/).
252//!
253//! ## Web / Browser Focus
254//!
255//! Both in terms of scope and performance, the focus is on the Web. For scope,
256//! this means that encoding_rs implements the Encoding Standard fully and
257//! doesn't implement encodings that are not specified in the Encoding
258//! Standard. For performance, this means that decoding performance is
259//! important as well as performance for encoding into UTF-8 or encoding the
260//! Basic Latin range (ASCII) into legacy encodings. Non-Basic Latin needs to
261//! be encoded into legacy encodings in only two places in the Web platform: in
262//! the query part of URLs, in which case it's a matter of relatively rare
263//! error handling, and in form submission, in which case the user action and
264//! networking tend to hide the performance of the encoder.
265//!
266//! Deemphasizing performance of encoding non-Basic Latin text into legacy
267//! encodings enables smaller code size thanks to the encoder side using the
268//! decode-optimized data tables without having encode-optimized data tables at
269//! all. Even in decoders, smaller lookup table size is preferred over avoiding
270//! multiplication operations.
271//!
272//! Additionally, performance is a non-goal for the ASCII-incompatible
273//! ISO-2022-JP encoding, which are rarely used on the Web. Instead of
274//! performance, the decoder for ISO-2022-JP optimizes for ease/clarity
275//! of implementation.
276//!
277//! Despite the browser focus, the hope is that non-browser applications
278//! that wish to consume Web content or submit Web forms in a Web-compatible
279//! way will find encoding_rs useful. While encoding_rs does not try to match
280//! Windows behavior, many of the encodings are close enough to legacy
281//! encodings implemented by Windows that applications that need to consume
282//! data in legacy Windows encodins may find encoding_rs useful. The
283//! [codepage](https://crates.io/crates/codepage) crate maps from Windows
284//! code page identifiers onto encoding_rs `Encoding`s and vice versa.
285//!
286//! For decoding email, UTF-7 support is needed (unfortunately) in additition
287//! to the encodings defined in the Encoding Standard. The
288//! [charset](https://crates.io/crates/charset) wraps encoding_rs and adds
289//! UTF-7 decoding for email purposes.
290//!
291//! For single-byte DOS encodings beyond the ones supported by the Encoding
292//! Standard, there is the [`oem_cp`](https://crates.io/crates/oem_cp) crate.
293//!
294//! # Preparing Text for the Encoders
295//!
296//! Normalizing text into Unicode Normalization Form C prior to encoding text
297//! into a legacy encoding minimizes unmappable characters. Text can be
298//! normalized to Unicode Normalization Form C using the
299//! [`icu_normalizer`](https://crates.io/crates/icu_normalizer) crate, which
300//! is part of [ICU4X](https://icu4x.unicode.org/).
301//!
302//! The exception is windows-1258, which after normalizing to Unicode
303//! Normalization Form C requires tone marks to be decomposed in order to
304//! minimize unmappable characters. Vietnamese tone marks can be decomposed
305//! using the [`detone`](https://crates.io/crates/detone) crate.
306//!
307//! # Streaming & Non-Streaming; Rust & C/C++
308//!
309//! The API in Rust has two modes of operation: streaming and non-streaming.
310//! The streaming API is the foundation of the implementation and should be
311//! used when processing data that arrives piecemeal from an i/o stream. The
312//! streaming API has an FFI wrapper (as a [separate crate][1]) that exposes it
313//! to C callers. The non-streaming part of the API is for Rust callers only and
314//! is smart about borrowing instead of copying when possible. When
315//! streamability is not needed, the non-streaming API should be preferrer in
316//! order to avoid copying data when a borrow suffices.
317//!
318//! There is no analogous C API exposed via FFI, mainly because C doesn't have
319//! standard types for growable byte buffers and Unicode strings that know
320//! their length.
321//!
322//! The C API (header file generated at `target/include/encoding_rs.h` when
323//! building encoding_rs) can, in turn, be wrapped for use from C++. Such a
324//! C++ wrapper can re-create the non-streaming API in C++ for C++ callers.
325//! The C binding comes with a [C++17 wrapper][2] that uses standard library +
326//! [GSL][3] types and that recreates the non-streaming API in C++ on top of
327//! the streaming API. A C++ wrapper with XPCOM/MFBT types is available as
328//! [`mozilla::Encoding`][4].
329//!
330//! The `Encoding` type is common to both the streaming and non-streaming
331//! modes. In the streaming mode, decoding operations are performed with a
332//! `Decoder` and encoding operations with an `Encoder` object obtained via
333//! `Encoding`. In the non-streaming mode, decoding and encoding operations are
334//! performed using methods on `Encoding` objects themselves, so the `Decoder`
335//! and `Encoder` objects are not used at all.
336//!
337//! [1]: https://github.com/hsivonen/encoding_c
338//! [2]: https://github.com/hsivonen/encoding_c/blob/master/include/encoding_rs_cpp.h
339//! [3]: https://github.com/Microsoft/GSL/
340//! [4]: https://searchfox.org/mozilla-central/source/intl/Encoding.h
341//!
342//! # Memory management
343//!
344//! The non-streaming mode never performs heap allocations (even the methods
345//! that write into a `Vec<u8>` or a `String` by taking them as arguments do
346//! not reallocate the backing buffer of the `Vec<u8>` or the `String`). That
347//! is, the non-streaming mode uses caller-allocated buffers exclusively.
348//!
349//! The methods of the streaming mode that return a `Vec<u8>` or a `String`
350//! perform heap allocations but only to allocate the backing buffer of the
351//! `Vec<u8>` or the `String`.
352//!
353//! `Encoding` is always statically allocated. `Decoder` and `Encoder` need no
354//! `Drop` cleanup.
355//!
356//! # Buffer reading and writing behavior
357//!
358//! Based on experience gained with the `java.nio.charset` encoding converter
359//! API and with the Gecko uconv encoding converter API, the buffer reading
360//! and writing behaviors of encoding_rs are asymmetric: input buffers are
361//! fully drained but output buffers are not always fully filled.
362//!
363//! When reading from an input buffer, encoding_rs always consumes all input
364//! up to the next error or to the end of the buffer. In particular, when
365//! decoding, even if the input buffer ends in the middle of a byte sequence
366//! for a character, the decoder consumes all input. This has the benefit that
367//! the caller of the API can always fill the next buffer from the start from
368//! whatever source the bytes come from and never has to first copy the last
369//! bytes of the previous buffer to the start of the next buffer. However, when
370//! encoding, the UTF-8 input buffers have to end at a character boundary, which
371//! is a requirement for the Rust `str` type anyway, and UTF-16 input buffer
372//! boundaries falling in the middle of a surrogate pair result in both
373//! suggorates being treated individually as unpaired surrogates.
374//!
375//! Additionally, decoders guarantee that they can be fed even one byte at a
376//! time and encoders guarantee that they can be fed even one code point at a
377//! time. This has the benefit of not placing restrictions on the size of
378//! chunks the content arrives e.g. from network.
379//!
380//! When writing into an output buffer, encoding_rs makes sure that the code
381//! unit sequence for a character is never split across output buffer
382//! boundaries. This may result in wasted space at the end of an output buffer,
383//! but the advantages are that the output side of both decoders and encoders
384//! is greatly simplified compared to designs that attempt to fill output
385//! buffers exactly even when that entails splitting a code unit sequence and
386//! when encoding_rs methods return to the caller, the output produces thus
387//! far is always valid taken as whole. (In the case of encoding to ISO-2022-JP,
388//! the output needs to be considered as a whole, because the latest output
389//! buffer taken alone might not be valid taken alone if the transition away
390//! from the ASCII state occurred in an earlier output buffer. However, since
391//! the ISO-2022-JP decoder doesn't treat streams that don't end in the ASCII
392//! state as being in error despite the encoder generating a transition to the
393//! ASCII state at the end, the claim about the partial output taken as a whole
394//! being valid is true even for ISO-2022-JP.)
395//!
396//! # Error Reporting
397//!
398//! Based on experience gained with the `java.nio.charset` encoding converter
399//! API and with the Gecko uconv encoding converter API, the error reporting
400//! behaviors of encoding_rs are asymmetric: decoder errors include offsets
401//! that leave it up to the caller to extract the erroneous bytes from the
402//! input stream if the caller wishes to do so but encoder errors provide the
403//! code point associated with the error without requiring the caller to
404//! extract it from the input on its own.
405//!
406//! On the encoder side, an error is always triggered by the most recently
407//! pushed Unicode scalar, which makes it simple to pass the `char` to the
408//! caller. Also, it's very typical for the caller to wish to do something with
409//! this data: generate a numeric escape for the character. Additionally, the
410//! ISO-2022-JP encoder reports U+FFFD instead of the actual input character in
411//! certain cases, so requiring the caller to extract the character from the
412//! input buffer would require the caller to handle ISO-2022-JP details.
413//! Furthermore, requiring the caller to extract the character from the input
414//! buffer would require the caller to implement UTF-8 or UTF-16 math, which is
415//! the job of an encoding conversion library.
416//!
417//! On the decoder side, errors are triggered in more complex ways. For
418//! example, when decoding the sequence ESC, '$', _buffer boundary_, 'A' as
419//! ISO-2022-JP, the ESC byte is in error, but this is discovered only after
420//! the buffer boundary when processing 'A'. Thus, the bytes in error might not
421//! be the ones most recently pushed to the decoder and the error might not even
422//! be in the current buffer.
423//!
424//! Some encoding conversion APIs address the problem by not acknowledging
425//! trailing bytes of an input buffer as consumed if it's still possible for
426//! future bytes to cause the trailing bytes to be in error. This way, error
427//! reporting can always refer to the most recently pushed buffer. This has the
428//! problem that the caller of the API has to copy the unconsumed trailing
429//! bytes to the start of the next buffer before being able to fill the rest
430//! of the next buffer. This is annoying, error-prone and inefficient.
431//!
432//! A possible solution would be making the decoder remember recently consumed
433//! bytes in order to be able to include a copy of the erroneous bytes when
434//! reporting an error. This has two problem: First, callers a rarely
435//! interested in the erroneous bytes, so attempts to identify them are most
436//! often just overhead anyway. Second, the rare applications that are
437//! interested typically care about the location of the error in the input
438//! stream.
439//!
440//! To keep the API convenient for common uses and the overhead low while making
441//! it possible to develop applications, such as HTML validators, that care
442//! about which bytes were in error, encoding_rs reports the length of the
443//! erroneous sequence and the number of bytes consumed after the erroneous
444//! sequence. As long as the caller doesn't discard the 6 most recent bytes,
445//! this makes it possible for callers that care about the erroneous bytes to
446//! locate them.
447//!
448//! # No Convenience API for Custom Replacements
449//!
450//! The Web Platform and, therefore, the Encoding Standard supports only one
451//! error recovery mode for decoders and only one error recovery mode for
452//! encoders. The supported error recovery mode for decoders is emitting the
453//! REPLACEMENT CHARACTER on error. The supported error recovery mode for
454//! encoders is emitting an HTML decimal numeric character reference for
455//! unmappable characters.
456//!
457//! Since encoding_rs is Web-focused, these are the only error recovery modes
458//! for which convenient support is provided. Moreover, on the decoder side,
459//! there aren't really good alternatives for emitting the REPLACEMENT CHARACTER
460//! on error (other than treating errors as fatal). In particular, simply
461//! ignoring errors is a
462//! [security problem](http://www.unicode.org/reports/tr36/#Substituting_for_Ill_Formed_Subsequences),
463//! so it would be a bad idea for encoding_rs to provide a mode that encouraged
464//! callers to ignore errors.
465//!
466//! On the encoder side, there are plausible alternatives for HTML decimal
467//! numeric character references. For example, when outputting CSS, CSS-style
468//! escapes would seem to make sense. However, instead of facilitating the
469//! output of CSS, JS, etc. in non-UTF-8 encodings, encoding_rs takes the design
470//! position that you shouldn't generate output in encodings other than UTF-8,
471//! except where backward compatibility with interacting with the legacy Web
472//! requires it. The legacy Web requires it only when parsing the query strings
473//! of URLs and when submitting forms, and those two both use HTML decimal
474//! numeric character references.
475//!
476//! While encoding_rs doesn't make encoder replacements other than HTML decimal
477//! numeric character references easy, it does make them _possible_.
478//! `encode_from_utf8()`, which emits HTML decimal numeric character references
479//! for unmappable characters, is implemented on top of
480//! `encode_from_utf8_without_replacement()`. Applications that really, really
481//! want other replacement schemes for unmappable characters can likewise
482//! implement them on top of `encode_from_utf8_without_replacement()`.
483//!
484//! # No Extensibility by Design
485//!
486//! The set of encodings supported by encoding_rs is not extensible by design.
487//! That is, `Encoding`, `Decoder` and `Encoder` are intentionally `struct`s
488//! rather than `trait`s. encoding_rs takes the design position that all future
489//! text interchange should be done using UTF-8, which can represent all of
490//! Unicode. (It is, in fact, the only encoding supported by the Encoding
491//! Standard and encoding_rs that can represent all of Unicode and that has
492//! encoder support. UTF-16LE and UTF-16BE don't have encoder support, and
493//! gb18030 cannot encode U+E5E5.) The other encodings are supported merely for
494//! legacy compatibility and not due to non-UTF-8 encodings having benefits
495//! other than being able to consume legacy content.
496//!
497//! Considering that UTF-8 can represent all of Unicode and is already supported
498//! by all Web browsers, introducing a new encoding wouldn't add to the
499//! expressiveness but would add to compatibility problems. In that sense,
500//! adding new encodings to the Web Platform doesn't make sense, and, in fact,
501//! post-UTF-8 attempts at encodings, such as BOCU-1, have been rejected from
502//! the Web Platform. On the other hand, the set of legacy encodings that must
503//! be supported for a Web browser to be able to be successful is not going to
504//! expand. Empirically, the set of encodings specified in the Encoding Standard
505//! is already sufficient and the set of legacy encodings won't grow
506//! retroactively.
507//!
508//! Since extensibility doesn't make sense considering the Web focus of
509//! encoding_rs and adding encodings to Web clients would be actively harmful,
510//! it makes sense to make the set of encodings that encoding_rs supports
511//! non-extensible and to take the (admittedly small) benefits arising from
512//! that, such as the size of `Decoder` and `Encoder` objects being known ahead
513//!  of time, which enables stack allocation thereof.
514//!
515//! This does have downsides for applications that might want to put encoding_rs
516//! to non-Web uses if those non-Web uses involve legacy encodings that aren't
517//! needed for Web uses. The needs of such applications should not complicate
518//! encoding_rs itself, though. It is up to those applications to provide a
519//! framework that delegates the operations with encodings that encoding_rs
520//! supports to encoding_rs and operations with other encodings to something
521//! else (as opposed to encoding_rs itself providing an extensibility
522//! framework).
523//!
524//! # Panics
525//!
526//! Methods in encoding_rs can panic if the API is used against the requirements
527//! stated in the documentation, if a state that's supposed to be impossible
528//! is reached due to an internal bug or on integer overflow. When used
529//! according to documentation with buffer sizes that stay below integer
530//! overflow, in the absence of internal bugs, encoding_rs does not panic.
531//!
532//! Panics arising from API misuse aren't documented beyond this on individual
533//! methods.
534//!
535//! # At-Risk Parts of the API
536//!
537//! The foreseeable source of partially backward-incompatible API change is the
538//! way the instances of `Encoding` are made available.
539//!
540//! If Rust changes to allow the entries of `[&'static Encoding; N]` to be
541//! initialized with `static`s of type `&'static Encoding`, the non-reference
542//! `FOO_INIT` public `Encoding` instances will be removed from the public API.
543//!
544//! If Rust changes to make the referent of `pub const FOO: &'static Encoding`
545//! unique when the constant is used in different crates, the reference-typed
546//! `static`s for the encoding instances will be changed from `static` to
547//! `const` and the non-reference-typed `_INIT` instances will be removed.
548//!
549//! # Mapping Spec Concepts onto the API
550//!
551//! <table>
552//! <thead>
553//! <tr><th>Spec Concept</th><th>Streaming</th><th>Non-Streaming</th></tr>
554//! </thead>
555//! <tbody>
556//! <tr><td><a href="https://encoding.spec.whatwg.org/#encoding">encoding</a></td><td><code>&amp;'static Encoding</code></td><td><code>&amp;'static Encoding</code></td></tr>
557//! <tr><td><a href="https://encoding.spec.whatwg.org/#utf-8">UTF-8 encoding</a></td><td><code>UTF_8</code></td><td><code>UTF_8</code></td></tr>
558//! <tr><td><a href="https://encoding.spec.whatwg.org/#concept-encoding-get">get an encoding</a></td><td><code>Encoding::for_label(<var>label</var>)</code></td><td><code>Encoding::for_label(<var>label</var>)</code></td></tr>
559//! <tr><td><a href="https://encoding.spec.whatwg.org/#name">name</a></td><td><code><var>encoding</var>.name()</code></td><td><code><var>encoding</var>.name()</code></td></tr>
560//! <tr><td><a href="https://encoding.spec.whatwg.org/#get-an-output-encoding">get an output encoding</a></td><td><code><var>encoding</var>.output_encoding()</code></td><td><code><var>encoding</var>.output_encoding()</code></td></tr>
561//! <tr><td><a href="https://encoding.spec.whatwg.org/#decode">decode</a></td><td><code>let d = <var>encoding</var>.new_decoder();<br>let res = d.decode_to_<var>*</var>(<var>src</var>, <var>dst</var>, false);<br>// &hellip;</br>let last_res = d.decode_to_<var>*</var>(<var>src</var>, <var>dst</var>, true);</code></td><td><code><var>encoding</var>.decode(<var>src</var>)</code></td></tr>
562//! <tr><td><a href="https://encoding.spec.whatwg.org/#utf-8-decode">UTF-8 decode</a></td><td><code>let d = UTF_8.new_decoder_with_bom_removal();<br>let res = d.decode_to_<var>*</var>(<var>src</var>, <var>dst</var>, false);<br>// &hellip;</br>let last_res = d.decode_to_<var>*</var>(<var>src</var>, <var>dst</var>, true);</code></td><td><code>UTF_8.decode_with_bom_removal(<var>src</var>)</code></td></tr>
563//! <tr><td><a href="https://encoding.spec.whatwg.org/#utf-8-decode-without-bom">UTF-8 decode without BOM</a></td><td><code>let d = UTF_8.new_decoder_without_bom_handling();<br>let res = d.decode_to_<var>*</var>(<var>src</var>, <var>dst</var>, false);<br>// &hellip;</br>let last_res = d.decode_to_<var>*</var>(<var>src</var>, <var>dst</var>, true);</code></td><td><code>UTF_8.decode_without_bom_handling(<var>src</var>)</code></td></tr>
564//! <tr><td><a href="https://encoding.spec.whatwg.org/#utf-8-decode-without-bom-or-fail">UTF-8 decode without BOM or fail</a></td><td><code>let d = UTF_8.new_decoder_without_bom_handling();<br>let res = d.decode_to_<var>*</var>_without_replacement(<var>src</var>, <var>dst</var>, false);<br>// &hellip; (fail if malformed)</br>let last_res = d.decode_to_<var>*</var>_without_replacement(<var>src</var>, <var>dst</var>, true);<br>// (fail if malformed)</code></td><td><code>UTF_8.decode_without_bom_handling_and_without_replacement(<var>src</var>)</code></td></tr>
565//! <tr><td><a href="https://encoding.spec.whatwg.org/#encode">encode</a></td><td><code>let e = <var>encoding</var>.new_encoder();<br>let res = e.encode_to_<var>*</var>(<var>src</var>, <var>dst</var>, false);<br>// &hellip;</br>let last_res = e.encode_to_<var>*</var>(<var>src</var>, <var>dst</var>, true);</code></td><td><code><var>encoding</var>.encode(<var>src</var>)</code></td></tr>
566//! <tr><td><a href="https://encoding.spec.whatwg.org/#utf-8-encode">UTF-8 encode</a></td><td>Use the UTF-8 nature of Rust strings directly:<br><code><var>write</var>(<var>src</var>.as_bytes());<br>// refill src<br><var>write</var>(<var>src</var>.as_bytes());<br>// refill src<br><var>write</var>(<var>src</var>.as_bytes());<br>// &hellip;</code></td><td>Use the UTF-8 nature of Rust strings directly:<br><code><var>src</var>.as_bytes()</code></td></tr>
567//! </tbody>
568//! </table>
569//!
570//! # Compatibility with the rust-encoding API
571//!
572//! The crate
573//! [encoding_rs_compat](https://github.com/hsivonen/encoding_rs_compat/)
574//! is a drop-in replacement for rust-encoding 0.2.32 that implements (most of)
575//! the API of rust-encoding 0.2.32 on top of encoding_rs.
576//!
577//! # Mapping rust-encoding concepts to encoding_rs concepts
578//!
579//! The following table provides a mapping from rust-encoding constructs to
580//! encoding_rs ones.
581//!
582//! <table>
583//! <thead>
584//! <tr><th>rust-encoding</th><th>encoding_rs</th></tr>
585//! </thead>
586//! <tbody>
587//! <tr><td><code>encoding::EncodingRef</code></td><td><code>&amp;'static encoding_rs::Encoding</code></td></tr>
588//! <tr><td><code>encoding::all::<var>WINDOWS_31J</var></code> (not based on the WHATWG name for some encodings)</td><td><code>encoding_rs::<var>SHIFT_JIS</var></code> (always the WHATWG name uppercased and hyphens replaced with underscores)</td></tr>
589//! <tr><td><code>encoding::all::ERROR</code></td><td>Not available because not in the Encoding Standard</td></tr>
590//! <tr><td><code>encoding::all::ASCII</code></td><td>Not available because not in the Encoding Standard</td></tr>
591//! <tr><td><code>encoding::all::ISO_8859_1</code></td><td>Not available because not in the Encoding Standard</td></tr>
592//! <tr><td><code>encoding::all::HZ</code></td><td>Not available because not in the Encoding Standard</td></tr>
593//! <tr><td><code>encoding::label::encoding_from_whatwg_label(<var>string</var>)</code></td><td><code>encoding_rs::Encoding::for_label(<var>string</var>)</code></td></tr>
594//! <tr><td><code><var>enc</var>.whatwg_name()</code> (always lower case)</td><td><code><var>enc</var>.name()</code> (potentially mixed case)</td></tr>
595//! <tr><td><code><var>enc</var>.name()</code></td><td>Not available because not in the Encoding Standard</td></tr>
596//! <tr><td><code>encoding::decode(<var>bytes</var>, encoding::DecoderTrap::Replace, <var>enc</var>)</code></td><td><code><var>enc</var>.decode(<var>bytes</var>)</code></td></tr>
597//! <tr><td><code><var>enc</var>.decode(<var>bytes</var>, encoding::DecoderTrap::Replace)</code></td><td><code><var>enc</var>.decode_without_bom_handling(<var>bytes</var>)</code></td></tr>
598//! <tr><td><code><var>enc</var>.encode(<var>string</var>, encoding::EncoderTrap::NcrEscape)</code></td><td><code><var>enc</var>.encode(<var>string</var>)</code></td></tr>
599//! <tr><td><code><var>enc</var>.raw_decoder()</code></td><td><code><var>enc</var>.new_decoder_without_bom_handling()</code></td></tr>
600//! <tr><td><code><var>enc</var>.raw_encoder()</code></td><td><code><var>enc</var>.new_encoder()</code></td></tr>
601//! <tr><td><code>encoding::RawDecoder</code></td><td><code>encoding_rs::Decoder</code></td></tr>
602//! <tr><td><code>encoding::RawEncoder</code></td><td><code>encoding_rs::Encoder</code></td></tr>
603//! <tr><td><code><var>raw_decoder</var>.raw_feed(<var>src</var>, <var>dst_string</var>)</code></td><td><code><var>dst_string</var>.reserve(<var>decoder</var>.max_utf8_buffer_length_without_replacement(<var>src</var>.len()));<br><var>decoder</var>.decode_to_string_without_replacement(<var>src</var>, <var>dst_string</var>, false)</code></td></tr>
604//! <tr><td><code><var>raw_encoder</var>.raw_feed(<var>src</var>, <var>dst_vec</var>)</code></td><td><code><var>dst_vec</var>.reserve(<var>encoder</var>.max_buffer_length_from_utf8_without_replacement(<var>src</var>.len()));<br><var>encoder</var>.encode_from_utf8_to_vec_without_replacement(<var>src</var>, <var>dst_vec</var>, false)</code></td></tr>
605//! <tr><td><code><var>raw_decoder</var>.raw_finish(<var>dst</var>)</code></td><td><code><var>dst_string</var>.reserve(<var>decoder</var>.max_utf8_buffer_length_without_replacement(0));<br><var>decoder</var>.decode_to_string_without_replacement(b"", <var>dst</var>, true)</code></td></tr>
606//! <tr><td><code><var>raw_encoder</var>.raw_finish(<var>dst</var>)</code></td><td><code><var>dst_vec</var>.reserve(<var>encoder</var>.max_buffer_length_from_utf8_without_replacement(0));<br><var>encoder</var>.encode_from_utf8_to_vec_without_replacement("", <var>dst</var>, true)</code></td></tr>
607//! <tr><td><code>encoding::DecoderTrap::Strict</code></td><td><code>decode*</code> methods that have <code>_without_replacement</code> in their name (and treating the `Malformed` result as fatal).</td></tr>
608//! <tr><td><code>encoding::DecoderTrap::Replace</code></td><td><code>decode*</code> methods that <i>do not</i> have <code>_without_replacement</code> in their name.</td></tr>
609//! <tr><td><code>encoding::DecoderTrap::Ignore</code></td><td>It is a bad idea to ignore errors due to security issues, but this could be implemented using <code>decode*</code> methods that have <code>_without_replacement</code> in their name.</td></tr>
610//! <tr><td><code>encoding::DecoderTrap::Call(DecoderTrapFunc)</code></td><td>Can be implemented using <code>decode*</code> methods that have <code>_without_replacement</code> in their name.</td></tr>
611//! <tr><td><code>encoding::EncoderTrap::Strict</code></td><td><code>encode*</code> methods that have <code>_without_replacement</code> in their name (and treating the `Unmappable` result as fatal).</td></tr>
612//! <tr><td><code>encoding::EncoderTrap::Replace</code></td><td>Can be implemented using <code>encode*</code> methods that have <code>_without_replacement</code> in their name.</td></tr>
613//! <tr><td><code>encoding::EncoderTrap::Ignore</code></td><td>It is a bad idea to ignore errors due to security issues, but this could be implemented using <code>encode*</code> methods that have <code>_without_replacement</code> in their name.</td></tr>
614//! <tr><td><code>encoding::EncoderTrap::NcrEscape</code></td><td><code>encode*</code> methods that <i>do not</i> have <code>_without_replacement</code> in their name.</td></tr>
615//! <tr><td><code>encoding::EncoderTrap::Call(EncoderTrapFunc)</code></td><td>Can be implemented using <code>encode*</code> methods that have <code>_without_replacement</code> in their name.</td></tr>
616//! </tbody>
617//! </table>
618//!
619//! # Relationship with Windows Code Pages
620//!
621//! Despite the Web and browser focus, the encodings defined by the Encoding
622//! Standard and implemented by this crate may be useful for decoding legacy
623//! data that uses Windows code pages. The following table names the single-byte
624//! encodings
625//! that have a closely related Windows code page, the number of the closest
626//! code page, a column indicating whether Windows maps unassigned code points
627//! to the Unicode Private Use Area instead of U+FFFD and a remark number
628//! indicating remarks in the list after the table.
629//!
630//! <table>
631//! <thead>
632//! <tr><th>Encoding</th><th>Code Page</th><th>PUA</th><th>Remarks</th></tr>
633//! </thead>
634//! <tbody>
635//! <tr><td>Shift_JIS</td><td>932</td><td></td><td></td></tr>
636//! <tr><td>GBK</td><td>936</td><td></td><td></td></tr>
637//! <tr><td>EUC-KR</td><td>949</td><td></td><td></td></tr>
638//! <tr><td>Big5</td><td>950</td><td></td><td></td></tr>
639//! <tr><td>IBM866</td><td>866</td><td></td><td></td></tr>
640//! <tr><td>windows-874</td><td>874</td><td>&bullet;</td><td></td></tr>
641//! <tr><td>UTF-16LE</td><td>1200</td><td></td><td></td></tr>
642//! <tr><td>UTF-16BE</td><td>1201</td><td></td><td></td></tr>
643//! <tr><td>windows-1250</td><td>1250</td><td></td><td></td></tr>
644//! <tr><td>windows-1251</td><td>1251</td><td></td><td></td></tr>
645//! <tr><td>windows-1252</td><td>1252</td><td></td><td></td></tr>
646//! <tr><td>windows-1253</td><td>1253</td><td>&bullet;</td><td></td></tr>
647//! <tr><td>windows-1254</td><td>1254</td><td></td><td></td></tr>
648//! <tr><td>windows-1255</td><td>1255</td><td>&bullet;</td><td></td></tr>
649//! <tr><td>windows-1256</td><td>1256</td><td></td><td></td></tr>
650//! <tr><td>windows-1257</td><td>1257</td><td>&bullet;</td><td></td></tr>
651//! <tr><td>windows-1258</td><td>1258</td><td></td><td></td></tr>
652//! <tr><td>macintosh</td><td>10000</td><td></td><td>1</td></tr>
653//! <tr><td>x-mac-cyrillic</td><td>10017</td><td></td><td>2</td></tr>
654//! <tr><td>KOI8-R</td><td>20866</td><td></td><td></td></tr>
655//! <tr><td>EUC-JP</td><td>20932</td><td></td><td></td></tr>
656//! <tr><td>KOI8-U</td><td>21866</td><td></td><td></td></tr>
657//! <tr><td>ISO-8859-2</td><td>28592</td><td></td><td></td></tr>
658//! <tr><td>ISO-8859-3</td><td>28593</td><td></td><td></td></tr>
659//! <tr><td>ISO-8859-4</td><td>28594</td><td></td><td></td></tr>
660//! <tr><td>ISO-8859-5</td><td>28595</td><td></td><td></td></tr>
661//! <tr><td>ISO-8859-6</td><td>28596</td><td>&bullet;</td><td></td></tr>
662//! <tr><td>ISO-8859-7</td><td>28597</td><td>&bullet;</td><td>3</td></tr>
663//! <tr><td>ISO-8859-8</td><td>28598</td><td>&bullet;</td><td>4</td></tr>
664//! <tr><td>ISO-8859-13</td><td>28603</td><td>&bullet;</td><td></td></tr>
665//! <tr><td>ISO-8859-15</td><td>28605</td><td></td><td></td></tr>
666//! <tr><td>ISO-8859-8-I</td><td>38598</td><td></td><td>5</td></tr>
667//! <tr><td>ISO-2022-JP</td><td>50220</td><td></td><td></td></tr>
668//! <tr><td>gb18030</td><td>54936</td><td></td><td></td></tr>
669//! <tr><td>UTF-8</td><td>65001</td><td></td><td></td></tr>
670//! </tbody>
671//! </table>
672//!
673//! 1. Windows decodes 0xBD to U+2126 OHM SIGN instead of U+03A9 GREEK CAPITAL LETTER OMEGA.
674//! 2. Windows decodes 0xFF to U+00A4 CURRENCY SIGN instead of U+20AC EURO SIGN.
675//! 3. Windows decodes the currency signs at 0xA4 and 0xA5 as well as 0xAA,
676//!    which should be U+037A GREEK YPOGEGRAMMENI, to PUA code points. Windows
677//!    decodes 0xA1 to U+02BD MODIFIER LETTER REVERSED COMMA instead of U+2018
678//!    LEFT SINGLE QUOTATION MARK and 0xA2 to U+02BC MODIFIER LETTER APOSTROPHE
679//!    instead of U+2019 RIGHT SINGLE QUOTATION MARK.
680//! 4. Windows decodes 0xAF to OVERLINE instead of MACRON and 0xFE and 0xFD to PUA instead
681//!    of LRM and RLM.
682//! 5. Remarks from the previous item apply.
683//!
684//! The differences between this crate and Windows in the case of multibyte encodings
685//! are not yet fully documented here. The lack of remarks above should not be taken
686//! as indication of lack of differences.
687//!
688//! # Notable Differences from IANA Naming
689//!
690//! In some cases, the Encoding Standard specifies the popular unextended encoding
691//! name where in IANA terms one of the other labels would be more precise considering
692//! the extensions that the Encoding Standard has unified into the encoding.
693//!
694//! <table>
695//! <thead>
696//! <tr><th>Encoding</th><th>IANA</th></tr>
697//! </thead>
698//! <tbody>
699//! <tr><td>Big5</td><td>Big5-HKSCS</td></tr>
700//! <tr><td>EUC-KR</td><td>windows-949</td></tr>
701//! <tr><td>Shift_JIS</td><td>windows-31j</td></tr>
702//! <tr><td>x-mac-cyrillic</td><td>x-mac-ukrainian</td></tr>
703//! </tbody>
704//! </table>
705//!
706//! In other cases where the Encoding Standard unifies unextended and extended
707//! variants of an encoding, the encoding gets the name of the extended
708//! variant.
709//!
710//! <table>
711//! <thead>
712//! <tr><th>IANA</th><th>Unified into Encoding</th></tr>
713//! </thead>
714//! <tbody>
715//! <tr><td>ISO-8859-1</td><td>windows-1252</td></tr>
716//! <tr><td>ISO-8859-9</td><td>windows-1254</td></tr>
717//! <tr><td>TIS-620</td><td>windows-874</td></tr>
718//! </tbody>
719//! </table>
720//!
721//! See the section [_UTF-16LE, UTF-16BE and Unicode Encoding Schemes_](#utf-16le-utf-16be-and-unicode-encoding-schemes)
722//! for discussion about the UTF-16 family.
723
724#![cfg_attr(not(feature = "std"), no_std)]
725#![cfg_attr(feature = "simd-accel", allow(internal_features))]
726#![cfg_attr(feature = "simd-accel", feature(core_intrinsics))]
727#![cfg_attr(
728    all(feature = "simd-accel", target_endian = "little"),
729    feature(portable_simd)
730)]
731// These are for working around
732// https://github.com/rust-lang/stdarch/issues/2208
733// https://github.com/rust-lang/rust/issues/159464
734// https://github.com/rust-lang/rust/pull/161558
735#![cfg_attr(
736    all(slow_mm_packus_epi16, feature = "simd-accel", target_feature = "sse2"),
737    feature(link_llvm_intrinsics)
738)]
739#![cfg_attr(
740    all(slow_mm_packus_epi16, feature = "simd-accel", target_feature = "sse2"),
741    feature(abi_unadjusted)
742)]
743#![cfg_attr(
744    all(slow_mm_packus_epi16, feature = "simd-accel", target_feature = "sse2"),
745    feature(simd_ffi)
746)]
747
748#[cfg(feature = "alloc")]
749#[cfg_attr(test, macro_use)]
750extern crate alloc;
751
752extern crate core;
753#[macro_use]
754extern crate cfg_if;
755
756#[cfg(feature = "serde")]
757extern crate serde;
758
759#[cfg(all(test, feature = "serde"))]
760extern crate bincode;
761#[cfg(all(test, feature = "serde"))]
762#[macro_use]
763extern crate serde_derive;
764#[cfg(all(test, feature = "serde"))]
765extern crate serde_json;
766
767// Build time optimization.
768cfg_if! {
769    if #[cfg(all(feature = "simd-accel", feature = "std", any(target_arch = "x86_64", target_arch = "x86"), not(all(target_feature = "avx2", target_feature = "bmi1"))))] {
770        use multiversion::multiversion;
771    } else {
772        use multiversion_no_op::multiversion;
773    }
774}
775
776#[macro_use]
777mod macros;
778
779#[cfg(all(feature = "simd-accel", target_endian = "little",))]
780mod simd_funcs;
781
782#[cfg(all(test, feature = "alloc"))]
783mod testing;
784
785mod big5;
786mod euc_jp;
787mod euc_kr;
788mod gb18030;
789mod gb18030_2022;
790mod iso_2022_jp;
791mod replacement;
792mod shift_jis;
793mod single_byte;
794mod utf_16;
795mod utf_8;
796mod x_user_defined;
797
798mod ascii;
799mod data;
800mod handles;
801mod variant;
802
803pub mod mem;
804
805use crate::ascii::ascii_valid_up_to;
806use crate::ascii::iso_2022_jp_ascii_valid_up_to;
807use crate::utf_8::utf8_valid_up_to;
808use crate::variant::*;
809
810#[cfg(feature = "alloc")]
811use alloc::borrow::Cow;
812#[cfg(feature = "alloc")]
813use alloc::string::String;
814#[cfg(feature = "alloc")]
815use alloc::vec::Vec;
816#[cfg(feature = "alloc")]
817use core::mem::MaybeUninit;
818
819use core::cmp::Ordering;
820use core::hash::Hash;
821use core::hash::Hasher;
822
823#[cfg(feature = "serde")]
824use serde::de::Visitor;
825#[cfg(feature = "serde")]
826use serde::{Deserialize, Deserializer, Serialize, Serializer};
827
828/// This has to be the max length of an NCR instead of max
829/// minus one, because we can't rely on getting the minus
830/// one from the space reserved for the current unmappable,
831/// because the ISO-2022-JP encoder can fill up that space
832/// with a state transition escape.
833const NCR_EXTRA: usize = 10; // &#1114111;
834
835// BEGIN GENERATED CODE. PLEASE DO NOT EDIT.
836// Instead, please regenerate using generate-encoding-data.py
837
838const LONGEST_LABEL_LENGTH: usize = 19; // cseucpkdfmtjapanese
839
840/// The initializer for the [Big5](static.BIG5.html) encoding.
841///
842/// For use only for taking the address of this form when
843/// Rust prohibits the use of the non-`_INIT` form directly,
844/// such as in initializers of other `static`s. If in doubt,
845/// use the corresponding non-`_INIT` reference-typed `static`.
846///
847/// This part of the public API will go away if Rust changes
848/// to make the referent of `pub const FOO: &'static Encoding`
849/// unique cross-crate or if Rust starts allowing static arrays
850/// to be initialized with `pub static FOO: &'static Encoding`
851/// items.
852pub static BIG5_INIT: Encoding = Encoding {
853    name: "Big5",
854    variant: VariantEncoding::Big5,
855};
856
857/// The Big5 encoding.
858///
859/// This is Big5 with HKSCS with mappings to more recent Unicode assignments
860/// instead of the Private Use Area code points that have been used historically.
861/// It is believed to be able to decode existing Web content in a way that makes
862/// sense.
863///
864/// To avoid form submissions generating data that Web servers don't understand,
865/// the encoder doesn't use the HKSCS byte sequences that precede the unextended
866/// Big5 in the lexical order.
867///
868/// [Index visualization](https://encoding.spec.whatwg.org/big5.html),
869/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/big5-bmp.html)
870///
871/// This encoding is designed to be suited for decoding the Windows code page 950
872/// and its HKSCS patched "951" variant such that the text makes sense, given
873/// assignments that Unicode has made after those encodings used Private Use
874/// Area characters.
875///
876/// This will change from `static` to `const` if Rust changes
877/// to make the referent of `pub const FOO: &'static Encoding`
878/// unique cross-crate, so don't take the address of this
879/// `static`.
880pub static BIG5: &'static Encoding = &BIG5_INIT;
881
882/// The initializer for the [EUC-JP](static.EUC_JP.html) encoding.
883///
884/// For use only for taking the address of this form when
885/// Rust prohibits the use of the non-`_INIT` form directly,
886/// such as in initializers of other `static`s. If in doubt,
887/// use the corresponding non-`_INIT` reference-typed `static`.
888///
889/// This part of the public API will go away if Rust changes
890/// to make the referent of `pub const FOO: &'static Encoding`
891/// unique cross-crate or if Rust starts allowing static arrays
892/// to be initialized with `pub static FOO: &'static Encoding`
893/// items.
894pub static EUC_JP_INIT: Encoding = Encoding {
895    name: "EUC-JP",
896    variant: VariantEncoding::EucJp,
897};
898
899/// The EUC-JP encoding.
900///
901/// This is the legacy Unix encoding for Japanese.
902///
903/// For compatibility with Web servers that don't expect three-byte sequences
904/// in form submissions, the encoder doesn't generate three-byte sequences.
905/// That is, the JIS X 0212 support is decode-only.
906///
907/// [Index visualization](https://encoding.spec.whatwg.org/jis0208.html),
908/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/jis0208-bmp.html)
909/// [Index visualization for decode-only JIS X 0212](https://encoding.spec.whatwg.org/jis0212.html),
910/// [Visualization of BMP coverage for decode-only JIS X 0212](https://encoding.spec.whatwg.org/jis0212-bmp.html)
911///
912/// This encoding roughly matches the Windows code page 20932. There are error
913/// handling differences and a handful of 2-byte sequences that decode differently.
914/// Additionall, Windows doesn't support 3-byte sequences.
915///
916/// This will change from `static` to `const` if Rust changes
917/// to make the referent of `pub const FOO: &'static Encoding`
918/// unique cross-crate, so don't take the address of this
919/// `static`.
920pub static EUC_JP: &'static Encoding = &EUC_JP_INIT;
921
922/// The initializer for the [EUC-KR](static.EUC_KR.html) encoding.
923///
924/// For use only for taking the address of this form when
925/// Rust prohibits the use of the non-`_INIT` form directly,
926/// such as in initializers of other `static`s. If in doubt,
927/// use the corresponding non-`_INIT` reference-typed `static`.
928///
929/// This part of the public API will go away if Rust changes
930/// to make the referent of `pub const FOO: &'static Encoding`
931/// unique cross-crate or if Rust starts allowing static arrays
932/// to be initialized with `pub static FOO: &'static Encoding`
933/// items.
934pub static EUC_KR_INIT: Encoding = Encoding {
935    name: "EUC-KR",
936    variant: VariantEncoding::EucKr,
937};
938
939/// The EUC-KR encoding.
940///
941/// This is the Korean encoding for Windows. It extends the Unix legacy encoding
942/// for Korean, based on KS X 1001 (which also formed the base of MacKorean on Mac OS
943/// Classic), with all the characters from the Hangul Syllables block of Unicode.
944///
945/// [Index visualization](https://encoding.spec.whatwg.org/euc-kr.html),
946/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/euc-kr-bmp.html)
947///
948/// This encoding matches the Windows code page 949, except Windows decodes byte 0x80
949/// to U+0080 and some byte sequences that are error per the Encoding Standard to
950/// the question mark or the Private Use Area.
951///
952/// This will change from `static` to `const` if Rust changes
953/// to make the referent of `pub const FOO: &'static Encoding`
954/// unique cross-crate, so don't take the address of this
955/// `static`.
956pub static EUC_KR: &'static Encoding = &EUC_KR_INIT;
957
958/// The initializer for the [GBK](static.GBK.html) encoding.
959///
960/// For use only for taking the address of this form when
961/// Rust prohibits the use of the non-`_INIT` form directly,
962/// such as in initializers of other `static`s. If in doubt,
963/// use the corresponding non-`_INIT` reference-typed `static`.
964///
965/// This part of the public API will go away if Rust changes
966/// to make the referent of `pub const FOO: &'static Encoding`
967/// unique cross-crate or if Rust starts allowing static arrays
968/// to be initialized with `pub static FOO: &'static Encoding`
969/// items.
970pub static GBK_INIT: Encoding = Encoding {
971    name: "GBK",
972    variant: VariantEncoding::Gbk,
973};
974
975/// The GBK encoding.
976///
977/// The decoder for this encoding is the same as the decoder for gb18030.
978/// The encoder side of this encoding is GBK with Windows code page 936 euro
979/// sign behavior and with the changes to two-byte sequences made in GB18030-2022.
980/// GBK extends GB2312-80 to cover the CJK Unified Ideographs Unicode block as
981/// well as a handful of ideographs from the CJK Unified Ideographs Extension A
982/// and CJK Compatibility Ideographs blocks.
983///
984/// Unlike e.g. in the case of ISO-8859-1 and windows-1252, GBK encoder wasn't
985/// unified with the gb18030 encoder in the Encoding Standard out of concern
986/// that servers that expect GBK form submissions might not be able to handle
987/// the four-byte sequences.
988///
989/// [Index visualization for the two-byte sequences](https://encoding.spec.whatwg.org/gb18030.html),
990/// [Visualization of BMP coverage of the two-byte index](https://encoding.spec.whatwg.org/gb18030-bmp.html)
991///
992/// The encoder of this encoding roughly matches the Windows code page 936.
993/// The decoder side is a superset.
994///
995/// This will change from `static` to `const` if Rust changes
996/// to make the referent of `pub const FOO: &'static Encoding`
997/// unique cross-crate, so don't take the address of this
998/// `static`.
999pub static GBK: &'static Encoding = &GBK_INIT;
1000
1001/// The initializer for the [IBM866](static.IBM866.html) encoding.
1002///
1003/// For use only for taking the address of this form when
1004/// Rust prohibits the use of the non-`_INIT` form directly,
1005/// such as in initializers of other `static`s. If in doubt,
1006/// use the corresponding non-`_INIT` reference-typed `static`.
1007///
1008/// This part of the public API will go away if Rust changes
1009/// to make the referent of `pub const FOO: &'static Encoding`
1010/// unique cross-crate or if Rust starts allowing static arrays
1011/// to be initialized with `pub static FOO: &'static Encoding`
1012/// items.
1013pub static IBM866_INIT: Encoding = Encoding {
1014    name: "IBM866",
1015    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.ibm866, 0x0440, 96, 16),
1016};
1017
1018/// The IBM866 encoding.
1019///
1020/// This the most notable one of the DOS Cyrillic code pages. It has the same
1021/// box drawing characters as code page 437, so it can be used for decoding
1022/// DOS-era ASCII + box drawing data.
1023///
1024/// [Index visualization](https://encoding.spec.whatwg.org/ibm866.html),
1025/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/ibm866-bmp.html)
1026///
1027/// This encoding matches the Windows code page 866.
1028///
1029/// This will change from `static` to `const` if Rust changes
1030/// to make the referent of `pub const FOO: &'static Encoding`
1031/// unique cross-crate, so don't take the address of this
1032/// `static`.
1033pub static IBM866: &'static Encoding = &IBM866_INIT;
1034
1035/// The initializer for the [ISO-2022-JP](static.ISO_2022_JP.html) encoding.
1036///
1037/// For use only for taking the address of this form when
1038/// Rust prohibits the use of the non-`_INIT` form directly,
1039/// such as in initializers of other `static`s. If in doubt,
1040/// use the corresponding non-`_INIT` reference-typed `static`.
1041///
1042/// This part of the public API will go away if Rust changes
1043/// to make the referent of `pub const FOO: &'static Encoding`
1044/// unique cross-crate or if Rust starts allowing static arrays
1045/// to be initialized with `pub static FOO: &'static Encoding`
1046/// items.
1047pub static ISO_2022_JP_INIT: Encoding = Encoding {
1048    name: "ISO-2022-JP",
1049    variant: VariantEncoding::Iso2022Jp,
1050};
1051
1052/// The ISO-2022-JP encoding.
1053///
1054/// This the primary pre-UTF-8 encoding for Japanese email. It uses the ASCII
1055/// byte range to encode non-Basic Latin characters. It's the only encoding
1056/// supported by this crate whose encoder is stateful.
1057///
1058/// [Index visualization](https://encoding.spec.whatwg.org/jis0208.html),
1059/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/jis0208-bmp.html)
1060///
1061/// This encoding roughly matches the Windows code page 50220. Notably, Windows
1062/// uses U+30FB in place of the REPLACEMENT CHARACTER and otherwise differs in
1063/// error handling.
1064///
1065/// This will change from `static` to `const` if Rust changes
1066/// to make the referent of `pub const FOO: &'static Encoding`
1067/// unique cross-crate, so don't take the address of this
1068/// `static`.
1069pub static ISO_2022_JP: &'static Encoding = &ISO_2022_JP_INIT;
1070
1071/// The initializer for the [ISO-8859-10](static.ISO_8859_10.html) encoding.
1072///
1073/// For use only for taking the address of this form when
1074/// Rust prohibits the use of the non-`_INIT` form directly,
1075/// such as in initializers of other `static`s. If in doubt,
1076/// use the corresponding non-`_INIT` reference-typed `static`.
1077///
1078/// This part of the public API will go away if Rust changes
1079/// to make the referent of `pub const FOO: &'static Encoding`
1080/// unique cross-crate or if Rust starts allowing static arrays
1081/// to be initialized with `pub static FOO: &'static Encoding`
1082/// items.
1083pub static ISO_8859_10_INIT: Encoding = Encoding {
1084    name: "ISO-8859-10",
1085    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.iso_8859_10, 0x00DA, 90, 6),
1086};
1087
1088/// The ISO-8859-10 encoding.
1089///
1090/// This is the Nordic part of the ISO/IEC 8859 encoding family. This encoding
1091/// is also known as Latin 6.
1092///
1093/// [Index visualization](https://encoding.spec.whatwg.org/iso-8859-10.html),
1094/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/iso-8859-10-bmp.html)
1095///
1096/// The Windows code page number for this encoding is 28600, but kernel32.dll
1097/// does not support this encoding.
1098///
1099/// This will change from `static` to `const` if Rust changes
1100/// to make the referent of `pub const FOO: &'static Encoding`
1101/// unique cross-crate, so don't take the address of this
1102/// `static`.
1103pub static ISO_8859_10: &'static Encoding = &ISO_8859_10_INIT;
1104
1105/// The initializer for the [ISO-8859-13](static.ISO_8859_13.html) encoding.
1106///
1107/// For use only for taking the address of this form when
1108/// Rust prohibits the use of the non-`_INIT` form directly,
1109/// such as in initializers of other `static`s. If in doubt,
1110/// use the corresponding non-`_INIT` reference-typed `static`.
1111///
1112/// This part of the public API will go away if Rust changes
1113/// to make the referent of `pub const FOO: &'static Encoding`
1114/// unique cross-crate or if Rust starts allowing static arrays
1115/// to be initialized with `pub static FOO: &'static Encoding`
1116/// items.
1117pub static ISO_8859_13_INIT: Encoding = Encoding {
1118    name: "ISO-8859-13",
1119    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.iso_8859_13, 0x00DF, 95, 1),
1120};
1121
1122/// The ISO-8859-13 encoding.
1123///
1124/// This is the Baltic part of the ISO/IEC 8859 encoding family. This encoding
1125/// is also known as Latin 7.
1126///
1127/// [Index visualization](https://encoding.spec.whatwg.org/iso-8859-13.html),
1128/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/iso-8859-13-bmp.html)
1129///
1130/// This encoding matches the Windows code page 28603, except Windows decodes
1131/// unassigned code points to the Private Use Area of Unicode.
1132///
1133/// This will change from `static` to `const` if Rust changes
1134/// to make the referent of `pub const FOO: &'static Encoding`
1135/// unique cross-crate, so don't take the address of this
1136/// `static`.
1137pub static ISO_8859_13: &'static Encoding = &ISO_8859_13_INIT;
1138
1139/// The initializer for the [ISO-8859-14](static.ISO_8859_14.html) encoding.
1140///
1141/// For use only for taking the address of this form when
1142/// Rust prohibits the use of the non-`_INIT` form directly,
1143/// such as in initializers of other `static`s. If in doubt,
1144/// use the corresponding non-`_INIT` reference-typed `static`.
1145///
1146/// This part of the public API will go away if Rust changes
1147/// to make the referent of `pub const FOO: &'static Encoding`
1148/// unique cross-crate or if Rust starts allowing static arrays
1149/// to be initialized with `pub static FOO: &'static Encoding`
1150/// items.
1151pub static ISO_8859_14_INIT: Encoding = Encoding {
1152    name: "ISO-8859-14",
1153    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.iso_8859_14, 0x00DF, 95, 17),
1154};
1155
1156/// The ISO-8859-14 encoding.
1157///
1158/// This is the Celtic part of the ISO/IEC 8859 encoding family. This encoding
1159/// is also known as Latin 8.
1160///
1161/// [Index visualization](https://encoding.spec.whatwg.org/iso-8859-14.html),
1162/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/iso-8859-14-bmp.html)
1163///
1164/// The Windows code page number for this encoding is 28604, but kernel32.dll
1165/// does not support this encoding.
1166///
1167/// This will change from `static` to `const` if Rust changes
1168/// to make the referent of `pub const FOO: &'static Encoding`
1169/// unique cross-crate, so don't take the address of this
1170/// `static`.
1171pub static ISO_8859_14: &'static Encoding = &ISO_8859_14_INIT;
1172
1173/// The initializer for the [ISO-8859-15](static.ISO_8859_15.html) encoding.
1174///
1175/// For use only for taking the address of this form when
1176/// Rust prohibits the use of the non-`_INIT` form directly,
1177/// such as in initializers of other `static`s. If in doubt,
1178/// use the corresponding non-`_INIT` reference-typed `static`.
1179///
1180/// This part of the public API will go away if Rust changes
1181/// to make the referent of `pub const FOO: &'static Encoding`
1182/// unique cross-crate or if Rust starts allowing static arrays
1183/// to be initialized with `pub static FOO: &'static Encoding`
1184/// items.
1185pub static ISO_8859_15_INIT: Encoding = Encoding {
1186    name: "ISO-8859-15",
1187    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.iso_8859_15, 0x00BF, 63, 65),
1188};
1189
1190/// The ISO-8859-15 encoding.
1191///
1192/// This is the revised Western European part of the ISO/IEC 8859 encoding
1193/// family. This encoding is also known as Latin 9.
1194///
1195/// [Index visualization](https://encoding.spec.whatwg.org/iso-8859-15.html),
1196/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/iso-8859-15-bmp.html)
1197///
1198/// This encoding matches the Windows code page 28605.
1199///
1200/// This will change from `static` to `const` if Rust changes
1201/// to make the referent of `pub const FOO: &'static Encoding`
1202/// unique cross-crate, so don't take the address of this
1203/// `static`.
1204pub static ISO_8859_15: &'static Encoding = &ISO_8859_15_INIT;
1205
1206/// The initializer for the [ISO-8859-16](static.ISO_8859_16.html) encoding.
1207///
1208/// For use only for taking the address of this form when
1209/// Rust prohibits the use of the non-`_INIT` form directly,
1210/// such as in initializers of other `static`s. If in doubt,
1211/// use the corresponding non-`_INIT` reference-typed `static`.
1212///
1213/// This part of the public API will go away if Rust changes
1214/// to make the referent of `pub const FOO: &'static Encoding`
1215/// unique cross-crate or if Rust starts allowing static arrays
1216/// to be initialized with `pub static FOO: &'static Encoding`
1217/// items.
1218pub static ISO_8859_16_INIT: Encoding = Encoding {
1219    name: "ISO-8859-16",
1220    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.iso_8859_16, 0x00DF, 95, 4),
1221};
1222
1223/// The ISO-8859-16 encoding.
1224///
1225/// This is the South-Eastern European part of the ISO/IEC 8859 encoding
1226/// family. This encoding is also known as Latin 10.
1227///
1228/// [Index visualization](https://encoding.spec.whatwg.org/iso-8859-16.html),
1229/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/iso-8859-16-bmp.html)
1230///
1231/// The Windows code page number for this encoding is 28606, but kernel32.dll
1232/// does not support this encoding.
1233///
1234/// This will change from `static` to `const` if Rust changes
1235/// to make the referent of `pub const FOO: &'static Encoding`
1236/// unique cross-crate, so don't take the address of this
1237/// `static`.
1238pub static ISO_8859_16: &'static Encoding = &ISO_8859_16_INIT;
1239
1240/// The initializer for the [ISO-8859-2](static.ISO_8859_2.html) encoding.
1241///
1242/// For use only for taking the address of this form when
1243/// Rust prohibits the use of the non-`_INIT` form directly,
1244/// such as in initializers of other `static`s. If in doubt,
1245/// use the corresponding non-`_INIT` reference-typed `static`.
1246///
1247/// This part of the public API will go away if Rust changes
1248/// to make the referent of `pub const FOO: &'static Encoding`
1249/// unique cross-crate or if Rust starts allowing static arrays
1250/// to be initialized with `pub static FOO: &'static Encoding`
1251/// items.
1252pub static ISO_8859_2_INIT: Encoding = Encoding {
1253    name: "ISO-8859-2",
1254    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.iso_8859_2, 0x00DF, 95, 1),
1255};
1256
1257/// The ISO-8859-2 encoding.
1258///
1259/// This is the Central European part of the ISO/IEC 8859 encoding family. This encoding is also known as Latin 2.
1260///
1261/// [Index visualization](https://encoding.spec.whatwg.org/iso-8859-2.html),
1262/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/iso-8859-2-bmp.html)
1263///
1264/// This encoding matches the Windows code page 28592.
1265///
1266/// This will change from `static` to `const` if Rust changes
1267/// to make the referent of `pub const FOO: &'static Encoding`
1268/// unique cross-crate, so don't take the address of this
1269/// `static`.
1270pub static ISO_8859_2: &'static Encoding = &ISO_8859_2_INIT;
1271
1272/// The initializer for the [ISO-8859-3](static.ISO_8859_3.html) encoding.
1273///
1274/// For use only for taking the address of this form when
1275/// Rust prohibits the use of the non-`_INIT` form directly,
1276/// such as in initializers of other `static`s. If in doubt,
1277/// use the corresponding non-`_INIT` reference-typed `static`.
1278///
1279/// This part of the public API will go away if Rust changes
1280/// to make the referent of `pub const FOO: &'static Encoding`
1281/// unique cross-crate or if Rust starts allowing static arrays
1282/// to be initialized with `pub static FOO: &'static Encoding`
1283/// items.
1284pub static ISO_8859_3_INIT: Encoding = Encoding {
1285    name: "ISO-8859-3",
1286    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.iso_8859_3, 0x00DF, 95, 4),
1287};
1288
1289/// The ISO-8859-3 encoding.
1290///
1291/// This is the South European part of the ISO/IEC 8859 encoding family. This encoding is also known as Latin 3.
1292///
1293/// [Index visualization](https://encoding.spec.whatwg.org/iso-8859-3.html),
1294/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/iso-8859-3-bmp.html)
1295///
1296/// This encoding matches the Windows code page 28593.
1297///
1298/// This will change from `static` to `const` if Rust changes
1299/// to make the referent of `pub const FOO: &'static Encoding`
1300/// unique cross-crate, so don't take the address of this
1301/// `static`.
1302pub static ISO_8859_3: &'static Encoding = &ISO_8859_3_INIT;
1303
1304/// The initializer for the [ISO-8859-4](static.ISO_8859_4.html) encoding.
1305///
1306/// For use only for taking the address of this form when
1307/// Rust prohibits the use of the non-`_INIT` form directly,
1308/// such as in initializers of other `static`s. If in doubt,
1309/// use the corresponding non-`_INIT` reference-typed `static`.
1310///
1311/// This part of the public API will go away if Rust changes
1312/// to make the referent of `pub const FOO: &'static Encoding`
1313/// unique cross-crate or if Rust starts allowing static arrays
1314/// to be initialized with `pub static FOO: &'static Encoding`
1315/// items.
1316pub static ISO_8859_4_INIT: Encoding = Encoding {
1317    name: "ISO-8859-4",
1318    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.iso_8859_4, 0x00DF, 95, 1),
1319};
1320
1321/// The ISO-8859-4 encoding.
1322///
1323/// This is the North European part of the ISO/IEC 8859 encoding family. This encoding is also known as Latin 4.
1324///
1325/// [Index visualization](https://encoding.spec.whatwg.org/iso-8859-4.html),
1326/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/iso-8859-4-bmp.html)
1327///
1328/// This encoding matches the Windows code page 28594.
1329///
1330/// This will change from `static` to `const` if Rust changes
1331/// to make the referent of `pub const FOO: &'static Encoding`
1332/// unique cross-crate, so don't take the address of this
1333/// `static`.
1334pub static ISO_8859_4: &'static Encoding = &ISO_8859_4_INIT;
1335
1336/// The initializer for the [ISO-8859-5](static.ISO_8859_5.html) encoding.
1337///
1338/// For use only for taking the address of this form when
1339/// Rust prohibits the use of the non-`_INIT` form directly,
1340/// such as in initializers of other `static`s. If in doubt,
1341/// use the corresponding non-`_INIT` reference-typed `static`.
1342///
1343/// This part of the public API will go away if Rust changes
1344/// to make the referent of `pub const FOO: &'static Encoding`
1345/// unique cross-crate or if Rust starts allowing static arrays
1346/// to be initialized with `pub static FOO: &'static Encoding`
1347/// items.
1348pub static ISO_8859_5_INIT: Encoding = Encoding {
1349    name: "ISO-8859-5",
1350    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.iso_8859_5, 0x040E, 46, 66),
1351};
1352
1353/// The ISO-8859-5 encoding.
1354///
1355/// This is the Cyrillic part of the ISO/IEC 8859 encoding family.
1356///
1357/// [Index visualization](https://encoding.spec.whatwg.org/iso-8859-5.html),
1358/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/iso-8859-5-bmp.html)
1359///
1360/// This encoding matches the Windows code page 28595.
1361///
1362/// This will change from `static` to `const` if Rust changes
1363/// to make the referent of `pub const FOO: &'static Encoding`
1364/// unique cross-crate, so don't take the address of this
1365/// `static`.
1366pub static ISO_8859_5: &'static Encoding = &ISO_8859_5_INIT;
1367
1368/// The initializer for the [ISO-8859-6](static.ISO_8859_6.html) encoding.
1369///
1370/// For use only for taking the address of this form when
1371/// Rust prohibits the use of the non-`_INIT` form directly,
1372/// such as in initializers of other `static`s. If in doubt,
1373/// use the corresponding non-`_INIT` reference-typed `static`.
1374///
1375/// This part of the public API will go away if Rust changes
1376/// to make the referent of `pub const FOO: &'static Encoding`
1377/// unique cross-crate or if Rust starts allowing static arrays
1378/// to be initialized with `pub static FOO: &'static Encoding`
1379/// items.
1380pub static ISO_8859_6_INIT: Encoding = Encoding {
1381    name: "ISO-8859-6",
1382    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.iso_8859_6, 0x0621, 65, 26),
1383};
1384
1385/// The ISO-8859-6 encoding.
1386///
1387/// This is the Arabic part of the ISO/IEC 8859 encoding family.
1388///
1389/// [Index visualization](https://encoding.spec.whatwg.org/iso-8859-6.html),
1390/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/iso-8859-6-bmp.html)
1391///
1392/// This encoding matches the Windows code page 28596, except Windows decodes
1393/// unassigned code points to the Private Use Area of Unicode.
1394///
1395/// This will change from `static` to `const` if Rust changes
1396/// to make the referent of `pub const FOO: &'static Encoding`
1397/// unique cross-crate, so don't take the address of this
1398/// `static`.
1399pub static ISO_8859_6: &'static Encoding = &ISO_8859_6_INIT;
1400
1401/// The initializer for the [ISO-8859-7](static.ISO_8859_7.html) encoding.
1402///
1403/// For use only for taking the address of this form when
1404/// Rust prohibits the use of the non-`_INIT` form directly,
1405/// such as in initializers of other `static`s. If in doubt,
1406/// use the corresponding non-`_INIT` reference-typed `static`.
1407///
1408/// This part of the public API will go away if Rust changes
1409/// to make the referent of `pub const FOO: &'static Encoding`
1410/// unique cross-crate or if Rust starts allowing static arrays
1411/// to be initialized with `pub static FOO: &'static Encoding`
1412/// items.
1413pub static ISO_8859_7_INIT: Encoding = Encoding {
1414    name: "ISO-8859-7",
1415    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.iso_8859_7, 0x03A3, 83, 44),
1416};
1417
1418/// The ISO-8859-7 encoding.
1419///
1420/// This is the Greek part of the ISO/IEC 8859 encoding family.
1421///
1422/// [Index visualization](https://encoding.spec.whatwg.org/iso-8859-7.html),
1423/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/iso-8859-7-bmp.html)
1424///
1425/// This encoding roughly matches the Windows code page 28597. Windows decodes
1426/// unassigned code points, the currency signs at 0xA4 and 0xA5 as well as
1427/// 0xAA, which should be U+037A GREEK YPOGEGRAMMENI, to the Private Use Area
1428/// of Unicode. Windows decodes 0xA1 to U+02BD MODIFIER LETTER REVERSED COMMA
1429/// instead of U+2018 LEFT SINGLE QUOTATION MARK and 0xA2 to U+02BC MODIFIER
1430/// LETTER APOSTROPHE instead of U+2019 RIGHT SINGLE QUOTATION MARK.
1431///
1432/// This will change from `static` to `const` if Rust changes
1433/// to make the referent of `pub const FOO: &'static Encoding`
1434/// unique cross-crate, so don't take the address of this
1435/// `static`.
1436pub static ISO_8859_7: &'static Encoding = &ISO_8859_7_INIT;
1437
1438/// The initializer for the [ISO-8859-8](static.ISO_8859_8.html) encoding.
1439///
1440/// For use only for taking the address of this form when
1441/// Rust prohibits the use of the non-`_INIT` form directly,
1442/// such as in initializers of other `static`s. If in doubt,
1443/// use the corresponding non-`_INIT` reference-typed `static`.
1444///
1445/// This part of the public API will go away if Rust changes
1446/// to make the referent of `pub const FOO: &'static Encoding`
1447/// unique cross-crate or if Rust starts allowing static arrays
1448/// to be initialized with `pub static FOO: &'static Encoding`
1449/// items.
1450pub static ISO_8859_8_INIT: Encoding = Encoding {
1451    name: "ISO-8859-8",
1452    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.iso_8859_8, 0x05D0, 96, 27),
1453};
1454
1455/// The ISO-8859-8 encoding.
1456///
1457/// This is the Hebrew part of the ISO/IEC 8859 encoding family in visual order.
1458///
1459/// [Index visualization](https://encoding.spec.whatwg.org/iso-8859-8.html),
1460/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/iso-8859-8-bmp.html)
1461///
1462/// This encoding roughly matches the Windows code page 28598. Windows decodes
1463/// 0xAF to OVERLINE instead of MACRON and 0xFE and 0xFD to the Private Use
1464/// Area instead of LRM and RLM. Windows decodes unassigned code points to
1465/// the private use area.
1466///
1467/// This will change from `static` to `const` if Rust changes
1468/// to make the referent of `pub const FOO: &'static Encoding`
1469/// unique cross-crate, so don't take the address of this
1470/// `static`.
1471pub static ISO_8859_8: &'static Encoding = &ISO_8859_8_INIT;
1472
1473/// The initializer for the [ISO-8859-8-I](static.ISO_8859_8_I.html) encoding.
1474///
1475/// For use only for taking the address of this form when
1476/// Rust prohibits the use of the non-`_INIT` form directly,
1477/// such as in initializers of other `static`s. If in doubt,
1478/// use the corresponding non-`_INIT` reference-typed `static`.
1479///
1480/// This part of the public API will go away if Rust changes
1481/// to make the referent of `pub const FOO: &'static Encoding`
1482/// unique cross-crate or if Rust starts allowing static arrays
1483/// to be initialized with `pub static FOO: &'static Encoding`
1484/// items.
1485pub static ISO_8859_8_I_INIT: Encoding = Encoding {
1486    name: "ISO-8859-8-I",
1487    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.iso_8859_8, 0x05D0, 96, 27),
1488};
1489
1490/// The ISO-8859-8-I encoding.
1491///
1492/// This is the Hebrew part of the ISO/IEC 8859 encoding family in logical order.
1493///
1494/// [Index visualization](https://encoding.spec.whatwg.org/iso-8859-8.html),
1495/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/iso-8859-8-bmp.html)
1496///
1497/// This encoding roughly matches the Windows code page 38598. Windows decodes
1498/// 0xAF to OVERLINE instead of MACRON and 0xFE and 0xFD to the Private Use
1499/// Area instead of LRM and RLM. Windows decodes unassigned code points to
1500/// the private use area.
1501///
1502/// This will change from `static` to `const` if Rust changes
1503/// to make the referent of `pub const FOO: &'static Encoding`
1504/// unique cross-crate, so don't take the address of this
1505/// `static`.
1506pub static ISO_8859_8_I: &'static Encoding = &ISO_8859_8_I_INIT;
1507
1508/// The initializer for the [KOI8-R](static.KOI8_R.html) encoding.
1509///
1510/// For use only for taking the address of this form when
1511/// Rust prohibits the use of the non-`_INIT` form directly,
1512/// such as in initializers of other `static`s. If in doubt,
1513/// use the corresponding non-`_INIT` reference-typed `static`.
1514///
1515/// This part of the public API will go away if Rust changes
1516/// to make the referent of `pub const FOO: &'static Encoding`
1517/// unique cross-crate or if Rust starts allowing static arrays
1518/// to be initialized with `pub static FOO: &'static Encoding`
1519/// items.
1520pub static KOI8_R_INIT: Encoding = Encoding {
1521    name: "KOI8-R",
1522    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.koi8_r, 0x044E, 64, 1),
1523};
1524
1525/// The KOI8-R encoding.
1526///
1527/// This is an encoding for Russian from [RFC 1489](https://tools.ietf.org/html/rfc1489).
1528///
1529/// [Index visualization](https://encoding.spec.whatwg.org/koi8-r.html),
1530/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/koi8-r-bmp.html)
1531///
1532/// This encoding matches the Windows code page 20866.
1533///
1534/// This will change from `static` to `const` if Rust changes
1535/// to make the referent of `pub const FOO: &'static Encoding`
1536/// unique cross-crate, so don't take the address of this
1537/// `static`.
1538pub static KOI8_R: &'static Encoding = &KOI8_R_INIT;
1539
1540/// The initializer for the [KOI8-U](static.KOI8_U.html) encoding.
1541///
1542/// For use only for taking the address of this form when
1543/// Rust prohibits the use of the non-`_INIT` form directly,
1544/// such as in initializers of other `static`s. If in doubt,
1545/// use the corresponding non-`_INIT` reference-typed `static`.
1546///
1547/// This part of the public API will go away if Rust changes
1548/// to make the referent of `pub const FOO: &'static Encoding`
1549/// unique cross-crate or if Rust starts allowing static arrays
1550/// to be initialized with `pub static FOO: &'static Encoding`
1551/// items.
1552pub static KOI8_U_INIT: Encoding = Encoding {
1553    name: "KOI8-U",
1554    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.koi8_u, 0x044E, 64, 1),
1555};
1556
1557/// The KOI8-U encoding.
1558///
1559/// This is an encoding for Ukrainian adapted from KOI8-R.
1560///
1561/// [Index visualization](https://encoding.spec.whatwg.org/koi8-u.html),
1562/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/koi8-u-bmp.html)
1563///
1564/// This encoding matches the Windows code page 21866.
1565///
1566/// This will change from `static` to `const` if Rust changes
1567/// to make the referent of `pub const FOO: &'static Encoding`
1568/// unique cross-crate, so don't take the address of this
1569/// `static`.
1570pub static KOI8_U: &'static Encoding = &KOI8_U_INIT;
1571
1572/// The initializer for the [Shift_JIS](static.SHIFT_JIS.html) encoding.
1573///
1574/// For use only for taking the address of this form when
1575/// Rust prohibits the use of the non-`_INIT` form directly,
1576/// such as in initializers of other `static`s. If in doubt,
1577/// use the corresponding non-`_INIT` reference-typed `static`.
1578///
1579/// This part of the public API will go away if Rust changes
1580/// to make the referent of `pub const FOO: &'static Encoding`
1581/// unique cross-crate or if Rust starts allowing static arrays
1582/// to be initialized with `pub static FOO: &'static Encoding`
1583/// items.
1584pub static SHIFT_JIS_INIT: Encoding = Encoding {
1585    name: "Shift_JIS",
1586    variant: VariantEncoding::ShiftJis,
1587};
1588
1589/// The Shift_JIS encoding.
1590///
1591/// This is the Japanese encoding for Windows.
1592///
1593/// [Index visualization](https://encoding.spec.whatwg.org/shift_jis.html),
1594/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/shift_jis-bmp.html)
1595///
1596/// This encoding matches the Windows code page 932, except Windows decodes some byte
1597/// sequences that are error per the Encoding Standard to the question mark or the
1598/// Private Use Area and generally uses U+30FB in place of the REPLACEMENT CHARACTER.
1599///
1600/// This will change from `static` to `const` if Rust changes
1601/// to make the referent of `pub const FOO: &'static Encoding`
1602/// unique cross-crate, so don't take the address of this
1603/// `static`.
1604pub static SHIFT_JIS: &'static Encoding = &SHIFT_JIS_INIT;
1605
1606/// The initializer for the [UTF-16BE](static.UTF_16BE.html) encoding.
1607///
1608/// For use only for taking the address of this form when
1609/// Rust prohibits the use of the non-`_INIT` form directly,
1610/// such as in initializers of other `static`s. If in doubt,
1611/// use the corresponding non-`_INIT` reference-typed `static`.
1612///
1613/// This part of the public API will go away if Rust changes
1614/// to make the referent of `pub const FOO: &'static Encoding`
1615/// unique cross-crate or if Rust starts allowing static arrays
1616/// to be initialized with `pub static FOO: &'static Encoding`
1617/// items.
1618pub static UTF_16BE_INIT: Encoding = Encoding {
1619    name: "UTF-16BE",
1620    variant: VariantEncoding::Utf16Be,
1621};
1622
1623/// The UTF-16BE encoding.
1624///
1625/// This decode-only encoding uses 16-bit code units due to Unicode originally
1626/// having been designed as a 16-bit reportoire. In the absence of a byte order
1627/// mark the big endian byte order is assumed.
1628///
1629/// There is no corresponding encoder in this crate or in the Encoding
1630/// Standard. The output encoding of this encoding is UTF-8.
1631///
1632/// This encoding matches the Windows code page 1201.
1633///
1634/// This will change from `static` to `const` if Rust changes
1635/// to make the referent of `pub const FOO: &'static Encoding`
1636/// unique cross-crate, so don't take the address of this
1637/// `static`.
1638pub static UTF_16BE: &'static Encoding = &UTF_16BE_INIT;
1639
1640/// The initializer for the [UTF-16LE](static.UTF_16LE.html) encoding.
1641///
1642/// For use only for taking the address of this form when
1643/// Rust prohibits the use of the non-`_INIT` form directly,
1644/// such as in initializers of other `static`s. If in doubt,
1645/// use the corresponding non-`_INIT` reference-typed `static`.
1646///
1647/// This part of the public API will go away if Rust changes
1648/// to make the referent of `pub const FOO: &'static Encoding`
1649/// unique cross-crate or if Rust starts allowing static arrays
1650/// to be initialized with `pub static FOO: &'static Encoding`
1651/// items.
1652pub static UTF_16LE_INIT: Encoding = Encoding {
1653    name: "UTF-16LE",
1654    variant: VariantEncoding::Utf16Le,
1655};
1656
1657/// The UTF-16LE encoding.
1658///
1659/// This decode-only encoding uses 16-bit code units due to Unicode originally
1660/// having been designed as a 16-bit reportoire. In the absence of a byte order
1661/// mark the little endian byte order is assumed.
1662///
1663/// There is no corresponding encoder in this crate or in the Encoding
1664/// Standard. The output encoding of this encoding is UTF-8.
1665///
1666/// This encoding matches the Windows code page 1200.
1667///
1668/// This will change from `static` to `const` if Rust changes
1669/// to make the referent of `pub const FOO: &'static Encoding`
1670/// unique cross-crate, so don't take the address of this
1671/// `static`.
1672pub static UTF_16LE: &'static Encoding = &UTF_16LE_INIT;
1673
1674/// The initializer for the [UTF-8](static.UTF_8.html) encoding.
1675///
1676/// For use only for taking the address of this form when
1677/// Rust prohibits the use of the non-`_INIT` form directly,
1678/// such as in initializers of other `static`s. If in doubt,
1679/// use the corresponding non-`_INIT` reference-typed `static`.
1680///
1681/// This part of the public API will go away if Rust changes
1682/// to make the referent of `pub const FOO: &'static Encoding`
1683/// unique cross-crate or if Rust starts allowing static arrays
1684/// to be initialized with `pub static FOO: &'static Encoding`
1685/// items.
1686pub static UTF_8_INIT: Encoding = Encoding {
1687    name: "UTF-8",
1688    variant: VariantEncoding::Utf8,
1689};
1690
1691/// The UTF-8 encoding.
1692///
1693/// This is the encoding that should be used for all new development as it can
1694/// represent all of Unicode.
1695///
1696/// This encoding matches the Windows code page 65001, except Windows differs
1697/// in the number of errors generated for some erroneous byte sequences.
1698///
1699/// This will change from `static` to `const` if Rust changes
1700/// to make the referent of `pub const FOO: &'static Encoding`
1701/// unique cross-crate, so don't take the address of this
1702/// `static`.
1703pub static UTF_8: &'static Encoding = &UTF_8_INIT;
1704
1705/// The initializer for the [gb18030](static.GB18030.html) encoding.
1706///
1707/// For use only for taking the address of this form when
1708/// Rust prohibits the use of the non-`_INIT` form directly,
1709/// such as in initializers of other `static`s. If in doubt,
1710/// use the corresponding non-`_INIT` reference-typed `static`.
1711///
1712/// This part of the public API will go away if Rust changes
1713/// to make the referent of `pub const FOO: &'static Encoding`
1714/// unique cross-crate or if Rust starts allowing static arrays
1715/// to be initialized with `pub static FOO: &'static Encoding`
1716/// items.
1717pub static GB18030_INIT: Encoding = Encoding {
1718    name: "gb18030",
1719    variant: VariantEncoding::Gb18030,
1720};
1721
1722/// The gb18030 encoding.
1723///
1724/// This encoding matches GB18030-2022 except the two-byte sequence 0xA3 0xA0
1725/// maps to U+3000 for compatibility with existing Web content and the four-byte
1726/// sequences for the non-PUA characters that got two-byte sequences still decode
1727/// to the same non-PUA characters as in GB18030-2005. As a result, this encoding
1728/// can represent all of Unicode except for 19 private-use characters.
1729///
1730/// [Index visualization for the two-byte sequences](https://encoding.spec.whatwg.org/gb18030.html),
1731/// [Visualization of BMP coverage of the two-byte index](https://encoding.spec.whatwg.org/gb18030-bmp.html)
1732///
1733/// This encoding matches the Windows code page 54936.
1734///
1735/// This will change from `static` to `const` if Rust changes
1736/// to make the referent of `pub const FOO: &'static Encoding`
1737/// unique cross-crate, so don't take the address of this
1738/// `static`.
1739pub static GB18030: &'static Encoding = &GB18030_INIT;
1740
1741/// The initializer for the [macintosh](static.MACINTOSH.html) encoding.
1742///
1743/// For use only for taking the address of this form when
1744/// Rust prohibits the use of the non-`_INIT` form directly,
1745/// such as in initializers of other `static`s. If in doubt,
1746/// use the corresponding non-`_INIT` reference-typed `static`.
1747///
1748/// This part of the public API will go away if Rust changes
1749/// to make the referent of `pub const FOO: &'static Encoding`
1750/// unique cross-crate or if Rust starts allowing static arrays
1751/// to be initialized with `pub static FOO: &'static Encoding`
1752/// items.
1753pub static MACINTOSH_INIT: Encoding = Encoding {
1754    name: "macintosh",
1755    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.macintosh, 0x00CD, 106, 3),
1756};
1757
1758/// The macintosh encoding.
1759///
1760/// This is the MacRoman encoding from Mac OS Classic.
1761///
1762/// [Index visualization](https://encoding.spec.whatwg.org/macintosh.html),
1763/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/macintosh-bmp.html)
1764///
1765/// This encoding matches the Windows code page 10000, except Windows decodes
1766/// 0xBD to U+2126 OHM SIGN instead of U+03A9 GREEK CAPITAL LETTER OMEGA.
1767///
1768/// This will change from `static` to `const` if Rust changes
1769/// to make the referent of `pub const FOO: &'static Encoding`
1770/// unique cross-crate, so don't take the address of this
1771/// `static`.
1772pub static MACINTOSH: &'static Encoding = &MACINTOSH_INIT;
1773
1774/// The initializer for the [replacement](static.REPLACEMENT.html) encoding.
1775///
1776/// For use only for taking the address of this form when
1777/// Rust prohibits the use of the non-`_INIT` form directly,
1778/// such as in initializers of other `static`s. If in doubt,
1779/// use the corresponding non-`_INIT` reference-typed `static`.
1780///
1781/// This part of the public API will go away if Rust changes
1782/// to make the referent of `pub const FOO: &'static Encoding`
1783/// unique cross-crate or if Rust starts allowing static arrays
1784/// to be initialized with `pub static FOO: &'static Encoding`
1785/// items.
1786pub static REPLACEMENT_INIT: Encoding = Encoding {
1787    name: "replacement",
1788    variant: VariantEncoding::Replacement,
1789};
1790
1791/// The replacement encoding.
1792///
1793/// This decode-only encoding decodes all non-zero-length streams to a single
1794/// REPLACEMENT CHARACTER. Its purpose is to avoid the use of an
1795/// ASCII-compatible fallback encoding (typically windows-1252) for some
1796/// encodings that are no longer supported by the Web Platform and that
1797/// would be dangerous to treat as ASCII-compatible.
1798///
1799/// There is no corresponding encoder. The output encoding of this encoding
1800/// is UTF-8.
1801///
1802/// This encoding does not have a Windows code page number.
1803///
1804/// This will change from `static` to `const` if Rust changes
1805/// to make the referent of `pub const FOO: &'static Encoding`
1806/// unique cross-crate, so don't take the address of this
1807/// `static`.
1808pub static REPLACEMENT: &'static Encoding = &REPLACEMENT_INIT;
1809
1810/// The initializer for the [windows-1250](static.WINDOWS_1250.html) encoding.
1811///
1812/// For use only for taking the address of this form when
1813/// Rust prohibits the use of the non-`_INIT` form directly,
1814/// such as in initializers of other `static`s. If in doubt,
1815/// use the corresponding non-`_INIT` reference-typed `static`.
1816///
1817/// This part of the public API will go away if Rust changes
1818/// to make the referent of `pub const FOO: &'static Encoding`
1819/// unique cross-crate or if Rust starts allowing static arrays
1820/// to be initialized with `pub static FOO: &'static Encoding`
1821/// items.
1822pub static WINDOWS_1250_INIT: Encoding = Encoding {
1823    name: "windows-1250",
1824    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.windows_1250, 0x00DC, 92, 2),
1825};
1826
1827/// The windows-1250 encoding.
1828///
1829/// This is the Central European encoding for Windows.
1830///
1831/// [Index visualization](https://encoding.spec.whatwg.org/windows-1250.html),
1832/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/windows-1250-bmp.html)
1833///
1834/// This encoding matches the Windows code page 1250.
1835///
1836/// This will change from `static` to `const` if Rust changes
1837/// to make the referent of `pub const FOO: &'static Encoding`
1838/// unique cross-crate, so don't take the address of this
1839/// `static`.
1840pub static WINDOWS_1250: &'static Encoding = &WINDOWS_1250_INIT;
1841
1842/// The initializer for the [windows-1251](static.WINDOWS_1251.html) encoding.
1843///
1844/// For use only for taking the address of this form when
1845/// Rust prohibits the use of the non-`_INIT` form directly,
1846/// such as in initializers of other `static`s. If in doubt,
1847/// use the corresponding non-`_INIT` reference-typed `static`.
1848///
1849/// This part of the public API will go away if Rust changes
1850/// to make the referent of `pub const FOO: &'static Encoding`
1851/// unique cross-crate or if Rust starts allowing static arrays
1852/// to be initialized with `pub static FOO: &'static Encoding`
1853/// items.
1854pub static WINDOWS_1251_INIT: Encoding = Encoding {
1855    name: "windows-1251",
1856    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.windows_1251, 0x0410, 64, 64),
1857};
1858
1859/// The windows-1251 encoding.
1860///
1861/// This is the Cyrillic encoding for Windows.
1862///
1863/// [Index visualization](https://encoding.spec.whatwg.org/windows-1251.html),
1864/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/windows-1251-bmp.html)
1865///
1866/// This encoding matches the Windows code page 1251.
1867///
1868/// This will change from `static` to `const` if Rust changes
1869/// to make the referent of `pub const FOO: &'static Encoding`
1870/// unique cross-crate, so don't take the address of this
1871/// `static`.
1872pub static WINDOWS_1251: &'static Encoding = &WINDOWS_1251_INIT;
1873
1874/// The initializer for the [windows-1252](static.WINDOWS_1252.html) encoding.
1875///
1876/// For use only for taking the address of this form when
1877/// Rust prohibits the use of the non-`_INIT` form directly,
1878/// such as in initializers of other `static`s. If in doubt,
1879/// use the corresponding non-`_INIT` reference-typed `static`.
1880///
1881/// This part of the public API will go away if Rust changes
1882/// to make the referent of `pub const FOO: &'static Encoding`
1883/// unique cross-crate or if Rust starts allowing static arrays
1884/// to be initialized with `pub static FOO: &'static Encoding`
1885/// items.
1886pub static WINDOWS_1252_INIT: Encoding = Encoding {
1887    name: "windows-1252",
1888    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.windows_1252, 0x00A0, 32, 96),
1889};
1890
1891/// The windows-1252 encoding.
1892///
1893/// This is the Western encoding for Windows. It is an extension of ISO-8859-1,
1894/// which is known as Latin 1.
1895///
1896/// [Index visualization](https://encoding.spec.whatwg.org/windows-1252.html),
1897/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/windows-1252-bmp.html)
1898///
1899/// This encoding matches the Windows code page 1252.
1900///
1901/// This will change from `static` to `const` if Rust changes
1902/// to make the referent of `pub const FOO: &'static Encoding`
1903/// unique cross-crate, so don't take the address of this
1904/// `static`.
1905pub static WINDOWS_1252: &'static Encoding = &WINDOWS_1252_INIT;
1906
1907/// The initializer for the [windows-1253](static.WINDOWS_1253.html) encoding.
1908///
1909/// For use only for taking the address of this form when
1910/// Rust prohibits the use of the non-`_INIT` form directly,
1911/// such as in initializers of other `static`s. If in doubt,
1912/// use the corresponding non-`_INIT` reference-typed `static`.
1913///
1914/// This part of the public API will go away if Rust changes
1915/// to make the referent of `pub const FOO: &'static Encoding`
1916/// unique cross-crate or if Rust starts allowing static arrays
1917/// to be initialized with `pub static FOO: &'static Encoding`
1918/// items.
1919pub static WINDOWS_1253_INIT: Encoding = Encoding {
1920    name: "windows-1253",
1921    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.windows_1253, 0x03A3, 83, 44),
1922};
1923
1924/// The windows-1253 encoding.
1925///
1926/// This is the Greek encoding for Windows. It is mostly an extension of
1927/// ISO-8859-7, but U+0386 is mapped to a different byte.
1928///
1929/// [Index visualization](https://encoding.spec.whatwg.org/windows-1253.html),
1930/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/windows-1253-bmp.html)
1931///
1932/// This encoding matches the Windows code page 1253, except Windows decodes
1933/// unassigned code points to the Private Use Area of Unicode.
1934///
1935/// This will change from `static` to `const` if Rust changes
1936/// to make the referent of `pub const FOO: &'static Encoding`
1937/// unique cross-crate, so don't take the address of this
1938/// `static`.
1939pub static WINDOWS_1253: &'static Encoding = &WINDOWS_1253_INIT;
1940
1941/// The initializer for the [windows-1254](static.WINDOWS_1254.html) encoding.
1942///
1943/// For use only for taking the address of this form when
1944/// Rust prohibits the use of the non-`_INIT` form directly,
1945/// such as in initializers of other `static`s. If in doubt,
1946/// use the corresponding non-`_INIT` reference-typed `static`.
1947///
1948/// This part of the public API will go away if Rust changes
1949/// to make the referent of `pub const FOO: &'static Encoding`
1950/// unique cross-crate or if Rust starts allowing static arrays
1951/// to be initialized with `pub static FOO: &'static Encoding`
1952/// items.
1953pub static WINDOWS_1254_INIT: Encoding = Encoding {
1954    name: "windows-1254",
1955    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.windows_1254, 0x00DF, 95, 17),
1956};
1957
1958/// The windows-1254 encoding.
1959///
1960/// This is the Turkish encoding for Windows. It is an extension of ISO-8859-9,
1961/// which is known as Latin 5.
1962///
1963/// [Index visualization](https://encoding.spec.whatwg.org/windows-1254.html),
1964/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/windows-1254-bmp.html)
1965///
1966/// This encoding matches the Windows code page 1254.
1967///
1968/// This will change from `static` to `const` if Rust changes
1969/// to make the referent of `pub const FOO: &'static Encoding`
1970/// unique cross-crate, so don't take the address of this
1971/// `static`.
1972pub static WINDOWS_1254: &'static Encoding = &WINDOWS_1254_INIT;
1973
1974/// The initializer for the [windows-1255](static.WINDOWS_1255.html) encoding.
1975///
1976/// For use only for taking the address of this form when
1977/// Rust prohibits the use of the non-`_INIT` form directly,
1978/// such as in initializers of other `static`s. If in doubt,
1979/// use the corresponding non-`_INIT` reference-typed `static`.
1980///
1981/// This part of the public API will go away if Rust changes
1982/// to make the referent of `pub const FOO: &'static Encoding`
1983/// unique cross-crate or if Rust starts allowing static arrays
1984/// to be initialized with `pub static FOO: &'static Encoding`
1985/// items.
1986pub static WINDOWS_1255_INIT: Encoding = Encoding {
1987    name: "windows-1255",
1988    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.windows_1255, 0x05D0, 96, 27),
1989};
1990
1991/// The windows-1255 encoding.
1992///
1993/// This is the Hebrew encoding for Windows. It is an extension of ISO-8859-8-I,
1994/// except for a currency sign swap.
1995///
1996/// [Index visualization](https://encoding.spec.whatwg.org/windows-1255.html),
1997/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/windows-1255-bmp.html)
1998///
1999/// This encoding matches the Windows code page 1255, except Windows decodes
2000/// unassigned code points to the Private Use Area of Unicode.
2001///
2002/// This will change from `static` to `const` if Rust changes
2003/// to make the referent of `pub const FOO: &'static Encoding`
2004/// unique cross-crate, so don't take the address of this
2005/// `static`.
2006pub static WINDOWS_1255: &'static Encoding = &WINDOWS_1255_INIT;
2007
2008/// The initializer for the [windows-1256](static.WINDOWS_1256.html) encoding.
2009///
2010/// For use only for taking the address of this form when
2011/// Rust prohibits the use of the non-`_INIT` form directly,
2012/// such as in initializers of other `static`s. If in doubt,
2013/// use the corresponding non-`_INIT` reference-typed `static`.
2014///
2015/// This part of the public API will go away if Rust changes
2016/// to make the referent of `pub const FOO: &'static Encoding`
2017/// unique cross-crate or if Rust starts allowing static arrays
2018/// to be initialized with `pub static FOO: &'static Encoding`
2019/// items.
2020pub static WINDOWS_1256_INIT: Encoding = Encoding {
2021    name: "windows-1256",
2022    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.windows_1256, 0x0621, 65, 22),
2023};
2024
2025/// The windows-1256 encoding.
2026///
2027/// This is the Arabic encoding for Windows.
2028///
2029/// [Index visualization](https://encoding.spec.whatwg.org/windows-1256.html),
2030/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/windows-1256-bmp.html)
2031///
2032/// This encoding matches the Windows code page 1256.
2033///
2034/// This will change from `static` to `const` if Rust changes
2035/// to make the referent of `pub const FOO: &'static Encoding`
2036/// unique cross-crate, so don't take the address of this
2037/// `static`.
2038pub static WINDOWS_1256: &'static Encoding = &WINDOWS_1256_INIT;
2039
2040/// The initializer for the [windows-1257](static.WINDOWS_1257.html) encoding.
2041///
2042/// For use only for taking the address of this form when
2043/// Rust prohibits the use of the non-`_INIT` form directly,
2044/// such as in initializers of other `static`s. If in doubt,
2045/// use the corresponding non-`_INIT` reference-typed `static`.
2046///
2047/// This part of the public API will go away if Rust changes
2048/// to make the referent of `pub const FOO: &'static Encoding`
2049/// unique cross-crate or if Rust starts allowing static arrays
2050/// to be initialized with `pub static FOO: &'static Encoding`
2051/// items.
2052pub static WINDOWS_1257_INIT: Encoding = Encoding {
2053    name: "windows-1257",
2054    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.windows_1257, 0x00DF, 95, 1),
2055};
2056
2057/// The windows-1257 encoding.
2058///
2059/// This is the Baltic encoding for Windows.
2060///
2061/// [Index visualization](https://encoding.spec.whatwg.org/windows-1257.html),
2062/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/windows-1257-bmp.html)
2063///
2064/// This encoding matches the Windows code page 1257, except Windows decodes
2065/// unassigned code points to the Private Use Area of Unicode.
2066///
2067/// This will change from `static` to `const` if Rust changes
2068/// to make the referent of `pub const FOO: &'static Encoding`
2069/// unique cross-crate, so don't take the address of this
2070/// `static`.
2071pub static WINDOWS_1257: &'static Encoding = &WINDOWS_1257_INIT;
2072
2073/// The initializer for the [windows-1258](static.WINDOWS_1258.html) encoding.
2074///
2075/// For use only for taking the address of this form when
2076/// Rust prohibits the use of the non-`_INIT` form directly,
2077/// such as in initializers of other `static`s. If in doubt,
2078/// use the corresponding non-`_INIT` reference-typed `static`.
2079///
2080/// This part of the public API will go away if Rust changes
2081/// to make the referent of `pub const FOO: &'static Encoding`
2082/// unique cross-crate or if Rust starts allowing static arrays
2083/// to be initialized with `pub static FOO: &'static Encoding`
2084/// items.
2085pub static WINDOWS_1258_INIT: Encoding = Encoding {
2086    name: "windows-1258",
2087    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.windows_1258, 0x00DF, 95, 4),
2088};
2089
2090/// The windows-1258 encoding.
2091///
2092/// This is the Vietnamese encoding for Windows.
2093///
2094/// [Index visualization](https://encoding.spec.whatwg.org/windows-1258.html),
2095/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/windows-1258-bmp.html)
2096///
2097/// This encoding matches the Windows code page 1258 when used in the
2098/// non-normalizing mode. Unlike with the other single-byte encodings, the
2099/// result of decoding is not necessarily in Normalization Form C. On the
2100/// other hand, input in the Normalization Form C is not encoded without
2101/// replacement. In general, it's a bad idea to encode to encodings other
2102/// than UTF-8, but this encoding is especially hazardous to encode to.
2103///
2104/// This will change from `static` to `const` if Rust changes
2105/// to make the referent of `pub const FOO: &'static Encoding`
2106/// unique cross-crate, so don't take the address of this
2107/// `static`.
2108pub static WINDOWS_1258: &'static Encoding = &WINDOWS_1258_INIT;
2109
2110/// The initializer for the [windows-874](static.WINDOWS_874.html) encoding.
2111///
2112/// For use only for taking the address of this form when
2113/// Rust prohibits the use of the non-`_INIT` form directly,
2114/// such as in initializers of other `static`s. If in doubt,
2115/// use the corresponding non-`_INIT` reference-typed `static`.
2116///
2117/// This part of the public API will go away if Rust changes
2118/// to make the referent of `pub const FOO: &'static Encoding`
2119/// unique cross-crate or if Rust starts allowing static arrays
2120/// to be initialized with `pub static FOO: &'static Encoding`
2121/// items.
2122pub static WINDOWS_874_INIT: Encoding = Encoding {
2123    name: "windows-874",
2124    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.windows_874, 0x0E01, 33, 58),
2125};
2126
2127/// The windows-874 encoding.
2128///
2129/// This is the Thai encoding for Windows. It is an extension of TIS-620 / ISO-8859-11.
2130///
2131/// [Index visualization](https://encoding.spec.whatwg.org/windows-874.html),
2132/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/windows-874-bmp.html)
2133///
2134/// This encoding matches the Windows code page 874, except Windows decodes
2135/// unassigned code points to the Private Use Area of Unicode.
2136///
2137/// This will change from `static` to `const` if Rust changes
2138/// to make the referent of `pub const FOO: &'static Encoding`
2139/// unique cross-crate, so don't take the address of this
2140/// `static`.
2141pub static WINDOWS_874: &'static Encoding = &WINDOWS_874_INIT;
2142
2143/// The initializer for the [x-mac-cyrillic](static.X_MAC_CYRILLIC.html) encoding.
2144///
2145/// For use only for taking the address of this form when
2146/// Rust prohibits the use of the non-`_INIT` form directly,
2147/// such as in initializers of other `static`s. If in doubt,
2148/// use the corresponding non-`_INIT` reference-typed `static`.
2149///
2150/// This part of the public API will go away if Rust changes
2151/// to make the referent of `pub const FOO: &'static Encoding`
2152/// unique cross-crate or if Rust starts allowing static arrays
2153/// to be initialized with `pub static FOO: &'static Encoding`
2154/// items.
2155pub static X_MAC_CYRILLIC_INIT: Encoding = Encoding {
2156    name: "x-mac-cyrillic",
2157    variant: VariantEncoding::SingleByte(&data::SINGLE_BYTE_DATA.x_mac_cyrillic, 0x0430, 96, 31),
2158};
2159
2160/// The x-mac-cyrillic encoding.
2161///
2162/// This is the MacUkrainian encoding from Mac OS Classic.
2163///
2164/// [Index visualization](https://encoding.spec.whatwg.org/x-mac-cyrillic.html),
2165/// [Visualization of BMP coverage](https://encoding.spec.whatwg.org/x-mac-cyrillic-bmp.html)
2166///
2167/// This encoding matches the Windows code page 10017.
2168///
2169/// This will change from `static` to `const` if Rust changes
2170/// to make the referent of `pub const FOO: &'static Encoding`
2171/// unique cross-crate, so don't take the address of this
2172/// `static`.
2173pub static X_MAC_CYRILLIC: &'static Encoding = &X_MAC_CYRILLIC_INIT;
2174
2175/// The initializer for the [x-user-defined](static.X_USER_DEFINED.html) encoding.
2176///
2177/// For use only for taking the address of this form when
2178/// Rust prohibits the use of the non-`_INIT` form directly,
2179/// such as in initializers of other `static`s. If in doubt,
2180/// use the corresponding non-`_INIT` reference-typed `static`.
2181///
2182/// This part of the public API will go away if Rust changes
2183/// to make the referent of `pub const FOO: &'static Encoding`
2184/// unique cross-crate or if Rust starts allowing static arrays
2185/// to be initialized with `pub static FOO: &'static Encoding`
2186/// items.
2187pub static X_USER_DEFINED_INIT: Encoding = Encoding {
2188    name: "x-user-defined",
2189    variant: VariantEncoding::UserDefined,
2190};
2191
2192/// The x-user-defined encoding.
2193///
2194/// This encoding offsets the non-ASCII bytes by `0xF700` thereby decoding
2195/// them to the Private Use Area of Unicode. It was used for loading binary
2196/// data into a JavaScript string using `XMLHttpRequest` before XHR supported
2197/// the `"arraybuffer"` response type.
2198///
2199/// This encoding does not have a Windows code page number.
2200///
2201/// This will change from `static` to `const` if Rust changes
2202/// to make the referent of `pub const FOO: &'static Encoding`
2203/// unique cross-crate, so don't take the address of this
2204/// `static`.
2205pub static X_USER_DEFINED: &'static Encoding = &X_USER_DEFINED_INIT;
2206
2207static LABELS_SORTED: [&'static str; 228] = [
2208    "l1",
2209    "l2",
2210    "l3",
2211    "l4",
2212    "l5",
2213    "l6",
2214    "l9",
2215    "866",
2216    "mac",
2217    "koi",
2218    "gbk",
2219    "big5",
2220    "utf8",
2221    "koi8",
2222    "sjis",
2223    "ucs-2",
2224    "ms932",
2225    "cp866",
2226    "utf-8",
2227    "cp819",
2228    "ascii",
2229    "x-gbk",
2230    "greek",
2231    "cp1250",
2232    "cp1251",
2233    "latin1",
2234    "gb2312",
2235    "cp1252",
2236    "latin2",
2237    "cp1253",
2238    "latin3",
2239    "cp1254",
2240    "latin4",
2241    "cp1255",
2242    "csbig5",
2243    "latin5",
2244    "utf-16",
2245    "cp1256",
2246    "ibm866",
2247    "latin6",
2248    "cp1257",
2249    "cp1258",
2250    "greek8",
2251    "ibm819",
2252    "arabic",
2253    "visual",
2254    "korean",
2255    "euc-jp",
2256    "koi8-r",
2257    "koi8_r",
2258    "euc-kr",
2259    "x-sjis",
2260    "koi8-u",
2261    "hebrew",
2262    "tis-620",
2263    "gb18030",
2264    "ksc5601",
2265    "gb_2312",
2266    "dos-874",
2267    "cn-big5",
2268    "unicode",
2269    "chinese",
2270    "logical",
2271    "cskoi8r",
2272    "cseuckr",
2273    "koi8-ru",
2274    "x-cp1250",
2275    "ksc_5601",
2276    "x-cp1251",
2277    "iso88591",
2278    "csgb2312",
2279    "x-cp1252",
2280    "iso88592",
2281    "x-cp1253",
2282    "iso88593",
2283    "ecma-114",
2284    "x-cp1254",
2285    "iso88594",
2286    "x-cp1255",
2287    "iso88595",
2288    "x-x-big5",
2289    "x-cp1256",
2290    "csibm866",
2291    "iso88596",
2292    "x-cp1257",
2293    "iso88597",
2294    "asmo-708",
2295    "ecma-118",
2296    "elot_928",
2297    "x-cp1258",
2298    "iso88598",
2299    "iso88599",
2300    "cyrillic",
2301    "utf-16be",
2302    "utf-16le",
2303    "us-ascii",
2304    "ms_kanji",
2305    "x-euc-jp",
2306    "iso885910",
2307    "iso8859-1",
2308    "iso885911",
2309    "iso8859-2",
2310    "iso8859-3",
2311    "iso885913",
2312    "iso8859-4",
2313    "iso885914",
2314    "iso8859-5",
2315    "iso885915",
2316    "iso8859-6",
2317    "iso8859-7",
2318    "iso8859-8",
2319    "iso-ir-58",
2320    "iso8859-9",
2321    "csunicode",
2322    "macintosh",
2323    "shift-jis",
2324    "shift_jis",
2325    "iso-ir-100",
2326    "iso8859-10",
2327    "iso-ir-110",
2328    "gb_2312-80",
2329    "iso-8859-1",
2330    "iso_8859-1",
2331    "iso-ir-101",
2332    "iso8859-11",
2333    "iso-8859-2",
2334    "iso_8859-2",
2335    "hz-gb-2312",
2336    "iso-8859-3",
2337    "iso_8859-3",
2338    "iso8859-13",
2339    "iso-8859-4",
2340    "iso_8859-4",
2341    "iso8859-14",
2342    "iso-ir-144",
2343    "iso-8859-5",
2344    "iso_8859-5",
2345    "iso8859-15",
2346    "iso-8859-6",
2347    "iso_8859-6",
2348    "iso-ir-126",
2349    "iso-8859-7",
2350    "iso_8859-7",
2351    "iso-ir-127",
2352    "iso-ir-157",
2353    "iso-8859-8",
2354    "iso_8859-8",
2355    "iso-ir-138",
2356    "iso-ir-148",
2357    "iso-8859-9",
2358    "iso_8859-9",
2359    "iso-ir-109",
2360    "iso-ir-149",
2361    "big5-hkscs",
2362    "csshiftjis",
2363    "iso-8859-10",
2364    "iso-8859-11",
2365    "csisolatin1",
2366    "csisolatin2",
2367    "iso-8859-13",
2368    "csisolatin3",
2369    "iso-8859-14",
2370    "windows-874",
2371    "csisolatin4",
2372    "iso-8859-15",
2373    "iso_8859-15",
2374    "csisolatin5",
2375    "iso-8859-16",
2376    "csisolatin6",
2377    "windows-949",
2378    "csisolatin9",
2379    "csiso88596e",
2380    "csiso88598e",
2381    "unicodefffe",
2382    "unicodefeff",
2383    "csmacintosh",
2384    "csiso88596i",
2385    "csiso88598i",
2386    "windows-31j",
2387    "x-mac-roman",
2388    "iso-2022-cn",
2389    "iso-2022-jp",
2390    "csiso2022jp",
2391    "iso-2022-kr",
2392    "csiso2022kr",
2393    "replacement",
2394    "windows-1250",
2395    "windows-1251",
2396    "windows-1252",
2397    "windows-1253",
2398    "windows-1254",
2399    "windows-1255",
2400    "windows-1256",
2401    "windows-1257",
2402    "windows-1258",
2403    "iso-8859-6-e",
2404    "iso-8859-8-e",
2405    "iso-8859-6-i",
2406    "iso-8859-8-i",
2407    "sun_eu_greek",
2408    "csksc56011987",
2409    "unicode20utf8",
2410    "unicode11utf8",
2411    "ks_c_5601-1987",
2412    "ansi_x3.4-1968",
2413    "ks_c_5601-1989",
2414    "x-mac-cyrillic",
2415    "x-user-defined",
2416    "csiso58gb231280",
2417    "iso-10646-ucs-2",
2418    "iso_8859-1:1987",
2419    "iso_8859-2:1987",
2420    "iso_8859-6:1987",
2421    "iso_8859-7:1987",
2422    "iso_8859-3:1988",
2423    "iso_8859-4:1988",
2424    "iso_8859-5:1988",
2425    "iso_8859-8:1988",
2426    "x-unicode20utf8",
2427    "iso_8859-9:1989",
2428    "csisolatingreek",
2429    "x-mac-ukrainian",
2430    "iso-2022-cn-ext",
2431    "csisolatinarabic",
2432    "csisolatinhebrew",
2433    "unicode-1-1-utf-8",
2434    "csisolatincyrillic",
2435    "cseucpkdfmtjapanese",
2436];
2437
2438static ENCODINGS_IN_LABEL_SORT: [&'static Encoding; 228] = [
2439    &WINDOWS_1252_INIT,
2440    &ISO_8859_2_INIT,
2441    &ISO_8859_3_INIT,
2442    &ISO_8859_4_INIT,
2443    &WINDOWS_1254_INIT,
2444    &ISO_8859_10_INIT,
2445    &ISO_8859_15_INIT,
2446    &IBM866_INIT,
2447    &MACINTOSH_INIT,
2448    &KOI8_R_INIT,
2449    &GBK_INIT,
2450    &BIG5_INIT,
2451    &UTF_8_INIT,
2452    &KOI8_R_INIT,
2453    &SHIFT_JIS_INIT,
2454    &UTF_16LE_INIT,
2455    &SHIFT_JIS_INIT,
2456    &IBM866_INIT,
2457    &UTF_8_INIT,
2458    &WINDOWS_1252_INIT,
2459    &WINDOWS_1252_INIT,
2460    &GBK_INIT,
2461    &ISO_8859_7_INIT,
2462    &WINDOWS_1250_INIT,
2463    &WINDOWS_1251_INIT,
2464    &WINDOWS_1252_INIT,
2465    &GBK_INIT,
2466    &WINDOWS_1252_INIT,
2467    &ISO_8859_2_INIT,
2468    &WINDOWS_1253_INIT,
2469    &ISO_8859_3_INIT,
2470    &WINDOWS_1254_INIT,
2471    &ISO_8859_4_INIT,
2472    &WINDOWS_1255_INIT,
2473    &BIG5_INIT,
2474    &WINDOWS_1254_INIT,
2475    &UTF_16LE_INIT,
2476    &WINDOWS_1256_INIT,
2477    &IBM866_INIT,
2478    &ISO_8859_10_INIT,
2479    &WINDOWS_1257_INIT,
2480    &WINDOWS_1258_INIT,
2481    &ISO_8859_7_INIT,
2482    &WINDOWS_1252_INIT,
2483    &ISO_8859_6_INIT,
2484    &ISO_8859_8_INIT,
2485    &EUC_KR_INIT,
2486    &EUC_JP_INIT,
2487    &KOI8_R_INIT,
2488    &KOI8_R_INIT,
2489    &EUC_KR_INIT,
2490    &SHIFT_JIS_INIT,
2491    &KOI8_U_INIT,
2492    &ISO_8859_8_INIT,
2493    &WINDOWS_874_INIT,
2494    &GB18030_INIT,
2495    &EUC_KR_INIT,
2496    &GBK_INIT,
2497    &WINDOWS_874_INIT,
2498    &BIG5_INIT,
2499    &UTF_16LE_INIT,
2500    &GBK_INIT,
2501    &ISO_8859_8_I_INIT,
2502    &KOI8_R_INIT,
2503    &EUC_KR_INIT,
2504    &KOI8_U_INIT,
2505    &WINDOWS_1250_INIT,
2506    &EUC_KR_INIT,
2507    &WINDOWS_1251_INIT,
2508    &WINDOWS_1252_INIT,
2509    &GBK_INIT,
2510    &WINDOWS_1252_INIT,
2511    &ISO_8859_2_INIT,
2512    &WINDOWS_1253_INIT,
2513    &ISO_8859_3_INIT,
2514    &ISO_8859_6_INIT,
2515    &WINDOWS_1254_INIT,
2516    &ISO_8859_4_INIT,
2517    &WINDOWS_1255_INIT,
2518    &ISO_8859_5_INIT,
2519    &BIG5_INIT,
2520    &WINDOWS_1256_INIT,
2521    &IBM866_INIT,
2522    &ISO_8859_6_INIT,
2523    &WINDOWS_1257_INIT,
2524    &ISO_8859_7_INIT,
2525    &ISO_8859_6_INIT,
2526    &ISO_8859_7_INIT,
2527    &ISO_8859_7_INIT,
2528    &WINDOWS_1258_INIT,
2529    &ISO_8859_8_INIT,
2530    &WINDOWS_1254_INIT,
2531    &ISO_8859_5_INIT,
2532    &UTF_16BE_INIT,
2533    &UTF_16LE_INIT,
2534    &WINDOWS_1252_INIT,
2535    &SHIFT_JIS_INIT,
2536    &EUC_JP_INIT,
2537    &ISO_8859_10_INIT,
2538    &WINDOWS_1252_INIT,
2539    &WINDOWS_874_INIT,
2540    &ISO_8859_2_INIT,
2541    &ISO_8859_3_INIT,
2542    &ISO_8859_13_INIT,
2543    &ISO_8859_4_INIT,
2544    &ISO_8859_14_INIT,
2545    &ISO_8859_5_INIT,
2546    &ISO_8859_15_INIT,
2547    &ISO_8859_6_INIT,
2548    &ISO_8859_7_INIT,
2549    &ISO_8859_8_INIT,
2550    &GBK_INIT,
2551    &WINDOWS_1254_INIT,
2552    &UTF_16LE_INIT,
2553    &MACINTOSH_INIT,
2554    &SHIFT_JIS_INIT,
2555    &SHIFT_JIS_INIT,
2556    &WINDOWS_1252_INIT,
2557    &ISO_8859_10_INIT,
2558    &ISO_8859_4_INIT,
2559    &GBK_INIT,
2560    &WINDOWS_1252_INIT,
2561    &WINDOWS_1252_INIT,
2562    &ISO_8859_2_INIT,
2563    &WINDOWS_874_INIT,
2564    &ISO_8859_2_INIT,
2565    &ISO_8859_2_INIT,
2566    &REPLACEMENT_INIT,
2567    &ISO_8859_3_INIT,
2568    &ISO_8859_3_INIT,
2569    &ISO_8859_13_INIT,
2570    &ISO_8859_4_INIT,
2571    &ISO_8859_4_INIT,
2572    &ISO_8859_14_INIT,
2573    &ISO_8859_5_INIT,
2574    &ISO_8859_5_INIT,
2575    &ISO_8859_5_INIT,
2576    &ISO_8859_15_INIT,
2577    &ISO_8859_6_INIT,
2578    &ISO_8859_6_INIT,
2579    &ISO_8859_7_INIT,
2580    &ISO_8859_7_INIT,
2581    &ISO_8859_7_INIT,
2582    &ISO_8859_6_INIT,
2583    &ISO_8859_10_INIT,
2584    &ISO_8859_8_INIT,
2585    &ISO_8859_8_INIT,
2586    &ISO_8859_8_INIT,
2587    &WINDOWS_1254_INIT,
2588    &WINDOWS_1254_INIT,
2589    &WINDOWS_1254_INIT,
2590    &ISO_8859_3_INIT,
2591    &EUC_KR_INIT,
2592    &BIG5_INIT,
2593    &SHIFT_JIS_INIT,
2594    &ISO_8859_10_INIT,
2595    &WINDOWS_874_INIT,
2596    &WINDOWS_1252_INIT,
2597    &ISO_8859_2_INIT,
2598    &ISO_8859_13_INIT,
2599    &ISO_8859_3_INIT,
2600    &ISO_8859_14_INIT,
2601    &WINDOWS_874_INIT,
2602    &ISO_8859_4_INIT,
2603    &ISO_8859_15_INIT,
2604    &ISO_8859_15_INIT,
2605    &WINDOWS_1254_INIT,
2606    &ISO_8859_16_INIT,
2607    &ISO_8859_10_INIT,
2608    &EUC_KR_INIT,
2609    &ISO_8859_15_INIT,
2610    &ISO_8859_6_INIT,
2611    &ISO_8859_8_INIT,
2612    &UTF_16BE_INIT,
2613    &UTF_16LE_INIT,
2614    &MACINTOSH_INIT,
2615    &ISO_8859_6_INIT,
2616    &ISO_8859_8_I_INIT,
2617    &SHIFT_JIS_INIT,
2618    &MACINTOSH_INIT,
2619    &REPLACEMENT_INIT,
2620    &ISO_2022_JP_INIT,
2621    &ISO_2022_JP_INIT,
2622    &REPLACEMENT_INIT,
2623    &REPLACEMENT_INIT,
2624    &REPLACEMENT_INIT,
2625    &WINDOWS_1250_INIT,
2626    &WINDOWS_1251_INIT,
2627    &WINDOWS_1252_INIT,
2628    &WINDOWS_1253_INIT,
2629    &WINDOWS_1254_INIT,
2630    &WINDOWS_1255_INIT,
2631    &WINDOWS_1256_INIT,
2632    &WINDOWS_1257_INIT,
2633    &WINDOWS_1258_INIT,
2634    &ISO_8859_6_INIT,
2635    &ISO_8859_8_INIT,
2636    &ISO_8859_6_INIT,
2637    &ISO_8859_8_I_INIT,
2638    &ISO_8859_7_INIT,
2639    &EUC_KR_INIT,
2640    &UTF_8_INIT,
2641    &UTF_8_INIT,
2642    &EUC_KR_INIT,
2643    &WINDOWS_1252_INIT,
2644    &EUC_KR_INIT,
2645    &X_MAC_CYRILLIC_INIT,
2646    &X_USER_DEFINED_INIT,
2647    &GBK_INIT,
2648    &UTF_16LE_INIT,
2649    &WINDOWS_1252_INIT,
2650    &ISO_8859_2_INIT,
2651    &ISO_8859_6_INIT,
2652    &ISO_8859_7_INIT,
2653    &ISO_8859_3_INIT,
2654    &ISO_8859_4_INIT,
2655    &ISO_8859_5_INIT,
2656    &ISO_8859_8_INIT,
2657    &UTF_8_INIT,
2658    &WINDOWS_1254_INIT,
2659    &ISO_8859_7_INIT,
2660    &X_MAC_CYRILLIC_INIT,
2661    &REPLACEMENT_INIT,
2662    &ISO_8859_6_INIT,
2663    &ISO_8859_8_INIT,
2664    &UTF_8_INIT,
2665    &ISO_8859_5_INIT,
2666    &EUC_JP_INIT,
2667];
2668
2669// END GENERATED CODE
2670
2671/// An encoding as defined in the [Encoding Standard][1].
2672///
2673/// An _encoding_ defines a mapping from a `u8` sequence to a `char` sequence
2674/// and, in most cases, vice versa. Each encoding has a name, an output
2675/// encoding, and one or more labels.
2676///
2677/// _Labels_ are ASCII-case-insensitive strings that are used to identify an
2678/// encoding in formats and protocols. The _name_ of the encoding is the
2679/// preferred label in the case appropriate for returning from the
2680/// [`characterSet`][2] property of the `Document` DOM interface.
2681///
2682/// The _output encoding_ is the encoding used for form submission and URL
2683/// parsing on Web pages in the encoding. This is UTF-8 for the replacement,
2684/// UTF-16LE and UTF-16BE encodings and the encoding itself for other
2685/// encodings.
2686///
2687/// [1]: https://encoding.spec.whatwg.org/
2688/// [2]: https://dom.spec.whatwg.org/#dom-document-characterset
2689///
2690/// # Streaming vs. Non-Streaming
2691///
2692/// When you have the entire input in a single buffer, you can use the
2693/// methods [`decode()`][3], [`decode_with_bom_removal()`][4],
2694/// [`decode_without_bom_handling()`][5],
2695/// [`decode_without_bom_handling_and_without_replacement()`][6] and
2696/// [`encode()`][7]. (These methods are available to Rust callers only and are
2697/// not available in the C API.) Unlike the rest of the API available to Rust,
2698/// these methods perform heap allocations. You should the `Decoder` and
2699/// `Encoder` objects when your input is split into multiple buffers or when
2700/// you want to control the allocation of the output buffers.
2701///
2702/// [3]: #method.decode
2703/// [4]: #method.decode_with_bom_removal
2704/// [5]: #method.decode_without_bom_handling
2705/// [6]: #method.decode_without_bom_handling_and_without_replacement
2706/// [7]: #method.encode
2707///
2708/// # Instances
2709///
2710/// All instances of `Encoding` are statically allocated and have the `'static`
2711/// lifetime. There is precisely one unique `Encoding` instance for each
2712/// encoding defined in the Encoding Standard.
2713///
2714/// To obtain a reference to a particular encoding whose identity you know at
2715/// compile time, use a `static` that refers to encoding. There is a `static`
2716/// for each encoding. The `static`s are named in all caps with hyphens
2717/// replaced with underscores (and in C/C++ have `_ENCODING` appended to the
2718/// name). For example, if you know at compile time that you will want to
2719/// decode using the UTF-8 encoding, use the `UTF_8` `static` (`UTF_8_ENCODING`
2720/// in C/C++).
2721///
2722/// Additionally, there are non-reference-typed forms ending with `_INIT` to
2723/// work around the problem that `static`s of the type `&'static Encoding`
2724/// cannot be used to initialize items of an array whose type is
2725/// `[&'static Encoding; N]`.
2726///
2727/// If you don't know what encoding you need at compile time and need to
2728/// dynamically get an encoding by label, use
2729/// <code>Encoding::<a href="#method.for_label">for_label</a>(<var>label</var>)</code>.
2730///
2731/// Instances of `Encoding` can be compared with `==` (in both Rust and in
2732/// C/C++).
2733pub struct Encoding {
2734    name: &'static str,
2735    variant: VariantEncoding,
2736}
2737
2738impl Encoding {
2739    /// Implements the
2740    /// [_get an encoding_](https://encoding.spec.whatwg.org/#concept-encoding-get)
2741    /// algorithm.
2742    ///
2743    /// If, after ASCII-lowercasing and removing leading and trailing
2744    /// whitespace, the argument matches a label defined in the Encoding
2745    /// Standard, `Some(&'static Encoding)` representing the corresponding
2746    /// encoding is returned. If there is no match, `None` is returned.
2747    ///
2748    /// This is the right method to use if the action upon the method returning
2749    /// `None` is to use a fallback encoding (e.g. `WINDOWS_1252`) instead.
2750    /// When the action upon the method returning `None` is not to proceed with
2751    /// a fallback but to refuse processing, `for_label_no_replacement()` is more
2752    /// appropriate.
2753    ///
2754    /// The argument is of type `&[u8]` instead of `&str` to save callers
2755    /// that are extracting the label from a non-UTF-8 protocol the trouble
2756    /// of conversion to UTF-8. (If you have a `&str`, just call `.as_bytes()`
2757    /// on it.)
2758    ///
2759    /// Available via the C wrapper.
2760    ///
2761    /// # Example
2762    /// ```
2763    /// use encoding_rs::Encoding;
2764    ///
2765    /// assert_eq!(Some(encoding_rs::UTF_8), Encoding::for_label(b"utf-8"));
2766    /// assert_eq!(Some(encoding_rs::UTF_8), Encoding::for_label(b"unicode11utf8"));
2767    ///
2768    /// assert_eq!(Some(encoding_rs::ISO_8859_2), Encoding::for_label(b"latin2"));
2769    ///
2770    /// assert_eq!(Some(encoding_rs::UTF_16BE), Encoding::for_label(b"utf-16be"));
2771    ///
2772    /// assert_eq!(None, Encoding::for_label(b"unrecognized label"));
2773    /// ```
2774    pub fn for_label(label: &[u8]) -> Option<&'static Encoding> {
2775        let mut trimmed = [0u8; LONGEST_LABEL_LENGTH];
2776        let mut trimmed_pos = 0usize;
2777        let mut iter = label.iter();
2778        // before
2779        loop {
2780            match iter.next() {
2781                None => {
2782                    return None;
2783                }
2784                Some(byte) => {
2785                    // The characters used in labels are:
2786                    // a-z (except q, but excluding it below seems excessive)
2787                    // 0-9
2788                    // . _ - :
2789                    match *byte {
2790                        0x09u8 | 0x0Au8 | 0x0Cu8 | 0x0Du8 | 0x20u8 => {
2791                            continue;
2792                        }
2793                        b'A'..=b'Z' => {
2794                            trimmed[trimmed_pos] = *byte + 0x20u8;
2795                            trimmed_pos = 1usize;
2796                            break;
2797                        }
2798                        b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' | b':' | b'.' => {
2799                            trimmed[trimmed_pos] = *byte;
2800                            trimmed_pos = 1usize;
2801                            break;
2802                        }
2803                        _ => {
2804                            return None;
2805                        }
2806                    }
2807                }
2808            }
2809        }
2810        // inside
2811        loop {
2812            match iter.next() {
2813                None => {
2814                    break;
2815                }
2816                Some(byte) => {
2817                    match *byte {
2818                        0x09u8 | 0x0Au8 | 0x0Cu8 | 0x0Du8 | 0x20u8 => {
2819                            break;
2820                        }
2821                        b'A'..=b'Z' => {
2822                            if trimmed_pos == LONGEST_LABEL_LENGTH {
2823                                // There's no encoding with a label this long
2824                                return None;
2825                            }
2826                            trimmed[trimmed_pos] = *byte + 0x20u8;
2827                            trimmed_pos += 1usize;
2828                            continue;
2829                        }
2830                        b'a'..=b'z' | b'0'..=b'9' | b'-' | b'_' | b':' | b'.' => {
2831                            if trimmed_pos == LONGEST_LABEL_LENGTH {
2832                                // There's no encoding with a label this long
2833                                return None;
2834                            }
2835                            trimmed[trimmed_pos] = *byte;
2836                            trimmed_pos += 1usize;
2837                            continue;
2838                        }
2839                        _ => {
2840                            return None;
2841                        }
2842                    }
2843                }
2844            }
2845        }
2846        // after
2847        loop {
2848            match iter.next() {
2849                None => {
2850                    break;
2851                }
2852                Some(byte) => {
2853                    match *byte {
2854                        0x09u8 | 0x0Au8 | 0x0Cu8 | 0x0Du8 | 0x20u8 => {
2855                            continue;
2856                        }
2857                        _ => {
2858                            // There's no label with space in the middle
2859                            return None;
2860                        }
2861                    }
2862                }
2863            }
2864        }
2865        let candidate = &trimmed[..trimmed_pos];
2866        match LABELS_SORTED.binary_search_by(|probe| {
2867            let bytes = probe.as_bytes();
2868            let c = bytes.len().cmp(&candidate.len());
2869            if c != Ordering::Equal {
2870                return c;
2871            }
2872            let probe_iter = bytes.iter().rev();
2873            let candidate_iter = candidate.iter().rev();
2874            probe_iter.cmp(candidate_iter)
2875        }) {
2876            Ok(i) => Some(ENCODINGS_IN_LABEL_SORT[i]),
2877            Err(_) => None,
2878        }
2879    }
2880
2881    /// This method behaves the same as `for_label()`, except when `for_label()`
2882    /// would return `Some(REPLACEMENT)`, this method returns `None` instead.
2883    ///
2884    /// This method is useful in scenarios where a fatal error is required
2885    /// upon invalid label, because in those cases the caller typically wishes
2886    /// to treat the labels that map to the replacement encoding as fatal
2887    /// errors, too.
2888    ///
2889    /// It is not OK to use this method when the action upon the method returning
2890    /// `None` is to use a fallback encoding (e.g. `WINDOWS_1252`). In such a
2891    /// case, the `for_label()` method should be used instead in order to avoid
2892    /// unsafe fallback for labels that `for_label()` maps to `Some(REPLACEMENT)`.
2893    ///
2894    /// Available via the C wrapper.
2895    #[inline]
2896    pub fn for_label_no_replacement(label: &[u8]) -> Option<&'static Encoding> {
2897        match Encoding::for_label(label) {
2898            None => None,
2899            Some(encoding) => {
2900                if encoding == REPLACEMENT {
2901                    None
2902                } else {
2903                    Some(encoding)
2904                }
2905            }
2906        }
2907    }
2908
2909    /// Performs non-incremental BOM sniffing.
2910    ///
2911    /// The argument must either be a buffer representing the entire input
2912    /// stream (non-streaming case) or a buffer representing at least the first
2913    /// three bytes of the input stream (streaming case).
2914    ///
2915    /// Returns `Some((UTF_8, 3))`, `Some((UTF_16LE, 2))` or
2916    /// `Some((UTF_16BE, 2))` if the argument starts with the UTF-8, UTF-16LE
2917    /// or UTF-16BE BOM or `None` otherwise.
2918    ///
2919    /// Available via the C wrapper.
2920    #[inline]
2921    pub fn for_bom(buffer: &[u8]) -> Option<(&'static Encoding, usize)> {
2922        if buffer.starts_with(b"\xEF\xBB\xBF") {
2923            Some((UTF_8, 3))
2924        } else if buffer.starts_with(b"\xFF\xFE") {
2925            Some((UTF_16LE, 2))
2926        } else if buffer.starts_with(b"\xFE\xFF") {
2927            Some((UTF_16BE, 2))
2928        } else {
2929            None
2930        }
2931    }
2932
2933    /// Returns the name of this encoding.
2934    ///
2935    /// This name is appropriate to return as-is from the DOM
2936    /// `document.characterSet` property.
2937    ///
2938    /// Available via the C wrapper.
2939    #[inline]
2940    pub fn name(&'static self) -> &'static str {
2941        self.name
2942    }
2943
2944    /// Checks whether the _output encoding_ of this encoding can encode every
2945    /// `char`. (Only true if the output encoding is UTF-8.)
2946    ///
2947    /// Available via the C wrapper.
2948    #[inline]
2949    pub fn can_encode_everything(&'static self) -> bool {
2950        self.output_encoding() == UTF_8
2951    }
2952
2953    /// Checks whether the bytes 0x00...0x7F map exclusively to the characters
2954    /// U+0000...U+007F and vice versa.
2955    ///
2956    /// Available via the C wrapper.
2957    #[inline]
2958    pub fn is_ascii_compatible(&'static self) -> bool {
2959        !(self == REPLACEMENT || self == UTF_16BE || self == UTF_16LE || self == ISO_2022_JP)
2960    }
2961
2962    /// Checks whether this encoding maps one byte to one Basic Multilingual
2963    /// Plane code point (i.e. byte length equals decoded UTF-16 length) and
2964    /// vice versa (for mappable characters).
2965    ///
2966    /// `true` iff this encoding is on the list of [Legacy single-byte
2967    /// encodings](https://encoding.spec.whatwg.org/#legacy-single-byte-encodings)
2968    /// in the spec or x-user-defined.
2969    ///
2970    /// Available via the C wrapper.
2971    #[inline]
2972    pub fn is_single_byte(&'static self) -> bool {
2973        self.variant.is_single_byte()
2974    }
2975
2976    /// Checks whether the bytes 0x00...0x7F map mostly to the characters
2977    /// U+0000...U+007F and vice versa.
2978    #[cfg(feature = "alloc")]
2979    #[inline]
2980    fn is_potentially_borrowable(&'static self) -> bool {
2981        !(self == REPLACEMENT || self == UTF_16BE || self == UTF_16LE)
2982    }
2983
2984    /// Returns the _output encoding_ of this encoding. This is UTF-8 for
2985    /// UTF-16BE, UTF-16LE, and replacement and the encoding itself otherwise.
2986    ///
2987    /// _Note:_ The _output encoding_ concept is needed for form submission and
2988    /// error handling in the query strings of URLs in the Web Platform.
2989    ///
2990    /// Available via the C wrapper.
2991    #[inline]
2992    pub fn output_encoding(&'static self) -> &'static Encoding {
2993        if self == REPLACEMENT || self == UTF_16BE || self == UTF_16LE {
2994            UTF_8
2995        } else {
2996            self
2997        }
2998    }
2999
3000    /// Decode complete input to `Cow<'a, str>` _with BOM sniffing_ and with
3001    /// malformed sequences replaced with the REPLACEMENT CHARACTER when the
3002    /// entire input is available as a single buffer (i.e. the end of the
3003    /// buffer marks the end of the stream).
3004    ///
3005    /// The BOM, if any, does not appear in the output.
3006    ///
3007    /// This method implements the (non-streaming version of) the
3008    /// [_decode_](https://encoding.spec.whatwg.org/#decode) spec concept.
3009    ///
3010    /// The second item in the returned tuple is the encoding that was actually
3011    /// used (which may differ from this encoding thanks to BOM sniffing).
3012    ///
3013    /// The third item in the returned tuple indicates whether there were
3014    /// malformed sequences (that were replaced with the REPLACEMENT CHARACTER).
3015    ///
3016    /// _Note:_ It is wrong to use this when the input buffer represents only
3017    /// a segment of the input instead of the whole input. Use `new_decoder()`
3018    /// when decoding segmented input.
3019    ///
3020    /// This method performs a one or two heap allocations for the backing
3021    /// buffer of the `String` when unable to borrow. (One allocation if not
3022    /// errors and potentially another one in the presence of errors.) The
3023    /// first allocation assumes jemalloc and may not be optimal with
3024    /// allocators that do not use power-of-two buckets. A borrow is performed
3025    /// if decoding UTF-8 and the input is valid UTF-8, if decoding an
3026    /// ASCII-compatible encoding and the input is ASCII-only, or when decoding
3027    /// ISO-2022-JP and the input is entirely in the ASCII state without state
3028    /// transitions.
3029    ///
3030    /// # Panics
3031    ///
3032    /// If the size calculation for a heap-allocated backing buffer overflows
3033    /// `usize`.
3034    ///
3035    /// Available to Rust only and only with the `alloc` feature enabled (enabled
3036    /// by default).
3037    #[cfg(feature = "alloc")]
3038    #[inline]
3039    pub fn decode<'a>(&'static self, bytes: &'a [u8]) -> (Cow<'a, str>, &'static Encoding, bool) {
3040        let (encoding, without_bom) = match Encoding::for_bom(bytes) {
3041            Some((encoding, bom_length)) => (encoding, &bytes[bom_length..]),
3042            None => (self, bytes),
3043        };
3044        let (cow, had_errors) = encoding.decode_without_bom_handling(without_bom);
3045        (cow, encoding, had_errors)
3046    }
3047
3048    /// Decode complete input to `Cow<'a, str>` _with BOM removal_ and with
3049    /// malformed sequences replaced with the REPLACEMENT CHARACTER when the
3050    /// entire input is available as a single buffer (i.e. the end of the
3051    /// buffer marks the end of the stream).
3052    ///
3053    /// Only an initial byte sequence that is a BOM for this encoding is removed.
3054    ///
3055    /// When invoked on `UTF_8`, this method implements the (non-streaming
3056    /// version of) the
3057    /// [_UTF-8 decode_](https://encoding.spec.whatwg.org/#utf-8-decode) spec
3058    /// concept.
3059    ///
3060    /// The second item in the returned pair indicates whether there were
3061    /// malformed sequences (that were replaced with the REPLACEMENT CHARACTER).
3062    ///
3063    /// _Note:_ It is wrong to use this when the input buffer represents only
3064    /// a segment of the input instead of the whole input. Use
3065    /// `new_decoder_with_bom_removal()` when decoding segmented input.
3066    ///
3067    /// This method performs a one or two heap allocations for the backing
3068    /// buffer of the `String` when unable to borrow. (One allocation if not
3069    /// errors and potentially another one in the presence of errors.) The
3070    /// first allocation assumes jemalloc and may not be optimal with
3071    /// allocators that do not use power-of-two buckets. A borrow is performed
3072    /// if decoding UTF-8 and the input is valid UTF-8, if decoding an
3073    /// ASCII-compatible encoding and the input is ASCII-only, or when decoding
3074    /// ISO-2022-JP and the input is entirely in the ASCII state without state
3075    /// transitions.
3076    ///
3077    /// # Panics
3078    ///
3079    /// If the size calculation for a heap-allocated backing buffer overflows
3080    /// `usize`.
3081    ///
3082    /// Available to Rust only and only with the `alloc` feature enabled (enabled
3083    /// by default).
3084    #[cfg(feature = "alloc")]
3085    #[inline]
3086    pub fn decode_with_bom_removal<'a>(&'static self, bytes: &'a [u8]) -> (Cow<'a, str>, bool) {
3087        let without_bom = if self == UTF_8 && bytes.starts_with(b"\xEF\xBB\xBF") {
3088            &bytes[3..]
3089        } else if (self == UTF_16LE && bytes.starts_with(b"\xFF\xFE"))
3090            || (self == UTF_16BE && bytes.starts_with(b"\xFE\xFF"))
3091        {
3092            &bytes[2..]
3093        } else {
3094            bytes
3095        };
3096        self.decode_without_bom_handling(without_bom)
3097    }
3098
3099    /// Decode complete input to `Cow<'a, str>` _without BOM handling_ and
3100    /// with malformed sequences replaced with the REPLACEMENT CHARACTER when
3101    /// the entire input is available as a single buffer (i.e. the end of the
3102    /// buffer marks the end of the stream).
3103    ///
3104    /// When invoked on `UTF_8`, this method implements the (non-streaming
3105    /// version of) the
3106    /// [_UTF-8 decode without BOM_](https://encoding.spec.whatwg.org/#utf-8-decode-without-bom)
3107    /// spec concept.
3108    ///
3109    /// The second item in the returned pair indicates whether there were
3110    /// malformed sequences (that were replaced with the REPLACEMENT CHARACTER).
3111    ///
3112    /// _Note:_ It is wrong to use this when the input buffer represents only
3113    /// a segment of the input instead of the whole input. Use
3114    /// `new_decoder_without_bom_handling()` when decoding segmented input.
3115    ///
3116    /// This method performs a one or two heap allocations for the backing
3117    /// buffer of the `String` when unable to borrow. (One allocation if not
3118    /// errors and potentially another one in the presence of errors.) The
3119    /// first allocation assumes jemalloc and may not be optimal with
3120    /// allocators that do not use power-of-two buckets. A borrow is performed
3121    /// if decoding UTF-8 and the input is valid UTF-8, if decoding an
3122    /// ASCII-compatible encoding and the input is ASCII-only, or when decoding
3123    /// ISO-2022-JP and the input is entirely in the ASCII state without state
3124    /// transitions.
3125    ///
3126    /// # Panics
3127    ///
3128    /// If the size calculation for a heap-allocated backing buffer overflows
3129    /// `usize`.
3130    ///
3131    /// Available to Rust only and only with the `alloc` feature enabled (enabled
3132    /// by default).
3133    #[cfg(feature = "alloc")]
3134    pub fn decode_without_bom_handling<'a>(&'static self, bytes: &'a [u8]) -> (Cow<'a, str>, bool) {
3135        let (mut decoder, mut string, mut total_read) = if self.is_potentially_borrowable() {
3136            let valid_up_to = if self == UTF_8 {
3137                utf8_valid_up_to(bytes)
3138            } else if self == ISO_2022_JP {
3139                iso_2022_jp_ascii_valid_up_to(bytes)
3140            } else {
3141                ascii_valid_up_to(bytes)
3142            };
3143            if valid_up_to == bytes.len() {
3144                let str: &str = unsafe { core::str::from_utf8_unchecked(bytes) };
3145                return (Cow::Borrowed(str), false);
3146            }
3147            let decoder = self.new_decoder_without_bom_handling();
3148
3149            let rounded_without_replacement = checked_next_power_of_two(checked_add(
3150                valid_up_to,
3151                decoder.max_utf8_buffer_length_without_replacement(bytes.len() - valid_up_to),
3152            ));
3153            let with_replacement = checked_add(
3154                valid_up_to,
3155                decoder.max_utf8_buffer_length(bytes.len() - valid_up_to),
3156            );
3157            let mut string = String::with_capacity(
3158                checked_min(rounded_without_replacement, with_replacement).unwrap(),
3159            );
3160
3161            // SAFETY: We have validated that `bytes[..valid_up_to]` is valid UTF-8,
3162            // so it's OK to write that into `String` via `Vec`.
3163            let vec = unsafe { string.as_mut_vec() };
3164            vec.extend_from_slice(&bytes[..valid_up_to]);
3165            (decoder, string, valid_up_to)
3166        } else {
3167            let decoder = self.new_decoder_without_bom_handling();
3168            let rounded_without_replacement = checked_next_power_of_two(
3169                decoder.max_utf8_buffer_length_without_replacement(bytes.len()),
3170            );
3171            let with_replacement = decoder.max_utf8_buffer_length(bytes.len());
3172            let string = String::with_capacity(
3173                checked_min(rounded_without_replacement, with_replacement).unwrap(),
3174            );
3175            (decoder, string, 0)
3176        };
3177
3178        let mut total_had_errors = false;
3179        loop {
3180            let (result, read, had_errors) =
3181                decoder.decode_to_string(&bytes[total_read..], &mut string, true);
3182            total_read += read;
3183            total_had_errors |= had_errors;
3184            match result {
3185                CoderResult::InputEmpty => {
3186                    debug_assert_eq!(total_read, bytes.len());
3187                    return (Cow::Owned(string), total_had_errors);
3188                }
3189                CoderResult::OutputFull => {
3190                    // Allocate for the worst case. That is, we should come
3191                    // here at most once per invocation of this method.
3192                    let needed = decoder.max_utf8_buffer_length(bytes.len() - total_read);
3193                    string.reserve(needed.unwrap());
3194                }
3195            }
3196        }
3197    }
3198
3199    /// Decode complete input to `Cow<'a, str>` _without BOM handling_ and
3200    /// _with malformed sequences treated as fatal_ when the entire input is
3201    /// available as a single buffer (i.e. the end of the buffer marks the end
3202    /// of the stream).
3203    ///
3204    /// When invoked on `UTF_8`, this method implements the (non-streaming
3205    /// version of) the
3206    /// [_UTF-8 decode without BOM or fail_](https://encoding.spec.whatwg.org/#utf-8-decode-without-bom-or-fail)
3207    /// spec concept.
3208    ///
3209    /// Returns `None` if a malformed sequence was encountered and the result
3210    /// of the decode as `Some(String)` otherwise.
3211    ///
3212    /// _Note:_ It is wrong to use this when the input buffer represents only
3213    /// a segment of the input instead of the whole input. Use
3214    /// `new_decoder_without_bom_handling()` when decoding segmented input.
3215    ///
3216    /// This method performs a single heap allocation for the backing
3217    /// buffer of the `String` when unable to borrow. A borrow is performed if
3218    /// decoding UTF-8 and the input is valid UTF-8, if decoding an
3219    /// ASCII-compatible encoding and the input is ASCII-only, or when decoding
3220    /// ISO-2022-JP and the input is entirely in the ASCII state without state
3221    /// transitions.
3222    ///
3223    /// # Panics
3224    ///
3225    /// If the size calculation for a heap-allocated backing buffer overflows
3226    /// `usize`.
3227    ///
3228    /// Available to Rust only and only with the `alloc` feature enabled (enabled
3229    /// by default).
3230    #[cfg(feature = "alloc")]
3231    pub fn decode_without_bom_handling_and_without_replacement<'a>(
3232        &'static self,
3233        bytes: &'a [u8],
3234    ) -> Option<Cow<'a, str>> {
3235        if self == UTF_8 {
3236            let valid_up_to = utf8_valid_up_to(bytes);
3237            if valid_up_to == bytes.len() {
3238                let str: &str = unsafe { core::str::from_utf8_unchecked(bytes) };
3239                return Some(Cow::Borrowed(str));
3240            }
3241            return None;
3242        }
3243        let (mut decoder, mut string, input) = if self.is_potentially_borrowable() {
3244            let valid_up_to = if self == ISO_2022_JP {
3245                iso_2022_jp_ascii_valid_up_to(bytes)
3246            } else {
3247                ascii_valid_up_to(bytes)
3248            };
3249            if valid_up_to == bytes.len() {
3250                let str: &str = unsafe { core::str::from_utf8_unchecked(bytes) };
3251                return Some(Cow::Borrowed(str));
3252            }
3253            let decoder = self.new_decoder_without_bom_handling();
3254            let mut string = String::with_capacity(
3255                checked_add(
3256                    valid_up_to,
3257                    decoder.max_utf8_buffer_length_without_replacement(bytes.len() - valid_up_to),
3258                )
3259                .unwrap(),
3260            );
3261            // SAFETY: We have validated that `bytes[..valid_up_to]` is valid UTF-8,
3262            // so it's OK to write that into `String` via `Vec`.
3263            let vec = unsafe { string.as_mut_vec() };
3264            vec.extend_from_slice(&bytes[..valid_up_to]);
3265            (decoder, string, &bytes[valid_up_to..])
3266        } else {
3267            let decoder = self.new_decoder_without_bom_handling();
3268            let string = String::with_capacity(
3269                decoder
3270                    .max_utf8_buffer_length_without_replacement(bytes.len())
3271                    .unwrap(),
3272            );
3273            (decoder, string, bytes)
3274        };
3275        let (result, read) = decoder.decode_to_string_without_replacement(input, &mut string, true);
3276        match result {
3277            DecoderResult::InputEmpty => {
3278                debug_assert_eq!(read, input.len());
3279                Some(Cow::Owned(string))
3280            }
3281            DecoderResult::Malformed(_, _) => None,
3282            DecoderResult::OutputFull => unreachable!(),
3283        }
3284    }
3285
3286    /// Encode complete input to `Cow<'a, [u8]>` using the
3287    /// [_output encoding_](Encoding::output_encoding) of this encoding with
3288    /// unmappable characters replaced with decimal numeric character references
3289    /// when the entire input is available as a single buffer (i.e. the end of
3290    /// the buffer marks the end of the stream).
3291    ///
3292    /// This method implements the (non-streaming version of) the
3293    /// [_encode_](https://encoding.spec.whatwg.org/#encode) spec concept. For
3294    /// the [_UTF-8 encode_](https://encoding.spec.whatwg.org/#utf-8-encode)
3295    /// spec concept, it is slightly more efficient to use
3296    /// <code><var>string</var>.as_bytes()</code> instead of invoking this
3297    /// method on `UTF_8`.
3298    ///
3299    /// The second item in the returned tuple is the encoding that was actually
3300    /// used (*which may differ from this encoding thanks to some encodings
3301    /// having UTF-8 as their output encoding*).
3302    ///
3303    /// The third item in the returned tuple indicates whether there were
3304    /// unmappable characters (that were replaced with HTML numeric character
3305    /// references).
3306    ///
3307    /// _Note:_ It is wrong to use this when the input buffer represents only
3308    /// a segment of the input instead of the whole input. Use `new_encoder()`
3309    /// when encoding segmented output.
3310    ///
3311    /// When encoding to UTF-8 or when encoding an ASCII-only input to a
3312    /// ASCII-compatible encoding, this method returns a borrow of the input
3313    /// without a heap allocation. Otherwise, this method performs a single
3314    /// heap allocation for the backing buffer of the `Vec<u8>` if there are no
3315    /// unmappable characters and potentially multiple heap allocations if
3316    /// there are. These allocations are tuned for jemalloc and may not be
3317    /// optimal when using a different allocator that doesn't use power-of-two
3318    /// buckets.
3319    ///
3320    /// # Panics
3321    ///
3322    /// If the size calculation for a heap-allocated backing buffer overflows
3323    /// `usize`.
3324    ///
3325    /// Available to Rust only and only with the `alloc` feature enabled (enabled
3326    /// by default).
3327    #[cfg(feature = "alloc")]
3328    pub fn encode<'a>(&'static self, string: &'a str) -> (Cow<'a, [u8]>, &'static Encoding, bool) {
3329        let output_encoding = self.output_encoding();
3330        if output_encoding == UTF_8 {
3331            return (Cow::Borrowed(string.as_bytes()), output_encoding, false);
3332        }
3333        debug_assert!(output_encoding.is_potentially_borrowable());
3334        let bytes = string.as_bytes();
3335        let valid_up_to = if output_encoding == ISO_2022_JP {
3336            iso_2022_jp_ascii_valid_up_to(bytes)
3337        } else {
3338            ascii_valid_up_to(bytes)
3339        };
3340        if valid_up_to == bytes.len() {
3341            return (Cow::Borrowed(bytes), output_encoding, false);
3342        }
3343        let mut encoder = output_encoding.new_encoder();
3344        let mut vec: Vec<u8> = Vec::with_capacity(
3345            (checked_add(
3346                valid_up_to,
3347                encoder.max_buffer_length_from_utf8_if_no_unmappables(string.len() - valid_up_to),
3348            ))
3349            .unwrap()
3350            .next_power_of_two(),
3351        );
3352        vec.extend_from_slice(&bytes[..valid_up_to]);
3353        let mut total_read = valid_up_to;
3354        let mut total_had_errors = false;
3355        loop {
3356            let (result, read, had_errors) =
3357                encoder.encode_from_utf8_to_vec(&string[total_read..], &mut vec, true);
3358            total_read += read;
3359            total_had_errors |= had_errors;
3360            match result {
3361                CoderResult::InputEmpty => {
3362                    debug_assert_eq!(total_read, string.len());
3363                    return (Cow::Owned(vec), output_encoding, total_had_errors);
3364                }
3365                CoderResult::OutputFull => {
3366                    // reserve_exact wants to know how much more on top of current
3367                    // length--not current capacity.
3368                    let needed = encoder
3369                        .max_buffer_length_from_utf8_if_no_unmappables(string.len() - total_read);
3370                    let rounded = (checked_add(vec.capacity(), needed))
3371                        .unwrap()
3372                        .next_power_of_two();
3373                    let additional = rounded - vec.len();
3374                    vec.reserve_exact(additional);
3375                }
3376            }
3377        }
3378    }
3379
3380    fn new_variant_decoder(&'static self) -> VariantDecoder {
3381        self.variant.new_variant_decoder()
3382    }
3383
3384    /// Instantiates a new decoder for this encoding with BOM sniffing enabled.
3385    ///
3386    /// BOM sniffing may cause the returned decoder to morph into a decoder
3387    /// for UTF-8, UTF-16LE or UTF-16BE instead of this encoding. The BOM
3388    /// does not appear in the output.
3389    ///
3390    /// Available via the C wrapper.
3391    #[inline]
3392    pub fn new_decoder(&'static self) -> Decoder {
3393        Decoder::new(self, self.new_variant_decoder(), BomHandling::Sniff)
3394    }
3395
3396    /// Instantiates a new decoder for this encoding with BOM removal.
3397    ///
3398    /// If the input starts with bytes that are the BOM for this encoding,
3399    /// those bytes are removed. However, the decoder never morphs into a
3400    /// decoder for another encoding: A BOM for another encoding is treated as
3401    /// (potentially malformed) input to the decoding algorithm for this
3402    /// encoding.
3403    ///
3404    /// Available via the C wrapper.
3405    #[inline]
3406    pub fn new_decoder_with_bom_removal(&'static self) -> Decoder {
3407        Decoder::new(self, self.new_variant_decoder(), BomHandling::Remove)
3408    }
3409
3410    /// Instantiates a new decoder for this encoding with BOM handling disabled.
3411    ///
3412    /// If the input starts with bytes that look like a BOM, those bytes are
3413    /// not treated as a BOM. (Hence, the decoder never morphs into a decoder
3414    /// for another encoding.)
3415    ///
3416    /// _Note:_ If the caller has performed BOM sniffing on its own but has not
3417    /// removed the BOM, the caller should use `new_decoder_with_bom_removal()`
3418    /// instead of this method to cause the BOM to be removed.
3419    ///
3420    /// Available via the C wrapper.
3421    #[inline]
3422    pub fn new_decoder_without_bom_handling(&'static self) -> Decoder {
3423        Decoder::new(self, self.new_variant_decoder(), BomHandling::Off)
3424    }
3425
3426    /// Instantiates a new encoder for the [_output encoding_](Encoding::output_encoding)
3427    /// of this encoding.
3428    ///
3429    /// _Note:_ The output encoding of UTF-16BE, UTF-16LE, and replacement is UTF-8. There
3430    /// is no encoder for UTF-16BE, UTF-16LE, and replacement themselves.
3431    ///
3432    /// Available via the C wrapper.
3433    #[inline]
3434    pub fn new_encoder(&'static self) -> Encoder {
3435        let enc = self.output_encoding();
3436        enc.variant.new_encoder(enc)
3437    }
3438
3439    /// Validates UTF-8.
3440    ///
3441    /// Returns the index of the first byte that makes the input malformed as
3442    /// UTF-8 or the length of the slice if the slice is entirely valid.
3443    ///
3444    /// This is currently faster than the corresponding standard library
3445    /// functionality. If this implementation gets upstreamed to the standard
3446    /// library, this method may be removed in the future.
3447    ///
3448    /// Available via the C wrapper.
3449    pub fn utf8_valid_up_to(bytes: &[u8]) -> usize {
3450        utf8_valid_up_to(bytes)
3451    }
3452
3453    /// Validates ASCII.
3454    ///
3455    /// Returns the index of the first byte that makes the input malformed as
3456    /// ASCII or the length of the slice if the slice is entirely valid.
3457    ///
3458    /// Available via the C wrapper.
3459    pub fn ascii_valid_up_to(bytes: &[u8]) -> usize {
3460        ascii_valid_up_to(bytes)
3461    }
3462
3463    /// Validates ISO-2022-JP ASCII-state data.
3464    ///
3465    /// Returns the index of the first byte that makes the input not
3466    /// representable in the ASCII state of ISO-2022-JP or the length of the
3467    /// slice if the slice is entirely representable in the ASCII state of
3468    /// ISO-2022-JP.
3469    ///
3470    /// Available via the C wrapper.
3471    pub fn iso_2022_jp_ascii_valid_up_to(bytes: &[u8]) -> usize {
3472        iso_2022_jp_ascii_valid_up_to(bytes)
3473    }
3474}
3475
3476impl PartialEq for Encoding {
3477    #[inline]
3478    fn eq(&self, other: &Encoding) -> bool {
3479        ::core::ptr::eq(self, other)
3480    }
3481}
3482
3483impl Eq for Encoding {}
3484
3485#[cfg(test)]
3486impl PartialOrd for Encoding {
3487    #[inline]
3488    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
3489        (self as *const Encoding as usize).partial_cmp(&(other as *const Encoding as usize))
3490    }
3491}
3492
3493#[cfg(test)]
3494impl Ord for Encoding {
3495    #[inline]
3496    fn cmp(&self, other: &Self) -> Ordering {
3497        (self as *const Encoding as usize).cmp(&(other as *const Encoding as usize))
3498    }
3499}
3500
3501impl Hash for Encoding {
3502    #[inline]
3503    fn hash<H: Hasher>(&self, state: &mut H) {
3504        (self as *const Encoding).hash(state);
3505    }
3506}
3507
3508impl core::fmt::Debug for Encoding {
3509    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
3510        f.debug_struct("Encoding")
3511            .field("name", &self.name)
3512            .finish_non_exhaustive()
3513    }
3514}
3515
3516#[cfg(feature = "serde")]
3517impl Serialize for Encoding {
3518    #[inline]
3519    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
3520    where
3521        S: Serializer,
3522    {
3523        serializer.serialize_str(self.name)
3524    }
3525}
3526
3527#[cfg(feature = "serde")]
3528struct EncodingVisitor;
3529
3530#[cfg(feature = "serde")]
3531impl<'de> Visitor<'de> for EncodingVisitor {
3532    type Value = &'static Encoding;
3533
3534    fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
3535        formatter.write_str("a valid encoding label")
3536    }
3537
3538    fn visit_str<E>(self, value: &str) -> Result<&'static Encoding, E>
3539    where
3540        E: serde::de::Error,
3541    {
3542        if let Some(enc) = Encoding::for_label(value.as_bytes()) {
3543            Ok(enc)
3544        } else {
3545            Err(E::custom(alloc::format!(
3546                "invalid encoding label: {}",
3547                value
3548            )))
3549        }
3550    }
3551}
3552
3553#[cfg(feature = "serde")]
3554impl<'de> Deserialize<'de> for &'static Encoding {
3555    fn deserialize<D>(deserializer: D) -> Result<&'static Encoding, D::Error>
3556    where
3557        D: Deserializer<'de>,
3558    {
3559        deserializer.deserialize_str(EncodingVisitor)
3560    }
3561}
3562
3563/// Tracks the life cycle of a decoder from BOM sniffing to conversion to end.
3564#[derive(PartialEq, Debug, Copy, Clone)]
3565enum DecoderLifeCycle {
3566    /// The decoder has seen no input yet.
3567    AtStart,
3568    /// The decoder has seen no input yet but expects UTF-8.
3569    AtUtf8Start,
3570    /// The decoder has seen no input yet but expects UTF-16BE.
3571    AtUtf16BeStart,
3572    /// The decoder has seen no input yet but expects UTF-16LE.
3573    AtUtf16LeStart,
3574    /// The decoder has seen EF.
3575    SeenUtf8First,
3576    /// The decoder has seen EF, BB.
3577    SeenUtf8Second,
3578    /// The decoder has seen FE.
3579    SeenUtf16BeFirst,
3580    /// The decoder has seen FF.
3581    SeenUtf16LeFirst,
3582    /// Saw EF, BB but not BF, there was a buffer boundary after BB and the
3583    /// underlying decoder reported EF as an error, so we need to remember to
3584    /// push BB before the next buffer.
3585    ConvertingWithPendingBB,
3586    /// No longer looking for a BOM and EOF not yet seen.
3587    Converting,
3588    /// EOF has been seen.
3589    Finished,
3590}
3591
3592/// Communicate the BOM handling mode.
3593#[derive(Debug, Copy, Clone)]
3594enum BomHandling {
3595    /// Don't handle the BOM
3596    Off,
3597    /// Sniff for UTF-8, UTF-16BE or UTF-16LE BOM
3598    Sniff,
3599    /// Remove the BOM only if it's the BOM for this encoding
3600    Remove,
3601}
3602
3603/// Result of a (potentially partial) decode or encode operation with
3604/// replacement.
3605#[must_use]
3606#[derive(Debug, PartialEq, Eq)]
3607pub enum CoderResult {
3608    /// The input was exhausted.
3609    ///
3610    /// If this result was returned from a call where `last` was `true`, the
3611    /// conversion process has completed. Otherwise, the caller should call a
3612    /// decode or encode method again with more input.
3613    InputEmpty,
3614
3615    /// The converter cannot produce another unit of output, because the output
3616    /// buffer does not have enough space left.
3617    ///
3618    /// The caller must provide more output space upon the next call and re-push
3619    /// the remaining input to the converter.
3620    OutputFull,
3621}
3622
3623/// Result of a (potentially partial) decode operation without replacement.
3624#[must_use]
3625#[derive(Debug, PartialEq, Eq)]
3626pub enum DecoderResult {
3627    /// The input was exhausted.
3628    ///
3629    /// If this result was returned from a call where `last` was `true`, the
3630    /// decoding process has completed. Otherwise, the caller should call a
3631    /// decode method again with more input.
3632    InputEmpty,
3633
3634    /// The decoder cannot produce another unit of output, because the output
3635    /// buffer does not have enough space left.
3636    ///
3637    /// The caller must provide more output space upon the next call and re-push
3638    /// the remaining input to the decoder.
3639    OutputFull,
3640
3641    /// The decoder encountered a malformed byte sequence.
3642    ///
3643    /// The caller must either treat this as a fatal error or must append one
3644    /// REPLACEMENT CHARACTER (U+FFFD) to the output and then re-push the
3645    /// the remaining input to the decoder.
3646    ///
3647    /// The first wrapped integer indicates the length of the malformed byte
3648    /// sequence. The second wrapped integer indicates the number of bytes
3649    /// that were consumed after the malformed sequence. If the second
3650    /// integer is zero, the last byte that was consumed is the last byte of
3651    /// the malformed sequence. Note that the malformed bytes may have been part
3652    /// of an earlier input buffer.
3653    ///
3654    /// The first wrapped integer can have values 1, 2, 3 or 4. The second
3655    /// wrapped integer can have values 0, 1, 2 or 3. The worst-case sum
3656    /// of the two is 6, which happens with ISO-2022-JP.
3657    Malformed(u8, u8), // u8 instead of usize to avoid useless bloat
3658}
3659
3660/// A converter that decodes a byte stream into Unicode according to a
3661/// character encoding in a streaming (incremental) manner.
3662///
3663/// The various `decode_*` methods take an input buffer (`src`) and an output
3664/// buffer `dst` both of which are caller-allocated. There are variants for
3665/// both UTF-8 and UTF-16 output buffers.
3666///
3667/// A `decode_*` method decodes bytes from `src` into Unicode characters stored
3668/// into `dst` until one of the following three things happens:
3669///
3670/// 1. A malformed byte sequence is encountered (`*_without_replacement`
3671///    variants only).
3672///
3673/// 2. The output buffer has been filled so near capacity that the decoder
3674///    cannot be sure that processing an additional byte of input wouldn't
3675///    cause so much output that the output buffer would overflow.
3676///
3677/// 3. All the input bytes have been processed.
3678///
3679/// The `decode_*` method then returns tuple of a status indicating which one
3680/// of the three reasons to return happened, how many input bytes were read,
3681/// how many output code units (`u8` when decoding into UTF-8 and `u16`
3682/// when decoding to UTF-16) were written (except when decoding into `String`,
3683/// whose length change indicates this), and in the case of the
3684/// variants performing replacement, a boolean indicating whether an error was
3685/// replaced with the REPLACEMENT CHARACTER during the call.
3686///
3687/// The number of bytes "written" is what's logically written. Garbage may be
3688/// written in the output buffer beyond the point logically written to.
3689/// Therefore, if you wish to decode into an `&mut str`, you should use the
3690/// methods that take an `&mut str` argument instead of the ones that take an
3691/// `&mut [u8]` argument. The former take care of overwriting the trailing
3692/// garbage to ensure the UTF-8 validity of the `&mut str` as a whole, but the
3693/// latter don't.
3694///
3695/// In the case of the `*_without_replacement` variants, the status is a
3696/// [`DecoderResult`][1] enumeration (possibilities `Malformed`, `OutputFull` and
3697/// `InputEmpty` corresponding to the three cases listed above).
3698///
3699/// In the case of methods whose name does not end with
3700/// `*_without_replacement`, malformed sequences are automatically replaced
3701/// with the REPLACEMENT CHARACTER and errors do not cause the methods to
3702/// return early.
3703///
3704/// When decoding to UTF-8, the output buffer must have at least 4 bytes of
3705/// space. When decoding to UTF-16, the output buffer must have at least two
3706/// UTF-16 code units (`u16`) of space.
3707///
3708/// When decoding to UTF-8 without replacement, the methods are guaranteed
3709/// not to return indicating that more output space is needed if the length
3710/// of the output buffer is at least the length returned by
3711/// [`max_utf8_buffer_length_without_replacement()`][2]. When decoding to UTF-8
3712/// with replacement, the length of the output buffer that guarantees the
3713/// methods not to return indicating that more output space is needed is given
3714/// by [`max_utf8_buffer_length()`][3]. When decoding to UTF-16 with
3715/// or without replacement, the length of the output buffer that guarantees
3716/// the methods not to return indicating that more output space is needed is
3717/// given by [`max_utf16_buffer_length()`][4].
3718///
3719/// The output written into `dst` is guaranteed to be valid UTF-8 or UTF-16,
3720/// and the output after each `decode_*` call is guaranteed to consist of
3721/// complete characters. (I.e. the code unit sequence for the last character is
3722/// guaranteed not to be split across output buffers.)
3723///
3724/// The boolean argument `last` indicates that the end of the stream is reached
3725/// when all the bytes in `src` have been consumed.
3726///
3727/// A `Decoder` object can be used to incrementally decode a byte stream.
3728///
3729/// During the processing of a single stream, the caller must call `decode_*`
3730/// zero or more times with `last` set to `false` and then call `decode_*` at
3731/// least once with `last` set to `true`. If `decode_*` returns `InputEmpty`,
3732/// the processing of the stream has ended. Otherwise, the caller must call
3733/// `decode_*` again with `last` set to `true` (or treat a `Malformed` result as
3734///  a fatal error).
3735///
3736/// Once the stream has ended, the `Decoder` object must not be used anymore.
3737/// That is, you need to create another one to process another stream.
3738///
3739/// When the decoder returns `OutputFull` or the decoder returns `Malformed` and
3740/// the caller does not wish to treat it as a fatal error, the input buffer
3741/// `src` may not have been completely consumed. In that case, the caller must
3742/// pass the unconsumed contents of `src` to `decode_*` again upon the next
3743/// call.
3744///
3745/// [1]: enum.DecoderResult.html
3746/// [2]: #method.max_utf8_buffer_length_without_replacement
3747/// [3]: #method.max_utf8_buffer_length
3748/// [4]: #method.max_utf16_buffer_length
3749///
3750/// # Infinite loops
3751///
3752/// When converting with a fixed-size output buffer whose size is too small to
3753/// accommodate one character or (when applicable) one numeric character
3754/// reference of output, an infinite loop ensues. When converting with a
3755/// fixed-size output buffer, it generally makes sense to make the buffer
3756/// fairly large (e.g. couple of kilobytes).
3757pub struct Decoder {
3758    encoding: &'static Encoding,
3759    variant: VariantDecoder,
3760    life_cycle: DecoderLifeCycle,
3761}
3762
3763impl Decoder {
3764    fn new(enc: &'static Encoding, decoder: VariantDecoder, sniffing: BomHandling) -> Decoder {
3765        Decoder {
3766            encoding: enc,
3767            variant: decoder,
3768            life_cycle: match sniffing {
3769                BomHandling::Off => DecoderLifeCycle::Converting,
3770                BomHandling::Sniff => DecoderLifeCycle::AtStart,
3771                BomHandling::Remove => {
3772                    if enc == UTF_8 {
3773                        DecoderLifeCycle::AtUtf8Start
3774                    } else if enc == UTF_16BE {
3775                        DecoderLifeCycle::AtUtf16BeStart
3776                    } else if enc == UTF_16LE {
3777                        DecoderLifeCycle::AtUtf16LeStart
3778                    } else {
3779                        DecoderLifeCycle::Converting
3780                    }
3781                }
3782            },
3783        }
3784    }
3785
3786    /// The `Encoding` this `Decoder` is for.
3787    ///
3788    /// BOM sniffing can change the return value of this method during the life
3789    /// of the decoder.
3790    ///
3791    /// Available via the C wrapper.
3792    #[inline]
3793    pub fn encoding(&self) -> &'static Encoding {
3794        self.encoding
3795    }
3796
3797    /// Query the worst-case UTF-8 output size _with replacement_.
3798    ///
3799    /// Returns the size of the output buffer in UTF-8 code units (`u8`)
3800    /// that will not overflow given the current state of the decoder and
3801    /// `byte_length` number of additional input bytes when decoding with
3802    /// errors handled by outputting a REPLACEMENT CHARACTER for each malformed
3803    /// sequence or `None` if `usize` would overflow.
3804    ///
3805    /// Available via the C wrapper.
3806    pub fn max_utf8_buffer_length(&self, byte_length: usize) -> Option<usize> {
3807        // Need to consider a) the decoder morphing due to the BOM and b) a partial
3808        // BOM getting pushed to the underlying decoder.
3809        match self.life_cycle {
3810            DecoderLifeCycle::Converting
3811            | DecoderLifeCycle::AtUtf8Start
3812            | DecoderLifeCycle::AtUtf16LeStart
3813            | DecoderLifeCycle::AtUtf16BeStart => {
3814                return self.variant.max_utf8_buffer_length(byte_length);
3815            }
3816            DecoderLifeCycle::AtStart => {
3817                if let Some(utf8_bom) = checked_add(3, byte_length.checked_mul(3))
3818                    && let Some(utf16_bom) = checked_add(
3819                        1,
3820                        checked_mul(3, checked_div(byte_length.checked_add(1), 2)),
3821                    )
3822                {
3823                    let utf_bom = core::cmp::max(utf8_bom, utf16_bom);
3824                    let encoding = self.encoding();
3825                    if encoding == UTF_8 || encoding == UTF_16LE || encoding == UTF_16BE {
3826                        // No need to consider the internal state of the underlying decoder,
3827                        // because it is at start, because no data has reached it yet.
3828                        return Some(utf_bom);
3829                    } else if let Some(non_bom) = self.variant.max_utf8_buffer_length(byte_length) {
3830                        return Some(core::cmp::max(utf_bom, non_bom));
3831                    }
3832                }
3833            }
3834            DecoderLifeCycle::SeenUtf8First | DecoderLifeCycle::SeenUtf8Second => {
3835                // Add two bytes even when only one byte has been seen,
3836                // because the one byte can become a lead byte in multibyte
3837                // decoders, but only after the decoder has been queried
3838                // for max length, so the decoder's own logic for adding
3839                // one for a pending lead cannot work.
3840                if let Some(sum) = byte_length.checked_add(2)
3841                    && let Some(utf8_bom) = checked_add(3, sum.checked_mul(3))
3842                {
3843                    if self.encoding() == UTF_8 {
3844                        // No need to consider the internal state of the underlying decoder,
3845                        // because it is at start, because no data has reached it yet.
3846                        return Some(utf8_bom);
3847                    } else if let Some(non_bom) = self.variant.max_utf8_buffer_length(sum) {
3848                        return Some(core::cmp::max(utf8_bom, non_bom));
3849                    }
3850                }
3851            }
3852            DecoderLifeCycle::ConvertingWithPendingBB => {
3853                if let Some(sum) = byte_length.checked_add(2) {
3854                    return self.variant.max_utf8_buffer_length(sum);
3855                }
3856            }
3857            DecoderLifeCycle::SeenUtf16LeFirst | DecoderLifeCycle::SeenUtf16BeFirst => {
3858                // Add two bytes even when only one byte has been seen,
3859                // because the one byte can become a lead byte in multibyte
3860                // decoders, but only after the decoder has been queried
3861                // for max length, so the decoder's own logic for adding
3862                // one for a pending lead cannot work.
3863                if let Some(sum) = byte_length.checked_add(2)
3864                    && let Some(utf16_bom) =
3865                        checked_add(1, checked_mul(3, checked_div(sum.checked_add(1), 2)))
3866                {
3867                    let encoding = self.encoding();
3868                    if encoding == UTF_16LE || encoding == UTF_16BE {
3869                        // No need to consider the internal state of the underlying decoder,
3870                        // because it is at start, because no data has reached it yet.
3871                        return Some(utf16_bom);
3872                    } else if let Some(non_bom) = self.variant.max_utf8_buffer_length(sum) {
3873                        return Some(core::cmp::max(utf16_bom, non_bom));
3874                    }
3875                }
3876            }
3877            DecoderLifeCycle::Finished => panic!("Must not use a decoder that has finished."),
3878        }
3879        None
3880    }
3881
3882    /// Query the worst-case UTF-8 output size _without replacement_.
3883    ///
3884    /// Returns the size of the output buffer in UTF-8 code units (`u8`)
3885    /// that will not overflow given the current state of the decoder and
3886    /// `byte_length` number of additional input bytes when decoding without
3887    /// replacement error handling or `None` if `usize` would overflow.
3888    ///
3889    /// Note that this value may be too small for the `_with_replacement` case.
3890    /// Use `max_utf8_buffer_length()` for that case.
3891    ///
3892    /// Available via the C wrapper.
3893    pub fn max_utf8_buffer_length_without_replacement(&self, byte_length: usize) -> Option<usize> {
3894        // Need to consider a) the decoder morphing due to the BOM and b) a partial
3895        // BOM getting pushed to the underlying decoder.
3896        match self.life_cycle {
3897            DecoderLifeCycle::Converting
3898            | DecoderLifeCycle::AtUtf8Start
3899            | DecoderLifeCycle::AtUtf16LeStart
3900            | DecoderLifeCycle::AtUtf16BeStart => {
3901                return self
3902                    .variant
3903                    .max_utf8_buffer_length_without_replacement(byte_length);
3904            }
3905            DecoderLifeCycle::AtStart => {
3906                if let Some(utf8_bom) = byte_length.checked_add(3)
3907                    && let Some(utf16_bom) = checked_add(
3908                        1,
3909                        checked_mul(3, checked_div(byte_length.checked_add(1), 2)),
3910                    )
3911                {
3912                    let utf_bom = core::cmp::max(utf8_bom, utf16_bom);
3913                    let encoding = self.encoding();
3914                    if encoding == UTF_8 || encoding == UTF_16LE || encoding == UTF_16BE {
3915                        // No need to consider the internal state of the underlying decoder,
3916                        // because it is at start, because no data has reached it yet.
3917                        return Some(utf_bom);
3918                    } else if let Some(non_bom) = self
3919                        .variant
3920                        .max_utf8_buffer_length_without_replacement(byte_length)
3921                    {
3922                        return Some(core::cmp::max(utf_bom, non_bom));
3923                    }
3924                }
3925            }
3926            DecoderLifeCycle::SeenUtf8First | DecoderLifeCycle::SeenUtf8Second => {
3927                // Add two bytes even when only one byte has been seen,
3928                // because the one byte can become a lead byte in multibyte
3929                // decoders, but only after the decoder has been queried
3930                // for max length, so the decoder's own logic for adding
3931                // one for a pending lead cannot work.
3932                if let Some(sum) = byte_length.checked_add(2)
3933                    && let Some(utf8_bom) = sum.checked_add(3)
3934                {
3935                    if self.encoding() == UTF_8 {
3936                        // No need to consider the internal state of the underlying decoder,
3937                        // because it is at start, because no data has reached it yet.
3938                        return Some(utf8_bom);
3939                    } else if let Some(non_bom) =
3940                        self.variant.max_utf8_buffer_length_without_replacement(sum)
3941                    {
3942                        return Some(core::cmp::max(utf8_bom, non_bom));
3943                    }
3944                }
3945            }
3946            DecoderLifeCycle::ConvertingWithPendingBB => {
3947                if let Some(sum) = byte_length.checked_add(2) {
3948                    return self.variant.max_utf8_buffer_length_without_replacement(sum);
3949                }
3950            }
3951            DecoderLifeCycle::SeenUtf16LeFirst | DecoderLifeCycle::SeenUtf16BeFirst => {
3952                // Add two bytes even when only one byte has been seen,
3953                // because the one byte can become a lead byte in multibyte
3954                // decoders, but only after the decoder has been queried
3955                // for max length, so the decoder's own logic for adding
3956                // one for a pending lead cannot work.
3957                if let Some(sum) = byte_length.checked_add(2)
3958                    && let Some(utf16_bom) =
3959                        checked_add(1, checked_mul(3, checked_div(sum.checked_add(1), 2)))
3960                {
3961                    let encoding = self.encoding();
3962                    if encoding == UTF_16LE || encoding == UTF_16BE {
3963                        // No need to consider the internal state of the underlying decoder,
3964                        // because it is at start, because no data has reached it yet.
3965                        return Some(utf16_bom);
3966                    } else if let Some(non_bom) =
3967                        self.variant.max_utf8_buffer_length_without_replacement(sum)
3968                    {
3969                        return Some(core::cmp::max(utf16_bom, non_bom));
3970                    }
3971                }
3972            }
3973            DecoderLifeCycle::Finished => panic!("Must not use a decoder that has finished."),
3974        }
3975        None
3976    }
3977
3978    /// Incrementally decode a byte stream into UTF-8 with malformed sequences
3979    /// replaced with the REPLACEMENT CHARACTER.
3980    ///
3981    /// See the documentation of the struct for documentation for `decode_*`
3982    /// methods collectively.
3983    ///
3984    /// Available via the C wrapper.
3985    pub fn decode_to_utf8(
3986        &mut self,
3987        src: &[u8],
3988        dst: &mut [u8],
3989        last: bool,
3990    ) -> (CoderResult, usize, usize, bool) {
3991        let mut had_errors = false;
3992        let mut total_read = 0usize;
3993        let mut total_written = 0usize;
3994        loop {
3995            let (result, read, written) = self.decode_to_utf8_without_replacement(
3996                &src[total_read..],
3997                &mut dst[total_written..],
3998                last,
3999            );
4000            total_read += read;
4001            total_written += written;
4002            match result {
4003                DecoderResult::InputEmpty => {
4004                    return (
4005                        CoderResult::InputEmpty,
4006                        total_read,
4007                        total_written,
4008                        had_errors,
4009                    );
4010                }
4011                DecoderResult::OutputFull => {
4012                    return (
4013                        CoderResult::OutputFull,
4014                        total_read,
4015                        total_written,
4016                        had_errors,
4017                    );
4018                }
4019                DecoderResult::Malformed(_, _) => {
4020                    had_errors = true;
4021                    // There should always be space for the U+FFFD, because
4022                    // otherwise we'd have gotten OutputFull already.
4023                    // XXX: is the above comment actually true for UTF-8 itself?
4024                    // TODO: Consider having fewer bound checks here.
4025                    dst[total_written] = 0xEFu8;
4026                    total_written += 1;
4027                    dst[total_written] = 0xBFu8;
4028                    total_written += 1;
4029                    dst[total_written] = 0xBDu8;
4030                    total_written += 1;
4031                }
4032            }
4033        }
4034    }
4035
4036    /// Incrementally decode a byte stream into UTF-8 with malformed sequences
4037    /// replaced with the REPLACEMENT CHARACTER with type system signaling
4038    /// of UTF-8 validity.
4039    ///
4040    /// This methods calls `decode_to_utf8` and then zeroes enough subsequent
4041    /// bytes to maintain the invariant of `str`.
4042    ///
4043    /// See the documentation of the struct for documentation for `decode_*`
4044    /// methods collectively.
4045    ///
4046    /// Available to Rust only.
4047    pub fn decode_to_str(
4048        &mut self,
4049        src: &[u8],
4050        dst: &mut str,
4051        last: bool,
4052    ) -> (CoderResult, usize, usize, bool) {
4053        // SAFETY: We trust that `decode_to_utf8` writes
4054        // valid UTF-8. To make the part of the slice after what was reported
4055        // as logically written by that funtion, we use knowledge of the internals
4056        // to overwrite trailing garbage that may have been written. Then we also
4057        // overwrite a possible partial UTF-8 byte sequence after that. Then the
4058        // rest must be valid on the assumption that `dst` was valid to begin with.
4059        // In case of a panic, the `ScopeGuard` zeros the whole slice, which ensures
4060        // it's valid UTF-8 in an use-after-panic scenario when unwinding is enabled.
4061        // (Relevant only if there's a panic due to a crate-internal bug. Panics
4062        // arising from misuse of the public API don't need this guard and end up
4063        // zeroing the slice unnecessarily.)
4064        let mut bytes = scopeguard::guard(unsafe { dst.as_bytes_mut() }, |bytes| {
4065            bytes.iter_mut().for_each(|b| *b = 0)
4066        });
4067        let (result, read, written, replaced) = self.decode_to_utf8(src, &mut bytes, last);
4068        let len = bytes.len();
4069        let mut trail = written;
4070        // Non-UTF-8 ASCII-compatible decoders may write up to `MAX_STRIDE_SIZE`
4071        // bytes of trailing garbage. No need to optimize non-ASCII-compatible
4072        // encodings to avoid overwriting here.
4073        if self.encoding != UTF_8 {
4074            let max = core::cmp::min(len, trail + ascii::MAX_STRIDE_SIZE);
4075            while trail < max {
4076                bytes[trail] = 0;
4077                trail += 1;
4078            }
4079        }
4080        while trail < len && ((bytes[trail] & 0xC0) == 0x80) {
4081            bytes[trail] = 0;
4082            trail += 1;
4083        }
4084        // Defuse the zeroing guard.
4085        let _ = scopeguard::ScopeGuard::<&mut [u8], _>::into_inner(bytes);
4086        (result, read, written, replaced)
4087    }
4088
4089    /// Incrementally decode a byte stream into UTF-8 with malformed sequences
4090    /// replaced with the REPLACEMENT CHARACTER using a `String` receiver.
4091    ///
4092    /// Like the others, this method follows the logic that the output buffer is
4093    /// caller-allocated. This method treats the capacity of the `String` as
4094    /// the output limit. That is, this method guarantees not to cause a
4095    /// reallocation of the backing buffer of `String`.
4096    ///
4097    /// The return value is a tuple that contains the `DecoderResult`, the
4098    /// number of bytes read and a boolean indicating whether replacements
4099    /// were done. The number of bytes written is signaled via the length of
4100    /// the `String` changing.
4101    ///
4102    /// See the documentation of the struct for documentation for `decode_*`
4103    /// methods collectively.
4104    ///
4105    /// Available to Rust only and only with the `alloc` feature enabled (enabled
4106    /// by default).
4107    #[cfg(feature = "alloc")]
4108    pub fn decode_to_string(
4109        &mut self,
4110        src: &[u8],
4111        dst: &mut String,
4112        last: bool,
4113    ) -> (CoderResult, usize, bool) {
4114        // SAFETY: Writing to `String` by using it as `Vec` is safe
4115        // iff the result is valid UTF-8 afterwards. We trust
4116        // `decode_to_utf8` below to write valid UTF-8 and
4117        // we trust that we update the length correctly below.
4118        // Furthermore, the length update is the last operation, so
4119        // if an earlier step panics, the logically exposed part of the
4120        // `Vec`/`String` remains unchanged.
4121        let vec = unsafe { dst.as_mut_vec() };
4122        let old_len = vec.len();
4123        let spare_capacity = minimally_init(vec.spare_capacity_mut());
4124        let (result, read, written, replaced) = self.decode_to_utf8(src, spare_capacity, last);
4125        debug_assert!(written <= spare_capacity.len());
4126        let new_len = old_len + written;
4127        assert!(new_len <= vec.capacity());
4128        // SAFETY: We trust that `decode_to_utf8` wrote valid UTF-8
4129        // to `spare_capacity[..written]`. Also, regarding the information
4130        // disclosure risk of `minimally_init`, this also means trusting
4131        // that every byte of `spare_capacity[..written]` got overwritten.
4132        // (We're no worse off than before regarding
4133        // `spare_capacity[written..]`) which remains not logically exposed.)
4134        // We (non-debug )asserted immediately above that `new_len` conforms
4135        // to the invariant that it must not exceed `vec.capacity()`.
4136        unsafe {
4137            vec.set_len(new_len);
4138        }
4139        (result, read, replaced)
4140    }
4141
4142    public_decode_function!(/// Incrementally decode a byte stream into UTF-8
4143                            /// _without replacement_.
4144                            ///
4145                            /// See the documentation of the struct for
4146                            /// documentation for `decode_*` methods
4147                            /// collectively.
4148                            ///
4149                            /// Available via the C wrapper.
4150                            ,
4151                            decode_to_utf8_without_replacement,
4152                            decode_to_utf8_raw,
4153                            decode_to_utf8_checking_end,
4154                            decode_to_utf8_after_one_potential_bom_byte,
4155                            decode_to_utf8_after_two_potential_bom_bytes,
4156                            decode_to_utf8_checking_end_with_offset,
4157                            u8);
4158
4159    /// Incrementally decode a byte stream into UTF-8 with type system signaling
4160    /// of UTF-8 validity.
4161    ///
4162    /// This methods calls `decode_to_utf8_without_replacement` and then zeroes enough subsequent
4163    /// bytes to maintain the invariant of `str`.
4164    ///
4165    /// See the documentation of the struct for documentation for `decode_*`
4166    /// methods collectively.
4167    ///
4168    /// Available to Rust only.
4169    pub fn decode_to_str_without_replacement(
4170        &mut self,
4171        src: &[u8],
4172        dst: &mut str,
4173        last: bool,
4174    ) -> (DecoderResult, usize, usize) {
4175        // SAFETY: We trust that `decode_to_utf8_without_replacement` writes
4176        // valid UTF-8. To make the part of the slice after what was reported
4177        // as logically written by that funtion, we use knowledge of the internals
4178        // to overwrite trailing garbage that may have been written. Then we also
4179        // overwrite a possible partial UTF-8 byte sequence after that. Then the
4180        // rest must be valid on the assumption that `dst` was valid to begin with.
4181        // In case of a panic, the `ScopeGuard` zeros the whole slice, which ensures
4182        // it's valid UTF-8 in an use-after-panic scenario when unwinding is enabled.
4183        // (Relevant only if there's a panic due to a crate-internal bug. Panics
4184        // arising from misuse of the public API don't need this guard and end up
4185        // zeroing the slice unnecessarily.)
4186        let mut bytes = scopeguard::guard(unsafe { dst.as_bytes_mut() }, |bytes| {
4187            bytes.iter_mut().for_each(|b| *b = 0)
4188        });
4189        let (result, read, written) =
4190            self.decode_to_utf8_without_replacement(src, &mut bytes, last);
4191        let len = bytes.len();
4192        let mut trail = written;
4193        // Non-UTF-8 ASCII-compatible decoders may write up to `MAX_STRIDE_SIZE`
4194        // bytes of trailing garbage. No need to optimize non-ASCII-compatible
4195        // encodings to avoid overwriting here.
4196        if self.encoding != UTF_8 {
4197            let max = core::cmp::min(len, trail + ascii::MAX_STRIDE_SIZE);
4198            while trail < max {
4199                bytes[trail] = 0;
4200                trail += 1;
4201            }
4202        }
4203        while trail < len && ((bytes[trail] & 0xC0) == 0x80) {
4204            bytes[trail] = 0;
4205            trail += 1;
4206        }
4207        // Defuse the zeroing guard.
4208        let _ = scopeguard::ScopeGuard::<&mut [u8], _>::into_inner(bytes);
4209        (result, read, written)
4210    }
4211
4212    /// Incrementally decode a byte stream into UTF-8 using a `String` receiver.
4213    ///
4214    /// Like the others, this method follows the logic that the output buffer is
4215    /// caller-allocated. This method treats the capacity of the `String` as
4216    /// the output limit. That is, this method guarantees not to cause a
4217    /// reallocation of the backing buffer of `String`.
4218    ///
4219    /// The return value is a pair that contains the `DecoderResult` and the
4220    /// number of bytes read. The number of bytes written is signaled via
4221    /// the length of the `String` changing.
4222    ///
4223    /// See the documentation of the struct for documentation for `decode_*`
4224    /// methods collectively.
4225    ///
4226    /// Available to Rust only and only with the `alloc` feature enabled (enabled
4227    /// by default).
4228    #[cfg(feature = "alloc")]
4229    pub fn decode_to_string_without_replacement(
4230        &mut self,
4231        src: &[u8],
4232        dst: &mut String,
4233        last: bool,
4234    ) -> (DecoderResult, usize) {
4235        // SAFETY: Writing to `String` by using it as `Vec` is safe
4236        // iff the result is valid UTF-8 afterwards. We trust
4237        // `decode_to_utf8_without_replacement` below to write valid UTF-8 and
4238        // we trust that we update the length correctly below.
4239        // Furthermore, the length update is the last operation, so
4240        // if an earlier step panics, the logically exposed part of the
4241        // `Vec`/`String` remains unchanged.
4242        let vec = unsafe { dst.as_mut_vec() };
4243        let old_len = vec.len();
4244        let spare_capacity = minimally_init(vec.spare_capacity_mut());
4245        let (result, read, written) =
4246            self.decode_to_utf8_without_replacement(src, spare_capacity, last);
4247        debug_assert!(written <= spare_capacity.len());
4248        let new_len = old_len + written;
4249        assert!(new_len <= vec.capacity());
4250        // SAFETY: We trust that `decode_to_utf8_without_replacement` wrote valid UTF-8
4251        // to `spare_capacity[..written]`. Also, regarding the information
4252        // disclosure risk of `minimally_init`, this also means trusting
4253        // that every byte of `spare_capacity[..written]` got overwritten.
4254        // (We're no worse off than before regarding
4255        // `spare_capacity[written..]`) which remains not logically exposed.)
4256        // We (non-debug )asserted immediately above that `new_len` conforms
4257        // to the invariant that it must not exceed `vec.capacity()`.
4258        unsafe {
4259            vec.set_len(new_len);
4260        }
4261        (result, read)
4262    }
4263
4264    /// Query the worst-case UTF-16 output size (with or without replacement).
4265    ///
4266    /// Returns the size of the output buffer in UTF-16 code units (`u16`)
4267    /// that will not overflow given the current state of the decoder and
4268    /// `byte_length` number of additional input bytes or `None` if `usize`
4269    /// would overflow.
4270    ///
4271    /// Since the REPLACEMENT CHARACTER fits into one UTF-16 code unit, the
4272    /// return value of this method applies also in the
4273    /// `_without_replacement` case.
4274    ///
4275    /// Available via the C wrapper.
4276    pub fn max_utf16_buffer_length(&self, byte_length: usize) -> Option<usize> {
4277        // Need to consider a) the decoder morphing due to the BOM and b) a partial
4278        // BOM getting pushed to the underlying decoder.
4279        match self.life_cycle {
4280            DecoderLifeCycle::Converting
4281            | DecoderLifeCycle::AtUtf8Start
4282            | DecoderLifeCycle::AtUtf16LeStart
4283            | DecoderLifeCycle::AtUtf16BeStart => {
4284                return self.variant.max_utf16_buffer_length(byte_length);
4285            }
4286            DecoderLifeCycle::AtStart => {
4287                if let Some(utf8_bom) = byte_length.checked_add(1)
4288                    && let Some(utf16_bom) =
4289                        checked_add(1, checked_div(byte_length.checked_add(1), 2))
4290                {
4291                    let utf_bom = core::cmp::max(utf8_bom, utf16_bom);
4292                    let encoding = self.encoding();
4293                    if encoding == UTF_8 || encoding == UTF_16LE || encoding == UTF_16BE {
4294                        // No need to consider the internal state of the underlying decoder,
4295                        // because it is at start, because no data has reached it yet.
4296                        return Some(utf_bom);
4297                    } else if let Some(non_bom) = self.variant.max_utf16_buffer_length(byte_length)
4298                    {
4299                        return Some(core::cmp::max(utf_bom, non_bom));
4300                    }
4301                }
4302            }
4303            DecoderLifeCycle::SeenUtf8First | DecoderLifeCycle::SeenUtf8Second => {
4304                // Add two bytes even when only one byte has been seen,
4305                // because the one byte can become a lead byte in multibyte
4306                // decoders, but only after the decoder has been queried
4307                // for max length, so the decoder's own logic for adding
4308                // one for a pending lead cannot work.
4309                if let Some(sum) = byte_length.checked_add(2)
4310                    && let Some(utf8_bom) = sum.checked_add(1)
4311                {
4312                    if self.encoding() == UTF_8 {
4313                        // No need to consider the internal state of the underlying decoder,
4314                        // because it is at start, because no data has reached it yet.
4315                        return Some(utf8_bom);
4316                    } else if let Some(non_bom) = self.variant.max_utf16_buffer_length(sum) {
4317                        return Some(core::cmp::max(utf8_bom, non_bom));
4318                    }
4319                }
4320            }
4321            DecoderLifeCycle::ConvertingWithPendingBB => {
4322                if let Some(sum) = byte_length.checked_add(2) {
4323                    return self.variant.max_utf16_buffer_length(sum);
4324                }
4325            }
4326            DecoderLifeCycle::SeenUtf16LeFirst | DecoderLifeCycle::SeenUtf16BeFirst => {
4327                // Add two bytes even when only one byte has been seen,
4328                // because the one byte can become a lead byte in multibyte
4329                // decoders, but only after the decoder has been queried
4330                // for max length, so the decoder's own logic for adding
4331                // one for a pending lead cannot work.
4332                if let Some(sum) = byte_length.checked_add(2)
4333                    && let Some(utf16_bom) = checked_add(1, checked_div(sum.checked_add(1), 2))
4334                {
4335                    let encoding = self.encoding();
4336                    if encoding == UTF_16LE || encoding == UTF_16BE {
4337                        // No need to consider the internal state of the underlying decoder,
4338                        // because it is at start, because no data has reached it yet.
4339                        return Some(utf16_bom);
4340                    } else if let Some(non_bom) = self.variant.max_utf16_buffer_length(sum) {
4341                        return Some(core::cmp::max(utf16_bom, non_bom));
4342                    }
4343                }
4344            }
4345            DecoderLifeCycle::Finished => panic!("Must not use a decoder that has finished."),
4346        }
4347        None
4348    }
4349
4350    /// Incrementally decode a byte stream into UTF-16 with malformed sequences
4351    /// replaced with the REPLACEMENT CHARACTER.
4352    ///
4353    /// See the documentation of the struct for documentation for `decode_*`
4354    /// methods collectively.
4355    ///
4356    /// Available via the C wrapper.
4357    pub fn decode_to_utf16(
4358        &mut self,
4359        src: &[u8],
4360        dst: &mut [u16],
4361        last: bool,
4362    ) -> (CoderResult, usize, usize, bool) {
4363        let mut had_errors = false;
4364        let mut total_read = 0usize;
4365        let mut total_written = 0usize;
4366        loop {
4367            let (result, read, written) = self.decode_to_utf16_without_replacement(
4368                &src[total_read..],
4369                &mut dst[total_written..],
4370                last,
4371            );
4372            total_read += read;
4373            total_written += written;
4374            match result {
4375                DecoderResult::InputEmpty => {
4376                    return (
4377                        CoderResult::InputEmpty,
4378                        total_read,
4379                        total_written,
4380                        had_errors,
4381                    );
4382                }
4383                DecoderResult::OutputFull => {
4384                    return (
4385                        CoderResult::OutputFull,
4386                        total_read,
4387                        total_written,
4388                        had_errors,
4389                    );
4390                }
4391                DecoderResult::Malformed(_, _) => {
4392                    had_errors = true;
4393                    // There should always be space for the U+FFFD, because
4394                    // otherwise we'd have gotten OutputFull already.
4395                    dst[total_written] = 0xFFFD;
4396                    total_written += 1;
4397                }
4398            }
4399        }
4400    }
4401
4402    public_decode_function!(/// Incrementally decode a byte stream into UTF-16
4403                            /// _without replacement_.
4404                            ///
4405                            /// See the documentation of the struct for
4406                            /// documentation for `decode_*` methods
4407                            /// collectively.
4408                            ///
4409                            /// Available via the C wrapper.
4410                            ,
4411                            decode_to_utf16_without_replacement,
4412                            decode_to_utf16_raw,
4413                            decode_to_utf16_checking_end,
4414                            decode_to_utf16_after_one_potential_bom_byte,
4415                            decode_to_utf16_after_two_potential_bom_bytes,
4416                            decode_to_utf16_checking_end_with_offset,
4417                            u16);
4418
4419    /// Checks for compatibility with storing Unicode scalar values as unsigned
4420    /// bytes taking into account the state of the decoder.
4421    ///
4422    /// Returns `None` if the decoder is not in a neutral state, including waiting
4423    /// for the BOM, or if the encoding is never Latin1-byte-compatible.
4424    ///
4425    /// Otherwise returns the index of the first byte whose unsigned value doesn't
4426    /// directly correspond to the decoded Unicode scalar value, or the length
4427    /// of the input if all bytes in the input decode directly to scalar values
4428    /// corresponding to the unsigned byte values.
4429    ///
4430    /// Does not change the state of the decoder.
4431    ///
4432    /// Do not use this unless you are supporting SpiderMonkey/V8-style string
4433    /// storage optimizations.
4434    ///
4435    /// Available via the C wrapper.
4436    pub fn latin1_byte_compatible_up_to(&self, bytes: &[u8]) -> Option<usize> {
4437        match self.life_cycle {
4438            DecoderLifeCycle::Converting => self.variant.latin1_byte_compatible_up_to(bytes),
4439            DecoderLifeCycle::Finished => panic!("Must not use a decoder that has finished."),
4440            _ => None,
4441        }
4442    }
4443}
4444
4445impl core::fmt::Debug for Decoder {
4446    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
4447        f.debug_struct("Decoder")
4448            .field("encoding", self.encoding)
4449            .field("life_cycle", &self.life_cycle)
4450            .finish_non_exhaustive()
4451    }
4452}
4453
4454/// Result of a (potentially partial) encode operation without replacement.
4455#[must_use]
4456#[derive(Debug, PartialEq, Eq)]
4457pub enum EncoderResult {
4458    /// The input was exhausted.
4459    ///
4460    /// If this result was returned from a call where `last` was `true`, the
4461    /// decoding process has completed. Otherwise, the caller should call a
4462    /// decode method again with more input.
4463    InputEmpty,
4464
4465    /// The encoder cannot produce another unit of output, because the output
4466    /// buffer does not have enough space left.
4467    ///
4468    /// The caller must provide more output space upon the next call and re-push
4469    /// the remaining input to the decoder.
4470    OutputFull,
4471
4472    /// The encoder encountered an unmappable character.
4473    ///
4474    /// The caller must either treat this as a fatal error or must append
4475    /// a placeholder to the output and then re-push the remaining input to the
4476    /// encoder.
4477    Unmappable(char),
4478}
4479
4480impl EncoderResult {
4481    fn unmappable_from_bmp(bmp: u16) -> EncoderResult {
4482        EncoderResult::Unmappable(::core::char::from_u32(u32::from(bmp)).unwrap())
4483    }
4484}
4485
4486/// A converter that encodes a Unicode stream into bytes according to a
4487/// character encoding in a streaming (incremental) manner.
4488///
4489/// The various `encode_*` methods take an input buffer (`src`) and an output
4490/// buffer `dst` both of which are caller-allocated. There are variants for
4491/// both UTF-8 and UTF-16 input buffers.
4492///
4493/// An `encode_*` method encode characters from `src` into bytes characters
4494/// stored into `dst` until one of the following three things happens:
4495///
4496/// 1. An unmappable character is encountered (`*_without_replacement` variants
4497///    only).
4498///
4499/// 2. The output buffer has been filled so near capacity that the decoder
4500///    cannot be sure that processing an additional character of input wouldn't
4501///    cause so much output that the output buffer would overflow.
4502///
4503/// 3. All the input characters have been processed.
4504///
4505/// The `encode_*` method then returns tuple of a status indicating which one
4506/// of the three reasons to return happened, how many input code units (`u8`
4507/// when encoding from UTF-8 and `u16` when encoding from UTF-16) were read,
4508/// how many output bytes were written (except when encoding into `Vec<u8>`,
4509/// whose length change indicates this), and in the case of the variants that
4510/// perform replacement, a boolean indicating whether an unmappable
4511/// character was replaced with a numeric character reference during the call.
4512///
4513/// The number of bytes "written" is what's logically written. Garbage may be
4514/// written in the output buffer beyond the point logically written to.
4515///
4516/// In the case of the methods whose name ends with
4517/// `*_without_replacement`, the status is an [`EncoderResult`][1] enumeration
4518/// (possibilities `Unmappable`, `OutputFull` and `InputEmpty` corresponding to
4519/// the three cases listed above).
4520///
4521/// In the case of methods whose name does not end with
4522/// `*_without_replacement`, unmappable characters are automatically replaced
4523/// with the corresponding numeric character references and unmappable
4524/// characters do not cause the methods to return early.
4525///
4526/// When encoding from UTF-8 without replacement, the methods are guaranteed
4527/// not to return indicating that more output space is needed if the length
4528/// of the output buffer is at least the length returned by
4529/// [`max_buffer_length_from_utf8_without_replacement()`][2]. When encoding from
4530/// UTF-8 with replacement, the length of the output buffer that guarantees the
4531/// methods not to return indicating that more output space is needed in the
4532/// absence of unmappable characters is given by
4533/// [`max_buffer_length_from_utf8_if_no_unmappables()`][3]. When encoding from
4534/// UTF-16 without replacement, the methods are guaranteed not to return
4535/// indicating that more output space is needed if the length of the output
4536/// buffer is at least the length returned by
4537/// [`max_buffer_length_from_utf16_without_replacement()`][4]. When encoding
4538/// from UTF-16 with replacement, the the length of the output buffer that
4539/// guarantees the methods not to return indicating that more output space is
4540/// needed in the absence of unmappable characters is given by
4541/// [`max_buffer_length_from_utf16_if_no_unmappables()`][5].
4542/// When encoding with replacement, applications are not expected to size the
4543/// buffer for the worst case ahead of time but to resize the buffer if there
4544/// are unmappable characters. This is why max length queries are only available
4545/// for the case where there are no unmappable characters.
4546///
4547/// When encoding from UTF-8, each `src` buffer _must_ be valid UTF-8. (When
4548/// calling from Rust, the type system takes care of this.) When encoding from
4549/// UTF-16, unpaired surrogates in the input are treated as U+FFFD REPLACEMENT
4550/// CHARACTERS. Therefore, in order for astral characters not to turn into a
4551/// pair of REPLACEMENT CHARACTERS, the caller must ensure that surrogate pairs
4552/// are not split across input buffer boundaries.
4553///
4554/// After an `encode_*` call returns, the output produced so far, taken as a
4555/// whole from the start of the stream, is guaranteed to consist of a valid
4556/// byte sequence in the target encoding. (I.e. the code unit sequence for a
4557/// character is guaranteed not to be split across output buffers. However, due
4558/// to the stateful nature of ISO-2022-JP, the stream needs to be considered
4559/// from the start for it to be valid. For other encodings, the validity holds
4560/// on a per-output buffer basis.)
4561///
4562/// The boolean argument `last` indicates that the end of the stream is reached
4563/// when all the characters in `src` have been consumed. This argument is needed
4564/// for ISO-2022-JP and is ignored for other encodings.
4565///
4566/// An `Encoder` object can be used to incrementally encode a byte stream.
4567///
4568/// During the processing of a single stream, the caller must call `encode_*`
4569/// zero or more times with `last` set to `false` and then call `encode_*` at
4570/// least once with `last` set to `true`. If `encode_*` returns `InputEmpty`,
4571/// the processing of the stream has ended. Otherwise, the caller must call
4572/// `encode_*` again with `last` set to `true` (or treat an `Unmappable` result
4573/// as a fatal error).
4574///
4575/// Once the stream has ended, the `Encoder` object must not be used anymore.
4576/// That is, you need to create another one to process another stream.
4577///
4578/// When the encoder returns `OutputFull` or the encoder returns `Unmappable`
4579/// and the caller does not wish to treat it as a fatal error, the input buffer
4580/// `src` may not have been completely consumed. In that case, the caller must
4581/// pass the unconsumed contents of `src` to `encode_*` again upon the next
4582/// call.
4583///
4584/// [1]: enum.EncoderResult.html
4585/// [2]: #method.max_buffer_length_from_utf8_without_replacement
4586/// [3]: #method.max_buffer_length_from_utf8_if_no_unmappables
4587/// [4]: #method.max_buffer_length_from_utf16_without_replacement
4588/// [5]: #method.max_buffer_length_from_utf16_if_no_unmappables
4589///
4590/// # Infinite loops
4591///
4592/// When converting with a fixed-size output buffer whose size is too small to
4593/// accommodate one character of output, an infinite loop ensues. When
4594/// converting with a fixed-size output buffer, it generally makes sense to
4595/// make the buffer fairly large (e.g. couple of kilobytes).
4596pub struct Encoder {
4597    encoding: &'static Encoding,
4598    variant: VariantEncoder,
4599}
4600
4601impl Encoder {
4602    fn new(enc: &'static Encoding, encoder: VariantEncoder) -> Encoder {
4603        Encoder {
4604            encoding: enc,
4605            variant: encoder,
4606        }
4607    }
4608
4609    /// The `Encoding` this `Encoder` is for.
4610    #[inline]
4611    pub fn encoding(&self) -> &'static Encoding {
4612        self.encoding
4613    }
4614
4615    /// Returns `true` if this is an ISO-2022-JP encoder that's not in the
4616    /// ASCII state and `false` otherwise.
4617    #[inline]
4618    pub fn has_pending_state(&self) -> bool {
4619        self.variant.has_pending_state()
4620    }
4621
4622    /// Query the worst-case output size when encoding from UTF-8 with
4623    /// replacement.
4624    ///
4625    /// Returns the size of the output buffer in bytes that will not overflow
4626    /// given the current state of the encoder and `byte_length` number of
4627    /// additional input code units if there are no unmappable characters in
4628    /// the input or `None` if `usize` would overflow.
4629    ///
4630    /// Available via the C wrapper.
4631    pub fn max_buffer_length_from_utf8_if_no_unmappables(
4632        &self,
4633        byte_length: usize,
4634    ) -> Option<usize> {
4635        checked_add(
4636            if self.encoding().can_encode_everything() {
4637                0
4638            } else {
4639                NCR_EXTRA
4640            },
4641            self.max_buffer_length_from_utf8_without_replacement(byte_length),
4642        )
4643    }
4644
4645    /// Query the worst-case output size when encoding from UTF-8 without
4646    /// replacement.
4647    ///
4648    /// Returns the size of the output buffer in bytes that will not overflow
4649    /// given the current state of the encoder and `byte_length` number of
4650    /// additional input code units or `None` if `usize` would overflow.
4651    ///
4652    /// Available via the C wrapper.
4653    pub fn max_buffer_length_from_utf8_without_replacement(
4654        &self,
4655        byte_length: usize,
4656    ) -> Option<usize> {
4657        self.variant
4658            .max_buffer_length_from_utf8_without_replacement(byte_length)
4659    }
4660
4661    /// Incrementally encode into byte stream from UTF-8 with unmappable
4662    /// characters replaced with HTML (decimal) numeric character references.
4663    ///
4664    /// See the documentation of the struct for documentation for `encode_*`
4665    /// methods collectively.
4666    ///
4667    /// Available via the C wrapper.
4668    pub fn encode_from_utf8(
4669        &mut self,
4670        src: &str,
4671        dst: &mut [u8],
4672        last: bool,
4673    ) -> (CoderResult, usize, usize, bool) {
4674        let dst_len = dst.len();
4675        let effective_dst_len = if self.encoding().can_encode_everything() {
4676            dst_len
4677        } else {
4678            if dst_len < NCR_EXTRA {
4679                if src.is_empty() && !(last && self.has_pending_state()) {
4680                    return (CoderResult::InputEmpty, 0, 0, false);
4681                }
4682                return (CoderResult::OutputFull, 0, 0, false);
4683            }
4684            dst_len - NCR_EXTRA
4685        };
4686        let mut had_unmappables = false;
4687        let mut total_read = 0usize;
4688        let mut total_written = 0usize;
4689        loop {
4690            let (result, read, written) = self.encode_from_utf8_without_replacement(
4691                &src[total_read..],
4692                &mut dst[total_written..effective_dst_len],
4693                last,
4694            );
4695            total_read += read;
4696            total_written += written;
4697            match result {
4698                EncoderResult::InputEmpty => {
4699                    return (
4700                        CoderResult::InputEmpty,
4701                        total_read,
4702                        total_written,
4703                        had_unmappables,
4704                    );
4705                }
4706                EncoderResult::OutputFull => {
4707                    return (
4708                        CoderResult::OutputFull,
4709                        total_read,
4710                        total_written,
4711                        had_unmappables,
4712                    );
4713                }
4714                EncoderResult::Unmappable(unmappable) => {
4715                    had_unmappables = true;
4716                    debug_assert!(dst.len() - total_written >= NCR_EXTRA);
4717                    debug_assert_ne!(self.encoding(), UTF_16BE);
4718                    debug_assert_ne!(self.encoding(), UTF_16LE);
4719                    // Additionally, Iso2022JpEncoder is responsible for
4720                    // transitioning to ASCII when returning with Unmappable.
4721                    total_written += write_ncr(unmappable, &mut dst[total_written..]);
4722                    if total_written >= effective_dst_len {
4723                        if total_read == src.len() && !(last && self.has_pending_state()) {
4724                            return (
4725                                CoderResult::InputEmpty,
4726                                total_read,
4727                                total_written,
4728                                had_unmappables,
4729                            );
4730                        }
4731                        return (
4732                            CoderResult::OutputFull,
4733                            total_read,
4734                            total_written,
4735                            had_unmappables,
4736                        );
4737                    }
4738                }
4739            }
4740        }
4741    }
4742
4743    /// Incrementally encode into byte stream from UTF-8 with unmappable
4744    /// characters replaced with HTML (decimal) numeric character references.
4745    ///
4746    /// See the documentation of the struct for documentation for `encode_*`
4747    /// methods collectively.
4748    ///
4749    /// Available to Rust only and only with the `alloc` feature enabled (enabled
4750    /// by default).
4751    #[cfg(feature = "alloc")]
4752    pub fn encode_from_utf8_to_vec(
4753        &mut self,
4754        src: &str,
4755        dst: &mut Vec<u8>,
4756        last: bool,
4757    ) -> (CoderResult, usize, bool) {
4758        let old_len = dst.len();
4759        let spare_capacity = minimally_init(dst.spare_capacity_mut());
4760        let (result, read, written, replaced) = self.encode_from_utf8(src, spare_capacity, last);
4761        debug_assert!(written <= spare_capacity.len());
4762        let new_len = old_len + written;
4763        assert!(new_len <= dst.capacity());
4764        // SAFETY: We trust that `encode_from_utf8` wrote to every byte of
4765        // to `spare_capacity[..written]`. Also, regarding the information
4766        // disclosure risk of `minimally_init`, this also means trusting
4767        // that every byte of `spare_capacity[..written]` got overwritten.
4768        // (We're no worse off than before regarding
4769        // `spare_capacity[written..]`) which remains not logically exposed.)
4770        // We (non-debug )asserted immediately above that `new_len` conforms
4771        // to the invariant that it must not exceed `dst.capacity()`.
4772        unsafe {
4773            dst.set_len(new_len);
4774        }
4775        (result, read, replaced)
4776    }
4777
4778    /// Incrementally encode into byte stream from UTF-8 _without replacement_.
4779    ///
4780    /// See the documentation of the struct for documentation for `encode_*`
4781    /// methods collectively.
4782    ///
4783    /// Available via the C wrapper.
4784    pub fn encode_from_utf8_without_replacement(
4785        &mut self,
4786        src: &str,
4787        dst: &mut [u8],
4788        last: bool,
4789    ) -> (EncoderResult, usize, usize) {
4790        self.variant.encode_from_utf8_raw(src, dst, last)
4791    }
4792
4793    /// Incrementally encode into byte stream from UTF-8 _without replacement_.
4794    ///
4795    /// See the documentation of the struct for documentation for `encode_*`
4796    /// methods collectively.
4797    ///
4798    /// Available to Rust only and only with the `alloc` feature enabled (enabled
4799    /// by default).
4800    #[cfg(feature = "alloc")]
4801    pub fn encode_from_utf8_to_vec_without_replacement(
4802        &mut self,
4803        src: &str,
4804        dst: &mut Vec<u8>,
4805        last: bool,
4806    ) -> (EncoderResult, usize) {
4807        let old_len = dst.len();
4808        let spare_capacity = minimally_init(dst.spare_capacity_mut());
4809        let (result, read, written) =
4810            self.encode_from_utf8_without_replacement(src, spare_capacity, last);
4811        debug_assert!(written <= spare_capacity.len());
4812        let new_len = old_len + written;
4813        assert!(new_len <= dst.capacity());
4814        // SAFETY: We trust that `encode_from_utf8_without_replacement` wrote to every byte of
4815        // to `spare_capacity[..written]`. Also, regarding the information
4816        // disclosure risk of `minimally_init`, this also means trusting
4817        // that every byte of `spare_capacity[..written]` got overwritten.
4818        // (We're no worse off than before regarding
4819        // `spare_capacity[written..]`) which remains not logically exposed.)
4820        // We (non-debug )asserted immediately above that `new_len` conforms
4821        // to the invariant that it must not exceed `dst.capacity()`.
4822        unsafe {
4823            dst.set_len(new_len);
4824        }
4825        (result, read)
4826    }
4827
4828    /// Query the worst-case output size when encoding from UTF-16 with
4829    /// replacement.
4830    ///
4831    /// Returns the size of the output buffer in bytes that will not overflow
4832    /// given the current state of the encoder and `u16_length` number of
4833    /// additional input code units if there are no unmappable characters in
4834    /// the input or `None` if `usize` would overflow.
4835    ///
4836    /// Available via the C wrapper.
4837    pub fn max_buffer_length_from_utf16_if_no_unmappables(
4838        &self,
4839        u16_length: usize,
4840    ) -> Option<usize> {
4841        checked_add(
4842            if self.encoding().can_encode_everything() {
4843                0
4844            } else {
4845                NCR_EXTRA
4846            },
4847            self.max_buffer_length_from_utf16_without_replacement(u16_length),
4848        )
4849    }
4850
4851    /// Query the worst-case output size when encoding from UTF-16 without
4852    /// replacement.
4853    ///
4854    /// Returns the size of the output buffer in bytes that will not overflow
4855    /// given the current state of the encoder and `u16_length` number of
4856    /// additional input code units or `None` if `usize` would overflow.
4857    ///
4858    /// Available via the C wrapper.
4859    pub fn max_buffer_length_from_utf16_without_replacement(
4860        &self,
4861        u16_length: usize,
4862    ) -> Option<usize> {
4863        self.variant
4864            .max_buffer_length_from_utf16_without_replacement(u16_length)
4865    }
4866
4867    /// Incrementally encode into byte stream from UTF-16 with unmappable
4868    /// characters replaced with HTML (decimal) numeric character references.
4869    ///
4870    /// See the documentation of the struct for documentation for `encode_*`
4871    /// methods collectively.
4872    ///
4873    /// Available via the C wrapper.
4874    pub fn encode_from_utf16(
4875        &mut self,
4876        src: &[u16],
4877        dst: &mut [u8],
4878        last: bool,
4879    ) -> (CoderResult, usize, usize, bool) {
4880        let dst_len = dst.len();
4881        let effective_dst_len = if self.encoding().can_encode_everything() {
4882            dst_len
4883        } else {
4884            if dst_len < NCR_EXTRA {
4885                if src.is_empty() && !(last && self.has_pending_state()) {
4886                    return (CoderResult::InputEmpty, 0, 0, false);
4887                }
4888                return (CoderResult::OutputFull, 0, 0, false);
4889            }
4890            dst_len - NCR_EXTRA
4891        };
4892        let mut had_unmappables = false;
4893        let mut total_read = 0usize;
4894        let mut total_written = 0usize;
4895        loop {
4896            let (result, read, written) = self.encode_from_utf16_without_replacement(
4897                &src[total_read..],
4898                &mut dst[total_written..effective_dst_len],
4899                last,
4900            );
4901            total_read += read;
4902            total_written += written;
4903            match result {
4904                EncoderResult::InputEmpty => {
4905                    return (
4906                        CoderResult::InputEmpty,
4907                        total_read,
4908                        total_written,
4909                        had_unmappables,
4910                    );
4911                }
4912                EncoderResult::OutputFull => {
4913                    return (
4914                        CoderResult::OutputFull,
4915                        total_read,
4916                        total_written,
4917                        had_unmappables,
4918                    );
4919                }
4920                EncoderResult::Unmappable(unmappable) => {
4921                    had_unmappables = true;
4922                    debug_assert!(dst.len() - total_written >= NCR_EXTRA);
4923                    // There are no UTF-16 encoders and even if there were,
4924                    // they'd never have unmappables.
4925                    debug_assert_ne!(self.encoding(), UTF_16BE);
4926                    debug_assert_ne!(self.encoding(), UTF_16LE);
4927                    // Additionally, Iso2022JpEncoder is responsible for
4928                    // transitioning to ASCII when returning with Unmappable
4929                    // from the jis0208 state. That is, when we encode
4930                    // ISO-2022-JP and come here, the encoder is in either the
4931                    // ASCII or the Roman state. We are allowed to generate any
4932                    // printable ASCII excluding \ and ~.
4933                    total_written += write_ncr(unmappable, &mut dst[total_written..]);
4934                    if total_written >= effective_dst_len {
4935                        if total_read == src.len() && !(last && self.has_pending_state()) {
4936                            return (
4937                                CoderResult::InputEmpty,
4938                                total_read,
4939                                total_written,
4940                                had_unmappables,
4941                            );
4942                        }
4943                        return (
4944                            CoderResult::OutputFull,
4945                            total_read,
4946                            total_written,
4947                            had_unmappables,
4948                        );
4949                    }
4950                }
4951            }
4952        }
4953    }
4954
4955    /// Incrementally encode into byte stream from UTF-16 _without replacement_.
4956    ///
4957    /// See the documentation of the struct for documentation for `encode_*`
4958    /// methods collectively.
4959    ///
4960    /// Available via the C wrapper.
4961    pub fn encode_from_utf16_without_replacement(
4962        &mut self,
4963        src: &[u16],
4964        dst: &mut [u8],
4965        last: bool,
4966    ) -> (EncoderResult, usize, usize) {
4967        self.variant.encode_from_utf16_raw(src, dst, last)
4968    }
4969}
4970
4971impl core::fmt::Debug for Encoder {
4972    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
4973        f.debug_struct("Encoder")
4974            .field("encoding", self.encoding)
4975            .finish_non_exhaustive()
4976    }
4977}
4978
4979/// Format an unmappable as NCR without heap allocation.
4980fn write_ncr(unmappable: char, dst: &mut [u8]) -> usize {
4981    // len is the number of decimal digits needed to represent unmappable plus
4982    // 3 (the length of "&#" and ";").
4983    let mut number = unmappable as u32;
4984    let len = if number >= 1_000_000u32 {
4985        10usize
4986    } else if number >= 100_000u32 {
4987        9usize
4988    } else if number >= 10_000u32 {
4989        8usize
4990    } else if number >= 1_000u32 {
4991        7usize
4992    } else if number >= 100u32 {
4993        6usize
4994    } else {
4995        // Review the outcome of https://github.com/whatwg/encoding/issues/15
4996        // to see if this case is possible
4997        5usize
4998    };
4999    debug_assert!(number >= 10u32);
5000    debug_assert!(len <= dst.len());
5001    let mut pos = len - 1;
5002    dst[pos] = b';';
5003    pos -= 1;
5004    loop {
5005        let rightmost = number % 10;
5006        dst[pos] = rightmost as u8 + b'0';
5007        pos -= 1;
5008        if number < 10 {
5009            break;
5010        }
5011        number /= 10;
5012    }
5013    dst[1] = b'#';
5014    dst[0] = b'&';
5015    len
5016}
5017
5018#[inline(always)]
5019fn in_range16(i: u16, start: u16, end: u16) -> bool {
5020    i.wrapping_sub(start) < (end - start)
5021}
5022
5023#[inline(always)]
5024fn in_range32(i: u32, start: u32, end: u32) -> bool {
5025    i.wrapping_sub(start) < (end - start)
5026}
5027
5028#[inline(always)]
5029fn in_inclusive_range8(i: u8, start: u8, end: u8) -> bool {
5030    i.wrapping_sub(start) <= (end - start)
5031}
5032
5033#[inline(always)]
5034fn in_inclusive_range16(i: u16, start: u16, end: u16) -> bool {
5035    i.wrapping_sub(start) <= (end - start)
5036}
5037
5038#[inline(always)]
5039fn in_inclusive_range32(i: u32, start: u32, end: u32) -> bool {
5040    i.wrapping_sub(start) <= (end - start)
5041}
5042
5043#[inline(always)]
5044fn in_inclusive_range(i: usize, start: usize, end: usize) -> bool {
5045    i.wrapping_sub(start) <= (end - start)
5046}
5047
5048#[inline(always)]
5049fn checked_add(num: usize, opt: Option<usize>) -> Option<usize> {
5050    if let Some(n) = opt {
5051        n.checked_add(num)
5052    } else {
5053        None
5054    }
5055}
5056
5057#[inline(always)]
5058fn checked_add_opt(one: Option<usize>, other: Option<usize>) -> Option<usize> {
5059    if let Some(n) = one {
5060        checked_add(n, other)
5061    } else {
5062        None
5063    }
5064}
5065
5066#[inline(always)]
5067fn checked_mul(num: usize, opt: Option<usize>) -> Option<usize> {
5068    if let Some(n) = opt {
5069        n.checked_mul(num)
5070    } else {
5071        None
5072    }
5073}
5074
5075#[inline(always)]
5076fn checked_div(opt: Option<usize>, num: usize) -> Option<usize> {
5077    if let Some(n) = opt {
5078        n.checked_div(num)
5079    } else {
5080        None
5081    }
5082}
5083
5084#[cfg(feature = "alloc")]
5085#[inline(always)]
5086fn checked_next_power_of_two(opt: Option<usize>) -> Option<usize> {
5087    opt.map(|n| n.next_power_of_two())
5088}
5089
5090#[cfg(feature = "alloc")]
5091#[inline(always)]
5092fn checked_min(one: Option<usize>, other: Option<usize>) -> Option<usize> {
5093    if let Some(a) = one {
5094        if let Some(b) = other {
5095            Some(::core::cmp::min(a, b))
5096        } else {
5097            Some(a)
5098        }
5099    } else {
5100        other
5101    }
5102}
5103
5104/// Smallest page size accoding to Wikipedia. If the pages are larger,
5105/// the code is still correct but does non-minimal writes.
5106///
5107/// We could confidently multiply this by 4 on aarch64 macOS, but
5108/// there is no point, since not initializing / initializing every
5109/// 4Kth byte / initializing everything makes no perf difference
5110/// at least on M3 Pro, so this whole thing is mainly for other
5111/// systems.
5112#[cfg(feature = "alloc")]
5113const SMALLEST_PAGE_SIZE: usize = 4096;
5114
5115/// Mask for the bits that are the offset within a page.
5116#[cfg(feature = "alloc")]
5117const PAGE_MASK: usize = SMALLEST_PAGE_SIZE - 1;
5118
5119/// When we only care about writing to a slice but `&mut [u8]` grants the
5120/// read capability and reading would be UB, this function does the minimum
5121/// writing to make the slice have arbitrary but fixed-value bytes. This
5122/// maintains correct boundary between `unsafe` and safe in terms of UB
5123/// avoidance resposibility even though we don't actually perform reads.
5124/// The caller must not rely on any byte in the slice that was already
5125/// initialized to retain its value after this function returns.
5126///
5127/// The point of wishing to not to contaminate all places with
5128/// `&mut [MaybeUninit<u8>]` is that `&mut [u8]` interacts better with
5129/// `core::simd` in a way that doesn't require `unsafe` in more places.
5130///
5131/// Note that the caller has to overwrite the exposed arbitrary but fixed-value
5132/// bytes to avoid information disclosure (somewhat analogously to reusing an
5133/// intermediate buffer created without any `unsafe`). This function is not
5134/// `unsafe`, because this function does not let the caller to experience UB.
5135/// Letting `&mut [MaybeUninit<u8>]` show up in more places in the crate internals
5136/// would not change the information disclosure risk in case there's a bug in
5137/// the tracking of how much has been written. Either way, the tracking of how
5138/// much has been written has to actually work, but it has a very good track
5139/// record of working.
5140///
5141/// On M3 Pro, we could just zero-initialize every byte without a notable
5142/// performance penalty, but on Zen 3 and Skylake, zeroing all bytes carries
5143/// a measurable penalty (in some cases only; depending on details of
5144/// subsequent writes!) but zeroing the first byte of every page does not
5145/// carry this perf penalty compared to not initializing anything (at least
5146/// when the slice is reasonable-sized relative to what meaningful data
5147/// end up written into it later).
5148#[cfg(feature = "alloc")]
5149fn minimally_init(buf: &mut [MaybeUninit<u8>]) -> &mut [u8] {
5150    // This loop is only broken out of as a goto forward. This structure
5151    // avoids borrowing for too long via `first_mut`.
5152    #[allow(clippy::never_loop, clippy::while_let_loop)]
5153    loop {
5154        if let Some(b) = buf.first_mut() {
5155            // Initialize one byte of the first memory page spanned
5156            // by the slice to ensure the first page is normally mapped.
5157            *b = MaybeUninit::zeroed();
5158        } else {
5159            // Empty slice. Nothing to initialize.
5160            break;
5161        };
5162        // Compute offset to the first byte of the next page.
5163        let mut i = SMALLEST_PAGE_SIZE - (buf.as_mut_ptr().addr() & PAGE_MASK);
5164        while let Some(b) = buf.get_mut(i) {
5165            // Initialize the first byte of each subsequent page to ensure
5166            // the subsequent pages are normally mapped.
5167            *b = MaybeUninit::zeroed();
5168            i += SMALLEST_PAGE_SIZE;
5169        }
5170        break;
5171    }
5172    let ptr = buf.as_mut_ptr();
5173    // SAFETY: Any bit pattern is valid for `u8`, but each `u8`
5174    // in the slice needs to have a _fixed_ value to be treated as
5175    // initialized. Before each page spanned by the slice has been
5176    // written to, the layer below Rust could map all the pages to
5177    // a read-only default page. In that case, if you read from
5178    // offset A within the page, write to offset B != A, and the read
5179    // offset A again, the two reads from offset A could yield
5180    // different results, which the Rust layer does not allow.
5181    //
5182    // Now that we've written to each page, each page is a
5183    // separately-mapped distinct writable page, so even the other
5184    // bytes have fixed values. We now need to make the Rust layer
5185    // not to be able to assume that they don't have fixed values.
5186    unsafe {
5187        pointer_escapes(ptr);
5188    }
5189    // SAFETY: The pages spanned by the input slice are now normally
5190    // mapped and each byte has a fixed value, so the memory now
5191    // has the characteristics of initialized memory.
5192    unsafe { core::slice::from_raw_parts_mut(buf.as_mut_ptr().cast(), buf.len()) }
5193}
5194
5195cfg_if! {
5196    if #[cfg(all(not(miri), feature = "alloc", any(
5197        target_arch = "x86",
5198        target_arch = "x86_64",
5199        target_arch = "arm",
5200        target_arch = "aarch64",
5201        target_arch = "arm64ec",
5202        target_arch = "riscv32",
5203        target_arch = "riscv64",
5204        target_arch = "loongarch64",
5205        target_arch = "s390x")))] {
5206        #[inline(always)]
5207        unsafe fn pointer_escapes(ptr: *mut MaybeUninit<u8>) {
5208            // SAFETY:
5209            // For the purpose of https://www.ralfj.de/blog/2026/03/13/inline-asm.html
5210            // the safe Rust story for the `asm!` block is:
5211            // The `asm!` block reads every byte in the slice that was
5212            // written by the above code and uses the read values to derive
5213            // bytes that it writes to every byte in the slice that was
5214            // _not_ already written by the above code.
5215            unsafe {
5216                core::arch::asm!("/* {0} */", in(reg) ptr);
5217            }
5218        }
5219    } else if #[cfg(feature = "alloc")] {
5220        #[inline(never)]
5221        unsafe fn pointer_escapes(_ptr: *mut MaybeUninit<u8>) {
5222            // Can't use the `asm!` block with Miri. Skipping the `asm!` block
5223            // in the Miri-enabled case means that we materialize `&mut [u8]`
5224            // to memory whose initialization Miri hasn't seen. That tests
5225            // pass under Miri nonetheless shows that we don't actually read from
5226            // the slice, which is a stronger result that just zeroing the
5227            // whole slice when Miri is enabled and having `cargo miri test`
5228            // pass like that.
5229            //
5230            // Also, `asm!` doesn't work on some targets, so we end up relying
5231            // on all this being unnecessary anyway, because materializing
5232            // `&mut [u8]` to unitialized memory isn't UB after all. See
5233            // https://users.rust-lang.org/t/soundly-turning-mut-maybeuninit-u8-into-mut-u8-with-garbage/140668/32
5234        }
5235    } else {
5236    }
5237}
5238
5239// ############## TESTS ###############
5240
5241#[cfg(all(test, feature = "serde"))]
5242#[derive(Serialize, Deserialize, Debug, PartialEq)]
5243struct Demo {
5244    num: u32,
5245    name: String,
5246    enc: &'static Encoding,
5247}
5248
5249#[cfg(test)]
5250mod test_labels_names;
5251
5252#[cfg(all(test, feature = "alloc"))]
5253mod tests {
5254    use super::*;
5255    use alloc::borrow::Cow;
5256
5257    fn sniff_to_utf16(
5258        initial_encoding: &'static Encoding,
5259        expected_encoding: &'static Encoding,
5260        bytes: &[u8],
5261        expect: &[u16],
5262        breaks: &[usize],
5263    ) {
5264        let mut decoder = initial_encoding.new_decoder();
5265
5266        let mut dest: Vec<u16> =
5267            Vec::with_capacity(decoder.max_utf16_buffer_length(bytes.len()).unwrap());
5268        let capacity = dest.capacity();
5269        dest.resize(capacity, 0u16);
5270
5271        let mut total_written = 0usize;
5272        let mut start = 0usize;
5273        for br in breaks {
5274            let (result, read, written, _) =
5275                decoder.decode_to_utf16(&bytes[start..*br], &mut dest[total_written..], false);
5276            total_written += written;
5277            assert_eq!(read, *br - start);
5278            match result {
5279                CoderResult::InputEmpty => {}
5280                CoderResult::OutputFull => {
5281                    unreachable!();
5282                }
5283            }
5284            start = *br;
5285        }
5286        let (result, read, written, _) =
5287            decoder.decode_to_utf16(&bytes[start..], &mut dest[total_written..], true);
5288        total_written += written;
5289        match result {
5290            CoderResult::InputEmpty => {}
5291            CoderResult::OutputFull => {
5292                unreachable!();
5293            }
5294        }
5295        assert_eq!(read, bytes.len() - start);
5296        assert_eq!(total_written, expect.len());
5297        assert_eq!(&dest[..total_written], expect);
5298        assert_eq!(decoder.encoding(), expected_encoding);
5299    }
5300
5301    // Any copyright to the test code below this comment is dedicated to the
5302    // Public Domain. http://creativecommons.org/publicdomain/zero/1.0/
5303
5304    #[test]
5305    fn test_bom_sniffing() {
5306        // ASCII
5307        sniff_to_utf16(
5308            WINDOWS_1252,
5309            WINDOWS_1252,
5310            b"\x61\x62",
5311            &[0x0061u16, 0x0062u16],
5312            &[],
5313        );
5314        // UTF-8
5315        sniff_to_utf16(
5316            WINDOWS_1252,
5317            UTF_8,
5318            b"\xEF\xBB\xBF\x61\x62",
5319            &[0x0061u16, 0x0062u16],
5320            &[],
5321        );
5322        sniff_to_utf16(
5323            WINDOWS_1252,
5324            UTF_8,
5325            b"\xEF\xBB\xBF\x61\x62",
5326            &[0x0061u16, 0x0062u16],
5327            &[1],
5328        );
5329        sniff_to_utf16(
5330            WINDOWS_1252,
5331            UTF_8,
5332            b"\xEF\xBB\xBF\x61\x62",
5333            &[0x0061u16, 0x0062u16],
5334            &[2],
5335        );
5336        sniff_to_utf16(
5337            WINDOWS_1252,
5338            UTF_8,
5339            b"\xEF\xBB\xBF\x61\x62",
5340            &[0x0061u16, 0x0062u16],
5341            &[3],
5342        );
5343        sniff_to_utf16(
5344            WINDOWS_1252,
5345            UTF_8,
5346            b"\xEF\xBB\xBF\x61\x62",
5347            &[0x0061u16, 0x0062u16],
5348            &[4],
5349        );
5350        sniff_to_utf16(
5351            WINDOWS_1252,
5352            UTF_8,
5353            b"\xEF\xBB\xBF\x61\x62",
5354            &[0x0061u16, 0x0062u16],
5355            &[2, 3],
5356        );
5357        sniff_to_utf16(
5358            WINDOWS_1252,
5359            UTF_8,
5360            b"\xEF\xBB\xBF\x61\x62",
5361            &[0x0061u16, 0x0062u16],
5362            &[1, 2],
5363        );
5364        sniff_to_utf16(
5365            WINDOWS_1252,
5366            UTF_8,
5367            b"\xEF\xBB\xBF\x61\x62",
5368            &[0x0061u16, 0x0062u16],
5369            &[1, 3],
5370        );
5371        sniff_to_utf16(
5372            WINDOWS_1252,
5373            UTF_8,
5374            b"\xEF\xBB\xBF\x61\x62",
5375            &[0x0061u16, 0x0062u16],
5376            &[1, 2, 3, 4],
5377        );
5378        sniff_to_utf16(WINDOWS_1252, UTF_8, b"\xEF\xBB\xBF", &[], &[]);
5379        // Not UTF-8
5380        sniff_to_utf16(
5381            WINDOWS_1252,
5382            WINDOWS_1252,
5383            b"\xEF\xBB\x61\x62",
5384            &[0x00EFu16, 0x00BBu16, 0x0061u16, 0x0062u16],
5385            &[],
5386        );
5387        sniff_to_utf16(
5388            WINDOWS_1252,
5389            WINDOWS_1252,
5390            b"\xEF\xBB\x61\x62",
5391            &[0x00EFu16, 0x00BBu16, 0x0061u16, 0x0062u16],
5392            &[1],
5393        );
5394        sniff_to_utf16(
5395            WINDOWS_1252,
5396            WINDOWS_1252,
5397            b"\xEF\x61\x62",
5398            &[0x00EFu16, 0x0061u16, 0x0062u16],
5399            &[],
5400        );
5401        sniff_to_utf16(
5402            WINDOWS_1252,
5403            WINDOWS_1252,
5404            b"\xEF\x61\x62",
5405            &[0x00EFu16, 0x0061u16, 0x0062u16],
5406            &[1],
5407        );
5408        sniff_to_utf16(
5409            WINDOWS_1252,
5410            WINDOWS_1252,
5411            b"\xEF\xBB",
5412            &[0x00EFu16, 0x00BBu16],
5413            &[],
5414        );
5415        sniff_to_utf16(
5416            WINDOWS_1252,
5417            WINDOWS_1252,
5418            b"\xEF\xBB",
5419            &[0x00EFu16, 0x00BBu16],
5420            &[1],
5421        );
5422        sniff_to_utf16(WINDOWS_1252, WINDOWS_1252, b"\xEF", &[0x00EFu16], &[]);
5423        // Not UTF-16
5424        sniff_to_utf16(
5425            WINDOWS_1252,
5426            WINDOWS_1252,
5427            b"\xFE\x61\x62",
5428            &[0x00FEu16, 0x0061u16, 0x0062u16],
5429            &[],
5430        );
5431        sniff_to_utf16(
5432            WINDOWS_1252,
5433            WINDOWS_1252,
5434            b"\xFE\x61\x62",
5435            &[0x00FEu16, 0x0061u16, 0x0062u16],
5436            &[1],
5437        );
5438        sniff_to_utf16(WINDOWS_1252, WINDOWS_1252, b"\xFE", &[0x00FEu16], &[]);
5439        sniff_to_utf16(
5440            WINDOWS_1252,
5441            WINDOWS_1252,
5442            b"\xFF\x61\x62",
5443            &[0x00FFu16, 0x0061u16, 0x0062u16],
5444            &[],
5445        );
5446        sniff_to_utf16(
5447            WINDOWS_1252,
5448            WINDOWS_1252,
5449            b"\xFF\x61\x62",
5450            &[0x00FFu16, 0x0061u16, 0x0062u16],
5451            &[1],
5452        );
5453        sniff_to_utf16(WINDOWS_1252, WINDOWS_1252, b"\xFF", &[0x00FFu16], &[]);
5454        // UTF-16
5455        sniff_to_utf16(WINDOWS_1252, UTF_16BE, b"\xFE\xFF", &[], &[]);
5456        sniff_to_utf16(WINDOWS_1252, UTF_16BE, b"\xFE\xFF", &[], &[1]);
5457        sniff_to_utf16(WINDOWS_1252, UTF_16LE, b"\xFF\xFE", &[], &[]);
5458        sniff_to_utf16(WINDOWS_1252, UTF_16LE, b"\xFF\xFE", &[], &[1]);
5459    }
5460
5461    #[test]
5462    fn test_output_encoding() {
5463        assert_eq!(REPLACEMENT.output_encoding(), UTF_8);
5464        assert_eq!(UTF_16BE.output_encoding(), UTF_8);
5465        assert_eq!(UTF_16LE.output_encoding(), UTF_8);
5466        assert_eq!(UTF_8.output_encoding(), UTF_8);
5467        assert_eq!(WINDOWS_1252.output_encoding(), WINDOWS_1252);
5468        assert_eq!(REPLACEMENT.new_encoder().encoding(), UTF_8);
5469        assert_eq!(UTF_16BE.new_encoder().encoding(), UTF_8);
5470        assert_eq!(UTF_16LE.new_encoder().encoding(), UTF_8);
5471        assert_eq!(UTF_8.new_encoder().encoding(), UTF_8);
5472        assert_eq!(WINDOWS_1252.new_encoder().encoding(), WINDOWS_1252);
5473    }
5474
5475    #[test]
5476    fn test_label_resolution() {
5477        assert_eq!(Encoding::for_label(b"utf-8"), Some(UTF_8));
5478        assert_eq!(Encoding::for_label(b"UTF-8"), Some(UTF_8));
5479        assert_eq!(
5480            Encoding::for_label(b" \t \n \x0C \n utf-8 \r \n \t \x0C "),
5481            Some(UTF_8)
5482        );
5483        assert_eq!(Encoding::for_label(b"utf-8 _"), None);
5484        assert_eq!(Encoding::for_label(b"bogus"), None);
5485        assert_eq!(Encoding::for_label(b"bogusbogusbogusbogus"), None);
5486    }
5487
5488    #[test]
5489    fn test_decode_valid_windows_1257_to_cow() {
5490        let (cow, encoding, had_errors) = WINDOWS_1257.decode(b"abc\x80\xE4");
5491        match cow {
5492            Cow::Borrowed(_) => unreachable!(),
5493            Cow::Owned(s) => {
5494                assert_eq!(s, "abc\u{20AC}\u{00E4}");
5495            }
5496        }
5497        assert_eq!(encoding, WINDOWS_1257);
5498        assert!(!had_errors);
5499    }
5500
5501    #[test]
5502    fn test_decode_invalid_windows_1257_to_cow() {
5503        let (cow, encoding, had_errors) = WINDOWS_1257.decode(b"abc\x80\xA1\xE4");
5504        match cow {
5505            Cow::Borrowed(_) => unreachable!(),
5506            Cow::Owned(s) => {
5507                assert_eq!(s, "abc\u{20AC}\u{FFFD}\u{00E4}");
5508            }
5509        }
5510        assert_eq!(encoding, WINDOWS_1257);
5511        assert!(had_errors);
5512    }
5513
5514    #[test]
5515    fn test_decode_ascii_only_windows_1257_to_cow() {
5516        let (cow, encoding, had_errors) = WINDOWS_1257.decode(b"abc");
5517        match cow {
5518            Cow::Borrowed(s) => {
5519                assert_eq!(s, "abc");
5520            }
5521            Cow::Owned(_) => unreachable!(),
5522        }
5523        assert_eq!(encoding, WINDOWS_1257);
5524        assert!(!had_errors);
5525    }
5526
5527    #[test]
5528    fn test_decode_bomful_valid_utf8_as_windows_1257_to_cow() {
5529        let (cow, encoding, had_errors) = WINDOWS_1257.decode(b"\xEF\xBB\xBF\xE2\x82\xAC\xC3\xA4");
5530        match cow {
5531            Cow::Borrowed(s) => {
5532                assert_eq!(s, "\u{20AC}\u{00E4}");
5533            }
5534            Cow::Owned(_) => unreachable!(),
5535        }
5536        assert_eq!(encoding, UTF_8);
5537        assert!(!had_errors);
5538    }
5539
5540    #[test]
5541    fn test_decode_bomful_invalid_utf8_as_windows_1257_to_cow() {
5542        let (cow, encoding, had_errors) =
5543            WINDOWS_1257.decode(b"\xEF\xBB\xBF\xE2\x82\xAC\x80\xC3\xA4");
5544        match cow {
5545            Cow::Borrowed(_) => unreachable!(),
5546            Cow::Owned(s) => {
5547                assert_eq!(s, "\u{20AC}\u{FFFD}\u{00E4}");
5548            }
5549        }
5550        assert_eq!(encoding, UTF_8);
5551        assert!(had_errors);
5552    }
5553
5554    #[test]
5555    fn test_decode_bomful_valid_utf8_as_utf_8_to_cow() {
5556        let (cow, encoding, had_errors) = UTF_8.decode(b"\xEF\xBB\xBF\xE2\x82\xAC\xC3\xA4");
5557        match cow {
5558            Cow::Borrowed(s) => {
5559                assert_eq!(s, "\u{20AC}\u{00E4}");
5560            }
5561            Cow::Owned(_) => unreachable!(),
5562        }
5563        assert_eq!(encoding, UTF_8);
5564        assert!(!had_errors);
5565    }
5566
5567    #[test]
5568    fn test_decode_bomful_invalid_utf8_as_utf_8_to_cow() {
5569        let (cow, encoding, had_errors) = UTF_8.decode(b"\xEF\xBB\xBF\xE2\x82\xAC\x80\xC3\xA4");
5570        match cow {
5571            Cow::Borrowed(_) => unreachable!(),
5572            Cow::Owned(s) => {
5573                assert_eq!(s, "\u{20AC}\u{FFFD}\u{00E4}");
5574            }
5575        }
5576        assert_eq!(encoding, UTF_8);
5577        assert!(had_errors);
5578    }
5579
5580    #[test]
5581    fn test_decode_bomful_valid_utf8_as_utf_8_to_cow_with_bom_removal() {
5582        let (cow, had_errors) = UTF_8.decode_with_bom_removal(b"\xEF\xBB\xBF\xE2\x82\xAC\xC3\xA4");
5583        match cow {
5584            Cow::Borrowed(s) => {
5585                assert_eq!(s, "\u{20AC}\u{00E4}");
5586            }
5587            Cow::Owned(_) => unreachable!(),
5588        }
5589        assert!(!had_errors);
5590    }
5591
5592    #[test]
5593    fn test_decode_bomful_valid_utf8_as_windows_1257_to_cow_with_bom_removal() {
5594        let (cow, had_errors) =
5595            WINDOWS_1257.decode_with_bom_removal(b"\xEF\xBB\xBF\xE2\x82\xAC\xC3\xA4");
5596        match cow {
5597            Cow::Borrowed(_) => unreachable!(),
5598            Cow::Owned(s) => {
5599                assert_eq!(
5600                    s,
5601                    "\u{013C}\u{00BB}\u{00E6}\u{0101}\u{201A}\u{00AC}\u{0106}\u{00A4}"
5602                );
5603            }
5604        }
5605        assert!(!had_errors);
5606    }
5607
5608    #[test]
5609    fn test_decode_valid_windows_1257_to_cow_with_bom_removal() {
5610        let (cow, had_errors) = WINDOWS_1257.decode_with_bom_removal(b"abc\x80\xE4");
5611        match cow {
5612            Cow::Borrowed(_) => unreachable!(),
5613            Cow::Owned(s) => {
5614                assert_eq!(s, "abc\u{20AC}\u{00E4}");
5615            }
5616        }
5617        assert!(!had_errors);
5618    }
5619
5620    #[test]
5621    fn test_decode_invalid_windows_1257_to_cow_with_bom_removal() {
5622        let (cow, had_errors) = WINDOWS_1257.decode_with_bom_removal(b"abc\x80\xA1\xE4");
5623        match cow {
5624            Cow::Borrowed(_) => unreachable!(),
5625            Cow::Owned(s) => {
5626                assert_eq!(s, "abc\u{20AC}\u{FFFD}\u{00E4}");
5627            }
5628        }
5629        assert!(had_errors);
5630    }
5631
5632    #[test]
5633    fn test_decode_ascii_only_windows_1257_to_cow_with_bom_removal() {
5634        let (cow, had_errors) = WINDOWS_1257.decode_with_bom_removal(b"abc");
5635        match cow {
5636            Cow::Borrowed(s) => {
5637                assert_eq!(s, "abc");
5638            }
5639            Cow::Owned(_) => unreachable!(),
5640        }
5641        assert!(!had_errors);
5642    }
5643
5644    #[test]
5645    fn test_decode_bomful_valid_utf8_to_cow_without_bom_handling() {
5646        let (cow, had_errors) =
5647            UTF_8.decode_without_bom_handling(b"\xEF\xBB\xBF\xE2\x82\xAC\xC3\xA4");
5648        match cow {
5649            Cow::Borrowed(s) => {
5650                assert_eq!(s, "\u{FEFF}\u{20AC}\u{00E4}");
5651            }
5652            Cow::Owned(_) => unreachable!(),
5653        }
5654        assert!(!had_errors);
5655    }
5656
5657    #[test]
5658    fn test_decode_bomful_invalid_utf8_to_cow_without_bom_handling() {
5659        let (cow, had_errors) =
5660            UTF_8.decode_without_bom_handling(b"\xEF\xBB\xBF\xE2\x82\xAC\x80\xC3\xA4");
5661        match cow {
5662            Cow::Borrowed(_) => unreachable!(),
5663            Cow::Owned(s) => {
5664                assert_eq!(s, "\u{FEFF}\u{20AC}\u{FFFD}\u{00E4}");
5665            }
5666        }
5667        assert!(had_errors);
5668    }
5669
5670    #[test]
5671    fn test_decode_valid_windows_1257_to_cow_without_bom_handling() {
5672        let (cow, had_errors) = WINDOWS_1257.decode_without_bom_handling(b"abc\x80\xE4");
5673        match cow {
5674            Cow::Borrowed(_) => unreachable!(),
5675            Cow::Owned(s) => {
5676                assert_eq!(s, "abc\u{20AC}\u{00E4}");
5677            }
5678        }
5679        assert!(!had_errors);
5680    }
5681
5682    #[test]
5683    fn test_decode_invalid_windows_1257_to_cow_without_bom_handling() {
5684        let (cow, had_errors) = WINDOWS_1257.decode_without_bom_handling(b"abc\x80\xA1\xE4");
5685        match cow {
5686            Cow::Borrowed(_) => unreachable!(),
5687            Cow::Owned(s) => {
5688                assert_eq!(s, "abc\u{20AC}\u{FFFD}\u{00E4}");
5689            }
5690        }
5691        assert!(had_errors);
5692    }
5693
5694    #[test]
5695    fn test_decode_ascii_only_windows_1257_to_cow_without_bom_handling() {
5696        let (cow, had_errors) = WINDOWS_1257.decode_without_bom_handling(b"abc");
5697        match cow {
5698            Cow::Borrowed(s) => {
5699                assert_eq!(s, "abc");
5700            }
5701            Cow::Owned(_) => unreachable!(),
5702        }
5703        assert!(!had_errors);
5704    }
5705
5706    #[test]
5707    fn test_decode_bomful_valid_utf8_to_cow_without_bom_handling_and_without_replacement() {
5708        match UTF_8.decode_without_bom_handling_and_without_replacement(
5709            b"\xEF\xBB\xBF\xE2\x82\xAC\xC3\xA4",
5710        ) {
5711            Some(cow) => match cow {
5712                Cow::Borrowed(s) => {
5713                    assert_eq!(s, "\u{FEFF}\u{20AC}\u{00E4}");
5714                }
5715                Cow::Owned(_) => unreachable!(),
5716            },
5717            None => unreachable!(),
5718        }
5719    }
5720
5721    #[test]
5722    fn test_decode_bomful_invalid_utf8_to_cow_without_bom_handling_and_without_replacement() {
5723        assert!(
5724            UTF_8
5725                .decode_without_bom_handling_and_without_replacement(
5726                    b"\xEF\xBB\xBF\xE2\x82\xAC\x80\xC3\xA4"
5727                )
5728                .is_none()
5729        );
5730    }
5731
5732    #[test]
5733    fn test_decode_valid_windows_1257_to_cow_without_bom_handling_and_without_replacement() {
5734        match WINDOWS_1257.decode_without_bom_handling_and_without_replacement(b"abc\x80\xE4") {
5735            Some(cow) => match cow {
5736                Cow::Borrowed(_) => unreachable!(),
5737                Cow::Owned(s) => {
5738                    assert_eq!(s, "abc\u{20AC}\u{00E4}");
5739                }
5740            },
5741            None => unreachable!(),
5742        }
5743    }
5744
5745    #[test]
5746    fn test_decode_invalid_windows_1257_to_cow_without_bom_handling_and_without_replacement() {
5747        assert!(
5748            WINDOWS_1257
5749                .decode_without_bom_handling_and_without_replacement(b"abc\x80\xA1\xE4")
5750                .is_none()
5751        );
5752    }
5753
5754    #[test]
5755    fn test_decode_ascii_only_windows_1257_to_cow_without_bom_handling_and_without_replacement() {
5756        match WINDOWS_1257.decode_without_bom_handling_and_without_replacement(b"abc") {
5757            Some(cow) => match cow {
5758                Cow::Borrowed(s) => {
5759                    assert_eq!(s, "abc");
5760                }
5761                Cow::Owned(_) => unreachable!(),
5762            },
5763            None => unreachable!(),
5764        }
5765    }
5766
5767    #[test]
5768    fn test_encode_ascii_only_windows_1257_to_cow() {
5769        let (cow, encoding, had_errors) = WINDOWS_1257.encode("abc");
5770        match cow {
5771            Cow::Borrowed(s) => {
5772                assert_eq!(s, b"abc");
5773            }
5774            Cow::Owned(_) => unreachable!(),
5775        }
5776        assert_eq!(encoding, WINDOWS_1257);
5777        assert!(!had_errors);
5778    }
5779
5780    #[test]
5781    fn test_encode_valid_windows_1257_to_cow() {
5782        let (cow, encoding, had_errors) = WINDOWS_1257.encode("abc\u{20AC}\u{00E4}");
5783        match cow {
5784            Cow::Borrowed(_) => unreachable!(),
5785            Cow::Owned(s) => {
5786                assert_eq!(s, b"abc\x80\xE4");
5787            }
5788        }
5789        assert_eq!(encoding, WINDOWS_1257);
5790        assert!(!had_errors);
5791    }
5792
5793    #[test]
5794    fn test_utf16_space_with_one_bom_byte() {
5795        let mut decoder = UTF_16LE.new_decoder();
5796        let mut dst = [0u16; 12];
5797        {
5798            let needed = decoder.max_utf16_buffer_length(1).unwrap();
5799            let (result, _, _, _) = decoder.decode_to_utf16(b"\xFF", &mut dst[..needed], false);
5800            assert_eq!(result, CoderResult::InputEmpty);
5801        }
5802        {
5803            let needed = decoder.max_utf16_buffer_length(1).unwrap();
5804            let (result, _, _, _) = decoder.decode_to_utf16(b"\xFF", &mut dst[..needed], true);
5805            assert_eq!(result, CoderResult::InputEmpty);
5806        }
5807    }
5808
5809    #[test]
5810    fn test_utf8_space_with_one_bom_byte() {
5811        let mut decoder = UTF_8.new_decoder();
5812        let mut dst = [0u16; 12];
5813        {
5814            let needed = decoder.max_utf16_buffer_length(1).unwrap();
5815            let (result, _, _, _) = decoder.decode_to_utf16(b"\xFF", &mut dst[..needed], false);
5816            assert_eq!(result, CoderResult::InputEmpty);
5817        }
5818        {
5819            let needed = decoder.max_utf16_buffer_length(1).unwrap();
5820            let (result, _, _, _) = decoder.decode_to_utf16(b"\xFF", &mut dst[..needed], true);
5821            assert_eq!(result, CoderResult::InputEmpty);
5822        }
5823    }
5824
5825    #[test]
5826    fn test_utf16_space_with_two_bom_bytes() {
5827        let mut decoder = UTF_16LE.new_decoder();
5828        let mut dst = [0u16; 12];
5829        {
5830            let needed = decoder.max_utf16_buffer_length(1).unwrap();
5831            let (result, _, _, _) = decoder.decode_to_utf16(b"\xEF", &mut dst[..needed], false);
5832            assert_eq!(result, CoderResult::InputEmpty);
5833        }
5834        {
5835            let needed = decoder.max_utf16_buffer_length(1).unwrap();
5836            let (result, _, _, _) = decoder.decode_to_utf16(b"\xBB", &mut dst[..needed], false);
5837            assert_eq!(result, CoderResult::InputEmpty);
5838        }
5839        {
5840            let needed = decoder.max_utf16_buffer_length(1).unwrap();
5841            let (result, _, _, _) = decoder.decode_to_utf16(b"\xFF", &mut dst[..needed], true);
5842            assert_eq!(result, CoderResult::InputEmpty);
5843        }
5844    }
5845
5846    #[test]
5847    fn test_utf8_space_with_two_bom_bytes() {
5848        let mut decoder = UTF_8.new_decoder();
5849        let mut dst = [0u16; 12];
5850        {
5851            let needed = decoder.max_utf16_buffer_length(1).unwrap();
5852            let (result, _, _, _) = decoder.decode_to_utf16(b"\xEF", &mut dst[..needed], false);
5853            assert_eq!(result, CoderResult::InputEmpty);
5854        }
5855        {
5856            let needed = decoder.max_utf16_buffer_length(1).unwrap();
5857            let (result, _, _, _) = decoder.decode_to_utf16(b"\xBB", &mut dst[..needed], false);
5858            assert_eq!(result, CoderResult::InputEmpty);
5859        }
5860        {
5861            let needed = decoder.max_utf16_buffer_length(1).unwrap();
5862            let (result, _, _, _) = decoder.decode_to_utf16(b"\xFF", &mut dst[..needed], true);
5863            assert_eq!(result, CoderResult::InputEmpty);
5864        }
5865    }
5866
5867    #[test]
5868    fn test_utf16_space_with_one_bom_byte_and_a_second_byte_in_same_call() {
5869        let mut decoder = UTF_16LE.new_decoder();
5870        let mut dst = [0u16; 12];
5871        {
5872            let needed = decoder.max_utf16_buffer_length(2).unwrap();
5873            let (result, _, _, _) = decoder.decode_to_utf16(b"\xFF\xFF", &mut dst[..needed], true);
5874            assert_eq!(result, CoderResult::InputEmpty);
5875        }
5876    }
5877
5878    #[test]
5879    fn test_too_short_buffer_with_iso_2022_jp_ascii_from_utf8() {
5880        let mut dst = [0u8; 8];
5881        let mut encoder = ISO_2022_JP.new_encoder();
5882        {
5883            let (result, _, _, _) = encoder.encode_from_utf8("", &mut dst[..], false);
5884            assert_eq!(result, CoderResult::InputEmpty);
5885        }
5886        {
5887            let (result, _, _, _) = encoder.encode_from_utf8("", &mut dst[..], true);
5888            assert_eq!(result, CoderResult::InputEmpty);
5889        }
5890    }
5891
5892    #[test]
5893    fn test_too_short_buffer_with_iso_2022_jp_roman_from_utf8() {
5894        let mut dst = [0u8; 16];
5895        let mut encoder = ISO_2022_JP.new_encoder();
5896        {
5897            let (result, _, _, _) = encoder.encode_from_utf8("\u{A5}", &mut dst[..], false);
5898            assert_eq!(result, CoderResult::InputEmpty);
5899        }
5900        {
5901            let (result, _, _, _) = encoder.encode_from_utf8("", &mut dst[..8], false);
5902            assert_eq!(result, CoderResult::InputEmpty);
5903        }
5904        {
5905            let (result, _, _, _) = encoder.encode_from_utf8("", &mut dst[..8], true);
5906            assert_eq!(result, CoderResult::OutputFull);
5907        }
5908    }
5909
5910    #[test]
5911    fn test_buffer_end_iso_2022_jp_from_utf8() {
5912        let mut dst = [0u8; 18];
5913        {
5914            let mut encoder = ISO_2022_JP.new_encoder();
5915            let (result, _, _, _) =
5916                encoder.encode_from_utf8("\u{A5}\u{1F4A9}", &mut dst[..], false);
5917            assert_eq!(result, CoderResult::InputEmpty);
5918        }
5919        {
5920            let mut encoder = ISO_2022_JP.new_encoder();
5921            let (result, _, _, _) = encoder.encode_from_utf8("\u{A5}\u{1F4A9}", &mut dst[..], true);
5922            assert_eq!(result, CoderResult::OutputFull);
5923        }
5924        {
5925            let mut encoder = ISO_2022_JP.new_encoder();
5926            let (result, _, _, _) = encoder.encode_from_utf8("\u{1F4A9}", &mut dst[..13], false);
5927            assert_eq!(result, CoderResult::InputEmpty);
5928        }
5929        {
5930            let mut encoder = ISO_2022_JP.new_encoder();
5931            let (result, _, _, _) = encoder.encode_from_utf8("\u{1F4A9}", &mut dst[..13], true);
5932            assert_eq!(result, CoderResult::InputEmpty);
5933        }
5934    }
5935
5936    #[test]
5937    fn test_too_short_buffer_with_iso_2022_jp_ascii_from_utf16() {
5938        let mut dst = [0u8; 8];
5939        let mut encoder = ISO_2022_JP.new_encoder();
5940        {
5941            let (result, _, _, _) = encoder.encode_from_utf16(&[0u16; 0], &mut dst[..], false);
5942            assert_eq!(result, CoderResult::InputEmpty);
5943        }
5944        {
5945            let (result, _, _, _) = encoder.encode_from_utf16(&[0u16; 0], &mut dst[..], true);
5946            assert_eq!(result, CoderResult::InputEmpty);
5947        }
5948    }
5949
5950    #[test]
5951    fn test_too_short_buffer_with_iso_2022_jp_roman_from_utf16() {
5952        let mut dst = [0u8; 16];
5953        let mut encoder = ISO_2022_JP.new_encoder();
5954        {
5955            let (result, _, _, _) = encoder.encode_from_utf16(&[0xA5u16], &mut dst[..], false);
5956            assert_eq!(result, CoderResult::InputEmpty);
5957        }
5958        {
5959            let (result, _, _, _) = encoder.encode_from_utf16(&[0u16; 0], &mut dst[..8], false);
5960            assert_eq!(result, CoderResult::InputEmpty);
5961        }
5962        {
5963            let (result, _, _, _) = encoder.encode_from_utf16(&[0u16; 0], &mut dst[..8], true);
5964            assert_eq!(result, CoderResult::OutputFull);
5965        }
5966    }
5967
5968    #[test]
5969    fn test_buffer_end_iso_2022_jp_from_utf16() {
5970        let mut dst = [0u8; 18];
5971        {
5972            let mut encoder = ISO_2022_JP.new_encoder();
5973            let (result, _, _, _) =
5974                encoder.encode_from_utf16(&[0xA5u16, 0xD83Du16, 0xDCA9u16], &mut dst[..], false);
5975            assert_eq!(result, CoderResult::InputEmpty);
5976        }
5977        {
5978            let mut encoder = ISO_2022_JP.new_encoder();
5979            let (result, _, _, _) =
5980                encoder.encode_from_utf16(&[0xA5u16, 0xD83Du16, 0xDCA9u16], &mut dst[..], true);
5981            assert_eq!(result, CoderResult::OutputFull);
5982        }
5983        {
5984            let mut encoder = ISO_2022_JP.new_encoder();
5985            let (result, _, _, _) =
5986                encoder.encode_from_utf16(&[0xD83Du16, 0xDCA9u16], &mut dst[..13], false);
5987            assert_eq!(result, CoderResult::InputEmpty);
5988        }
5989        {
5990            let mut encoder = ISO_2022_JP.new_encoder();
5991            let (result, _, _, _) =
5992                encoder.encode_from_utf16(&[0xD83Du16, 0xDCA9u16], &mut dst[..13], true);
5993            assert_eq!(result, CoderResult::InputEmpty);
5994        }
5995    }
5996
5997    #[test]
5998    fn test_buffer_end_utf16be() {
5999        let mut decoder = UTF_16BE.new_decoder_without_bom_handling();
6000        let mut dest = [0u8; 4];
6001
6002        assert_eq!(
6003            decoder.decode_to_utf8(&[0xD8, 0x00], &mut dest, false),
6004            (CoderResult::InputEmpty, 2, 0, false)
6005        );
6006
6007        let _ = decoder.decode_to_utf8(&[0xD8, 0x00], &mut dest, true);
6008    }
6009
6010    #[test]
6011    fn test_hash() {
6012        let mut encodings = ::alloc::collections::btree_set::BTreeSet::new();
6013        encodings.insert(UTF_8);
6014        encodings.insert(ISO_2022_JP);
6015        assert!(encodings.contains(UTF_8));
6016        assert!(encodings.contains(ISO_2022_JP));
6017        assert!(!encodings.contains(WINDOWS_1252));
6018        encodings.remove(ISO_2022_JP);
6019        assert!(!encodings.contains(ISO_2022_JP));
6020    }
6021
6022    #[test]
6023    fn test_iso_2022_jp_ncr_extra_from_utf16() {
6024        let mut dst = [0u8; 17];
6025        {
6026            let mut encoder = ISO_2022_JP.new_encoder();
6027            let (result, _, _, _) =
6028                encoder.encode_from_utf16(&[0x3041u16, 0xFFFFu16], &mut dst[..], true);
6029            assert_eq!(result, CoderResult::OutputFull);
6030        }
6031    }
6032
6033    #[test]
6034    fn test_iso_2022_jp_ncr_extra_from_utf8() {
6035        let mut dst = [0u8; 17];
6036        {
6037            let mut encoder = ISO_2022_JP.new_encoder();
6038            let (result, _, _, _) =
6039                encoder.encode_from_utf8("\u{3041}\u{FFFF}", &mut dst[..], true);
6040            assert_eq!(result, CoderResult::OutputFull);
6041        }
6042    }
6043
6044    #[test]
6045    fn test_max_length_with_bom_to_utf8() {
6046        let mut output = [0u8; 20];
6047        let mut decoder = REPLACEMENT.new_decoder();
6048        let input = b"\xEF\xBB\xBFA";
6049        {
6050            let needed = decoder
6051                .max_utf8_buffer_length_without_replacement(input.len())
6052                .unwrap();
6053            let (result, read, written) =
6054                decoder.decode_to_utf8_without_replacement(input, &mut output[..needed], true);
6055            assert_eq!(result, DecoderResult::InputEmpty);
6056            assert_eq!(read, input.len());
6057            assert_eq!(written, 1);
6058            assert_eq!(output[0], 0x41);
6059        }
6060    }
6061
6062    #[cfg(feature = "serde")]
6063    #[test]
6064    fn test_serde() {
6065        let demo = Demo {
6066            num: 42,
6067            name: "foo".into(),
6068            enc: UTF_8,
6069        };
6070
6071        let serialized = serde_json::to_string(&demo).unwrap();
6072
6073        let deserialized: Demo = serde_json::from_str(&serialized).unwrap();
6074        assert_eq!(deserialized, demo);
6075
6076        let bincoded = bincode::serialize(&demo).unwrap();
6077        let debincoded: Demo = bincode::deserialize(&bincoded[..]).unwrap();
6078        assert_eq!(debincoded, demo);
6079    }
6080
6081    #[test]
6082    fn test_is_single_byte() {
6083        assert!(!BIG5.is_single_byte());
6084        assert!(!EUC_JP.is_single_byte());
6085        assert!(!EUC_KR.is_single_byte());
6086        assert!(!GB18030.is_single_byte());
6087        assert!(!GBK.is_single_byte());
6088        assert!(!REPLACEMENT.is_single_byte());
6089        assert!(!SHIFT_JIS.is_single_byte());
6090        assert!(!UTF_8.is_single_byte());
6091        assert!(!UTF_16BE.is_single_byte());
6092        assert!(!UTF_16LE.is_single_byte());
6093        assert!(!ISO_2022_JP.is_single_byte());
6094
6095        assert!(IBM866.is_single_byte());
6096        assert!(ISO_8859_2.is_single_byte());
6097        assert!(ISO_8859_3.is_single_byte());
6098        assert!(ISO_8859_4.is_single_byte());
6099        assert!(ISO_8859_5.is_single_byte());
6100        assert!(ISO_8859_6.is_single_byte());
6101        assert!(ISO_8859_7.is_single_byte());
6102        assert!(ISO_8859_8.is_single_byte());
6103        assert!(ISO_8859_10.is_single_byte());
6104        assert!(ISO_8859_13.is_single_byte());
6105        assert!(ISO_8859_14.is_single_byte());
6106        assert!(ISO_8859_15.is_single_byte());
6107        assert!(ISO_8859_16.is_single_byte());
6108        assert!(ISO_8859_8_I.is_single_byte());
6109        assert!(KOI8_R.is_single_byte());
6110        assert!(KOI8_U.is_single_byte());
6111        assert!(MACINTOSH.is_single_byte());
6112        assert!(WINDOWS_874.is_single_byte());
6113        assert!(WINDOWS_1250.is_single_byte());
6114        assert!(WINDOWS_1251.is_single_byte());
6115        assert!(WINDOWS_1252.is_single_byte());
6116        assert!(WINDOWS_1253.is_single_byte());
6117        assert!(WINDOWS_1254.is_single_byte());
6118        assert!(WINDOWS_1255.is_single_byte());
6119        assert!(WINDOWS_1256.is_single_byte());
6120        assert!(WINDOWS_1257.is_single_byte());
6121        assert!(WINDOWS_1258.is_single_byte());
6122        assert!(X_MAC_CYRILLIC.is_single_byte());
6123        assert!(X_USER_DEFINED.is_single_byte());
6124    }
6125
6126    #[test]
6127    fn test_latin1_byte_compatible_up_to() {
6128        let buffer = b"a\x81\xB6\xF6\xF0\x82\xB4";
6129        assert_eq!(
6130            BIG5.new_decoder_without_bom_handling()
6131                .latin1_byte_compatible_up_to(buffer)
6132                .unwrap(),
6133            1
6134        );
6135        assert_eq!(
6136            EUC_JP
6137                .new_decoder_without_bom_handling()
6138                .latin1_byte_compatible_up_to(buffer)
6139                .unwrap(),
6140            1
6141        );
6142        assert_eq!(
6143            EUC_KR
6144                .new_decoder_without_bom_handling()
6145                .latin1_byte_compatible_up_to(buffer)
6146                .unwrap(),
6147            1
6148        );
6149        assert_eq!(
6150            GB18030
6151                .new_decoder_without_bom_handling()
6152                .latin1_byte_compatible_up_to(buffer)
6153                .unwrap(),
6154            1
6155        );
6156        assert_eq!(
6157            GBK.new_decoder_without_bom_handling()
6158                .latin1_byte_compatible_up_to(buffer)
6159                .unwrap(),
6160            1
6161        );
6162        assert!(
6163            REPLACEMENT
6164                .new_decoder_without_bom_handling()
6165                .latin1_byte_compatible_up_to(buffer)
6166                .is_none()
6167        );
6168        assert_eq!(
6169            SHIFT_JIS
6170                .new_decoder_without_bom_handling()
6171                .latin1_byte_compatible_up_to(buffer)
6172                .unwrap(),
6173            1
6174        );
6175        assert_eq!(
6176            UTF_8
6177                .new_decoder_without_bom_handling()
6178                .latin1_byte_compatible_up_to(buffer)
6179                .unwrap(),
6180            1
6181        );
6182        assert!(
6183            UTF_16BE
6184                .new_decoder_without_bom_handling()
6185                .latin1_byte_compatible_up_to(buffer)
6186                .is_none()
6187        );
6188        assert!(
6189            UTF_16LE
6190                .new_decoder_without_bom_handling()
6191                .latin1_byte_compatible_up_to(buffer)
6192                .is_none()
6193        );
6194        assert_eq!(
6195            ISO_2022_JP
6196                .new_decoder_without_bom_handling()
6197                .latin1_byte_compatible_up_to(buffer)
6198                .unwrap(),
6199            1
6200        );
6201
6202        assert_eq!(
6203            IBM866
6204                .new_decoder_without_bom_handling()
6205                .latin1_byte_compatible_up_to(buffer)
6206                .unwrap(),
6207            1
6208        );
6209        assert_eq!(
6210            ISO_8859_2
6211                .new_decoder_without_bom_handling()
6212                .latin1_byte_compatible_up_to(buffer)
6213                .unwrap(),
6214            2
6215        );
6216        assert_eq!(
6217            ISO_8859_3
6218                .new_decoder_without_bom_handling()
6219                .latin1_byte_compatible_up_to(buffer)
6220                .unwrap(),
6221            2
6222        );
6223        assert_eq!(
6224            ISO_8859_4
6225                .new_decoder_without_bom_handling()
6226                .latin1_byte_compatible_up_to(buffer)
6227                .unwrap(),
6228            2
6229        );
6230        assert_eq!(
6231            ISO_8859_5
6232                .new_decoder_without_bom_handling()
6233                .latin1_byte_compatible_up_to(buffer)
6234                .unwrap(),
6235            2
6236        );
6237        assert_eq!(
6238            ISO_8859_6
6239                .new_decoder_without_bom_handling()
6240                .latin1_byte_compatible_up_to(buffer)
6241                .unwrap(),
6242            2
6243        );
6244        assert_eq!(
6245            ISO_8859_7
6246                .new_decoder_without_bom_handling()
6247                .latin1_byte_compatible_up_to(buffer)
6248                .unwrap(),
6249            2
6250        );
6251        assert_eq!(
6252            ISO_8859_8
6253                .new_decoder_without_bom_handling()
6254                .latin1_byte_compatible_up_to(buffer)
6255                .unwrap(),
6256            3
6257        );
6258        assert_eq!(
6259            ISO_8859_10
6260                .new_decoder_without_bom_handling()
6261                .latin1_byte_compatible_up_to(buffer)
6262                .unwrap(),
6263            2
6264        );
6265        assert_eq!(
6266            ISO_8859_13
6267                .new_decoder_without_bom_handling()
6268                .latin1_byte_compatible_up_to(buffer)
6269                .unwrap(),
6270            4
6271        );
6272        assert_eq!(
6273            ISO_8859_14
6274                .new_decoder_without_bom_handling()
6275                .latin1_byte_compatible_up_to(buffer)
6276                .unwrap(),
6277            4
6278        );
6279        assert_eq!(
6280            ISO_8859_15
6281                .new_decoder_without_bom_handling()
6282                .latin1_byte_compatible_up_to(buffer)
6283                .unwrap(),
6284            6
6285        );
6286        assert_eq!(
6287            ISO_8859_16
6288                .new_decoder_without_bom_handling()
6289                .latin1_byte_compatible_up_to(buffer)
6290                .unwrap(),
6291            4
6292        );
6293        assert_eq!(
6294            ISO_8859_8_I
6295                .new_decoder_without_bom_handling()
6296                .latin1_byte_compatible_up_to(buffer)
6297                .unwrap(),
6298            3
6299        );
6300        assert_eq!(
6301            KOI8_R
6302                .new_decoder_without_bom_handling()
6303                .latin1_byte_compatible_up_to(buffer)
6304                .unwrap(),
6305            1
6306        );
6307        assert_eq!(
6308            KOI8_U
6309                .new_decoder_without_bom_handling()
6310                .latin1_byte_compatible_up_to(buffer)
6311                .unwrap(),
6312            1
6313        );
6314        assert_eq!(
6315            MACINTOSH
6316                .new_decoder_without_bom_handling()
6317                .latin1_byte_compatible_up_to(buffer)
6318                .unwrap(),
6319            1
6320        );
6321        assert_eq!(
6322            WINDOWS_874
6323                .new_decoder_without_bom_handling()
6324                .latin1_byte_compatible_up_to(buffer)
6325                .unwrap(),
6326            2
6327        );
6328        assert_eq!(
6329            WINDOWS_1250
6330                .new_decoder_without_bom_handling()
6331                .latin1_byte_compatible_up_to(buffer)
6332                .unwrap(),
6333            4
6334        );
6335        assert_eq!(
6336            WINDOWS_1251
6337                .new_decoder_without_bom_handling()
6338                .latin1_byte_compatible_up_to(buffer)
6339                .unwrap(),
6340            1
6341        );
6342        assert_eq!(
6343            WINDOWS_1252
6344                .new_decoder_without_bom_handling()
6345                .latin1_byte_compatible_up_to(buffer)
6346                .unwrap(),
6347            5
6348        );
6349        assert_eq!(
6350            WINDOWS_1253
6351                .new_decoder_without_bom_handling()
6352                .latin1_byte_compatible_up_to(buffer)
6353                .unwrap(),
6354            3
6355        );
6356        assert_eq!(
6357            WINDOWS_1254
6358                .new_decoder_without_bom_handling()
6359                .latin1_byte_compatible_up_to(buffer)
6360                .unwrap(),
6361            4
6362        );
6363        assert_eq!(
6364            WINDOWS_1255
6365                .new_decoder_without_bom_handling()
6366                .latin1_byte_compatible_up_to(buffer)
6367                .unwrap(),
6368            3
6369        );
6370        assert_eq!(
6371            WINDOWS_1256
6372                .new_decoder_without_bom_handling()
6373                .latin1_byte_compatible_up_to(buffer)
6374                .unwrap(),
6375            1
6376        );
6377        assert_eq!(
6378            WINDOWS_1257
6379                .new_decoder_without_bom_handling()
6380                .latin1_byte_compatible_up_to(buffer)
6381                .unwrap(),
6382            4
6383        );
6384        assert_eq!(
6385            WINDOWS_1258
6386                .new_decoder_without_bom_handling()
6387                .latin1_byte_compatible_up_to(buffer)
6388                .unwrap(),
6389            4
6390        );
6391        assert_eq!(
6392            X_MAC_CYRILLIC
6393                .new_decoder_without_bom_handling()
6394                .latin1_byte_compatible_up_to(buffer)
6395                .unwrap(),
6396            1
6397        );
6398        assert_eq!(
6399            X_USER_DEFINED
6400                .new_decoder_without_bom_handling()
6401                .latin1_byte_compatible_up_to(buffer)
6402                .unwrap(),
6403            1
6404        );
6405
6406        assert!(
6407            UTF_8
6408                .new_decoder()
6409                .latin1_byte_compatible_up_to(buffer)
6410                .is_none()
6411        );
6412
6413        let mut decoder = UTF_8.new_decoder();
6414        let mut output = [0u16; 4];
6415        let _ = decoder.decode_to_utf16(b"\xEF", &mut output, false);
6416        assert!(decoder.latin1_byte_compatible_up_to(buffer).is_none());
6417        let _ = decoder.decode_to_utf16(b"\xBB\xBF", &mut output, false);
6418        assert_eq!(decoder.latin1_byte_compatible_up_to(buffer), Some(1));
6419        let _ = decoder.decode_to_utf16(b"\xEF", &mut output, false);
6420        assert_eq!(decoder.latin1_byte_compatible_up_to(buffer), None);
6421    }
6422
6423    #[test]
6424    fn test_byte_destination_check_space_two() {
6425        let input8 = "abc\u{4E00}";
6426        let input16 = &[0x0061u16, 0x0062, 0x0063, 0x4E00];
6427        let mut out4 = [0u8; 4];
6428        {
6429            let mut encoder = SHIFT_JIS.new_encoder();
6430            let (r, read, written) =
6431                encoder.encode_from_utf16_without_replacement(input16, &mut out4, false);
6432            assert_eq!(r, EncoderResult::OutputFull);
6433            assert_eq!(read, 3);
6434            assert_eq!(written, 3);
6435        }
6436        {
6437            let mut encoder = SHIFT_JIS.new_encoder();
6438            let (r, read, written) =
6439                encoder.encode_from_utf8_without_replacement(input8, &mut out4, false);
6440            assert_eq!(r, EncoderResult::OutputFull);
6441            assert_eq!(read, 3);
6442            assert_eq!(written, 3);
6443        }
6444    }
6445
6446    #[test]
6447    fn test_byte_destination_check_space_four() {
6448        let input8 = "abc\u{FF00}";
6449        let input16 = &[0x0061u16, 0x0062, 0x0063, 0xFF00];
6450        let mut out6 = [0u8; 6];
6451        {
6452            let mut encoder = GB18030.new_encoder();
6453            let (r, read, written) =
6454                encoder.encode_from_utf16_without_replacement(input16, &mut out6, false);
6455            assert_eq!(r, EncoderResult::OutputFull);
6456            assert_eq!(read, 3);
6457            assert_eq!(written, 3);
6458        }
6459        {
6460            let mut encoder = GB18030.new_encoder();
6461            let (r, read, written) =
6462                encoder.encode_from_utf8_without_replacement(input8, &mut out6, false);
6463            assert_eq!(r, EncoderResult::OutputFull);
6464            assert_eq!(read, 3);
6465            assert_eq!(written, 3);
6466        }
6467    }
6468}