1use crate::BCDConversionError;
2use std::fmt::{Debug, Display};
3
4#[derive(Clone, Copy)]
5pub struct BCD<const BYTES: usize> {
6 data: [u8;BYTES]
7}
8
9#[derive(Clone)]
10pub struct DynBCD {
11 data: Vec<u8>
12}
13
14pub trait Convertible<T> {
15 fn convert(&self) -> T;
16}
17
18fn check_invalid_byte(val: u8) -> bool {
19 let high = (val & 0xf0) >> 0x04;
20 let low = val & 0x0f;
21 low > 9 || high > 9
22}
23
24fn check_invalid_bytes<'a>(it: impl Iterator<Item = &'a u8>) -> bool {
25 let mut it = it;
26 it.any(|val| check_invalid_byte(val.to_owned()))
27}
28
29impl<const BYTES_OG: usize, const BYTES_DST: usize> Convertible<BCD<BYTES_DST>> for BCD<BYTES_OG> {
30 fn convert(&self) -> BCD<BYTES_DST> {
31 if BYTES_OG >= BYTES_DST {
32 BCD {
33 data: self.data.into_iter().rev().take(BYTES_DST).rev().collect::<Vec<u8>>().try_into().unwrap()
34 }
35 }
36 else {
37 let mut new_data = vec![0;BYTES_DST-BYTES_OG];
38 new_data.append(&mut Vec::from(self.data));
39 BCD {
40 data: new_data.try_into().unwrap()
41 }
42 }
43 }
44}
45
46impl<const BYTES: usize> Debug for BCD<BYTES> {
47 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48 f.debug_struct("BCD")
49 .field("data", &self.data)
50 .field("computed_value", &Into::<u128>::into((*self).convert()))
51 .finish()
52 }
53}
54
55impl<const BYTES: usize> Display for BCD<BYTES> {
56 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57 write!(f, "BCD<{}> {{ \"computed_value\": {} }}", BYTES, Into::<u128>::into((*self).convert()))
58 }
59}
60
61impl Debug for DynBCD {
62 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63 f.debug_struct("DynBCD")
64 .field("data", &self.data)
65 .field("computed_value", &Into::<u128>::into(self.clone()))
66 .finish()
67 }
68}
69
70impl Display for DynBCD {
71 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72 write!(f, "DynBCD {{ \"computed_value\": {} }}", Into::<u128>::into(self.clone()))
73 }
74}
75
76impl<const BYTES: usize> IntoIterator for BCD<BYTES> {
77 type Item = u8;
78
79 type IntoIter = std::array::IntoIter<Self::Item,BYTES>;
80
81 fn into_iter(self) -> Self::IntoIter {
82 self.data.into_iter()
83 }
84}
85
86impl IntoIterator for DynBCD {
87 type Item = u8;
88
89 type IntoIter = std::vec::IntoIter<Self::Item>;
90
91 fn into_iter(self) -> Self::IntoIter {
92 self.data.into_iter()
93 }
94}
95
96impl<const BYTES: usize> From<BCD<BYTES>> for Vec<u8> {
97 fn from(data: BCD<BYTES>) -> Self {
98 Vec::from(data.data)
99 }
100}
101
102impl From<DynBCD> for Vec<u8> {
103 fn from(data: DynBCD) -> Self {
104 data.data
105 }
106}
107
108impl<const BYTES: usize> From<DynBCD> for BCD<BYTES> {
109 fn from(value: DynBCD) -> Self {
110 let mut new_data: Vec<u8> = value.data.into_iter().rev().take(BYTES).collect();
111 while new_data.len() < BYTES {
112 new_data.push(0);
113 }
114 let new_data: Vec<u8> = new_data.into_iter().rev().collect();
115 Self {
116 data: new_data.try_into().unwrap()
117 }
118 }
119}
120
121impl<const BYTES: usize> From<BCD<BYTES>> for DynBCD {
122 fn from(value: BCD<BYTES>) -> Self {
123 Self {
124 data: Vec::from(value.data)
125 }
126 }
127}
128
129impl TryFrom<&[u8]> for DynBCD {
130 type Error = BCDConversionError;
131
132 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
133 if check_invalid_bytes(value.iter()) {
134 return Err(BCDConversionError::new("Invalid format, found A-F"));
135 }
136 Ok(Self {
137 data: Vec::from(value)
138 })
139 }
140}
141
142impl<const BYTES: usize> TryFrom<&[u8]> for BCD<BYTES> {
143 type Error = BCDConversionError;
144
145 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
146 if check_invalid_bytes(value.iter()) {
147 return Err(BCDConversionError::new("Invalid format, found A-F"));
148 }
149 if value.len() >= BYTES {
150 let buffer: Vec<u8> = value.iter()
151 .rev().take(BYTES).rev()
152 .copied()
153 .collect();
154 Ok(Self {
155 data: buffer.try_into().unwrap()
156 })
157 }
158 else {
159 let mut buffer = vec![0;BYTES - value.len()];
160 buffer.extend(value.iter().copied());
161 Ok(Self {
162 data: buffer.try_into().unwrap()
163 })
164 }
165 }
166}
167
168impl<const BYTES_OG: usize, const BYTES_DST: usize> TryFrom<[u8;BYTES_OG]> for BCD<BYTES_DST> {
169 type Error = BCDConversionError;
170
171 fn try_from(value: [u8;BYTES_OG]) -> Result<Self, Self::Error> {
172 if check_invalid_bytes(value.iter()) {
173 return Err(BCDConversionError::new("Invalid format. Found A-F"));
174 }
175 if BYTES_OG >= BYTES_DST {
176 Ok(Self {
177 data: value[BYTES_OG-BYTES_DST..].try_into().unwrap()
178 })
179 }
180 else {
181 let mut new_data = vec![0;BYTES_DST-BYTES_OG];
182 new_data.append(&mut Vec::from(value));
183 Ok(Self {
184 data: new_data.try_into().unwrap()
185 })
186 }
187 }
188}
189
190impl<const BYTES_OG: usize, const BYTES_DST: usize> From<BCD<BYTES_OG>> for [u8;BYTES_DST] {
191 fn from(data: BCD<BYTES_OG>) -> Self {
192 if BYTES_OG >= BYTES_DST {
193 data.data.into_iter().rev().take(BYTES_DST).rev().collect::<Vec<u8>>().try_into().unwrap()
194 }
195 else {
196 let mut new_data = vec![0;BYTES_DST-BYTES_OG];
197 new_data.append(&mut Vec::from(data.data));
198 new_data.try_into().unwrap()
199 }
200 }
201}
202
203impl TryFrom<u8> for BCD<1> {
204 type Error = BCDConversionError;
205
206 fn try_from(value: u8) -> Result<Self, Self::Error> {
207 let n_bytes = value.to_ne_bytes().into_iter().count();
208 let max_val = (0..n_bytes).into_iter().fold(0, |acc, _| acc*100+99);
209 if value > max_val { return Err(Self::Error::new_with_template_description("u8", value, max_val)); }
210 let high = value/10;
211 let low = value%10;
212 Ok(Self{data: [high<<4|low]})
213 }
214}
215
216impl From<BCD<1>> for u8 {
217 fn from(val: BCD<1>) -> Self {
218 let high = (val.data[0] & 0xf0) >> 4;
219 let low = val.data[0] & 0x0f;
220 high*10+low
221 }
222}
223
224impl TryFrom<u16> for BCD<2> {
225 type Error = BCDConversionError;
226
227 fn try_from(value: u16) -> Result<Self, Self::Error> {
228 let n_bytes = value.to_ne_bytes().into_iter().count();
229 let max_val = (0..n_bytes).into_iter().fold(0, |acc, _| acc*100+99);
230 if value > max_val { return Err(Self::Error::new_with_template_description("u16", value, max_val)); }
231 let mut value = value;
232 let mut buffer: Vec<BCD<1>> = vec![];
233 while value != 0 {
234 let current = value%100;
235 buffer.push((current as u8).try_into()?);
236 value /= 100;
237 }
238 while buffer.len() < n_bytes {
239 buffer.push(BCD{ data: [0] });
240 }
241 let buffer: [u8; 2] = buffer.into_iter()
242 .rev()
243 .flat_map(|item| item.data)
244 .collect::<Vec<u8>>()
245 .try_into().unwrap();
246 Ok(Self::try_from(buffer).unwrap())
247 }
248}
249
250impl From<BCD<2>> for u16 {
251 fn from(value: BCD<2>) -> Self {
252 value.data.into_iter()
253 .fold(0, |acc, x| acc*100 + (Into::<u8>::into(BCD::try_from([x]).unwrap()) as Self))
254 }
255}
256
257impl TryFrom<u32> for BCD<4> {
258 type Error = BCDConversionError;
259
260 fn try_from(value: u32) -> Result<Self, Self::Error> {
261 let n_bytes = value.to_ne_bytes().into_iter().count();
262 let max_val = (0..n_bytes).into_iter().fold(0, |acc, _| acc*100+99);
263 if value > max_val { return Err(Self::Error::new_with_template_description("u32", value, max_val)); }
264 let mut value = value;
265 let mut buffer: Vec<BCD<1>> = vec![];
266 while value != 0 {
267 let current = value%100;
268 buffer.push((current as u8).try_into()?);
269 value /= 100;
270 }
271 while buffer.len() < n_bytes {
272 buffer.push(BCD{ data: [0] });
273 }
274 let buffer: [u8; 4] = buffer.into_iter()
275 .rev()
276 .flat_map(|item| item.data)
277 .collect::<Vec<u8>>()
278 .try_into().unwrap();
279 Ok(Self::try_from(buffer).unwrap())
280 }
281}
282
283impl From<BCD<4>> for u32 {
284 fn from(value: BCD<4>) -> Self {
285 value.data.into_iter()
286 .fold(0, |acc, x| acc*100 + (Into::<u8>::into(BCD::try_from([x]).unwrap()) as Self))
287 }
288}
289
290impl TryFrom<u64> for BCD<8> {
291 type Error = BCDConversionError;
292
293 fn try_from(value: u64) -> Result<Self, Self::Error> {
294 let n_bytes = value.to_ne_bytes().into_iter().count();
295 let max_val = (0..n_bytes).into_iter().fold(0, |acc, _| acc*100+99);
296 if value > max_val { return Err(Self::Error::new_with_template_description("u32", value, max_val)); }
297 let mut value = value;
298 let mut buffer: Vec<BCD<1>> = vec![];
299 while value != 0 {
300 let current = value%100;
301 buffer.push((current as u8).try_into()?);
302 value /= 100;
303 }
304 while buffer.len() < n_bytes {
305 buffer.push(BCD{ data: [0] });
306 }
307 let buffer: [u8; 8] = buffer.into_iter()
308 .rev()
309 .flat_map(|item| item.data)
310 .collect::<Vec<u8>>()
311 .try_into().unwrap();
312 Ok(Self::try_from(buffer).unwrap())
313 }
314}
315
316impl From<BCD<8>> for u64 {
317 fn from(value: BCD<8>) -> Self {
318 value.data.into_iter()
319 .fold(0, |acc, x| acc*100 + (Into::<u8>::into(BCD::try_from([x]).unwrap()) as Self))
320 }
321}
322
323impl TryFrom<u128> for BCD<16> {
324 type Error = BCDConversionError;
325
326 fn try_from(value: u128) -> Result<Self, Self::Error> {
327 let n_bytes = value.to_ne_bytes().into_iter().count();
328 let max_val = (0..n_bytes).into_iter().fold(0, |acc, _| acc*100+99);
329 if value > max_val { return Err(Self::Error::new_with_template_description("u32", value, max_val)); }
330 let mut value = value;
331 let mut buffer: Vec<BCD<1>> = vec![];
332 while value != 0 {
333 let current = value%100;
334 buffer.push((current as u8).try_into()?);
335 value /= 100;
336 }
337 while buffer.len() < n_bytes {
338 buffer.push(BCD{ data: [0] });
339 }
340 let buffer: [u8; 16] = buffer.into_iter()
341 .rev()
342 .flat_map(|item| item.data)
343 .collect::<Vec<u8>>()
344 .try_into().unwrap();
345 Ok(Self::try_from(buffer).unwrap())
346 }
347}
348
349impl From<BCD<16>> for u128 {
350 fn from(value: BCD<16>) -> Self {
351 value.data.into_iter()
352 .fold(0, |acc, x| acc*100 + (Into::<u8>::into(BCD::try_from([x]).unwrap()) as Self))
353 }
354}
355
356impl TryFrom<u8> for DynBCD {
357 type Error = BCDConversionError;
358
359 fn try_from(value: u8) -> Result<DynBCD, Self::Error> {
360 let n_bytes = value.to_ne_bytes().into_iter().count();
361 let max_val = (0..n_bytes).into_iter().fold(0, |acc, _| acc*100+99);
362 if value > max_val { return Err(Self::Error::new_with_template_description("u8", value, max_val)); }
363 let low = value % 10;
364 let high = value / 10;
365 Ok(Self {
366 data: vec![high<<4|low]
367 })
368 }
369}
370
371impl From<DynBCD> for u8 {
372 fn from(value: DynBCD) -> Self {
373 let value = value.data.into_iter().rev().next().unwrap();
374 let high = (value & 0xf0) >> 4;
375 let low = value & 0x0f;
376 high*10+low
377 }
378}
379
380impl TryFrom<u16> for DynBCD {
381 type Error = BCDConversionError;
382 fn try_from(value: u16) -> Result<DynBCD, Self::Error> {
383 let n_bytes = value.to_ne_bytes().into_iter().count();
384 let max_val = (0..n_bytes).into_iter().fold(0, |acc, _| acc*100+99);
385 if value > max_val { return Err(Self::Error::new_with_template_description("u16", value, max_val)); }
386 let mut value = value;
387 let mut buffer: Vec<BCD<1>> = vec![];
388 while value != 0 {
389 let current = (value % 100) as u8;
390 value /= 100;
391 buffer.push(current.try_into().unwrap());
392 }
393 let buffer = buffer.into_iter().rev().flat_map(|item| item.data).collect();
394 Ok(Self {
395 data: buffer
396 })
397 }
398}
399
400impl From<DynBCD> for u16 {
401 fn from(value: DynBCD) -> Self {
402 value.data.into_iter()
403 .fold(0, |acc, x| acc*100 + (Into::<u8>::into(BCD::try_from([x]).unwrap()) as Self))
404 }
405}
406
407impl TryFrom<u32> for DynBCD {
408 type Error = BCDConversionError;
409
410 fn try_from(value: u32) -> Result<DynBCD, Self::Error> {
411 let n_bytes = value.to_ne_bytes().into_iter().count();
412 let max_val = (0..n_bytes).into_iter().fold(0, |acc, _| acc*100+99);
413 if value > max_val { return Err(Self::Error::new_with_template_description("u32", value, max_val)); }
414 let mut value = value;
415 let mut buffer: Vec<BCD<1>> = vec![];
416 while value != 0 {
417 let current = (value % 100) as u8;
418 value /= 100;
419 buffer.push(current.try_into().unwrap());
420 }
421 let buffer = buffer.into_iter().rev().flat_map(|item| item.data).collect();
422 Ok(Self {
423 data: buffer
424 })
425 }
426}
427
428impl From<DynBCD> for u32 {
429 fn from(value: DynBCD) -> Self {
430 value.data.into_iter()
431 .fold(0, |acc, x| acc*100 + (Into::<u8>::into(BCD::try_from([x]).unwrap()) as Self))
432 }
433}
434
435impl TryFrom<u64> for DynBCD {
436 type Error = BCDConversionError;
437
438 fn try_from(value: u64) -> Result<DynBCD, Self::Error> {
439 let n_bytes = value.to_ne_bytes().into_iter().count();
440 let max_val = (0..n_bytes).into_iter().fold(0, |acc, _| acc*100+99);
441 if value > max_val { return Err(Self::Error::new_with_template_description("u64", value, max_val)); }
442 let mut value = value;
443 let mut buffer: Vec<BCD<1>> = vec![];
444 while value != 0 {
445 let current = (value % 100) as u8;
446 value /= 100;
447 buffer.push(current.try_into().unwrap());
448 }
449 let buffer = buffer.into_iter().rev().flat_map(|item| item.data).collect();
450 Ok(Self {
451 data: buffer
452 })
453 }
454}
455
456impl From<DynBCD> for u64 {
457 fn from(value: DynBCD) -> Self {
458 value.data.into_iter()
459 .fold(0, |acc, x| acc*100 + (Into::<u8>::into(BCD::try_from([x]).unwrap()) as Self))
460 }
461}
462
463impl TryFrom<u128> for DynBCD {
464 type Error = BCDConversionError;
465
466 fn try_from(value: u128) -> Result<DynBCD, Self::Error> {
467 let n_bytes = value.to_ne_bytes().into_iter().count();
468 let max_val = (0..n_bytes).into_iter().fold(0, |acc, _| acc*100+99);
469 if value > max_val { return Err(Self::Error::new_with_template_description("u128", value, max_val)); }
470 let mut value = value;
471 let mut buffer: Vec<BCD<1>> = vec![];
472 while value != 0 {
473 let current = (value % 100) as u8;
474 value /= 100;
475 buffer.push(current.try_into().unwrap());
476 }
477 let buffer = buffer.into_iter().rev().flat_map(|item| item.data).collect();
478 Ok(Self {
479 data: buffer
480 })
481 }
482}
483
484impl From<DynBCD> for u128 {
485 fn from(value: DynBCD) -> Self {
486 value.data.into_iter()
487 .fold(0, |acc, x| acc*100 + (Into::<u8>::into(BCD::try_from([x]).unwrap()) as Self))
488 }
489}
490
491impl<const BYTES: usize> BCD<BYTES> {
492 pub fn new(value: u128) -> Self {
493 let new_val: BCD<16> = value.try_into().unwrap();
494 new_val.convert()
495 }
496
497 pub fn get_number(&self) -> u128 {
498 (*self).convert().into()
499 }
500}
501
502impl DynBCD {
503 pub fn new(value: u128) -> Self {
504 value.try_into().unwrap()
505 }
506
507 pub fn get_number(&self) -> u128 {
508 self.clone().into()
509 }
510}