Skip to main content

anyxml_encoding/
utf8.rs

1use std::str::{from_utf8, from_utf8_unchecked};
2
3use crate::{DecodeError, Decoder, EncodeError, Encoder};
4
5/// Encoding name for UTF-8.
6pub const UTF8_NAME: &str = "UTF-8";
7
8/// Encoder for UTF-8.
9pub struct UTF8Encoder;
10impl Encoder for UTF8Encoder {
11    fn name(&self) -> &'static str {
12        UTF8_NAME
13    }
14
15    fn encode(
16        &mut self,
17        src: &str,
18        dst: &mut [u8],
19        finish: bool,
20    ) -> Result<(usize, usize), EncodeError> {
21        if src.is_empty() {
22            return if finish {
23                Ok((0, 0))
24            } else {
25                Err(EncodeError::InputIsEmpty)
26            };
27        }
28
29        if finish && src.len() > dst.len() {
30            return Err(EncodeError::OutputTooShort);
31        }
32
33        let len = src.len().min(dst.len());
34        dst[..len].copy_from_slice(&src.as_bytes()[..len]);
35        Ok((len, len))
36    }
37}
38
39/// Decoder for UTF-8.
40pub struct UTF8Decoder;
41impl Decoder for UTF8Decoder {
42    fn name(&self) -> &'static str {
43        UTF8_NAME
44    }
45
46    fn decode(
47        &mut self,
48        src: &[u8],
49        dst: &mut String,
50        finish: bool,
51    ) -> Result<(usize, usize), DecodeError> {
52        if src.is_empty() {
53            return Err(DecodeError::InputIsEmpty);
54        }
55        let len = dst.capacity() - dst.len();
56        if len < 4 {
57            return Err(DecodeError::OutputTooShort);
58        }
59
60        let len = len.min(src.len());
61        match from_utf8(&src[..len]) {
62            Ok(s) => {
63                dst.push_str(s);
64                Ok((len, len))
65            }
66            Err(err) => {
67                let up_to = err.valid_up_to();
68                dst.push_str(unsafe {
69                    // # Safety
70                    // This operation is safe due to the `Utf8Error` constraint.
71                    from_utf8_unchecked(&src[..up_to])
72                });
73                match err.error_len() {
74                    Some(len) => Err(DecodeError::Malformed {
75                        read: up_to + len,
76                        write: up_to,
77                        length: len,
78                        offset: 0,
79                    }),
80                    None => {
81                        if finish {
82                            Err(DecodeError::Malformed {
83                                read: len,
84                                write: up_to,
85                                length: len - up_to,
86                                offset: 0,
87                            })
88                        } else {
89                            Ok((up_to, up_to))
90                        }
91                    }
92                }
93            }
94        }
95    }
96}