host_can/
frame.rs

1use crate::id::Id;
2pub use embedded_can::Frame;
3
4type CanPdu = [u8; 8];
5
6/// A standard CAN 2.0 frame
7/// (NOTE: this will change to an enum w/standard, fd, error, etc.)
8#[derive(Copy, Clone, Debug)]
9pub struct CanFrame {
10    id: Id,
11    dlc: u8,
12    data: CanPdu,
13}
14
15impl PartialEq for CanFrame {
16    fn eq(&self, other: &Self) -> bool {
17        self.id == other.id
18            && self.dlc == other.dlc
19            && self.data[..self.dlc as usize]
20                == other.data[..other.dlc as usize]
21    }
22}
23
24impl Frame for CanFrame {
25    fn new(id: impl Into<Id>, data: &[u8]) -> Option<Self> {
26        let len = data.len();
27        if len > std::mem::size_of::<CanPdu>() {
28            return None;
29        }
30        let mut bytes = [0u8; 8];
31        bytes[..len].copy_from_slice(data);
32        Some(CanFrame {
33            id: id.into(),
34            dlc: len as u8,
35            data: bytes,
36        })
37    }
38
39    fn new_remote(_: impl Into<Id>, _: usize) -> Option<Self> {
40        None
41    }
42
43    fn is_extended(&self) -> bool {
44        match self.id {
45            embedded_can::Id::Extended(_) => true,
46            embedded_can::Id::Standard(_) => false,
47        }
48    }
49
50    fn is_remote_frame(&self) -> bool {
51        false
52    }
53
54    fn id(&self) -> embedded_can::Id {
55        self.id
56    }
57
58    fn dlc(&self) -> usize {
59        self.dlc as usize
60    }
61
62    fn data(&self) -> &[u8] {
63        &self.data[..self.dlc as usize]
64    }
65}
66
67// TODO: CanFdFrame
68
69#[cfg(test)]
70mod test {
71    use crate::id;
72
73    use super::CanFrame;
74    use embedded_can::Frame;
75
76    #[test]
77    fn frame_eq() {
78        let std_123_dlc_3a =
79            CanFrame::new(id::new_standard(0x123).unwrap(), &[0, 10, 20])
80                .unwrap();
81        let std_123_dlc_3b =
82            CanFrame::new(id::new_standard(0x123).unwrap(), &[0, 10, 20])
83                .unwrap();
84        let std_123_dlc_2 =
85            CanFrame::new(id::new_standard(0x123).unwrap(), &[0, 10]).unwrap();
86        let std_456_dlc_3 =
87            CanFrame::new(id::new_standard(0x456).unwrap(), &[0, 10, 20])
88                .unwrap();
89        let ext_123_dlc_3a =
90            CanFrame::new(id::new_extended(0x123).unwrap(), &[0, 10, 20])
91                .unwrap();
92        let ext_123_dlc_3b =
93            CanFrame::new(id::new_extended(0x123).unwrap(), &[0, 10, 20])
94                .unwrap();
95        let ext_123_dlc_2 =
96            CanFrame::new(id::new_extended(0x123).unwrap(), &[0, 10]).unwrap();
97        let ext_456_dlc_3 =
98            CanFrame::new(id::new_extended(0x123).unwrap(), &[0, 10, 20])
99                .unwrap();
100
101        // standard
102        assert_eq!(std_123_dlc_3a, std_123_dlc_3b);
103        assert_ne!(std_123_dlc_3a, std_123_dlc_2);
104        assert_ne!(std_123_dlc_2, std_456_dlc_3);
105
106        // standard != extended, even if IDs match
107        assert_ne!(std_123_dlc_3a, ext_123_dlc_3a);
108
109        // extended
110        assert_eq!(ext_123_dlc_3a, ext_123_dlc_3b);
111        assert_ne!(ext_123_dlc_3a, ext_123_dlc_2);
112        assert_ne!(ext_123_dlc_2, ext_456_dlc_3);
113    }
114}