qubit_codec_text/codec/
latin1_codec.rs1use crate::{
9 Charset,
10 CharsetCodec,
11 CharsetDecodeError,
12 CharsetDecodeErrorKind,
13 CharsetDecodeResult,
14 CharsetEncodeError,
15 CharsetEncodeErrorKind,
16 CharsetEncodeProbe,
17 CharsetEncodeResult,
18 Unicode,
19};
20use qubit_codec::Codec;
21
22#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
26pub struct Latin1Codec;
27
28impl Latin1Codec {
29 #[must_use]
35 #[inline(always)]
36 pub const fn charset(self) -> Charset {
37 Charset::ISO_8859_1
38 }
39}
40
41impl CharsetCodec for Latin1Codec {
42 #[inline(always)]
48 fn charset(&self) -> Charset {
49 Charset::ISO_8859_1
50 }
51}
52
53impl CharsetEncodeProbe for Latin1Codec {
54 #[inline]
69 fn encode_len(&self, ch: char, index: usize) -> CharsetEncodeResult<usize> {
70 let value = ch as u32;
71 if value > Unicode::LATIN1_MAX {
72 let kind = CharsetEncodeErrorKind::UnmappableCharacter { value };
73 return Err(CharsetEncodeError::new(
74 Charset::ISO_8859_1,
75 kind,
76 index,
77 ));
78 }
79
80 Ok(1)
81 }
82}
83
84unsafe impl Codec for Latin1Codec {
85 type Value = char;
86 type Unit = u8;
87 type DecodeError = CharsetDecodeError;
88 type EncodeError = CharsetEncodeError;
89
90 #[inline(always)]
91 fn min_units_per_value(&self) -> core::num::NonZeroUsize {
92 core::num::NonZeroUsize::MIN
93 }
94
95 #[inline(always)]
96 fn max_units_per_value(&self) -> core::num::NonZeroUsize {
97 core::num::NonZeroUsize::MIN
98 }
99
100 #[inline]
101 unsafe fn decode_unchecked(
102 &self,
103 input: &[u8],
104 index: usize,
105 ) -> CharsetDecodeResult<(char, core::num::NonZeroUsize)> {
106 if index > input.len() {
107 let kind = CharsetDecodeErrorKind::InvalidInputIndex {
108 input_len: input.len(),
109 };
110 return Err(CharsetDecodeError::new(
111 Charset::ISO_8859_1,
112 kind,
113 index,
114 ));
115 }
116 if index == input.len() {
117 let kind = CharsetDecodeErrorKind::IncompleteSequence {
118 required: 1,
119 available: 0,
120 };
121 return Err(CharsetDecodeError::new(
122 Charset::ISO_8859_1,
123 kind,
124 index,
125 ));
126 }
127
128 let value = input[index] as u32;
129 debug_assert!(index < input.len());
130 Ok((
131 Unicode::to_char(value)
132 .expect("valid Latin-1 byte decodes to Unicode scalar"),
133 core::num::NonZeroUsize::MIN,
134 ))
135 }
136
137 #[inline]
138 unsafe fn encode_unchecked(
139 &self,
140 ch: &char,
141 output: &mut [u8],
142 index: usize,
143 ) -> CharsetEncodeResult<usize> {
144 let value = *ch as u32;
145 if value > Unicode::LATIN1_MAX {
146 let kind = CharsetEncodeErrorKind::UnmappableCharacter { value };
147 return Err(CharsetEncodeError::new(
148 Charset::ISO_8859_1,
149 kind,
150 index,
151 ));
152 }
153 if index >= output.len() {
154 let kind = CharsetEncodeErrorKind::BufferTooSmall {
155 required: required_index(index, 1),
156 available: 0,
157 };
158 return Err(CharsetEncodeError::new(
159 Charset::ISO_8859_1,
160 kind,
161 index,
162 ));
163 }
164 output[index] = value as u8;
165 Ok(1)
166 }
167}
168
169#[inline(always)]
170const fn required_index(index: usize, required_units: usize) -> usize {
171 match index.checked_add(required_units) {
172 Some(required) => required,
173 None => usize::MAX,
174 }
175}