1use crate::{Vec, compact, vec};
4use serde::Serialize;
5
6pub trait Numeric: Sized + Default + Copy + Serialize {
8 const LENGTH: usize;
10
11 fn encode(&self) -> Vec<u8>;
13
14 fn decode(value: &[u8]) -> Self;
16
17 fn compact_encode(&self) -> Vec<u8>;
19
20 fn compact_decode(source: &[u8]) -> Self;
22
23 fn as_u64(&self) -> u64;
25
26 fn from_u64(value: u64) -> Self;
28}
29
30macro_rules! impl_numeric {
32 ($(($t:ty, $len:expr)),+) => {
33 $(
34 impl Numeric for $t {
35 const LENGTH: usize = $len;
36
37 fn encode(&self) -> Vec<u8> {
38 let bytes = self.to_le_bytes().to_vec();
39 let end = $len - self.leading_zeros() as usize / 8;
40 if end == 0 {
41 vec![0] } else {
43 bytes[..end].to_vec()
44 }
45 }
46
47 fn decode(source: &[u8]) -> Self {
48 let len = source.len();
49 let mut bytes = [0; $len];
50 bytes[0..len.min($len)].copy_from_slice(source);
51 Self::from_le_bytes(bytes)
52 }
53
54 fn compact_encode(&self) -> Vec<u8> {
55 compact::encode(*self as u64)
56 }
57
58 fn compact_decode(source: &[u8]) -> Self {
59 compact::decode(source) as $t
60 }
61
62 fn as_u64(&self) -> u64 {
63 *self as u64
64 }
65
66 fn from_u64(value: u64) -> Self {
67 value as $t
68 }
69 }
70 )+
71 }
72}
73
74impl_numeric! {
75 (i8, 1),
76 (u8, 1),
77 (i16, 2),
78 (u16, 2),
79 (i32, 4),
80 (u32, 4),
81 (i64, 8),
82 (u64, 8)
83}
84
85#[cfg(test)]
86macro_rules! test_codec {
87 ($t:ty, $source:expr) => {
88 let value = <$t>::from_le_bytes($source);
89 let encoded = value.encode();
90 let decoded = <$t>::decode(&encoded);
91 assert_eq!(value, decoded);
92 assert_eq!(
93 encoded.len(),
94 $source.len() - value.leading_zeros() as usize / 8,
95 );
96 };
97}
98
99#[test]
100fn i8() {
101 let values = vec![-128, -1, 0, 1, 127];
102 for value in values {
103 let encoded = value.encode();
104 let decoded = i8::decode(&encoded);
105 assert_eq!(value, decoded);
106 }
107}
108
109#[test]
110fn u8() {
111 let values = vec![0, 1, 127, 128, 255];
112 for value in values {
113 let encoded = value.encode();
114 let decoded = u8::decode(&encoded);
115 assert_eq!(value, decoded);
116 }
117}
118
119#[test]
120fn i16() {
121 let values = vec![[255, 0], [0, 255]];
122 for source in values {
123 test_codec!(i16, source);
124 }
125}
126
127#[test]
128fn u16() {
129 let values = vec![[255, 0], [0, 255]];
130 for source in values {
131 test_codec!(u16, source);
132 }
133}
134
135#[test]
136fn i32() {
137 let values = vec![
138 [255, 0, 0, 0],
139 [0, 255, 0, 0],
140 [0, 0, 255, 0],
141 [0, 0, 0, 255],
142 ];
143 for source in values {
144 test_codec!(i32, source);
145 }
146}
147
148#[test]
149fn u32() {
150 let values = vec![
151 [255, 0, 0, 0],
152 [0, 255, 0, 0],
153 [0, 0, 255, 0],
154 [0, 0, 0, 255],
155 ];
156 for source in values {
157 test_codec!(u32, source);
158 }
159}
160
161#[test]
162fn i64() {
163 let values = vec![
164 [255, 0, 0, 0, 0, 0, 0, 0],
165 [0, 255, 0, 0, 0, 0, 0, 0],
166 [0, 0, 255, 0, 0, 0, 0, 0],
167 [0, 0, 0, 255, 0, 0, 0, 0],
168 [0, 0, 0, 0, 255, 0, 0, 0],
169 [0, 0, 0, 0, 0, 255, 0, 0],
170 [0, 0, 0, 0, 0, 0, 255, 0],
171 [0, 0, 0, 0, 0, 0, 0, 255],
172 ];
173 for source in values {
174 test_codec!(i64, source);
175 }
176}
177
178#[test]
179fn u64() {
180 let values = vec![
181 [255, 0, 0, 0, 0, 0, 0, 0],
182 [0, 255, 0, 0, 0, 0, 0, 0],
183 [0, 0, 255, 0, 0, 0, 0, 0],
184 [0, 0, 0, 255, 0, 0, 0, 0],
185 [0, 0, 0, 0, 255, 0, 0, 0],
186 [0, 0, 0, 0, 0, 255, 0, 0],
187 [0, 0, 0, 0, 0, 0, 255, 0],
188 [0, 0, 0, 0, 0, 0, 0, 255],
189 ];
190 for source in values {
191 test_codec!(u64, source);
192 }
193}