1use crate::id::CanId;
2
3const CAN_MAX_LEN: usize = 8;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct CanFrame {
8 id: CanId,
9 len: u8,
10 data: [u8; 8],
11}
12
13impl CanFrame {
14 #[must_use]
18 pub fn new(id: CanId, data: &[u8]) -> Option<Self> {
19 if data.len() > CAN_MAX_LEN {
20 return None;
21 }
22 let mut buf = [0u8; 8];
23 buf[..data.len()].copy_from_slice(data);
24 #[allow(clippy::cast_possible_truncation)] Some(Self {
26 id,
27 len: data.len() as u8,
28 data: buf,
29 })
30 }
31
32 #[must_use]
34 pub const fn id(&self) -> CanId {
35 self.id
36 }
37
38 #[must_use]
43 pub const fn len(&self) -> usize {
44 self.len as usize
45 }
46
47 #[must_use]
49 pub const fn is_empty(&self) -> bool {
50 self.len == 0
51 }
52
53 #[must_use]
55 pub fn data(&self) -> &[u8] {
56 &self.data[..self.len as usize]
57 }
58}
59
60#[derive(Debug, Clone, PartialEq, Eq)]
67pub struct CanFdFrame {
68 id: CanId,
69 len: u8,
70 data: [u8; 64],
71 brs: bool,
72 esi: bool,
73}
74
75impl CanFdFrame {
76 #[must_use]
81 pub fn new(id: CanId, data: &[u8], brs: bool, esi: bool) -> Option<Self> {
82 if !matches!(data.len(), 0..=8 | 12 | 16 | 20 | 24 | 32 | 48 | 64) {
83 return None;
84 }
85 let mut buf = [0u8; 64];
86 buf[..data.len()].copy_from_slice(data);
87 #[allow(clippy::cast_possible_truncation)] Some(Self {
89 id,
90 len: data.len() as u8,
91 data: buf,
92 brs,
93 esi,
94 })
95 }
96
97 #[must_use]
99 pub const fn id(&self) -> CanId {
100 self.id
101 }
102
103 #[must_use]
108 pub const fn len(&self) -> usize {
109 self.len as usize
110 }
111
112 #[must_use]
114 pub const fn is_empty(&self) -> bool {
115 self.len == 0
116 }
117
118 #[must_use]
120 pub fn data(&self) -> &[u8] {
121 &self.data[..self.len as usize]
122 }
123
124 #[must_use]
126 pub const fn brs(&self) -> bool {
127 self.brs
128 }
129
130 #[must_use]
132 pub const fn esi(&self) -> bool {
133 self.esi
134 }
135}
136
137#[derive(Debug, Clone, PartialEq, Eq)]
139pub enum Frame {
140 Can(CanFrame),
141 Fd(CanFdFrame),
142}
143
144impl Frame {
145 #[must_use]
147 pub const fn id(&self) -> CanId {
148 match self {
149 Self::Can(f) => f.id(),
150 Self::Fd(f) => f.id(),
151 }
152 }
153
154 #[must_use]
156 pub fn data(&self) -> &[u8] {
157 match self {
158 Self::Can(f) => f.data(),
159 Self::Fd(f) => f.data(),
160 }
161 }
162
163 #[must_use]
165 pub const fn len(&self) -> usize {
166 match self {
167 Self::Can(f) => f.len(),
168 Self::Fd(f) => f.len(),
169 }
170 }
171
172 #[must_use]
174 pub const fn is_empty(&self) -> bool {
175 match self {
176 Self::Can(f) => f.is_empty(),
177 Self::Fd(f) => f.is_empty(),
178 }
179 }
180}
181
182#[derive(Debug, Clone)]
188pub struct Timestamped<F, T> {
189 frame: F,
190 timestamp: T,
191}
192
193impl<F, T> Timestamped<F, T> {
194 #[must_use]
196 pub const fn new(frame: F, timestamp: T) -> Self {
197 Self { frame, timestamp }
198 }
199
200 #[must_use]
202 pub const fn frame(&self) -> &F {
203 &self.frame
204 }
205
206 #[must_use]
208 pub const fn timestamp(&self) -> &T {
209 &self.timestamp
210 }
211
212 #[must_use]
214 pub fn into_frame(self) -> F {
215 self.frame
216 }
217}