rs_can/frame/
identifier.rs

1use bitflags::bitflags;
2use crate::constants::{EFF_MASK, SFF_MASK};
3
4bitflags! {
5    /// Identifier flags for indicating various frame types.
6    ///
7    /// These flags are applied logically in `can`, but flag values themselves correspond to the
8    /// format used by the Linux [SocketCAN][socketcan] library.  This lets flags be applied
9    /// logically to identifiers such that callers can construct their calls to the underlying CAN
10    /// transceivers/controllers in whatever way is required, but also provides a happy path for
11    /// SocketCAN users by allowing generation of the all-in-one 32-bit identifier value.
12    ///
13    /// [socketcan]: https://www.kernel.org/doc/Documentation/networking/can.txt
14    #[repr(transparent)]
15    pub struct IdentifierFlags: u32 {
16        /// The frame is using the extended format i.e. 29-bit extended identifiers.
17        const EXTENDED = 0x8000_0000;
18        /// The frame is a remote transmission request.
19        const REMOTE = 0x4000_0000;
20        /// The frame is an error frame.
21        const ERROR = 0x2000_0000;
22    }
23}
24
25#[derive(Debug, Copy, Clone, Eq, PartialEq)]
26pub struct Filter {
27    pub can_id: u32,
28    pub can_mask: u32,
29    pub extended: bool
30}
31
32impl From<(u32, u32)> for Filter {
33    fn from(value: (u32, u32)) -> Self {
34        Self {
35            can_id: value.0,
36            can_mask: value.1,
37            extended: false,
38        }
39    }
40}
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
43pub enum Id {
44    Standard(u16),
45    Extended(u32),
46}
47
48unsafe impl Send for Id {}
49unsafe impl Sync for Id {}
50
51impl Into<u32> for Id {
52    fn into(self) -> u32 {
53        match self {
54            Self::Standard(id) => id as u32,
55            Self::Extended(id) => id,
56        }
57    }
58}
59
60impl From<u32> for Id {
61    fn from(id: u32) -> Self {
62        Self::_from_bits(id)
63    }
64}
65
66impl Id {
67    #[inline]
68    pub fn new_standard(id: u16) -> Self {
69        Self::Standard(id)
70    }
71
72    #[inline]
73    pub fn new_extended(id: u32) -> Self {
74        Self::Extended(id)
75    }
76
77    #[inline]
78    pub fn from_bits(id: u32, force_extend: Option<bool>) -> Self {
79        match force_extend {
80            Some(true) => Self::Extended(id),
81            _ => Self::_from_bits(id)
82        }
83    }
84
85    #[inline]
86    pub fn into_bits(self) -> u32 {
87        match self {
88            Self::Standard(id) => id as u32,
89            Self::Extended(id) => id,
90        }
91    }
92
93    #[inline]
94    pub fn from_hex(hex_str: &str, force_extend: Option<bool>) -> Option<Self> {
95        let bits = u32::from_str_radix(hex_str, 16).ok()?;
96
97        Some(Self::from_bits(bits, force_extend))
98    }
99
100    #[inline]
101    pub fn into_hex(self) -> String {
102        std::fmt::format(format_args!("{:08X}", self.into_bits()))
103    }
104
105    /// Returns the Base ID part of this extended identifier.
106    #[inline]
107    pub fn standard_id(self) -> Self {
108        match self {
109            Self::Standard(_) => self,
110            Self::Extended(v) => Self::Standard((v >> 18) as u16),     // ID-28 to ID-18
111        }
112    }
113
114    /// Returns this CAN Identifier as a raw 32-bit integer.
115    #[inline]
116    pub fn as_raw(self) -> u32 {
117        self.into_bits()
118    }
119
120    #[inline]
121    pub fn is_extended(&self) -> bool {
122        matches!(self, Self::Extended(_))
123    }
124
125    #[inline]
126    fn _from_bits(id: u32) -> Self {
127        match id & IdentifierFlags::EXTENDED.bits() {
128            0 => if id > SFF_MASK {
129                Self::new_extended(id)
130            } else {
131                Self::new_standard(id as u16)
132            }
133            _ => Self::new_extended(id & EFF_MASK),
134        }
135    }
136}