1use crate::{
33 frame::Frame,
34 id::{id_from_raw, FdFlags},
35 CanAnyFrame, CanDataFrame, CanFdFrame, CanFrame, CanRemoteFrame, ConstructionError,
36};
37use embedded_can::Frame as EmbeddedFrame;
38use hex::FromHex;
39use itertools::Itertools;
40use libc::canid_t;
41use std::{
42 fmt,
43 fs::File,
44 io::{self, BufRead, BufReader},
45 path::Path,
46};
47use thiserror::Error;
48
49#[derive(Error, Debug)]
51pub enum ParseError {
52 #[error(transparent)]
54 Io(#[from] io::Error),
55 #[error("Unexpected end of line")]
57 UnexpectedEndOfLine,
58 #[error("Invalid timestamp")]
60 InvalidTimestamp,
61 #[error("Invalid device name")]
63 InvalidDeviceName,
64 #[error("Invalid CAN frame")]
66 InvalidCanFrame,
67 #[error(transparent)]
69 ConstructionError(#[from] ConstructionError),
70}
71
72#[derive(Debug, Clone)]
75pub struct CanDumpRecord {
76 pub t_us: u64,
78 pub device: String,
80 pub frame: CanAnyFrame,
82}
83
84impl fmt::Display for CanDumpRecord {
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 write!(
87 f,
88 "({:.6}) {} {:03X}",
89 1.0e-6 * self.t_us as f64,
90 self.device,
91 self.frame.raw_id()
92 )?;
93
94 use CanAnyFrame::*;
95 match self.frame {
96 Remote(frame) if frame.len() == 0 => f.write_str("#R"),
97 Remote(frame) => write!(f, "#R{}", frame.dlc()),
98 Error(_frame) => f.write_str(""),
99 Normal(frame) => {
100 let mut parts = frame.data().iter().map(|v| format!("{:02X}", v));
101 write!(f, "#{}", parts.join(""))
102 }
103 Fd(frame) => {
104 let mut parts = frame.data().iter().map(|v| format!("{:02X}", v));
105 write!(f, "##{}", parts.join(""))
106 }
107 }
108 }
109}
110
111#[derive(Debug)]
115pub struct Reader<R> {
117 rdr: R,
119 buf: String,
121}
122
123impl<R: io::Read> Reader<R> {
124 pub fn from_reader(rdr: R) -> Reader<BufReader<R>> {
126 Reader {
127 rdr: BufReader::new(rdr),
128 buf: String::with_capacity(256),
129 }
130 }
131}
132
133impl Reader<File> {
134 pub fn from_file<P: AsRef<Path>>(path: P) -> io::Result<Reader<BufReader<File>>> {
136 Ok(Reader::from_reader(File::open(path)?))
137 }
138}
139
140impl<R: BufRead> Reader<R> {
141 #[deprecated(since = "3.5.0", note = "Use `iter()`")]
143 pub fn records(&mut self) -> CanDumpRecords<R> {
144 CanDumpRecords { src: self }
145 }
146
147 pub fn next_record(&mut self) -> Result<Option<CanDumpRecord>, ParseError> {
149 self.buf.clear();
150 let nread = self.rdr.read_line(&mut self.buf)?;
151
152 if nread == 0 {
154 return Ok(None);
155 }
156
157 let line = self.buf[..nread].trim();
158 let mut field_iter = line.split(' ');
159
160 let ts = field_iter.next().ok_or(ParseError::UnexpectedEndOfLine)?;
162
163 if ts.len() < 3 || !ts.starts_with('(') || !ts.ends_with(')') {
164 return Err(ParseError::InvalidTimestamp);
165 }
166
167 let ts = &ts[1..ts.len() - 1];
168
169 let t_us = match ts.split_once('.') {
170 Some((num, mant)) => {
171 let num = num
172 .parse::<u64>()
173 .map_err(|_| ParseError::InvalidTimestamp)?;
174 let mant = mant
175 .parse::<u64>()
176 .map_err(|_| ParseError::InvalidTimestamp)?;
177 num.saturating_mul(1_000_000).saturating_add(mant)
178 }
179 _ => return Err(ParseError::InvalidTimestamp),
180 };
181
182 let device = field_iter
184 .next()
185 .ok_or(ParseError::UnexpectedEndOfLine)?
186 .to_string();
187
188 let can_raw = field_iter.next().ok_or(ParseError::UnexpectedEndOfLine)?;
190
191 let (can_id_str, mut can_data) = match can_raw.split_once('#') {
192 Some((id, data)) => (id, data),
193 _ => return Err(ParseError::InvalidCanFrame),
194 };
195
196 let can_id = canid_t::from_str_radix(can_id_str, 16)
198 .ok()
199 .and_then(id_from_raw)
200 .ok_or(ParseError::InvalidCanFrame)?;
201
202 let frame: CanAnyFrame = if can_data.starts_with('#') {
209 let fd_flags = can_data
210 .get(1..2)
211 .and_then(|s| u8::from_str_radix(s, 16).ok())
212 .map(FdFlags::from_bits_truncate)
213 .ok_or(ParseError::InvalidCanFrame)?;
214 Vec::from_hex(&can_data[2..])
215 .ok()
216 .and_then(|data| CanFdFrame::with_flags(can_id, &data, fd_flags))
217 .map(CanAnyFrame::Fd)
218 } else if can_data.starts_with('R') {
219 can_data = &can_data[1..];
220 let rlen = can_data.parse::<usize>().unwrap_or(0);
221 CanRemoteFrame::new_remote(can_id, rlen)
222 .map(CanFrame::Remote)
223 .map(CanAnyFrame::from)
224 } else {
225 Vec::from_hex(can_data)
226 .ok()
227 .and_then(|data| CanDataFrame::new(can_id, &data))
228 .map(CanFrame::Data)
229 .map(CanAnyFrame::from)
230 }
231 .ok_or(ParseError::InvalidCanFrame)?;
232
233 Ok(Some(CanDumpRecord {
234 t_us,
235 device,
236 frame,
237 }))
238 }
239}
240
241impl<R: BufRead> Iterator for Reader<R> {
242 type Item = Result<CanDumpRecord, ParseError>;
243
244 fn next(&mut self) -> Option<Self::Item> {
245 match self.next_record() {
247 Ok(Some(rec)) => Some(Ok(rec)),
248 Ok(None) => None,
249 Err(e) => Some(Err(e)),
250 }
251 }
252}
253
254#[derive(Debug)]
256pub struct CanDumpRecords<'a, R: 'a> {
257 src: &'a mut Reader<R>,
258}
259
260impl<R: io::Read> Iterator for CanDumpRecords<'_, BufReader<R>> {
261 type Item = Result<(u64, CanAnyFrame), ParseError>;
262
263 fn next(&mut self) -> Option<Self::Item> {
264 match self.src.next_record() {
266 Ok(Some(CanDumpRecord { t_us, frame, .. })) => Some(Ok((t_us, frame))),
267 Ok(None) => None,
268 Err(e) => Some(Err(e)),
269 }
270 }
271}
272
273#[cfg(test)]
276mod test {
277 use super::*;
278 use crate::{CanAnyFrame, Frame};
279 use embedded_can::Frame as EmbeddedFrame;
280
281 #[test]
282 fn test_simple_example() {
283 let input: &[u8] = b"(1469439874.299591) can1 080#\n\
284 (1469439874.299654) can1 701#7F";
285
286 let mut reader = Reader::from_reader(input);
287
288 let rec1 = reader.next_record().unwrap().unwrap();
289
290 assert_eq!(rec1.t_us, 1469439874299591);
291 assert_eq!(rec1.device, "can1");
292
293 if let CanAnyFrame::Normal(frame) = rec1.frame {
294 assert_eq!(frame.raw_id(), 0x080);
295 assert!(!frame.is_remote_frame());
296 assert!(!frame.is_error_frame());
297 assert!(!frame.is_extended());
298 assert_eq!(frame.data(), &[]);
299 } else {
300 panic!("Expected Normal frame, got FD");
301 }
302
303 let rec2 = reader.next_record().unwrap().unwrap();
304 assert_eq!(rec2.t_us, 1469439874299654);
305 assert_eq!(rec2.device, "can1");
306
307 if let CanAnyFrame::Normal(frame) = rec2.frame {
308 assert_eq!(frame.raw_id(), 0x701);
309 assert!(!frame.is_remote_frame());
310 assert!(!frame.is_error_frame());
311 assert!(!frame.is_extended());
312 assert_eq!(frame.data(), &[0x7F]);
313 } else {
314 panic!("Expected Normal frame, got FD");
315 }
316
317 assert!(reader.next_record().unwrap().is_none());
318 }
319
320 #[test]
321 fn test_extended_example() {
322 let input: &[u8] = b"(1469439874.299591) can1 080080#\n\
323 (1469439874.299654) can1 053701#7F";
324
325 let mut reader = Reader::from_reader(input);
326
327 let rec1 = reader.next_record().unwrap().unwrap();
328
329 assert_eq!(rec1.t_us, 1469439874299591);
330 assert_eq!(rec1.device, "can1");
331
332 if let CanAnyFrame::Normal(frame) = rec1.frame {
333 assert_eq!(frame.raw_id(), 0x080080);
334 assert_eq!(frame.is_remote_frame(), false);
335 assert_eq!(frame.is_error_frame(), false);
336 assert_eq!(frame.is_extended(), true);
337 assert_eq!(frame.data(), &[]);
338 } else {
339 panic!("Expected Normal frame, got FD");
340 }
341
342 let rec2 = reader.next_record().unwrap().unwrap();
343 assert_eq!(rec2.t_us, 1469439874299654);
344 assert_eq!(rec2.device, "can1");
345
346 if let CanAnyFrame::Normal(frame) = rec2.frame {
347 assert_eq!(frame.raw_id(), 0x053701);
348 assert_eq!(frame.is_remote_frame(), false);
349 assert_eq!(frame.is_error_frame(), false);
350 assert_eq!(frame.is_extended(), true);
351 assert_eq!(frame.data(), &[0x7F]);
352 } else {
353 panic!("Expected Normal frame, got FD");
354 }
355
356 assert!(reader.next_record().unwrap().is_none());
357 }
358
359 #[test]
360 fn test_remote() {
361 let input: &[u8] = b"(1469439874.299591) can0 080080#R\n\
362 (1469439874.299654) can0 053701#R4";
363
364 let mut reader = Reader::from_reader(input);
365
366 let rec1 = reader.next_record().unwrap().unwrap();
367
368 assert_eq!(rec1.t_us, 1469439874299591);
369 assert_eq!(rec1.device, "can0");
370
371 if let CanAnyFrame::Remote(frame) = rec1.frame {
372 assert_eq!(frame.raw_id(), 0x080080);
373 assert!(!frame.is_data_frame());
374 assert!(frame.is_remote_frame());
375 assert!(!frame.is_error_frame());
376 assert!(frame.is_extended());
377 assert_eq!(frame.len(), 0);
378 assert_eq!(frame.data(), &[]);
379 } else {
380 panic!("Expected Remote frame");
381 }
382
383 let rec2 = reader.next_record().unwrap().unwrap();
384 assert_eq!(rec2.t_us, 1469439874299654);
385 assert_eq!(rec2.device, "can0");
386
387 if let CanAnyFrame::Remote(frame) = rec2.frame {
388 assert_eq!(frame.raw_id(), 0x053701);
389 assert!(!frame.is_data_frame());
390 assert!(frame.is_remote_frame());
391 assert!(!frame.is_error_frame());
392 assert!(frame.is_extended());
393 assert_eq!(frame.len(), 4);
394 } else {
395 panic!("Expected Remote frame");
396 }
397
398 assert!(reader.next_record().unwrap().is_none());
399 }
400
401 #[test]
403 fn test_extended_id_fd() {
404 let input: &[u8] = b"(1234.567890) can0 12345678##500112233445566778899AABB";
405
406 let mut reader = Reader::from_reader(input);
407 let rec = reader.next_record().unwrap().unwrap();
408 let frame = CanFdFrame::try_from(rec.frame).unwrap();
409
410 assert!(frame.is_extended());
411 assert_eq!(0x12345678, frame.raw_id());
412 assert_eq!(5, frame.flags().bits());
413 assert_eq!(frame.dlc(), 0x09);
414 assert_eq!(frame.len(), 12);
415 assert_eq!(frame.data().len(), 12);
416 assert_eq!(
417 frame.data(),
418 &[0x0, 0x011, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB]
419 );
420 }
421
422 #[test]
423 fn test_fd() {
424 let input: &[u8] = b"(1469439874.299591) can1 080##0\n\
425 (1469439874.299654) can1 701##17F";
426
427 let mut reader = Reader::from_reader(input);
428
429 let rec1 = reader.next_record().unwrap().unwrap();
430
431 assert_eq!(rec1.t_us, 1469439874299591);
432 assert_eq!(rec1.device, "can1");
433 if let CanAnyFrame::Fd(frame) = rec1.frame {
434 assert_eq!(frame.raw_id(), 0x080);
435 assert!(!frame.is_remote_frame());
436 assert!(!frame.is_error_frame());
437 assert!(!frame.is_extended());
438 assert!(!frame.is_brs());
439 assert!(!frame.is_esi());
440 assert_eq!(0x04, frame.flags().bits());
441 assert_eq!(frame.dlc(), 0);
442 assert_eq!(frame.len(), 0);
443 assert_eq!(frame.data().len(), 0);
444 assert_eq!(frame.data(), &[]);
445 } else {
446 panic!("Expected FD frame, got Normal");
447 }
448
449 let rec2 = reader.next_record().unwrap().unwrap();
450 assert_eq!(rec2.t_us, 1469439874299654);
451 assert_eq!(rec2.device, "can1");
452 if let CanAnyFrame::Fd(frame) = rec2.frame {
453 assert_eq!(frame.raw_id(), 0x701);
454 assert!(!frame.is_remote_frame());
455 assert!(!frame.is_error_frame());
456 assert!(!frame.is_extended());
457 assert!(frame.is_brs());
458 assert!(!frame.is_esi());
459 assert_eq!(0x05, frame.flags().bits());
460 assert_eq!(frame.dlc(), 1);
461 assert_eq!(frame.len(), 1);
462 assert_eq!(frame.data().len(), 1);
463 assert_eq!(frame.data(), &[0x7F]);
464 } else {
465 panic!("Expected FD frame, got Normal");
466 }
467
468 assert!(reader.next_record().unwrap().is_none());
469 }
470}