1use crate::MAX_ID_BYTE_SIZE;
2
3pub mod decode;
4pub mod encode;
5
6#[repr(u8)]
7#[derive(Debug, Copy, Clone)]
8enum MessageType {
9 BasicId = 0,
10 Location = 1,
11 Auth = 2,
12 Selfid = 3,
13 System = 4,
14 OperatorId = 5,
15 MessagePack = 0xF,
16
17 Invalid,
18}
19
20impl From<u8> for MessageType {
21 fn from(value: u8) -> Self {
22 match value {
23 0 => MessageType::BasicId,
24 1 => MessageType::Location,
25 2 => MessageType::Auth,
26 3 => MessageType::Selfid,
27 4 => MessageType::System,
28 5 => MessageType::OperatorId,
29 0xF => MessageType::MessagePack,
30
31 _ => MessageType::Invalid,
32 }
33 }
34}
35
36pub fn copy_to_id(slice: &[u8]) -> [u8; 20] {
37 let mut buffer = [0u8; MAX_ID_BYTE_SIZE];
38 let max = if slice.len() <= MAX_ID_BYTE_SIZE {
39 slice.len()
40 } else {
41 MAX_ID_BYTE_SIZE
42 };
43 buffer[0..max].copy_from_slice(&slice[0..max]);
44 buffer
45}
46
47#[macro_export]
48macro_rules! bitmask {
49 ($lo:literal, $hi:literal) => {{
50 let mut pattern = 1;
51
52 for _ in 0..($hi - $lo) {
53 pattern = (pattern << 1) + 1;
54 }
55
56 for _ in 0..$lo {
57 pattern <<= 1;
58 }
59
60 pattern
61 }};
62}
63
64#[macro_export]
70macro_rules! get_bytes {
71 ($buf:expr, $off:expr, 1) => {{
72 $buf[$off]
73 }};
74
75 ($buf:expr, $off:expr, 2) => {{
76 [$buf[$off], $buf[$off + 1]]
77 }};
78
79 ($buf:expr, $off:expr, 3) => {{
80 [$buf[$off], $buf[$off + 1], $buf[$off + 2]]
81 }};
82
83 ($buf:expr, $off:expr, 4) => {{
84 [$buf[$off], $buf[$off + 1], $buf[$off + 2], $buf[$off + 3]]
85 }};
86
87 ($buf:expr, $off:expr, $len:expr) => {{
88 &$buf[$off..($off + $len)]
89 }};
90}
91
92#[macro_export]
97macro_rules! get_bits {
98 ($num:expr, $hi:literal..$lo:literal) => {{
99 let p = $crate::bitmask!($lo, $hi);
100 ($num & p) >> $lo
101 }};
102}
103
104#[macro_export]
105macro_rules! put_bits {
106 ($num:expr, $hi:literal..$lo:literal) => {{
107 let p = $crate::bitmask!($lo, $hi);
108 ($num & p) >> $lo
109 }};
110}
111
112#[cfg(test)]
113mod test {
114 use chrono::{SubsecRound, Utc};
115
116 use crate::{
117 codec::{copy_to_id, decode, encode},
118 data::{
119 basic_id::BasicId, location::Location, operator_id::OperatorId, system::System,
120 RemoteIDMessage,
121 },
122 };
123
124 #[test]
125 fn test_get_bits_trivial() {
126 assert_eq!(get_bits!(0b0000, 1..0), 0);
127 assert_eq!(get_bits!(0b0000, 2..0), 0);
128 assert_eq!(get_bits!(0b0000, 3..0), 0);
129 assert_eq!(get_bits!(0b0000, 4..0), 0);
130 }
131
132 #[test]
133 fn test_get_bits_all_ones() {
134 assert_eq!(get_bits!(0b1111, 0..0), 1);
135 assert_eq!(get_bits!(0b1111, 1..0), 3);
136 assert_eq!(get_bits!(0b1111, 2..0), 7);
137 assert_eq!(get_bits!(0b1111, 3..0), 15);
138
139 assert_eq!(get_bits!(0b1111, 1..1), 1);
140 assert_eq!(get_bits!(0b1111, 2..1), 3);
141 assert_eq!(get_bits!(0b1111, 3..1), 7);
142
143 assert_eq!(get_bits!(0b1111, 2..2), 1);
144 assert_eq!(get_bits!(0b1111, 3..2), 3);
145
146 assert_eq!(get_bits!(0b1111_1111, 3..3), 1);
147 assert_eq!(get_bits!(0b1111_1111, 4..3), 3);
148 assert_eq!(get_bits!(0b1111_1111, 5..3), 7);
149
150 assert_eq!(get_bits!(0b1111_1111, 7..7), 1);
151 assert_eq!(get_bits!(0b1111_1111, 8..8), 0);
152 assert_eq!(get_bits!(0b1111_1111, 9..8), 0);
153 }
154
155 #[test]
156 fn test_get_bits_x() {
157 let n = 0b0001_1100;
158 assert_eq!(get_bits!(n, 4..2), (n & 0b0001_1100) >> 2);
159
160 let n = 34;
161 assert_eq!(get_bits!(n, 7..3), (n & 0b1111_1000) >> 3);
162 }
163
164 #[test]
165 fn test_bitmask_from_0() {
166 assert_eq!(bitmask!(0, 0), 1);
167 assert_eq!(bitmask!(0, 1), 3);
168 assert_eq!(bitmask!(0, 2), 7);
169 assert_eq!(bitmask!(0, 3), 15);
170 assert_eq!(bitmask!(0, 4), 31);
171 assert_eq!(bitmask!(0, 5), 63);
172 assert_eq!(bitmask!(0, 6), 127);
173 assert_eq!(bitmask!(0, 7), 255);
174 }
175
176 #[test]
177 fn test_bitmask_one_bit() {
178 assert_eq!(bitmask!(1, 1), 2);
179 assert_eq!(bitmask!(2, 2), 4);
180 assert_eq!(bitmask!(3, 3), 8);
181 assert_eq!(bitmask!(4, 4), 16);
182 assert_eq!(bitmask!(5, 5), 32);
183 }
184
185 #[test]
186 fn test_bitmask_two_bits() {
187 assert_eq!(bitmask!(1, 2), 6);
188 assert_eq!(bitmask!(2, 3), 12);
189 assert_eq!(bitmask!(3, 4), 24);
190 assert_eq!(bitmask!(4, 5), 48);
191 }
192
193 #[test]
194 fn test_bitmask_three_bits() {
195 assert_eq!(bitmask!(1, 3), 14);
196 assert_eq!(bitmask!(2, 4), 28);
197 assert_eq!(bitmask!(3, 5), 56);
198 assert_eq!(bitmask!(4, 6), 112);
199 }
200
201 extern crate std;
202 #[test]
203 fn test_bitmask_xxx() {
204 let p = bitmask!(0, 3);
205 std::dbg!(p);
206 }
207
208 #[test]
209 fn test_recode_basic_id() {
210 let basic_id = RemoteIDMessage::BasicID(BasicId {
211 id_type: crate::data::basic_id::IdType::None,
212 ua_type: crate::data::basic_id::UAType::Aeroplane,
213 uas_id: copy_to_id("1\0".as_bytes()),
214 });
215
216 let mut buf = [0u8; 22];
217 encode::to_message_buffer(&basic_id, &mut buf);
218 let msg = decode::from_message_buffer(&buf).unwrap();
219 std::dbg!(&msg);
220 assert_eq!(basic_id, msg);
221 }
222
223 #[test]
224 fn test_recode_location() {
225 let location = RemoteIDMessage::Location(Location {
226 operational_status: crate::data::location::OperationalStatus::Undeclared,
227 height_type: crate::data::location::HeightType::AboveGroundLevel,
228 speed: 4.0,
229 vertical_speed: 2.0,
230 pressure_altitude: 3.0,
231 geodetic_altitude: 4.0,
232 track_direction: 5,
233 horizontal_accuracy: crate::data::location::HorizontalAccuracy::LessThan_10_NM,
234 vertical_accuracy: crate::data::location::VerticalAccuracy::LessThan_10_m,
235 latidute: 6.0,
236 longitude: 7.0,
237 height: 8.0,
238 baro_altitude_accuracy: crate::data::location::VerticalAccuracy::LessThan_10_m,
239 speed_accuracy: crate::data::location::SpeedAccuracy::LessThan_10_mps,
240 timestamp: 9.0,
241 timestamp_accuracy: None,
242 });
243
244 let mut buf = [0u8; 25];
245 encode::to_message_buffer(&location, &mut buf);
246
247 let msg = decode::from_message_buffer(&buf).unwrap();
248 std::dbg!(&msg);
249 assert_eq!(location, msg);
250 }
251
252 #[test]
253 fn test_recode_operator_id() {
254 let location = RemoteIDMessage::OperatorId(OperatorId {
255 id_type: crate::data::operator_id::OperatorIdType::Unknown(99),
256 operator_id: copy_to_id("1\0".as_bytes()),
257 });
258
259 let mut buf = [0u8; 25];
260 encode::to_message_buffer(&location, &mut buf);
261 let msg = decode::from_message_buffer(&buf).unwrap();
262
263 assert_eq!(location, msg);
264 }
265
266 #[test]
267 fn test_recode_system() {
268 let location = RemoteIDMessage::System(System {
269 classification_type: crate::data::system::ClassificationType::EuropeanUnion,
270 operator_location_type: crate::data::system::OperatorLocationType::Fixed,
271 operator_latidute: 10.0,
272 operator_longitude: 10.0,
273 area_count: 11,
274 area_radius: 1230.0,
275 area_ceiling: 1234.0,
276 area_floor: 1234.0,
277 ua_classification: crate::data::system::UaClassification {
278 category: crate::data::system::UaCategory::Certified,
279 class: crate::data::system::UaClass::Class0,
280 },
281 operator_altitude: 123.0,
282 timestamp: Utc::now().trunc_subsecs(0),
283 });
284
285 let mut buf = [0u8; 25];
286 encode::to_message_buffer(&location, &mut buf);
287 let msg = decode::from_message_buffer(&buf).unwrap();
288
289 assert_eq!(location, msg);
290 }
291}