1use std::num::Wrapping;
2
3pub trait FixChecksum {
4 fn checksum(self) -> Wrapping<u8>;
5}
6
7pub trait FixLength {
8 fn bytes_len(self) -> u32;
9}
10
11macro_rules! impl_checksum_unsigned {
12 ($type_name:ident) => {
13 impl FixChecksum for $type_name {
14 fn checksum(self) -> Wrapping<u8> {
15 if self == 0 {
16 Wrapping('0' as u8)
17 } else {
18 let mut total = Wrapping(0);
19 let mut tag = self;
20 while tag > 0 {
21 total += Wrapping((tag % 10) as u8) + Wrapping('0' as u8);
22 tag = tag / 10;
23 }
24 total
25 }
26 }
27 }
28 };}
29
30macro_rules! impl_bytes_len_unsigned {
31 ($type_name:ident) => {
32 impl FixLength for $type_name {
33 fn bytes_len(self) -> u32 {
34 if self == 0 {
35 1
36 } else {
37 let mut total = 0;
38 let mut tag = self;
39 while tag > 0 {
40 total += 1;
41 tag = tag / 10;
42 }
43 total
44 }
45 }
46 }
47 };}
48
49impl_checksum_unsigned!(u8);
50impl_checksum_unsigned!(u16);
51impl_checksum_unsigned!(u32);
52impl_checksum_unsigned!(u64);
53impl_checksum_unsigned!(u128);
54impl_bytes_len_unsigned!(u8);
55impl_bytes_len_unsigned!(u16);
56impl_bytes_len_unsigned!(u32);
57impl_bytes_len_unsigned!(u64);
58impl_bytes_len_unsigned!(u128);
59
60macro_rules! impl_checksum_signed {
61 ($type_name:ident) => {
62 impl FixChecksum for $type_name {
63 fn checksum(self) -> Wrapping<u8> {
64 if self == 0 {
65 Wrapping('0' as u8)
66 } else {
67 let checksum_neg = if self < 0 {
68 Wrapping('-' as u8)
69 } else {
70 Wrapping(0)
71 };
72 let mut total = Wrapping(0);
73 let mut tag = self.abs();
74 while tag > 0 {
75 total += Wrapping((tag % 10) as u8) + Wrapping('0' as u8);
76 tag = tag / 10;
77 }
78 total + checksum_neg
79 }
80 }
81 }
82 };}
83
84macro_rules! impl_bytes_len_signed {
85 ($type_name:ident) => {
86 impl FixLength for $type_name {
87 fn bytes_len(self) -> u32 {
88 if self == 0 {
89 1
90 } else {
91 let checksum_neg = if self < 0 {
92 1
93 } else {
94 0
95 };
96 let mut total = 0;
97 let mut tag = self.abs();
98 while tag > 0 {
99 total += 1;
100 tag = tag / 10;
101 }
102 total + checksum_neg
103 }
104 }
105 }
106 };}
107
108impl_checksum_signed!(i8);
109impl_checksum_signed!(i16);
110impl_checksum_signed!(i32);
111impl_checksum_signed!(i64);
112impl_checksum_signed!(i128);
113impl_bytes_len_signed!(i8);
114impl_bytes_len_signed!(i16);
115impl_bytes_len_signed!(i32);
116impl_bytes_len_signed!(i64);
117impl_bytes_len_signed!(i128);
118
119impl FixChecksum for &[u8] {
120 fn checksum(self) -> Wrapping<u8> {
121 self.iter().map(|b| Wrapping(*b)).sum()
122 }
123}
124
125impl FixLength for &[u8] {
126 fn bytes_len(self) -> u32 {
127 self.len() as u32
128 }
129}