rs_can/frame/
identifier.rs

1use crate::constants::{EFF_MASK, SFF_MASK};
2use bitflags::bitflags;
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, Default, Copy, Clone, Eq, PartialEq, Hash)]
26pub struct Filter {
27    pub can_id: u32,
28    pub can_mask: u32,
29    pub extended: bool,
30}
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
33pub enum Id {
34    Standard(u16),
35    Extended(u32),
36}
37
38unsafe impl Send for Id {}
39unsafe impl Sync for Id {}
40
41impl Into<u32> for Id {
42    /// 32-bit integer with extended flag
43    fn into(self) -> u32 {
44        self.into_bits()
45    }
46}
47
48impl From<u32> for Id {
49    /// Return [`Id::Extended`] if [`IdentifierFlags::EXTENDED`] bit is set
50    /// or `id` value rather than [`SFF_MASK`] else [`Id::Standard`]
51    fn from(id: u32) -> Self {
52        Self::_from_bits(id)
53    }
54}
55
56impl Id {
57    #[inline]
58    pub fn new_standard(id: u16) -> Self {
59        Self::Standard(id)
60    }
61
62    #[inline]
63    pub fn new_extended(id: u32) -> Self {
64        Self::Extended(id)
65    }
66
67    /// Return [`Id::Extended`] if `force_extend` is Some(true)
68    /// or [`IdentifierFlags::EXTENDED`] bit is set
69    /// or `id` value rather than [`SFF_MASK`]
70    /// else [`Id::Standard`]
71    #[inline]
72    pub fn from_bits(id: u32, force_extend: Option<bool>) -> Self {
73        match force_extend {
74            Some(true) => Self::Extended(id),
75            _ => Self::_from_bits(id),
76        }
77    }
78
79    /// Returns [`Id`] as a 32-bit integer with extended flag.
80    #[inline]
81    pub fn into_bits(self) -> u32 {
82        match self {
83            Self::Standard(id) => id as u32,
84            Self::Extended(id) => id | IdentifierFlags::EXTENDED.bits(),
85        }
86    }
87
88    /// Parse from a hex string.
89    #[inline]
90    pub fn from_hex(hex_str: &str, force_extend: Option<bool>) -> Option<Self> {
91        let bits = u32::from_str_radix(hex_str, 16).ok()?;
92
93        Some(Self::from_bits(bits, force_extend))
94    }
95
96    /// Display [`Id`] as hex string.
97    #[inline]
98    pub fn into_hex(self) -> String {
99        format!("{:08X}", self.into_bits())
100    }
101
102    /// Returns the Base ID part of this extended identifier.
103    #[inline]
104    pub fn standard_id(self) -> Self {
105        match self {
106            Self::Standard(_) => self,
107            Self::Extended(v) => Self::Standard((v >> 18) as u16), // ID-28 to ID-18
108        }
109    }
110
111    /// Returns [`Id`] as a 32-bit integer without extended flag.
112    #[inline]
113    pub fn as_raw(self) -> u32 {
114        match self {
115            Self::Standard(id) => id as u32,
116            Self::Extended(id) => id,
117        }
118    }
119
120    /// Return `true` if [`Id`] is extended else `false`
121    #[inline]
122    pub fn is_extended(&self) -> bool {
123        matches!(self, Self::Extended(_))
124    }
125
126    #[inline]
127    fn _from_bits(id: u32) -> Self {
128        match id & IdentifierFlags::EXTENDED.bits() {
129            0 => {
130                if id > SFF_MASK {
131                    Self::new_extended(id)
132                } else {
133                    Self::new_standard(id as u16)
134                }
135            }
136            _ => Self::new_extended(id & EFF_MASK),
137        }
138    }
139}