1#![cfg_attr(not(test), no_std)]
4
5mod frame;
6
7use embedded_can::{ExtendedId, Frame as _, Id, StandardId};
8pub use frame::Frame;
9use nom::{
10 branch::alt,
11 bytes::complete::{tag, take},
12 character::complete::{digit1, one_of},
13 combinator::map,
14 error::{Error, ErrorKind},
15 sequence::tuple,
16 Err, IResult,
17};
18
19#[derive(Debug, PartialEq, Eq, Copy, Clone)]
21#[repr(u8)]
22pub enum Bitrate {
23 Rate10kbit = 0,
24 Rate20kbit = 1,
25 Rate50kbit = 2,
26 Rate100kbit = 3,
27 Rate125kbit = 4,
28 Rate250kbit = 5,
29 Rate500kbit = 6,
30 Rate800kbit = 7,
31 Rate1000kbit = 8,
32}
33
34#[derive(Debug, PartialEq, Eq, Copy, Clone)]
36pub struct Setup {
37 pub bitrate: Bitrate,
38}
39
40impl Setup {
41 pub fn new(bitrate: Bitrate) -> Self {
42 Self { bitrate }
43 }
44
45 pub fn try_parse(input: &str) -> IResult<&str, Self> {
47 let (input, (_, bitrate, _)) = tuple((tag("S"), digit1, tag("\r")))(input)?;
48
49 let bitrate = match bitrate {
50 "0" => Bitrate::Rate10kbit,
51 "1" => Bitrate::Rate20kbit,
52 "2" => Bitrate::Rate50kbit,
53 "3" => Bitrate::Rate100kbit,
54 "4" => Bitrate::Rate125kbit,
55 "5" => Bitrate::Rate250kbit,
56 "6" => Bitrate::Rate500kbit,
57 "7" => Bitrate::Rate800kbit,
58 "8" => Bitrate::Rate1000kbit,
59 _ => return Err(Err::Failure(Error::new(input, ErrorKind::Digit))),
60 };
61
62 Ok((input, Self { bitrate }))
63 }
64}
65
66impl core::fmt::Display for Setup {
67 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
68 write!(f, "S{:}\r", self.bitrate as u8)
69 }
70}
71
72#[derive(Debug, PartialEq, Eq, Copy, Clone)]
74pub struct Open {}
75
76impl Open {
77 pub fn new() -> Self {
78 Self {}
79 }
80
81 pub fn try_parse(input: &str) -> IResult<&str, Self> {
83 let (input, _) = tag("O\r")(input)?;
84
85 Ok((input, Self::new()))
86 }
87}
88
89impl core::fmt::Display for Open {
90 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
91 write!(f, "O\r")
92 }
93}
94
95#[derive(Debug, PartialEq, Eq, Copy, Clone)]
97pub struct Close {}
98
99impl Close {
100 pub fn new() -> Self {
101 Self {}
102 }
103
104 pub fn try_parse(input: &str) -> IResult<&str, Self> {
106 let (input, _) = tag("C\r")(input)?;
107
108 Ok((input, Self::new()))
109 }
110}
111
112impl core::fmt::Display for Close {
113 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
114 write!(f, "C\r")
115 }
116}
117
118#[derive(Debug, PartialEq, Eq, Copy, Clone)]
120pub struct Transmit {
121 frame: Frame,
122}
123
124impl Transmit {
125 pub fn new(frame: &impl embedded_can::Frame) -> Self {
126 let frame = if frame.is_remote_frame() {
128 Frame::new_remote(frame.id(), frame.dlc()).unwrap()
129 } else {
130 Frame::new(frame.id(), frame.data()).unwrap()
131 };
132
133 Self { frame }
134 }
135
136 pub fn try_parse(input: &str) -> IResult<&str, Self> {
138 let (input, kind) = one_of("tTrR")(input)?;
139 let (input, id) = match kind {
140 't' | 'r' => {
141 let (input, id_hex) = take(3_usize)(input)?;
142 let id = u16::from_str_radix(id_hex, 16)
143 .map_err(|_| Err::Failure(Error::new(input, ErrorKind::HexDigit)))?;
144 (input, Id::Standard(StandardId::new(id).unwrap()))
145 }
146 'T' | 'R' => {
147 let (input, id_hex) = take(8_usize)(input)?;
148 let id = u32::from_str_radix(id_hex, 16)
149 .map_err(|_| Err::Failure(Error::new(input, ErrorKind::HexDigit)))?;
150 (input, Id::Extended(ExtendedId::new(id).unwrap()))
151 }
152 _ => unreachable!(), };
154
155 let (input, dlc) = take(1_usize)(input)?;
156 let dlc = usize::from_str_radix(dlc, 16)
157 .map_err(|_| Err::Failure(Error::new(input, ErrorKind::HexDigit)))?;
158
159 let (input, data) = if dlc > 0 {
160 take(dlc * 2_usize)(input)?
161 } else {
162 (input, "")
163 };
164
165 let data = if data.is_empty() {
166 [0; 8]
167 } else {
168 let mut array = [0; 8];
169 for i in 0..dlc {
170 array[i] = u8::from_str_radix(&data[i * 2..i * 2 + 2], 16)
171 .map_err(|_| Err::Failure(Error::new(input, ErrorKind::HexDigit)))?;
172 }
173 array
174 };
175
176 let frame = if kind == 't' || kind == 'T' {
177 Frame::new(id, &data[..dlc]).unwrap()
178 } else {
179 Frame::new_remote(id, dlc).unwrap()
180 };
181
182 let (input, _) = tag("\r")(input)?;
183
184 Ok((input, Self::new(&frame)))
185 }
186}
187
188impl core::fmt::Display for Transmit {
189 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
190 let cmd = match (self.frame.is_extended(), self.frame.is_remote_frame()) {
191 (false, false) => 't',
192 (true, false) => 'T',
193 (true, true) => 'R',
194 (false, true) => 'r',
195 };
196
197 match self.frame.id() {
198 Id::Standard(id) => write!(f, "{}{:03X}", cmd, id.as_raw())?,
199 Id::Extended(id) => write!(f, "{}{:08X}", cmd, id.as_raw())?,
200 }
201
202 write!(f, "{}", self.frame.dlc())?;
203
204 if self.frame.is_data_frame() {
205 for byte in self.frame.data() {
206 write!(f, "{:02X}", *byte)?;
207 }
208 }
209
210 write!(f, "\r")?;
211
212 Ok(())
213 }
214}
215
216#[derive(Debug, PartialEq, Eq, Copy, Clone)]
218pub enum Command {
219 Setup(Setup),
220 Open(Open),
221 Close(Close),
222 Transmit(Transmit),
223}
224
225impl Command {
226 pub fn try_parse(input: &str) -> IResult<&str, Self> {
228 alt((
229 map(Setup::try_parse, Command::Setup),
230 map(Open::try_parse, Command::Open),
231 map(Close::try_parse, Command::Close),
232 map(Transmit::try_parse, Command::Transmit),
233 ))(input)
234 }
235}
236
237impl core::fmt::Display for Command {
238 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
239 match self {
240 Command::Setup(setup) => setup.fmt(f),
241 Command::Open(open) => open.fmt(f),
242 Command::Close(close) => close.fmt(f),
243 Command::Transmit(transmit) => transmit.fmt(f),
244 }
245 }
246}
247
248#[cfg(test)]
249mod tests {
250 use super::*;
251 use embedded_can::{ExtendedId, StandardId};
252
253 #[test]
254 fn format_setup() {
255 let setup = Setup::new(Bitrate::Rate10kbit);
256 assert_eq!(format!("{}", setup), "S0\r");
257 }
258
259 #[test]
260 fn parse_setup() {
261 assert_eq!(
262 Setup::try_parse("S0\r"),
263 Ok((
264 "",
265 Setup {
266 bitrate: Bitrate::Rate10kbit
267 }
268 ))
269 );
270
271 assert!(Setup::try_parse("S9\r").is_err());
272 assert!(Setup::try_parse("SF\r").is_err());
273 assert!(Setup::try_parse("S \r").is_err());
274 }
275
276 #[test]
277 fn format_open() {
278 let open = Open::new();
279 assert_eq!(format!("{}", open), "O\r");
280 }
281
282 #[test]
283 fn parse_open() {
284 assert_eq!(Open::try_parse("O\r"), Ok(("", Open {})));
285
286 assert!(Close::try_parse("o\r").is_err());
287 }
288
289 #[test]
290 fn format_close() {
291 let close = Close::new();
292 assert_eq!(format!("{}", close), "C\r");
293 }
294
295 #[test]
296 fn parse_close() {
297 assert_eq!(Close::try_parse("C\r"), Ok(("", Close {})));
298
299 assert!(Close::try_parse("c\r").is_err());
300 }
301
302 #[test]
303 fn format_transmit() {
304 let frame = Frame::new(Id::Standard(StandardId::new(0x123).unwrap()), &[]).unwrap();
305 let transmit = Transmit::new(&frame);
306 assert_eq!(format!("{}", transmit), "t1230\r");
307
308 let frame = Frame::new(
309 Id::Standard(StandardId::new(0x456).unwrap()),
310 &[0x11, 0x22, 0x33],
311 )
312 .unwrap();
313 let transmit = Transmit::new(&frame);
314 assert_eq!(format!("{}", transmit), "t4563112233\r");
315
316 let frame = Frame::new(
317 Id::Extended(ExtendedId::new(0x12ABCDEF).unwrap()),
318 &[0xAA, 0x55],
319 )
320 .unwrap();
321 let transmit = Transmit::new(&frame);
322 assert_eq!(format!("{}", transmit), "T12ABCDEF2AA55\r");
323
324 let frame = Frame::new_remote(Id::Standard(StandardId::new(0x123).unwrap()), 0).unwrap();
325 let transmit = Transmit::new(&frame);
326 assert_eq!(format!("{}", transmit), "r1230\r");
327 }
328
329 #[test]
330 fn parse_transmit() {
331 assert_eq!(
332 Transmit::try_parse("t1230\r"),
333 Ok((
334 "",
335 Transmit::new(
336 &Frame::new(Id::Standard(StandardId::new(0x123).unwrap()), &[]).unwrap()
337 )
338 ))
339 );
340
341 assert_eq!(
342 Transmit::try_parse("t4563112233\r"),
343 Ok((
344 "",
345 Transmit::new(
346 &Frame::new(
347 Id::Standard(StandardId::new(0x456).unwrap()),
348 &[0x11, 0x22, 0x33]
349 )
350 .unwrap()
351 )
352 ))
353 );
354
355 assert_eq!(
356 Transmit::try_parse("T12ABCDEF2AA55\r"),
357 Ok((
358 "",
359 Transmit::new(
360 &Frame::new(
361 Id::Extended(ExtendedId::new(0x12ABCDEF).unwrap()),
362 &[0xAA, 0x55]
363 )
364 .unwrap()
365 )
366 ))
367 );
368
369 assert_eq!(
370 Transmit::try_parse("r1230\r"),
371 Ok((
372 "",
373 Transmit::new(
374 &Frame::new_remote(Id::Standard(StandardId::new(0x123).unwrap()), 0).unwrap()
375 )
376 ))
377 );
378 }
379
380 #[test]
381 fn format_command() {
382 let cmd = Command::Open(Open::new());
383 assert_eq!(format!("{}", cmd), "O\r");
384
385 let cmd = Command::Setup(Setup::new(Bitrate::Rate100kbit));
386 assert_eq!(format!("{}", cmd), "S3\r");
387 }
388
389 #[test]
390 fn parse_command() {
391 let cmd = Command::try_parse("O\r");
392 assert_eq!(cmd, Ok(("", Command::Open(Open::new()))));
393 }
394}