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
10use super::*;
11use crate::variant::*;
12
13pub struct ReplacementDecoder {
14 emitted: bool,
15}
16
17impl ReplacementDecoder {
18 pub fn new() -> VariantDecoder {
19 VariantDecoder::Replacement(ReplacementDecoder { emitted: false })
20 }
21
22 pub fn max_utf16_buffer_length(&self, _u16_length: usize) -> Option<usize> {
23 Some(1)
24 }
25
26 pub fn max_utf8_buffer_length_without_replacement(&self, _byte_length: usize) -> Option<usize> {
27 Some(3)
28 }
29
30 pub fn max_utf8_buffer_length(&self, _byte_length: usize) -> Option<usize> {
31 Some(3)
32 }
33
34 pub fn decode_to_utf16_raw(
35 &mut self,
36 src: &[u8],
37 dst: &mut [u16],
38 _last: bool,
39 ) -> (DecoderResult, usize, usize) {
40 // Don't err if the input stream is empty. See
41 // https://github.com/whatwg/encoding/issues/33
42 if self.emitted || src.is_empty() {
43 (DecoderResult::InputEmpty, src.len(), 0)
44 } else if dst.is_empty() {
45 // Make sure there's room for the replacement character.
46 (DecoderResult::OutputFull, 0, 0)
47 } else {
48 self.emitted = true;
49 (DecoderResult::Malformed(1, 0), 1, 0)
50 }
51 }
52
53 pub fn decode_to_utf8_raw(
54 &mut self,
55 src: &[u8],
56 dst: &mut [u8],
57 _last: bool,
58 ) -> (DecoderResult, usize, usize) {
59 // Don't err if the input stream is empty. See
60 // https://github.com/whatwg/encoding/issues/33
61 if self.emitted || src.is_empty() {
62 (DecoderResult::InputEmpty, src.len(), 0)
63 } else if dst.len() < 3 {
64 // Make sure there's room for the replacement character.
65 (DecoderResult::OutputFull, 0, 0)
66 } else {
67 self.emitted = true;
68 (DecoderResult::Malformed(1, 0), 1, 0)
69 }
70 }
71}
72
73// Any copyright to the test code below this comment is dedicated to the
74// Public Domain. http://creativecommons.org/publicdomain/zero/1.0/
75
76#[cfg(all(test, feature = "alloc"))]
77mod tests {
78 use super::super::testing::*;
79 use super::super::*;
80
81 fn decode_replacement(bytes: &[u8], expect: &str) {
82 decode_without_padding(REPLACEMENT, bytes, expect);
83 }
84
85 fn encode_replacement(string: &str, expect: &[u8]) {
86 encode(REPLACEMENT, string, expect);
87 }
88
89 #[test]
90 fn test_replacement_decode() {
91 decode_replacement(b"", "");
92 decode_replacement(b"A", "\u{FFFD}");
93 decode_replacement(b"AB", "\u{FFFD}");
94 }
95
96 #[test]
97 fn test_replacement_encode() {
98 // Empty
99 encode_replacement("", b"");
100
101 assert_eq!(REPLACEMENT.new_encoder().encoding(), UTF_8);
102 encode_replacement("\u{1F4A9}\u{2603}", "\u{1F4A9}\u{2603}".as_bytes());
103 }
104}
105