1use super::ids::*;
2use nom::{error::ParseError, number::streaming, IResult, Input};
3
4const BASIC_CODEC_VERSION: u8 = 1;
5
6#[derive(Clone, Debug)]
8pub struct Header {
9 pub service: Service,
10 pub request: u8,
11 pub msg_type: MsgType,
12 pub sequence: u32, }
14
15impl Header {
16 pub fn as_bytes(&self) -> [u8; 8] {
18 let header: u32 = (BASIC_CODEC_VERSION as u32) << 24
19 | ((self.service as u32) << 16)
20 | ((self.request as u32) << 8)
21 | (self.msg_type as u32);
22 let header = header.to_le_bytes();
23
24 let seq = self.sequence.to_le_bytes();
25
26 [
27 header[0], header[1], header[2], header[3], seq[0], seq[1], seq[2], seq[3],
28 ]
29 }
30
31 pub fn parse<I, E: ParseError<I>>(i: I) -> IResult<I, Self, E>
33 where
34 I: Input<Item = u8>,
35 {
36 let (i, header) = streaming::le_u32(i)?;
37 let (i, sequence) = streaming::le_u32(i)?;
38 Ok((
39 i,
40 Self {
41 service: (((header >> 16) & 0xff) as u8).into(),
42 request: ((header >> 8) & 0xff) as u8,
43 msg_type: ((header & 0xff) as u8).into(),
44 sequence,
45 },
46 ))
47 }
48}
49
50#[derive(Clone, Debug)]
52pub struct FrameHeader {
53 pub msg_length: u16,
54 pub crc16: u16,
55}
56
57impl FrameHeader {
58 pub fn new_from_msg(msg: &[u8]) -> Self {
60 Self {
61 msg_length: msg.len() as u16,
62 crc16: crc16(msg),
63 }
64 }
65
66 pub fn as_bytes(&self) -> [u8; 4] {
68 let (l, c) = (self.msg_length.to_le_bytes(), self.crc16.to_le_bytes());
69 [l[0], l[1], c[0], c[1]]
70 }
71
72 pub fn parse<I, E: ParseError<I>>(i: I) -> IResult<I, Self, E>
75 where
76 I: Input<Item = u8>,
77 {
78 let (i, msg_length) = streaming::le_u16(i)?;
79 let (i, crc16) = streaming::le_u16(i)?;
80 Ok((i, Self { msg_length, crc16 }))
81 }
82
83 pub fn check_crc<I, E>(&self, data: I) -> Result<(), super::Err<E>>
85 where
86 I: Input<Item = u8>,
87 {
88 if crc16(data) == self.crc16 {
89 Ok(())
90 } else {
91 Err(super::Err::CRCMismatch)
92 }
93 }
94}
95
96pub(crate) fn crc16<I>(data: I) -> u16
98where
99 I: Input<Item = u8>,
100{
101 let mut crc: u32 = 0xEF4A;
102
103 for b in data.iter_elements() {
104 crc ^= (b as u32) << 8;
105 for _ in 0..8 {
106 let mut temp: u32 = crc << 1;
107 if (crc & 0x8000) != 0 {
108 temp ^= 0x1021;
109 }
110 crc = temp;
111 }
112 }
113
114 crc as u16
115}