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 | use super::*; |
11 | use crate::variant::*; |
12 | |
13 | pub struct ReplacementDecoder { |
14 | emitted: bool, |
15 | } |
16 | |
17 | impl 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" ))] |
77 | mod 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 | |