1#[cfg(test)]
2mod tests;
3
4use core::cmp::Ordering;
5use core::ops::{Deref, DerefMut};
6
7use crate::{Id, IdReg};
8
9#[derive(Clone, Debug, Eq)]
11#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))]
12pub struct Frame {
13 pub(crate) id: IdReg,
14 pub(crate) data: Data,
15}
16
17impl Frame {
18 pub fn new_data(id: impl Into<Id>, data: impl Into<Data>) -> Self {
20 let id = match id.into() {
21 Id::Standard(id) => IdReg::new_standard(id),
22 Id::Extended(id) => IdReg::new_extended(id),
23 };
24
25 Self {
26 id,
27 data: data.into(),
28 }
29 }
30
31 pub fn new_remote(id: impl Into<Id>, dlc: u8) -> Self {
37 assert!(dlc <= 8);
38
39 let mut frame = Self::new_data(id, []);
40 frame.data.len = dlc;
43 frame.id = frame.id.with_rtr(true);
44 frame
45 }
46
47 #[inline]
49 pub fn is_extended(&self) -> bool {
50 self.id.is_extended()
51 }
52
53 #[inline]
55 pub fn is_standard(&self) -> bool {
56 self.id.is_standard()
57 }
58
59 #[inline]
61 pub fn is_remote_frame(&self) -> bool {
62 self.id.rtr()
63 }
64
65 #[inline]
67 pub fn is_data_frame(&self) -> bool {
68 !self.is_remote_frame()
69 }
70
71 #[inline]
73 pub fn id(&self) -> Id {
74 self.id.to_id()
75 }
76
77 #[inline]
79 pub fn priority(&self) -> FramePriority {
80 FramePriority(self.id)
81 }
82
83 #[inline]
88 pub fn dlc(&self) -> u8 {
89 self.data.len() as u8
90 }
91
92 pub fn data(&self) -> Option<&Data> {
96 if self.is_data_frame() {
97 Some(&self.data)
98 } else {
99 None
100 }
101 }
102}
103
104impl PartialEq for Frame {
105 fn eq(&self, other: &Self) -> bool {
106 match (self.data(), other.data()) {
107 (None, None) => self.id.eq(&other.id),
108 (Some(a), Some(b)) => self.id.eq(&other.id) && a.eq(b),
109 (None, Some(_)) | (Some(_), None) => false,
110 }
111 }
112}
113
114#[derive(Debug, Copy, Clone)]
126pub struct FramePriority(IdReg);
127
128impl Ord for FramePriority {
131 fn cmp(&self, other: &Self) -> Ordering {
132 self.0.cmp(&other.0)
133 }
134}
135
136impl PartialOrd for FramePriority {
137 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
138 Some(self.cmp(other))
139 }
140}
141
142impl PartialEq for FramePriority {
143 fn eq(&self, other: &Self) -> bool {
144 self.cmp(other) == Ordering::Equal
145 }
146}
147
148impl Eq for FramePriority {}
149
150#[derive(Debug, Copy, Clone)]
157pub struct Data {
158 pub(crate) len: u8,
159 pub(crate) bytes: [u8; 8],
160}
161
162impl Data {
163 pub fn new(data: &[u8]) -> Option<Self> {
169 if data.len() > 8 {
170 return None;
171 }
172
173 let mut bytes = [0; 8];
174 bytes[..data.len()].copy_from_slice(data);
175
176 Some(Self {
177 len: data.len() as u8,
178 bytes,
179 })
180 }
181
182 #[inline]
184 pub const fn empty() -> Self {
185 Self {
186 len: 0,
187 bytes: [0; 8],
188 }
189 }
190}
191
192impl Deref for Data {
193 type Target = [u8];
194
195 #[inline]
196 fn deref(&self) -> &[u8] {
197 &self.bytes[..usize::from(self.len)]
198 }
199}
200
201impl DerefMut for Data {
202 #[inline]
203 fn deref_mut(&mut self) -> &mut [u8] {
204 &mut self.bytes[..usize::from(self.len)]
205 }
206}
207
208impl AsRef<[u8]> for Data {
209 #[inline]
210 fn as_ref(&self) -> &[u8] {
211 self.deref()
212 }
213}
214
215impl AsMut<[u8]> for Data {
216 #[inline]
217 fn as_mut(&mut self) -> &mut [u8] {
218 self.deref_mut()
219 }
220}
221
222impl PartialEq for Data {
223 fn eq(&self, other: &Self) -> bool {
224 self.as_ref() == other.as_ref()
225 }
226}
227
228impl Eq for Data {}
229
230#[cfg(feature = "unstable-defmt")]
231impl defmt::Format for Data {
232 fn format(&self, fmt: defmt::Formatter<'_>) {
233 self.as_ref().format(fmt)
234 }
235}
236
237macro_rules! data_from_array {
238 ( $($len:literal),+ ) => {
239 $(
240 impl From<[u8; $len]> for Data {
241 #[inline]
242 fn from(arr: [u8; $len]) -> Self {
243 let mut bytes = [0; 8];
244 bytes[..$len].copy_from_slice(&arr);
245 Self {
246 len: $len,
247 bytes,
248 }
249 }
250 }
251 )+
252 };
253}
254
255data_from_array!(0, 1, 2, 3, 4, 5, 6, 7, 8);