va_ts/
annex_a2.rs

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
178/// ETSI EN 300 468 V1.15.1
179impl 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    // TODO: maybe use "encoding" (rust-encoding) crate?
191    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                // We have consumed the current input buffer
208            }
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    // sz to skip in buffer
220    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}