1use crate::CanId;
2use crate::error;
3
4#[derive(Copy, Clone)]
6#[repr(transparent)]
7pub struct CanFrame {
8 pub(crate) inner: crate::sys::CanFrame,
9}
10
11impl CanFrame {
12 #[inline]
17 pub fn new(id: impl Into<CanId>, data: impl Into<CanData>) -> Self {
18 Self {
19 inner: crate::sys::CanFrame::new(id, &data.into())
20 }
21 }
22
23 #[inline]
29 pub fn try_new<Id, Data>(id: Id, data: Data) -> Result<Self, error::TryNewCanFrameError>
30 where
31 Id: TryInto<CanId>,
32 error::TryNewCanFrameError: From<Id::Error>,
33 Data: TryInto<CanData>,
34 error::TryNewCanFrameError: From<Data::Error>,
35 {
36 Ok(Self::new(id.try_into()?, data.try_into()?))
37 }
38
39 #[inline]
44 pub fn new_rtr(id: impl Into<CanId>) -> Self {
45 Self {
46 inner: crate::sys::CanFrame::new_rtr(id),
47 }
48 }
49
50 #[inline]
52 pub fn id(&self) -> CanId {
53 self.inner.id()
54 }
55
56 #[inline]
63 pub fn is_rtr(&self) -> bool {
64 self.inner.is_rtr()
65 }
66
67 #[inline]
71 pub fn data(&self) -> Option<CanData> {
72 self.inner.data()
73 }
74
75 #[inline]
83 pub fn set_data_length_code(&mut self, dlc: u8) -> Result<(), error::InvalidDataLengthCode> {
84 self.inner.set_data_length_code(dlc)
85 .map_err(|()| error::InvalidDataLengthCode { value: dlc })
86 }
87
88 #[inline]
96 #[must_use = "this function returns a new frame, it does not modify self"]
97 pub fn with_data_length_code(mut self, dlc: u8) -> Result<Self, error::InvalidDataLengthCode> {
98 self.set_data_length_code(dlc)?;
99 Ok(self)
100 }
101
102 #[inline]
112 pub fn data_length_code(&self) -> u8 {
113 self.inner.data_length_code()
114 }
115}
116
117impl std::fmt::Debug for CanFrame {
118 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
119 let mut debug = f.debug_struct("CanFrame");
120 debug
121 .field("id", &format_args!("{:?}", self.id()))
122 .field("is_rtr", &self.is_rtr())
123 .field("data_length_code", &self.data_length_code());
124 if !self.is_rtr() {
125 debug.field("data", &format_args!("{:02X?}", self.data()));
126 }
127 debug.finish()
128 }
129}
130
131#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
135pub struct CanData {
136 pub(crate) data: [u8; 8],
137 pub(crate) len: u8,
138}
139
140impl CanData {
141 pub fn new(data: impl Into<CanData>) -> Self {
145 data.into()
146 }
147
148 pub fn try_new<E>(data: impl TryInto<CanData, Error = E>) -> Result<Self, E> {
152 data.try_into()
153 }
154
155 #[inline]
157 pub fn as_slice(&self) -> &[u8] {
158 &self.data[..self.len.into()]
159 }
160
161 #[inline]
163 pub fn as_slice_mut(&mut self) -> &mut [u8] {
164 &mut self.data[..self.len.into()]
165 }
166}
167
168impl std::fmt::Debug for CanData {
169 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
170 std::fmt::Debug::fmt(self.as_slice(), f)
171 }
172}
173impl std::ops::Deref for CanData {
174 type Target = [u8];
175
176 fn deref(&self) -> &Self::Target {
177 self.as_slice()
178 }
179}
180
181impl std::ops::DerefMut for CanData {
182 fn deref_mut(&mut self) -> &mut Self::Target {
183 self.as_slice_mut()
184 }
185}
186
187impl std::borrow::Borrow<[u8]> for CanData {
188 fn borrow(&self) -> &[u8] {
189 self.as_slice()
190 }
191}
192
193impl std::borrow::BorrowMut<[u8]> for CanData {
194 fn borrow_mut(&mut self) -> &mut [u8] {
195 self.as_slice_mut()
196 }
197}
198
199impl AsRef<[u8]> for CanData {
200 fn as_ref(&self) -> &[u8] {
201 self.as_slice()
202 }
203}
204
205impl AsMut<[u8]> for CanData {
206 fn as_mut(&mut self) -> &mut [u8] {
207 self.as_slice_mut()
208 }
209}
210
211impl PartialEq<[u8]> for CanData {
212 fn eq(&self, other: &[u8]) -> bool {
213 self.as_slice() == other
214 }
215}
216
217impl PartialEq<CanData> for [u8] {
218 fn eq(&self, other: &CanData) -> bool {
219 self == other.as_slice()
220 }
221}
222
223macro_rules! impl_from_array {
224 ($n:literal) => {
225 impl From<[u8; $n]> for CanData {
226 fn from(value: [u8; $n]) -> Self {
227 let mut data = [0; 8];
228 data[..value.len()].copy_from_slice(&value);
229 Self {
230 data,
231 len: $n,
232 }
233 }
234 }
235
236 impl<'a> From<&'a [u8; $n]> for CanData {
237 fn from(value: &'a [u8; $n]) -> Self {
238 let mut data = [0; 8];
239 data[..value.len()].copy_from_slice(value);
240 Self {
241 data,
242 len: $n,
243 }
244 }
245 }
246
247 impl TryFrom<CanData> for [u8; $n] {
248 type Error = core::array::TryFromSliceError;
249
250 fn try_from(other: CanData) -> Result<Self, Self::Error> {
251 other.as_slice().try_into()
252 }
253 }
254
255 impl<'a> TryFrom<&'a CanData> for [u8; $n] {
256 type Error = core::array::TryFromSliceError;
257
258 fn try_from(other: &'a CanData) -> Result<Self, Self::Error> {
259 other.as_slice().try_into()
260 }
261 }
262
263 impl PartialEq<[u8; $n]> for CanData {
264 fn eq(&self, other: &[u8; $n]) -> bool {
265 if self.len == $n {
266 &self.data[..$n] == other
267 } else {
268 false
269 }
270 }
271 }
272
273 impl PartialEq<CanData> for [u8; $n] {
274 fn eq(&self, other: &CanData) -> bool {
275 other == self
276 }
277 }
278 }
279}
280
281impl_from_array!(0);
282impl_from_array!(1);
283impl_from_array!(2);
284impl_from_array!(3);
285impl_from_array!(4);
286impl_from_array!(5);
287impl_from_array!(6);
288impl_from_array!(7);
289impl_from_array!(8);
290
291impl TryFrom<&[u8]> for CanData {
292 type Error = error::TryIntoCanDataError;
293
294 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
295 if value.len() > 8 {
296 Err(error::TryIntoCanDataError {
297 len: value.len(),
298 })
299 } else {
300 let mut data = [0; 8];
301 data[..value.len()].copy_from_slice(value);
302 Ok(Self {
303 data,
304 len: value.len() as u8,
305 })
306 }
307 }
308}
309
310impl TryFrom<&Vec<u8>> for CanData {
311 type Error = error::TryIntoCanDataError;
312
313 fn try_from(value: &Vec<u8>) -> Result<Self, Self::Error> {
314 value.as_slice().try_into()
315 }
316}
317
318impl TryFrom<&Box<[u8]>> for CanData {
319 type Error = error::TryIntoCanDataError;
320
321 fn try_from(value: &Box<[u8]>) -> Result<Self, Self::Error> {
322 let value: &[u8] = value;
323 value.try_into()
324 }
325}
326
327
328#[cfg(test)]
329mod test {
330 use super::*;
331 use assert2::assert;
332 use crate::can_id;
333
334 #[test]
335 fn can_frame_is_copy() {
336 let frame = CanFrame::new(1u8, [1, 2, 3, 4]);
337 let copy = frame;
338 assert!(copy.id() == can_id!(1));
339 assert!(copy.data() == Some(CanData::new([1, 2, 3, 4])));
340 }
341
342 #[test]
343 fn can_data_from_array() {
344 assert!(CanData::from([1]) == [1]);
345 assert!(CanData::from([1, 2]) == [1, 2]);
346 assert!(CanData::from([1, 2, 3]) == [1, 2, 3]);
347 assert!(CanData::from([1, 2, 3, 4, 5]) == [1, 2, 3, 4, 5]);
348 assert!(CanData::from([1, 2, 3, 4, 5, 6]) == [1, 2, 3, 4, 5, 6]);
349 assert!(CanData::from([1, 2, 3, 4, 5, 6, 7]) == [1, 2, 3, 4, 5, 6, 7]);
350 assert!(CanData::from([1, 2, 3, 4, 5, 6, 7, 8]) == [1, 2, 3, 4, 5, 6, 7, 8]);
351
352 assert!(CanData::from([1, 2]) != [1]);
353 assert!(CanData::from([1]) != [1, 2]);
354 }
355}