canlink_hal/filter/
id_filter.rs1use crate::error::FilterError;
6use crate::message::CanMessage;
7
8use super::MessageFilter;
9
10pub const MAX_STANDARD_ID: u32 = 0x7FF;
12
13pub const MAX_EXTENDED_ID: u32 = 0x1FFF_FFFF;
15
16#[derive(Debug, Clone)]
32pub struct IdFilter {
33 id: u32,
35 mask: u32,
37 extended: bool,
39 hardware: bool,
41}
42
43impl IdFilter {
44 #[must_use]
54 pub fn new(id: u32) -> Self {
55 assert!(id <= MAX_STANDARD_ID, "ID exceeds maximum standard ID");
56 Self {
57 id,
58 mask: MAX_STANDARD_ID,
59 extended: false,
60 hardware: true,
61 }
62 }
63
64 #[must_use]
80 pub fn with_mask(id: u32, mask: u32) -> Self {
81 Self {
82 id: id & mask,
83 mask,
84 extended: false,
85 hardware: true,
86 }
87 }
88
89 #[must_use]
99 pub fn new_extended(id: u32) -> Self {
100 assert!(id <= MAX_EXTENDED_ID, "ID exceeds maximum extended ID");
101 Self {
102 id,
103 mask: MAX_EXTENDED_ID,
104 extended: true,
105 hardware: true,
106 }
107 }
108
109 #[must_use]
111 pub fn with_mask_extended(id: u32, mask: u32) -> Self {
112 Self {
113 id: id & mask,
114 mask,
115 extended: true,
116 hardware: true,
117 }
118 }
119
120 pub fn try_new(id: u32) -> Result<Self, FilterError> {
126 if id > MAX_STANDARD_ID {
127 return Err(FilterError::IdOutOfRange {
128 id,
129 max: MAX_STANDARD_ID,
130 });
131 }
132 Ok(Self::new(id))
133 }
134
135 pub fn try_new_extended(id: u32) -> Result<Self, FilterError> {
141 if id > MAX_EXTENDED_ID {
142 return Err(FilterError::IdOutOfRange {
143 id,
144 max: MAX_EXTENDED_ID,
145 });
146 }
147 Ok(Self::new_extended(id))
148 }
149
150 pub fn set_hardware(&mut self, hardware: bool) {
152 self.hardware = hardware;
153 }
154
155 #[must_use]
157 pub fn id(&self) -> u32 {
158 self.id
159 }
160
161 #[must_use]
163 pub fn mask(&self) -> u32 {
164 self.mask
165 }
166
167 #[must_use]
169 pub fn is_extended(&self) -> bool {
170 self.extended
171 }
172}
173
174impl MessageFilter for IdFilter {
175 fn matches(&self, message: &CanMessage) -> bool {
176 let msg_id = message.id();
177 let is_extended = msg_id.is_extended();
178
179 if is_extended != self.extended {
181 return false;
182 }
183
184 let raw_id = msg_id.raw();
186 (raw_id & self.mask) == (self.id & self.mask)
187 }
188
189 fn priority(&self) -> u32 {
190 if self.mask == MAX_STANDARD_ID || self.mask == MAX_EXTENDED_ID {
192 100
193 } else {
194 50
195 }
196 }
197
198 fn is_hardware(&self) -> bool {
199 self.hardware
200 }
201}
202
203#[cfg(test)]
204mod tests {
205 use super::*;
206 use crate::message::CanMessage;
207
208 #[test]
209 fn test_exact_match() {
210 let filter = IdFilter::new(0x123);
211
212 let msg_match = CanMessage::new_standard(0x123, &[0u8; 8]).unwrap();
213 let msg_no_match = CanMessage::new_standard(0x456, &[0u8; 8]).unwrap();
214
215 assert!(filter.matches(&msg_match));
216 assert!(!filter.matches(&msg_no_match));
217 }
218
219 #[test]
220 fn test_mask_match() {
221 let filter = IdFilter::with_mask(0x120, 0x7F0);
223
224 let msg_120 = CanMessage::new_standard(0x120, &[0u8; 8]).unwrap();
225 let msg_12f_id = CanMessage::new_standard(0x12F, &[0u8; 8]).unwrap();
226 let msg_130 = CanMessage::new_standard(0x130, &[0u8; 8]).unwrap();
227
228 assert!(filter.matches(&msg_120));
229 assert!(filter.matches(&msg_12f_id));
230 assert!(!filter.matches(&msg_130));
231 }
232
233 #[test]
234 fn test_extended_filter() {
235 let filter = IdFilter::new_extended(0x1234_5678);
236
237 let msg_ext = CanMessage::new_extended(0x1234_5678, &[0u8; 8]).unwrap();
238 let msg_std = CanMessage::new_standard(0x123, &[0u8; 8]).unwrap();
239
240 assert!(filter.matches(&msg_ext));
241 assert!(!filter.matches(&msg_std)); }
243
244 #[test]
245 fn test_try_new_invalid() {
246 let result = IdFilter::try_new(0x800);
247 assert!(result.is_err());
248 }
249
250 #[test]
251 fn test_priority() {
252 let exact = IdFilter::new(0x123);
253 let masked = IdFilter::with_mask(0x120, 0x7F0);
254
255 assert!(exact.priority() > masked.priority());
256 }
257}