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>&'static Encoding</code></td><td><code>&'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>// …</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>// …</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>// …</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>// … (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>// …</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>// …</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>&'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>•</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>•</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>•</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>•</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>•</td><td></td></tr>
662//! <tr><td>ISO-8859-7</td><td>28597</td><td>•</td><td>3</td></tr>
663//! <tr><td>ISO-8859-8</td><td>28598</td><td>•</td><td>4</td></tr>
664//! <tr><td>ISO-8859-13</td><td>28603</td><td>•</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; // 
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}