rs_can/frame/
identifier.rs1use crate::{
2 constants::{EFF_MASK, SFF_MASK},
3 error::Error,
4 CanResult,
5};
6use bitflags::bitflags;
7use serde::{Deserialize, Serialize};
8
9bitflags! {
10 #[repr(transparent)]
20 pub struct IdentifierFlags: u32 {
21 const EXTENDED = 0x8000_0000;
23 const REMOTE = 0x4000_0000;
25 const ERROR = 0x2000_0000;
27 }
28}
29
30bitflags! {
31 #[repr(transparent)]
32 pub struct CanFdFlags: u8 {
33 const BRS = 0x01;
35 const ESI = 0x02;
37 const FDF = 0x04;
40 }
41}
42
43bitflags! {
44 #[repr(transparent)]
45 pub struct CanXlFlags: u8 {
46 const SEC = 0x01;
48 const RRS = 0x02;
50 const XLF = 0x80;
53 }
54}
55
56#[derive(Debug, Copy, Clone, Eq, PartialEq, Deserialize, Serialize, Hash)]
57pub enum Filter {
58 Standard { id: StandardId, mask: u16 },
59 Extended { id: ExtendedId, mask: u32 },
60}
61
62impl Default for Filter {
63 fn default() -> Self {
64 Self::Standard {
65 id: StandardId::default(),
66 mask: 0,
67 }
68 }
69}
70
71#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize, Hash)]
72pub enum Id {
73 Standard(StandardId),
74 Extended(ExtendedId),
75}
76
77#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Deserialize, Serialize, Hash)]
78pub struct StandardId(u16);
79
80#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Deserialize, Serialize, Hash)]
81pub struct ExtendedId(u32);
82
83impl StandardId {
84 pub const MAX: u16 = 0x7FF;
85
86 pub fn new(id: u16) -> CanResult<Self> {
87 if id > Self::MAX {
88 Err(Error::InvalidIdentifier(id as u32))
89 } else {
90 Ok(Self(id))
91 }
92 }
93
94 #[inline]
95 pub fn as_raw(self) -> u16 {
96 self.0
97 }
98}
99
100impl ExtendedId {
101 pub const MAX: u32 = 0x1FFF_FFFF;
102
103 pub fn new(id: u32) -> CanResult<Self> {
104 if id > Self::MAX {
105 Err(Error::InvalidIdentifier(id))
106 } else {
107 Ok(Self(id))
108 }
109 }
110
111 #[inline]
112 pub fn as_raw(self) -> u32 {
113 self.0
114 }
115}
116
117impl Into<u32> for Id {
118 fn into(self) -> u32 {
120 self.into_socketcan_bits()
121 }
122}
123
124impl TryFrom<u32> for Id {
125 type Error = Error;
126
127 fn try_from(v: u32) -> Result<Self, Self::Error> {
128 let flag_mask =
129 (IdentifierFlags::EXTENDED | IdentifierFlags::REMOTE | IdentifierFlags::ERROR).bits();
130 let raw = v & !flag_mask;
131
132 if v & IdentifierFlags::EXTENDED.bits() != 0 {
133 ExtendedId::new(raw & EFF_MASK).map(Id::Extended)
134 } else {
135 StandardId::new((raw & SFF_MASK) as u16).map(Id::Standard)
136 }
137 }
138}
139
140impl Id {
141 #[inline]
142 pub fn from_bits(raw: u32, extended: Option<bool>) -> CanResult<Self> {
143 match extended {
144 Some(true) => ExtendedId::new(raw & EFF_MASK).map(Self::Extended),
145 Some(false) => StandardId::new((raw & SFF_MASK) as u16).map(Self::Standard),
146 None => Self::try_from(raw),
147 }
148 }
149
150 #[inline]
151 pub fn as_raw(self) -> u32 {
152 match self {
153 Self::Standard(id) => id.as_raw() as u32,
154 Self::Extended(id) => id.as_raw(),
155 }
156 }
157
158 #[inline]
159 pub fn is_extended(&self) -> bool {
160 matches!(self, Self::Extended(_))
161 }
162
163 #[inline]
164 pub fn into_socketcan_bits(self) -> u32 {
165 match self {
166 Self::Standard(id) => id.as_raw() as u32,
167 Self::Extended(id) => id.as_raw() | IdentifierFlags::EXTENDED.bits(),
168 }
169 }
170
171 #[inline]
173 pub fn into_hex(self) -> String {
174 format!("{:08X}", self.into_socketcan_bits())
175 }
176}
177
178#[cfg(test)]
179mod tests {
180 use super::*;
181
182 #[test]
183 fn id_into_u32_uses_socketcan_bits() {
184 let extended = Id::Extended(ExtendedId::new(0x123456).unwrap());
185 let raw: u32 = extended.into();
186
187 assert_eq!(raw, 0x0012_3456 | IdentifierFlags::EXTENDED.bits());
188 }
189
190 #[test]
191 fn try_from_socketcan_bits_masks_non_identifier_flags() {
192 let bits = 0x0012_3456
193 | IdentifierFlags::EXTENDED.bits()
194 | IdentifierFlags::REMOTE.bits()
195 | IdentifierFlags::ERROR.bits();
196
197 let id = Id::try_from(bits).unwrap();
198 assert_eq!(id, Id::Extended(ExtendedId::new(0x0012_3456).unwrap()));
199 }
200}