encoding_rs/
replacement.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
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(test)]
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}