Skip to main content

anyxml_encoding/
utf8.rs

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