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