1mod data;
2mod error;
3mod fd_data;
4mod id;
5mod remote;
6
7use crate::sys;
8pub use data::DataFrame;
9pub use error::ErrorFrame;
10pub use fd_data::FdDataFrame;
11pub use id::Id;
12pub use remote::RemoteFrame;
13use std::mem::{size_of, size_of_val, MaybeUninit};
14use std::os::raw::c_void;
15
16#[non_exhaustive]
17#[derive(Clone, Copy, Debug)]
18#[cfg_attr(test, derive(PartialEq))]
19pub enum Frame {
20 Data(DataFrame),
21 FdData(FdDataFrame),
22 Remote(RemoteFrame),
23 #[doc(hidden)]
24 Error(ErrorFrame),
25}
26
27impl Frame {
28 pub(crate) unsafe fn from_raw(
29 frame: MaybeUninit<sys::canfd_frame>,
30 size: usize,
31 ) -> Option<Self> {
32 if size == size_of::<sys::can_frame>() {
33 let inner = *(frame.as_ptr() as *const sys::can_frame);
34 if inner.can_id & sys::CAN_RTR_FLAG != 0 {
35 Some(Self::Remote(RemoteFrame(inner)))
36 } else if inner.can_id & sys::CAN_ERR_FLAG != 0 {
37 Some(Self::Error(ErrorFrame(inner)))
38 } else {
39 Some(Self::Data(DataFrame(inner)))
40 }
41 } else if size == size_of::<sys::canfd_frame>() {
42 let inner = frame.assume_init();
43 assert_eq!(inner.can_id & (sys::CAN_RTR_FLAG | sys::CAN_ERR_FLAG), 0);
44 Some(Self::FdData(FdDataFrame(inner)))
45 } else {
46 None
47 }
48 }
49
50 pub(crate) fn as_ptr(&self) -> *const c_void {
51 match self {
52 Self::Data(DataFrame(inner))
53 | Self::Remote(RemoteFrame(inner))
54 | Self::Error(ErrorFrame(inner)) => inner as *const _ as _,
55 Self::FdData(FdDataFrame(inner)) => inner as *const _ as _,
56 }
57 }
58
59 pub(crate) fn size(&self) -> usize {
60 match self {
61 Self::Data(DataFrame(inner))
62 | Self::Remote(RemoteFrame(inner))
63 | Self::Error(ErrorFrame(inner)) => size_of_val(inner),
64 Self::FdData(FdDataFrame(inner)) => size_of_val(inner),
65 }
66 }
67}
68
69#[cfg(test)]
70mod tests;