1use std::str::{from_utf8, from_utf8_unchecked};
2
3use crate::{DecodeError, Decoder, EncodeError, Encoder};
4
5pub const UTF8_NAME: &str = "UTF-8";
7
8pub 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
39pub 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 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}