1use crate::error::{Error, Kind as ErrorKind};
2use std::convert::TryFrom;
3
4#[derive(Clone, Copy, Debug)]
5pub enum TableA3 {
6 IsoIec8859_5,
7 IsoIec8859_6,
8 IsoIec8859_7,
9 IsoIec8859_8,
10 IsoIec8859_9,
11 IsoIec8859_10,
12 IsoIec8859_11,
13 IsoIec8859_13,
14 IsoIec8859_14,
15 IsoIec8859_15,
16
17 IsoIec10646,
18 KSX10012004,
19 Gb2312_1980,
20 Big5subsetOfIsoIec10646,
21 Utf8encodingOfIsoIec10646,
22 DescribedByEncodingTypeId,
23
24 Reserved(u8),
25}
26
27impl TableA3 {
28 pub fn encoding(self) -> Option<&'static encoding_rs::Encoding> {
29 match self {
30 TableA3::IsoIec8859_5 => Some(encoding_rs::ISO_8859_5),
31 TableA3::IsoIec8859_6 => Some(encoding_rs::ISO_8859_6),
32 TableA3::IsoIec8859_7 => Some(encoding_rs::ISO_8859_7),
33 TableA3::IsoIec8859_8 => Some(encoding_rs::ISO_8859_8),
34 TableA3::IsoIec8859_13 => Some(encoding_rs::ISO_8859_13),
35 TableA3::IsoIec8859_14 => Some(encoding_rs::ISO_8859_14),
36 TableA3::IsoIec8859_15 => Some(encoding_rs::ISO_8859_15),
37 TableA3::Big5subsetOfIsoIec10646 => Some(encoding_rs::BIG5),
38 TableA3::Gb2312_1980 => Some(encoding_rs::GBK),
39 TableA3::Utf8encodingOfIsoIec10646 => Some(encoding_rs::UTF_8),
40 _ => None,
41 }
42 }
43}
44
45impl TryFrom<u8> for TableA3 {
46 type Error = Error;
47
48 fn try_from(d: u8) -> Result<Self, self::Error> {
49 if d > 0x1F {
50 return Err(Error::new(ErrorKind::AnnexA2TableA3Unexpected(d)));
51 }
52
53 Ok(match d {
54 0x01 => TableA3::IsoIec8859_5,
55 0x02 => TableA3::IsoIec8859_6,
56 0x03 => TableA3::IsoIec8859_7,
57 0x04 => TableA3::IsoIec8859_8,
58 0x05 => TableA3::IsoIec8859_9,
59 0x06 => TableA3::IsoIec8859_10,
60 0x07 => TableA3::IsoIec8859_11,
61
62 0x08 => TableA3::Reserved(d),
63
64 0x09 => TableA3::IsoIec8859_13,
65 0x0A => TableA3::IsoIec8859_14,
66 0x0B => TableA3::IsoIec8859_15,
67
68 0x0C..=0x0F => TableA3::Reserved(d),
69
70 0x11 => TableA3::IsoIec10646,
71 0x12 => TableA3::KSX10012004,
72 0x13 => TableA3::Gb2312_1980,
73 0x14 => TableA3::Big5subsetOfIsoIec10646,
74 0x15 => TableA3::Utf8encodingOfIsoIec10646,
75
76 0x16..=0x1E => TableA3::Reserved(d),
77
78 0x1F => TableA3::DescribedByEncodingTypeId,
79
80 _ => panic!("(annex-a2 table-a3 parse) unexpected value;"),
81 })
82 }
83}
84
85#[derive(Clone, Copy, Debug)]
86pub enum TableA4 {
87 IsoIec8859_1,
88 IsoIec8859_2,
89 IsoIec8859_3,
90 IsoIec8859_4,
91 IsoIec8859_5,
92 IsoIec8859_6,
93 IsoIec8859_7,
94 IsoIec8859_8,
95 IsoIec8859_9,
96 IsoIec8859_10,
97 IsoIec8859_11,
98 IsoIec8859_13,
99 IsoIec8859_14,
100 IsoIec8859_15,
101
102 Reserved(u8, u8),
103}
104
105impl TableA4 {
106 const SYNC_BYTE: u8 = 0x10;
107}
108
109impl TableA4 {
110 pub fn encoding(self) -> Option<&'static encoding_rs::Encoding> {
111 match self {
112 TableA4::IsoIec8859_1 => Some(encoding_rs::UTF_8),
113 TableA4::IsoIec8859_2 => Some(encoding_rs::ISO_8859_2),
114 TableA4::IsoIec8859_3 => Some(encoding_rs::ISO_8859_3),
115 TableA4::IsoIec8859_4 => Some(encoding_rs::ISO_8859_4),
116 TableA4::IsoIec8859_5 => Some(encoding_rs::ISO_8859_5),
117 TableA4::IsoIec8859_6 => Some(encoding_rs::ISO_8859_6),
118 TableA4::IsoIec8859_7 => Some(encoding_rs::ISO_8859_7),
119 TableA4::IsoIec8859_8 => Some(encoding_rs::ISO_8859_8),
120 TableA4::IsoIec8859_10 => Some(encoding_rs::ISO_8859_10),
121 TableA4::IsoIec8859_13 => Some(encoding_rs::ISO_8859_13),
122 TableA4::IsoIec8859_14 => Some(encoding_rs::ISO_8859_14),
123 TableA4::IsoIec8859_15 => Some(encoding_rs::ISO_8859_15),
124 _ => None,
125 }
126 }
127}
128
129impl<'buf> TryFrom<&'buf [u8]> for TableA4 {
130 type Error = Error;
131
132 fn try_from(buf: &'buf [u8]) -> Result<Self, self::Error> {
133 if buf.len() < 3 {
134 return Err(Error::new(ErrorKind::AnnexA2TableA4Buf(buf.len(), 3)));
135 }
136
137 let (b1, b2, b3) = (buf[0], buf[1], buf[2]);
138
139 if b1 != Self::SYNC_BYTE {
140 return Err(Error::new(ErrorKind::AnnexA2TableA4Unexpected(b1)));
141 }
142
143 Ok(match (b2, b3) {
144 (0x00, 0x01) => TableA4::IsoIec8859_1,
145 (0x00, 0x02) => TableA4::IsoIec8859_2,
146 (0x00, 0x03) => TableA4::IsoIec8859_3,
147 (0x00, 0x04) => TableA4::IsoIec8859_4,
148 (0x00, 0x05) => TableA4::IsoIec8859_5,
149 (0x00, 0x06) => TableA4::IsoIec8859_6,
150 (0x00, 0x07) => TableA4::IsoIec8859_7,
151 (0x00, 0x08) => TableA4::IsoIec8859_8,
152 (0x00, 0x09) => TableA4::IsoIec8859_9,
153 (0x00, 0x0A) => TableA4::IsoIec8859_10,
154 (0x00, 0x0B) => TableA4::IsoIec8859_11,
155 (0x00, 0x0D) => TableA4::IsoIec8859_13,
156 (0x00, 0x0E) => TableA4::IsoIec8859_14,
157 (0x00, 0x0F) => TableA4::IsoIec8859_15,
158
159 (0x00, 0x00) => TableA4::Reserved(b1, b2),
160 (0x00, 0x0C) => TableA4::Reserved(b1, b2),
161 (0x00, 0x10..=0xFF) => TableA4::Reserved(b1, b2),
162 (0x01..=0xFF, 0x00..=0xFF) => TableA4::Reserved(b1, b2),
163 })
164 }
165}
166
167#[derive(Clone, Copy, Debug)]
168pub enum AnnexA2 {
169 A3(TableA3),
170 A4(TableA4),
171
172 Reserved(u8),
173 Zero,
174
175 Default,
176}
177
178impl AnnexA2 {
180 fn encoding(self) -> Option<&'static encoding_rs::Encoding> {
181 match self {
182 AnnexA2::A3(a3) => a3.encoding(),
183 AnnexA2::A4(a4) => a4.encoding(),
184 AnnexA2::Default => Some(encoding_rs::UTF_8),
185 AnnexA2::Reserved(..) => None,
186 AnnexA2::Zero => None,
187 }
188 }
189
190 pub fn decode<'buf>(src_buf: &'buf [u8], dst_str: &'buf mut str) -> Result<AnnexA2, Error> {
192 let a2 = AnnexA2::try_from(src_buf)?;
193
194 let src_buf = &src_buf[a2.sz()..];
195
196 let encoding = match a2.encoding() {
197 Some(encoding) => encoding,
198 None => return Err(Error::new(ErrorKind::AnnexA2UnsupportedEncoding)),
199 };
200
201 let mut decoder = encoding.new_decoder();
202
203 let (result, _, _, had_errors) = decoder.decode_to_str(src_buf, dst_str, false);
204
205 match result {
206 encoding_rs::CoderResult::InputEmpty => {
207 }
209 encoding_rs::CoderResult::OutputFull => {}
210 }
211
212 if had_errors {
213 Err(Error::new(ErrorKind::AnnexA2Decode))
214 } else {
215 Ok(a2)
216 }
217 }
218
219 fn sz(self) -> usize {
221 match self {
222 AnnexA2::A3(..) => 1,
223 AnnexA2::A4(..) => 3,
224 AnnexA2::Default => 0,
225 _ => 0,
226 }
227 }
228}
229
230impl<'buf> TryFrom<&'buf [u8]> for AnnexA2 {
231 type Error = Error;
232
233 fn try_from(buf: &'buf [u8]) -> Result<Self, self::Error> {
234 if buf.is_empty() {
235 return Err(Error::new(ErrorKind::AnnexA2EmptyBuf));
236 }
237
238 let v = match buf[0] {
239 0x00 => AnnexA2::Zero,
240
241 0x20..=0xFF => AnnexA2::Default,
242
243 0x01..=0x07 | 0x09..=0x0B | 0x11..=0x15 | 0x1F => {
244 AnnexA2::A3(TableA3::try_from(buf[0])?)
245 }
246
247 0x10 => AnnexA2::A4(TableA4::try_from(buf)?),
248
249 0x08 | 0x0C..=0x0F | 0x16..=0x1E => AnnexA2::Reserved(buf[0]),
250 };
251
252 Ok(v)
253 }
254}
255
256#[cfg(test)]
257mod tests {
258 #[test]
259 fn decode() {}
260}