1use core::convert::TryInto;
6
7use crate::message::RawMessage;
8
9pub type MessageCode = u8;
10pub type ServiceCode = u8;
11pub type NodeId = u8;
12pub type IDSHeaderConfiguration = u8;
13
14#[derive(Clone, Copy, Debug)]
15pub struct IDSConfiguration(pub u8);
16
17#[derive(Clone, Copy, Debug)]
18pub struct HardwareRevision(pub u8);
19
20#[derive(Clone, Copy, Debug)]
21pub struct SoftwareRevision(pub u8);
22
23#[derive(Clone, Copy, Debug)]
24pub struct IDSResponse {
25 pub hw_rev: HardwareRevision,
26 pub sw_rev: SoftwareRevision,
27 pub configuration: IDSConfiguration,
28 pub header: IDSHeaderConfiguration,
29}
30
31#[derive(Clone, Copy, Debug, PartialEq)]
32pub enum ServiceCodeEnum {
33 IDS,
35 NSS,
37 DDS,
39 DUS,
41 SCS,
43 TIS,
45 FPS,
47 STS,
49 FSS,
51 TCS,
53 BSS,
55 NIS,
57 MIS,
59 MCS,
61 CSS,
63 DSS,
65 CUSTOM(u8),
67 UNKNOWN,
68}
69
70impl ServiceCodeEnum {
71 pub fn as_u8(&self) -> u8 {
82 u8::from(*self)
83 }
84}
85
86impl From<ServiceCodeEnum> for u8 {
87 fn from(code: ServiceCodeEnum) -> Self {
97 match code {
98 ServiceCodeEnum::IDS => 0,
99 ServiceCodeEnum::NSS => 1,
100 ServiceCodeEnum::DDS => 2,
101 ServiceCodeEnum::DUS => 3,
102 ServiceCodeEnum::SCS => 4,
103 ServiceCodeEnum::TIS => 5,
104 ServiceCodeEnum::FPS => 6,
105 ServiceCodeEnum::STS => 7,
106 ServiceCodeEnum::FSS => 8,
107 ServiceCodeEnum::TCS => 9,
108 ServiceCodeEnum::BSS => 10,
109 ServiceCodeEnum::NIS => 11,
110 ServiceCodeEnum::MIS => 12,
111 ServiceCodeEnum::MCS => 13,
112 ServiceCodeEnum::CSS => 14,
113 ServiceCodeEnum::DSS => 15,
114 ServiceCodeEnum::UNKNOWN => 0xFF,
115 ServiceCodeEnum::CUSTOM(id) => id,
116 }
117 }
118}
119
120impl From<u8> for ServiceCodeEnum {
121 fn from(code: u8) -> Self {
122 match code {
123 code if code == ServiceCodeEnum::IDS.as_u8() => ServiceCodeEnum::IDS,
124 code if code == ServiceCodeEnum::NSS.as_u8() => ServiceCodeEnum::NSS,
125 code if code == ServiceCodeEnum::DDS.as_u8() => ServiceCodeEnum::DDS,
126 code if code == ServiceCodeEnum::DUS.as_u8() => ServiceCodeEnum::DUS,
127 code if code == ServiceCodeEnum::SCS.as_u8() => ServiceCodeEnum::SCS,
128 code if code == ServiceCodeEnum::TIS.as_u8() => ServiceCodeEnum::TIS,
129 code if code == ServiceCodeEnum::FPS.as_u8() => ServiceCodeEnum::FPS,
130 code if code == ServiceCodeEnum::STS.as_u8() => ServiceCodeEnum::STS,
131 code if code == ServiceCodeEnum::FSS.as_u8() => ServiceCodeEnum::FSS,
132 code if code == ServiceCodeEnum::TCS.as_u8() => ServiceCodeEnum::TCS,
133 code if code == ServiceCodeEnum::BSS.as_u8() => ServiceCodeEnum::BSS,
134 code if code == ServiceCodeEnum::NIS.as_u8() => ServiceCodeEnum::NIS,
135 code if code == ServiceCodeEnum::MIS.as_u8() => ServiceCodeEnum::MIS,
136 code if code == ServiceCodeEnum::MCS.as_u8() => ServiceCodeEnum::MCS,
137 code if code == ServiceCodeEnum::CSS.as_u8() => ServiceCodeEnum::CSS,
138 code if code == ServiceCodeEnum::DSS.as_u8() => ServiceCodeEnum::DSS,
139 code if (100..=254).contains(&code) => ServiceCodeEnum::CUSTOM(code),
140 _ => ServiceCodeEnum::UNKNOWN,
141 }
142 }
143}
144
145#[derive(Clone, Copy, Debug, PartialEq)]
146pub enum MessageType {
147 EED(u16),
150 NSH(u16),
153 UDH(u16),
156 NOD(u16),
159 UDL(u16),
162 DSD(u16),
165 NSL(u16),
168 INVALID,
169}
170
171impl MessageType {
172 pub fn id(&self) -> u16 {
173 match *self {
174 MessageType::EED(id) => {
175 if id > 0x7F {
176 panic!("CANaerospace: Invalid Message ID({}) for EED Message.", id);
177 }
178 id
179 }
180 MessageType::NSH(id) => {
181 if !(0x80..=0xC7).contains(&id) {
182 panic!("CANaerospace: Invalid Message ID({}) for NSH Message.", id);
183 }
184 id
185 }
186 MessageType::UDH(id) => {
187 if !(0xC8..=0x12B).contains(&id) {
188 panic!("CANaerospace: Invalid Message ID({}) for UDH Message.", id);
189 }
190 id
191 }
192 MessageType::NOD(id) => {
193 if !(0x12C..=0x707).contains(&id) {
194 panic!("CANaerospace: Invalid Message ID({}) for NOD Message.", id);
195 }
196 id
197 }
198 MessageType::UDL(id) => {
199 if !(0x708..=0x76B).contains(&id) {
200 panic!("CANaerospace: Invalid Message ID({}) for UDL Message.", id);
201 }
202 id
203 }
204 MessageType::DSD(id) => {
205 if !(0x76C..=0x7CF).contains(&id) {
206 panic!("CANaerospace: Invalid Message ID({}) for DSD Message.", id);
207 }
208 id
209 }
210 MessageType::NSL(id) => {
211 if !(0x7D0..=0x7EF).contains(&id) {
212 panic!("CANaerospace: Invalid Message ID({}) for NSL Message.", id);
213 }
214 id
215 }
216 MessageType::INVALID => u16::MAX,
217 }
218 }
219}
220
221impl From<u16> for MessageType {
222 fn from(raw_id: u16) -> Self {
223 match raw_id {
224 0..=127 => MessageType::EED(raw_id),
225 128..=199 => MessageType::NSH(raw_id),
226 200..=299 => MessageType::UDH(raw_id),
227 300..=1799 => MessageType::NOD(raw_id),
228 1800..=1899 => MessageType::UDL(raw_id),
229 1900..=1999 => MessageType::DSD(raw_id),
230 2000..=2031 => MessageType::NSL(raw_id),
231 _ => MessageType::INVALID,
232 }
233 }
234}
235
236#[derive(Clone, Copy, Debug, PartialEq)]
237pub enum DataType {
238 NODATA,
239 ERROR(u32),
240 FLOAT(f32),
241 LONG(i32),
242 ULONG(u32),
243 BLONG(u32),
244 SHORT(i16),
245 USHORT(u16),
246 BSHORT(u16),
247 CHAR(i8),
248 UCHAR(u8),
249 BCHAR(u8),
250 SHORT2(i16, i16),
251 USHORT2(u16, u16),
252 BSHORT2(u16, u16),
253 CHAR4(i8, i8, i8, i8),
254 UCHAR4(u8, u8, u8, u8),
255 BCHAR4(u8, u8, u8, u8),
256 CHAR2(i8, i8),
257 UCHAR2(u8, u8),
258 BCHAR2(u8, u8),
259 MEMID(u32),
260 CHKSUM(u32),
261 ACHAR(u8),
262 ACHAR2(u8, u8),
263 ACHAR4(u8, u8, u8, u8),
264 CHAR3(i8, i8, i8),
265 UCHAR3(u8, u8, u8),
266 BCHAR3(u8, u8, u8),
267 ACHAR3(u8, u8, u8),
268 DOUBLEH(u32),
269 DOUBLEL(u32),
270 RESVD(u32),
271 UDEF { value: u32, type_id: u8 },
272}
273
274impl DataType {
275 pub fn type_id(&self) -> u8 {
276 match *self {
277 DataType::NODATA => 0x0,
278 DataType::ERROR(_) => 0x1,
279 DataType::FLOAT(_) => 0x2,
280 DataType::LONG(_) => 0x3,
281 DataType::ULONG(_) => 0x4,
282 DataType::BLONG(_) => 0x5,
283 DataType::SHORT(_) => 0x6,
284 DataType::USHORT(_) => 0x7,
285 DataType::BSHORT(_) => 0x8,
286 DataType::CHAR(_) => 0x9,
287 DataType::UCHAR(_) => 0xA,
288 DataType::BCHAR(_) => 0xB,
289 DataType::SHORT2(_, _) => 0xC,
290 DataType::USHORT2(_, _) => 0xD,
291 DataType::BSHORT2(_, _) => 0xE,
292 DataType::CHAR4(_, _, _, _) => 0xF,
293 DataType::UCHAR4(_, _, _, _) => 0x10,
294 DataType::BCHAR4(_, _, _, _) => 0x11,
295 DataType::CHAR2(_, _) => 0x12,
296 DataType::UCHAR2(_, _) => 0x13,
297 DataType::BCHAR2(_, _) => 0x14,
298 DataType::MEMID(_) => 0x15,
299 DataType::CHKSUM(_) => 0x16,
300 DataType::ACHAR(_) => 0x17,
301 DataType::ACHAR2(_, _) => 0x18,
302 DataType::ACHAR4(_, _, _, _) => 0x19,
303 DataType::CHAR3(_, _, _) => 0x1A,
304 DataType::UCHAR3(_, _, _) => 0x1B,
305 DataType::BCHAR3(_, _, _) => 0x1C,
306 DataType::ACHAR3(_, _, _) => 0x1D,
307 DataType::DOUBLEH(_) => 0x1E,
308 DataType::DOUBLEL(_) => 0x1F,
309 DataType::RESVD(_) => 0x20,
310 DataType::UDEF { value: _, type_id } => type_id,
311 }
312 }
313
314 pub fn is_empty(&self) -> bool {
315 *self == DataType::NODATA
316 }
317
318 pub fn len(&self) -> u8 {
319 match *self {
320 DataType::NODATA | DataType::RESVD(_) => 0,
321
322 DataType::ERROR(_)
323 | DataType::FLOAT(_)
324 | DataType::LONG(_)
325 | DataType::ULONG(_)
326 | DataType::BLONG(_)
327 | DataType::SHORT2(_, _)
328 | DataType::USHORT2(_, _)
329 | DataType::BSHORT2(_, _)
330 | DataType::CHAR4(_, _, _, _)
331 | DataType::UCHAR4(_, _, _, _)
332 | DataType::BCHAR4(_, _, _, _)
333 | DataType::MEMID(_)
334 | DataType::CHKSUM(_)
335 | DataType::ACHAR4(_, _, _, _)
336 | DataType::DOUBLEH(_)
337 | DataType::DOUBLEL(_) => 4,
338
339 DataType::SHORT(_)
340 | DataType::USHORT(_)
341 | DataType::BSHORT(_)
342 | DataType::CHAR2(_, _)
343 | DataType::UCHAR2(_, _)
344 | DataType::BCHAR2(_, _)
345 | DataType::ACHAR2(_, _) => 2,
346
347 DataType::CHAR(_) | DataType::UCHAR(_) | DataType::BCHAR(_) | DataType::ACHAR(_) => 1,
348
349 DataType::CHAR3(_, _, _)
350 | DataType::UCHAR3(_, _, _)
351 | DataType::BCHAR3(_, _, _)
352 | DataType::ACHAR3(_, _, _) => 3,
353
354 DataType::UDEF {
355 value: _,
356 type_id: _,
357 } => 4,
358 }
359 }
360
361 pub fn to_be_bytes(self) -> [u8; 4] {
362 match self {
363 DataType::NODATA => [0, 0, 0, 0],
364 DataType::ERROR(d) => d.to_be_bytes(),
365 DataType::FLOAT(d) => d.to_be_bytes(),
366 DataType::LONG(d) => d.to_be_bytes(),
367 DataType::ULONG(d) => d.to_be_bytes(),
368 DataType::BLONG(d) => d.to_be_bytes(),
369 DataType::SHORT(d) => {
370 let d_bytes = d.to_be_bytes();
371 [d_bytes[0], d_bytes[1], 0, 0]
372 }
373 DataType::USHORT(d) | DataType::BSHORT(d) => {
374 let d_bytes = d.to_be_bytes();
375 [d_bytes[0], d_bytes[1], 0, 0]
376 }
377 DataType::CHAR(d) => [d as u8, 0, 0, 0],
378 DataType::UCHAR(d) => [d, 0, 0, 0],
379 DataType::BCHAR(d) => [d, 0, 0, 0],
380 DataType::SHORT2(a, b) => {
381 let a_bytes = a.to_be_bytes();
382 let b_bytes = b.to_be_bytes();
383 [a_bytes[0], a_bytes[1], b_bytes[0], b_bytes[1]]
384 }
385 DataType::USHORT2(a, b) => {
386 let a_bytes = a.to_be_bytes();
387 let b_bytes = b.to_be_bytes();
388 [a_bytes[0], a_bytes[1], b_bytes[0], b_bytes[1]]
389 }
390 DataType::BSHORT2(a, b) => {
391 let a_bytes = a.to_be_bytes();
392 let b_bytes = b.to_be_bytes();
393 [a_bytes[0], a_bytes[1], b_bytes[0], b_bytes[1]]
394 }
395 DataType::CHAR4(a, b, c, d) => [a as u8, b as u8, c as u8, d as u8],
396 DataType::UCHAR4(a, b, c, d) => [a as u8, b as u8, c as u8, d as u8],
397 DataType::BCHAR4(a, b, c, d) => [a as u8, b as u8, c as u8, d as u8],
398 DataType::CHAR2(a, b) => [a as u8, b as u8, 0, 0],
399 DataType::UCHAR2(a, b) => [a as u8, b as u8, 0, 0],
400 DataType::BCHAR2(a, b) => [a as u8, b as u8, 0, 0],
401 DataType::MEMID(d) => d.to_be_bytes(),
402 DataType::CHKSUM(d) => d.to_be_bytes(),
403 DataType::ACHAR(a) => [a, 0, 0, 0],
404 DataType::ACHAR2(a, b) => [a, b, 0, 0],
405 DataType::ACHAR4(a, b, c, d) => [a, b, c, d],
406 DataType::CHAR3(a, b, c) => [a as u8, b as u8, c as u8, 0],
407 DataType::UCHAR3(a, b, c) => [a, b, c, 0],
408 DataType::BCHAR3(a, b, c) => [a, b, c, 0],
409 DataType::ACHAR3(a, b, c) => [a, b, c, 0],
410 DataType::DOUBLEH(d) => d.to_be_bytes(),
411 DataType::DOUBLEL(d) => d.to_be_bytes(),
412 DataType::RESVD(d) => d.to_be_bytes(),
413 DataType::UDEF { value, type_id: _ } => value.to_be_bytes(),
414 }
415 }
416}
417
418fn as_u32(arr: &[u8]) -> u32 {
419 u32::from_be_bytes(arr[..4].try_into().unwrap())
420}
421
422fn as_u16(arr: &[u8]) -> u16 {
423 u16::from_be_bytes(arr[..2].try_into().unwrap())
424}
425
426impl From<(u8, &[u8])> for DataType {
427 fn from(data: (u8, &[u8])) -> Self {
428 let (t, arr) = data;
429 match t {
430 0x0 => DataType::NODATA,
431 0x1 => DataType::ERROR(as_u32(arr)),
432 0x2 => DataType::FLOAT(as_u32(arr) as f32),
433 0x3 => DataType::LONG(as_u32(arr) as i32),
434 0x4 => DataType::ULONG(as_u32(arr)),
435 0x5 => DataType::BLONG(as_u32(arr)),
436 0x6 => DataType::SHORT(as_u16(arr) as i16),
437 0x7 => DataType::USHORT(as_u16(arr)),
438 0x8 => DataType::BSHORT(as_u16(arr)),
439 0x9 => DataType::CHAR(arr[0] as i8),
440 0xA => DataType::UCHAR(arr[0] as u8),
441 0xB => DataType::BCHAR(arr[0] as u8),
442 0xC => DataType::SHORT2(as_u16(arr) as i16, as_u16(&arr[2..]) as i16),
443 0xD => DataType::USHORT2(as_u16(arr), as_u16(arr)),
444 0xE => DataType::BSHORT2(as_u16(arr), as_u16(&arr[2..])),
445 0xF => DataType::CHAR4(arr[0] as i8, arr[1] as i8, arr[2] as i8, arr[3] as i8),
446 0x10 => DataType::UCHAR4(arr[0], arr[1], arr[2], arr[3]),
447 0x11 => DataType::BCHAR4(arr[0], arr[1], arr[2], arr[3]),
448 0x12 => DataType::CHAR2(arr[0] as i8, arr[1] as i8),
449 0x13 => DataType::UCHAR2(arr[0], arr[1]),
450 0x14 => DataType::BCHAR2(arr[0], arr[1]),
451 0x15 => DataType::MEMID(as_u32(arr)),
452 0x16 => DataType::CHKSUM(as_u32(arr)),
453 0x17 => DataType::ACHAR(arr[0]),
454 0x18 => DataType::ACHAR2(arr[0], arr[1]),
455 0x19 => DataType::ACHAR4(arr[0], arr[1], arr[2], arr[3]),
456 0x1A => DataType::CHAR3(arr[0] as i8, arr[1] as i8, arr[2] as i8),
457 0x1B => DataType::UCHAR3(arr[0], arr[1], arr[2]),
458 0x1C => DataType::BCHAR3(arr[0], arr[1], arr[2]),
459 0x1D => DataType::ACHAR3(arr[0], arr[1], arr[2]),
460 0x1E => DataType::DOUBLEH(as_u32(arr)),
461 0x1F => DataType::DOUBLEL(as_u32(arr)),
462 0x20 => DataType::RESVD(as_u32(arr)),
463 _ => DataType::UDEF {
464 value: as_u32(arr),
465 type_id: t,
466 },
467 }
468 }
469}
470
471impl From<&RawMessage> for DataType {
472 fn from(message: &RawMessage) -> Self {
473 DataType::from((message.data_type, &message.payload.data[..]))
474 }
475}