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 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}