1#[cfg(test)]
4mod tests;
5
6use crate::{Bitrate, CanFrame, Error, ExtIdentifier, Identifier};
7use defmt::Format;
8
9#[derive(Debug, Eq, PartialEq, Format)]
11#[non_exhaustive]
12pub enum Command {
13 SetupWithBitrate {
14 bitrate: Bitrate,
15 },
16
17 Open,
18
19 Close,
20
21 TxStandard {
22 identifier: Identifier,
23 frame: CanFrame,
24 },
25
26 TxExt {
28 identifier: ExtIdentifier,
29 frame: CanFrame,
30 },
31
32 TxStandardRtr {
33 identifier: Identifier,
34 len: u8,
35 },
36
37 TxExtRtr {
38 identifier: ExtIdentifier,
39 len: u8,
40 },
41
42 ReadStatus,
43 ReadVersion,
44 ReadSerial,
45 SetRxTimestamp {
46 timestamp: bool,
47 },
48}
49
50impl Command {
51 pub const MAX_ENCODED_LEN: usize = 1 + 8 + 1 + 16 + 1; pub fn decode(input: &[u8]) -> Result<Self, Error> {
56 let mut reader = Reader { input };
57
58 let op = reader.read_byte()?;
59 let cmd = match op {
60 b'S' => {
61 let bitrate = match reader.read_byte()? {
62 b'0' => Bitrate::_10kbit,
63 b'1' => Bitrate::_20kbit,
64 b'2' => Bitrate::_50kbit,
65 b'3' => Bitrate::_100kbit,
66 b'4' => Bitrate::_125kbit,
67 b'5' => Bitrate::_250kbit,
68 b'6' => Bitrate::_500kbit,
69 b'7' => Bitrate::_800kbit,
70 b'8' => Bitrate::_1mbit,
71 _ => return Err(Error::decode()),
72 };
73
74 Command::SetupWithBitrate { bitrate }
75 }
76 b'O' => Command::Open,
77 b'C' => Command::Close,
78 b't' => {
79 let identifier = reader.read_hex_identifier()?;
80 let len = reader.read_hex_u4()?;
81 if len > 8 {
82 return Err(Error::decode());
83 }
84 let frame = reader.read_frame(len)?;
85
86 Command::TxStandard { identifier, frame }
87 }
88 b'T' => {
89 let identifier = reader.read_hex_ext_identifier()?;
90 let len = reader.read_hex_u4()?;
91 if len > 8 {
92 return Err(Error::decode());
93 }
94 let frame = reader.read_frame(len)?;
95
96 Command::TxExt { identifier, frame }
97 }
98 b'r' => {
99 let identifier = reader.read_hex_identifier()?;
100 let len = reader.read_hex_u4()?;
101 if len > 8 {
102 return Err(Error::decode());
103 }
104
105 Command::TxStandardRtr { identifier, len }
106 }
107 b'R' => {
108 let identifier = reader.read_hex_ext_identifier()?;
109 let len = reader.read_hex_u4()?;
110 if len > 8 {
111 return Err(Error::decode());
112 }
113
114 Command::TxExtRtr { identifier, len }
115 }
116 b'F' => Command::ReadStatus,
117 b'V' => Command::ReadVersion,
118 b'N' => Command::ReadSerial,
119 b'Z' => {
120 let timestamp = match reader.read_byte()? {
121 b'0' => false,
122 b'1' => true,
123 _ => return Err(Error::decode()),
124 };
125
126 Command::SetRxTimestamp { timestamp }
127 }
128 _ => return Err(Error::decode()),
129 };
130
131 if reader.read_byte()? != b'\r' {
132 return Err(Error::decode());
133 }
134
135 if !reader.input.is_empty() {
137 return Err(Error::decode());
138 }
139
140 Ok(cmd)
141 }
142}
143
144#[derive(Default, Debug)]
149pub struct CommandBuf {
150 bytes: [u8; Command::MAX_ENCODED_LEN],
152 used: u8,
153}
154
155impl CommandBuf {
156 pub const fn new() -> Self {
158 Self {
159 bytes: [0; Command::MAX_ENCODED_LEN],
160 used: 0,
161 }
162 }
163
164 pub fn tail_mut(&mut self) -> &mut [u8] {
169 &mut self.bytes[usize::from(self.used)..]
170 }
171
172 fn is_full(&self) -> bool {
173 usize::from(self.used) == Command::MAX_ENCODED_LEN
174 }
175
176 fn find_cr(&self, start: usize) -> Option<usize> {
177 self.bytes[start..usize::from(self.used)]
178 .iter()
179 .position(|b| *b == b'\r')
180 .map(|pos| pos + start)
181 }
182
183 pub fn advance_by(&mut self, amount: u8) -> impl Iterator<Item = Result<Command, Error>> + '_ {
188 self.used += amount;
189 assert!(usize::from(self.used) <= Command::MAX_ENCODED_LEN);
190
191 CommandIter { buf: self, pos: 0 }
192 }
193}
194
195struct CommandIter<'a> {
196 buf: &'a mut CommandBuf,
197 pos: u8,
198}
199
200impl Iterator for CommandIter<'_> {
201 type Item = Result<Command, Error>;
202
203 fn next(&mut self) -> Option<Self::Item> {
204 let pos = usize::from(self.pos);
205 let end = match self.buf.find_cr(pos) {
206 Some(pos) => pos,
207 None if pos == 0 && self.buf.is_full() => {
208 self.pos = Command::MAX_ENCODED_LEN as u8;
213 return Some(Err(Error::decode()));
214 }
215 None => return None,
216 };
217
218 let cmd = &self.buf.bytes[pos..end + 1];
219 self.pos += cmd.len() as u8;
220
221 Some(Command::decode(cmd))
222 }
223}
224
225impl Drop for CommandIter<'_> {
226 fn drop(&mut self) {
227 let decoded_end = usize::from(self.pos);
228 self.buf.bytes.copy_within(decoded_end.., 0);
229 self.buf.used -= decoded_end as u8;
230 }
231}
232
233#[derive(Eq, PartialEq)]
234struct Reader<'a> {
235 input: &'a [u8],
236}
237
238impl<'a> Reader<'a> {
239 fn read_byte(&mut self) -> Result<u8, Error> {
240 match self.input {
241 [] => Err(Error::eof()),
242 [b, rest @ ..] => {
243 self.input = rest;
244 Ok(*b)
245 }
246 }
247 }
248
249 fn read_hex_digits(&mut self, digits: u8) -> Result<u32, Error> {
250 let mut val = 0;
251
252 for _ in 0..digits {
253 val <<= 4;
254 val |= unhex(self.read_byte()?)? as u32;
255 }
256
257 Ok(val)
258 }
259
260 fn read_hex_u4(&mut self) -> Result<u8, Error> {
261 Ok(self.read_hex_digits(1)? as u8)
262 }
263
264 fn read_hex_u8(&mut self) -> Result<u8, Error> {
265 Ok(self.read_hex_digits(2)? as u8)
266 }
267
268 fn read_hex_identifier(&mut self) -> Result<Identifier, Error> {
269 let raw = self.read_hex_digits(3)? as u16;
270 Identifier::from_raw(raw).ok_or(Error::decode())
271 }
272
273 fn read_hex_ext_identifier(&mut self) -> Result<ExtIdentifier, Error> {
274 let raw = self.read_hex_digits(8)?;
275 ExtIdentifier::from_raw(raw).ok_or(Error::decode())
276 }
277
278 fn read_frame(&mut self, len: u8) -> Result<CanFrame, Error> {
279 assert!(len <= 8);
280
281 let mut frame = CanFrame::new();
282
283 for _ in 0..len {
284 let byte = self.read_hex_u8()?;
285
286 frame.push(byte).unwrap();
288 }
289
290 Ok(frame)
291 }
292}
293
294fn unhex(digit: u8) -> Result<u8, Error> {
295 match digit {
296 b'0'..=b'9' => Ok(digit - b'0'),
297 b'A'..=b'F' => Ok(digit - b'A' + 10),
298 _ => Err(Error::decode()),
299 }
300}