1use super::*;
2use chrono::{NaiveDate, NaiveDateTime};
3use hex::{FromHex, ToHex};
4use std::mem::size_of;
5use yore::code_pages::CP437;
6
7pub trait Encoding<T> {
22 fn encode(input: &T) -> Vec<u8>;
23 fn decode(bytes: &[u8]) -> ZVTResult<(T, &[u8])>;
24}
25
26pub struct Default;
30
31macro_rules! encode_integral {
33 ($ty:ty, $name:ident, $encode:ident, $decode:ident) => {
34 impl Encoding<$ty> for $name {
35 fn encode(input: &$ty) -> Vec<u8> {
36 input.$encode().to_vec()
37 }
38
39 fn decode(data: &[u8]) -> ZVTResult<($ty, &[u8])> {
40 let size = size_of::<$ty>();
41
42 if data.len() < size {
43 Err(ZVTError::IncompleteData)
44 } else {
45 let bytes = data[0..size]
46 .try_into()
47 .map_err(|_| ZVTError::IncompleteData)?;
48 let res = <$ty>::$decode(bytes);
49 Ok((res, &data[size..]))
50 }
51 }
52 }
53 };
54}
55
56encode_integral!(u8, Default, to_le_bytes, from_le_bytes);
58encode_integral!(u16, Default, to_le_bytes, from_le_bytes);
59encode_integral!(u32, Default, to_le_bytes, from_le_bytes);
60encode_integral!(u64, Default, to_le_bytes, from_le_bytes);
61encode_integral!(usize, Default, to_le_bytes, from_le_bytes);
62
63impl Encoding<String> for Default {
67 fn encode(input: &String) -> Vec<u8> {
68 let res = CP437.encode(input).unwrap();
69 res.try_into().unwrap()
70 }
71
72 fn decode(data: &[u8]) -> ZVTResult<(String, &[u8])> {
73 Ok((
74 CP437.decode(data).trim_end_matches(0u8 as char).to_string(),
75 &[],
76 ))
77 }
78}
79
80impl Encoding<NaiveDateTime> for Default {
82 fn encode(_: &NaiveDateTime) -> Vec<u8> {
83 vec![]
84 }
85
86 fn decode(mut data: &[u8]) -> ZVTResult<(NaiveDateTime, &[u8])> {
87 let mut date = usize::default();
88 let mut time = u32::default();
89 let mut seen_tags = std::collections::HashSet::<u16>::new();
90 const DATE_TAG: u16 = 0x1f0e;
91 const TIME_TAG: u16 = 0x1f0f;
92 while !data.is_empty() {
93 let tag: Tag = Default::decode(data)?.0;
95 match tag.0 {
96 DATE_TAG => {
97 if !seen_tags.insert(DATE_TAG) {
98 return Err(ZVTError::DuplicateTag(Tag(DATE_TAG)));
99 }
100 (date, data) = <usize as ZvtSerializerImpl<
102 length::Tlv,
103 encoding::Bcd,
104 >>::deserialize_tagged(
105 data, Some(Tag(DATE_TAG))
106 )?;
107 }
108 TIME_TAG => {
109 if !seen_tags.insert(TIME_TAG) {
110 return Err(ZVTError::DuplicateTag(Tag(TIME_TAG)));
111 }
112 (time, data) =
113 <u32 as ZvtSerializerImpl<length::Tlv, encoding::Bcd>>::deserialize_tagged(
114 data,
115 Some(Tag(TIME_TAG)),
116 )?;
117 }
118 _ => break,
119 }
120 }
121 if seen_tags.len() != 2 {
123 return Err(ZVTError::IncompleteData);
124 }
125
126 Ok((
127 NaiveDate::from_ymd_opt(
128 date as i32 / 10000,
129 (date as u32 % 1000) / 100,
130 date as u32 % 100,
131 )
132 .unwrap()
133 .and_hms_opt(time / 10000, (time % 10000) / 100, time % 100)
134 .ok_or(ZVTError::IncompleteData)?,
135 data,
136 ))
137 }
138}
139
140impl encoding::Encoding<Tag> for Default {
144 fn encode(input: &Tag) -> Vec<u8> {
145 if (input.0 >> 8) == 0x1f {
146 input.0.to_be_bytes().to_vec()
147 } else {
148 vec![input.0 as u8]
149 }
150 }
151
152 fn decode(bytes: &[u8]) -> ZVTResult<(Tag, &[u8])> {
153 let (tag, new_bytes): (u8, _) = encoding::BigEndian::decode(bytes)?;
154 if tag == 0x1f {
155 if bytes.len() < 2 {
156 Err(ZVTError::IncompleteData)
157 } else {
158 let (tag, new_bytes): (u16, _) = encoding::BigEndian::decode(bytes)?;
159 Ok((Tag(tag), new_bytes))
160 }
161 } else {
162 Ok((Tag(tag as u16), new_bytes))
163 }
164 }
165}
166
167impl<T, E> Encoding<Option<T>> for E
168where
169 E: Encoding<T>,
170{
171 fn decode(data: &[u8]) -> ZVTResult<(Option<T>, &[u8])>
172 where
173 Self: Sized,
174 {
175 match E::decode(data) {
176 Err(err) => Err(err),
177 Ok(data) => Ok((Some(data.0), data.1)),
178 }
179 }
180
181 fn encode(input: &Option<T>) -> Vec<u8> {
182 match input {
183 None => vec![],
184 Some(inner) => E::encode(inner),
185 }
186 }
187}
188
189impl<T, E> Encoding<Vec<T>> for E
194where
195 E: Encoding<T>,
196{
197 fn encode(input: &Vec<T>) -> Vec<u8> {
198 input.iter().flat_map(|item| E::encode(item)).collect()
199 }
200
201 fn decode(mut bytes: &[u8]) -> ZVTResult<(Vec<T>, &[u8])> {
202 let mut out = Vec::new();
203 while !bytes.is_empty() {
204 let (res, tmp) = E::decode(bytes)?;
205 bytes = tmp;
206 out.push(res);
207 }
208 Ok((out, bytes))
209 }
210}
211
212pub struct BigEndian;
217
218encode_integral!(u8, BigEndian, to_be_bytes, from_be_bytes);
220encode_integral!(u16, BigEndian, to_be_bytes, from_be_bytes);
221encode_integral!(u32, BigEndian, to_be_bytes, from_be_bytes);
222encode_integral!(u64, BigEndian, to_be_bytes, from_be_bytes);
223encode_integral!(usize, BigEndian, to_be_bytes, from_be_bytes);
224
225impl encoding::Encoding<Tag> for BigEndian {
226 fn encode(input: &Tag) -> Vec<u8> {
227 encoding::BigEndian::encode(&input.0)
228 }
229
230 fn decode(bytes: &[u8]) -> ZVTResult<(Tag, &[u8])> {
231 let res: (u16, _) = encoding::BigEndian::decode(bytes)?;
232 Ok((Tag(res.0), res.1))
233 }
234}
235
236pub struct Bcd;
242
243macro_rules! bcd_integrals {
244 ($ty:ty) => {
245 impl Encoding<$ty> for Bcd {
246 fn encode(input: &$ty) -> Vec<u8> {
247 let mut k = *input;
248 let mut rv = vec![];
249 while k != 0 {
250 let mut curr = (k % 10) as u8;
251 k /= 10;
252 curr |= ((k % 10) as u8) << 4;
253 k /= 10;
254 rv.push(curr);
255 }
256 rv.reverse();
257 rv
258 }
259
260 fn decode(data: &[u8]) -> ZVTResult<($ty, &[u8])> {
261 let mut rv = 0;
262 for d in data.iter() {
263 let high = (d >> 4) as $ty;
264 let low = (d & 0xf) as $ty;
265 if low != 0xf {
266 rv = (rv * 100) + ((d >> 4) as $ty * 10) + low;
267 } else {
268 rv = (rv * 10) + high;
269 }
270 }
271 Ok((rv, &[]))
272 }
273 }
274 };
275}
276
277bcd_integrals!(u8);
278bcd_integrals!(u16);
279bcd_integrals!(u32);
280bcd_integrals!(u64);
281bcd_integrals!(usize);
282
283pub struct Hex;
284
285impl Encoding<String> for Hex {
286 fn encode(input: &String) -> Vec<u8> {
287 <Vec<u8>>::from_hex(input.clone().as_bytes()).unwrap()
288 }
289
290 fn decode(data: &[u8]) -> ZVTResult<(String, &[u8])> {
291 Ok((data.encode_hex(), &[]))
292 }
293}
294
295pub struct Utf8;
296
297impl Encoding<String> for Utf8 {
298 fn encode(_: &String) -> Vec<u8> {
299 vec![]
300 }
301
302 fn decode(data: &[u8]) -> ZVTResult<(String, &[u8])> {
303 let string = String::from_utf8(data.to_vec()).map_err(|_| ZVTError::IncompleteData)?;
304 Ok((string, &[]))
305 }
306}
307
308macro_rules! zvt_serializer_registry {
311 ($ty:ty) => {
312 impl<L: length::Length, E: encoding::Encoding<$ty>, TE: encoding::Encoding<Tag>>
313 ZvtSerializerImpl<L, E, TE> for $ty
314 {
315 }
316 };
317}
318
319zvt_serializer_registry!(u8);
320zvt_serializer_registry!(u16);
321zvt_serializer_registry!(u32);
322zvt_serializer_registry!(u64);
323zvt_serializer_registry!(usize);
324zvt_serializer_registry!(String);
325zvt_serializer_registry!(NaiveDateTime);
326
327#[cfg(test)]
328mod test {
329 use super::*;
330
331 #[test]
332 fn test_default() {
333 assert_eq!(Default::encode(&1234u16), [210, 4]);
335 assert_eq!(Default::encode(&1234u32), [210, 4, 0, 0]);
336 assert_eq!(Default::encode(&1234u64), [210, 4, 0, 0, 0, 0, 0, 0]);
337
338 let a: u16 = Default::decode(&[210, 4]).unwrap().0;
340 assert_eq!(a, 1234);
341 let a: u32 = Default::decode(&[210, 4, 0, 0]).unwrap().0;
342 assert_eq!(a, 1234);
343
344 let a: u64 = Default::decode(&[210, 4, 0, 0, 0, 0, 0, 0]).unwrap().0;
345 assert_eq!(a, 1234);
346
347 let a: ZVTResult<(u16, _)> = Default::decode(&[1]);
349 assert_eq!(a, Err(ZVTError::IncompleteData));
350 }
351
352 #[test]
353 fn test_big_endian() {
354 assert_eq!(BigEndian::encode(&1234u16), [4, 210]);
355 assert_eq!(BigEndian::encode(&1234u32), [0, 0, 4, 210]);
356 assert_eq!(BigEndian::encode(&1234u64), [0, 0, 0, 0, 0, 0, 4, 210]);
357
358 let a: u16 = BigEndian::decode(&[4, 210]).unwrap().0;
359 assert_eq!(a, 1234);
360 let a: u32 = BigEndian::decode(&[0, 0, 4, 210]).unwrap().0;
361 assert_eq!(a, 1234);
362
363 let a: u64 = BigEndian::decode(&[0, 0, 0, 0, 0, 0, 4, 210]).unwrap().0;
364 assert_eq!(a, 1234);
365
366 let a: ZVTResult<(u32, _)> = BigEndian::decode(&[1, 2, 3]);
367 assert_eq!(a, Err(ZVTError::IncompleteData));
368 }
369
370 #[test]
371 fn test_bcd() {
372 assert_eq!(Bcd::encode(&1234u16), [0x12, 0x34]);
373 let a: u16 = Bcd::decode(&[0x12, 0x34]).unwrap().0;
374 assert_eq!(a, 1234);
375 }
376}