canlink_hal/filter/
range_filter.rs1use crate::error::FilterError;
6use crate::message::CanMessage;
7
8use super::id_filter::{MAX_EXTENDED_ID, MAX_STANDARD_ID};
9use super::MessageFilter;
10
11#[derive(Debug, Clone)]
24pub struct RangeFilter {
25 start_id: u32,
27 end_id: u32,
29 extended: bool,
31}
32
33impl RangeFilter {
34 #[must_use]
45 pub fn new(start_id: u32, end_id: u32) -> Self {
46 assert!(start_id <= end_id, "start_id must be <= end_id");
47 assert!(end_id <= MAX_STANDARD_ID, "ID exceeds maximum standard ID");
48 Self {
49 start_id,
50 end_id,
51 extended: false,
52 }
53 }
54
55 #[must_use]
66 pub fn new_extended(start_id: u32, end_id: u32) -> Self {
67 assert!(start_id <= end_id, "start_id must be <= end_id");
68 assert!(end_id <= MAX_EXTENDED_ID, "ID exceeds maximum extended ID");
69 Self {
70 start_id,
71 end_id,
72 extended: true,
73 }
74 }
75
76 pub fn try_new(start_id: u32, end_id: u32) -> Result<Self, FilterError> {
83 if start_id > end_id {
84 return Err(FilterError::InvalidRange {
85 start: start_id,
86 end: end_id,
87 });
88 }
89 if end_id > MAX_STANDARD_ID {
90 return Err(FilterError::IdOutOfRange {
91 id: end_id,
92 max: MAX_STANDARD_ID,
93 });
94 }
95 Ok(Self::new(start_id, end_id))
96 }
97
98 pub fn try_new_extended(start_id: u32, end_id: u32) -> Result<Self, FilterError> {
105 if start_id > end_id {
106 return Err(FilterError::InvalidRange {
107 start: start_id,
108 end: end_id,
109 });
110 }
111 if end_id > MAX_EXTENDED_ID {
112 return Err(FilterError::IdOutOfRange {
113 id: end_id,
114 max: MAX_EXTENDED_ID,
115 });
116 }
117 Ok(Self::new_extended(start_id, end_id))
118 }
119
120 #[must_use]
122 pub fn start_id(&self) -> u32 {
123 self.start_id
124 }
125
126 #[must_use]
128 pub fn end_id(&self) -> u32 {
129 self.end_id
130 }
131
132 #[must_use]
134 pub fn is_extended(&self) -> bool {
135 self.extended
136 }
137
138 #[must_use]
140 pub fn range_size(&self) -> u32 {
141 self.end_id - self.start_id + 1
142 }
143}
144
145impl MessageFilter for RangeFilter {
146 fn matches(&self, message: &CanMessage) -> bool {
147 let msg_id = message.id();
148 let is_extended = msg_id.is_extended();
149
150 if is_extended != self.extended {
152 return false;
153 }
154
155 let raw_id = msg_id.raw();
157 raw_id >= self.start_id && raw_id <= self.end_id
158 }
159
160 fn priority(&self) -> u32 {
161 let range_size = self.end_id - self.start_id;
163 if range_size == 0 {
164 100 } else if range_size < 16 {
166 75
167 } else if range_size < 256 {
168 50
169 } else {
170 25
171 }
172 }
173
174 fn is_hardware(&self) -> bool {
175 false
178 }
179}
180
181#[cfg(test)]
182mod tests {
183 use super::*;
184 use crate::message::CanMessage;
185
186 #[test]
187 fn test_range_match() {
188 let filter = RangeFilter::new(0x100, 0x1FF);
189
190 let msg_100 = CanMessage::new_standard(0x100, &[0u8; 8]).unwrap();
191 let msg_150 = CanMessage::new_standard(0x150, &[0u8; 8]).unwrap();
192 let msg_1ff = CanMessage::new_standard(0x1FF, &[0u8; 8]).unwrap();
193 let msg_200 = CanMessage::new_standard(0x200, &[0u8; 8]).unwrap();
194 let msg_0ff = CanMessage::new_standard(0x0FF, &[0u8; 8]).unwrap();
195
196 assert!(filter.matches(&msg_100));
197 assert!(filter.matches(&msg_150));
198 assert!(filter.matches(&msg_1ff));
199 assert!(!filter.matches(&msg_200));
200 assert!(!filter.matches(&msg_0ff));
201 }
202
203 #[test]
204 fn test_single_id_range() {
205 let filter = RangeFilter::new(0x123, 0x123);
206
207 let msg_match = CanMessage::new_standard(0x123, &[0u8; 8]).unwrap();
208 let msg_no_match = CanMessage::new_standard(0x124, &[0u8; 8]).unwrap();
209
210 assert!(filter.matches(&msg_match));
211 assert!(!filter.matches(&msg_no_match));
212 }
213
214 #[test]
215 fn test_extended_range() {
216 let filter = RangeFilter::new_extended(0x10000, 0x1FFFF);
217
218 let msg_ext = CanMessage::new_extended(0x15000, &[0u8; 8]).unwrap();
219 let msg_std = CanMessage::new_standard(0x100, &[0u8; 8]).unwrap();
220
221 assert!(filter.matches(&msg_ext));
222 assert!(!filter.matches(&msg_std)); }
224
225 #[test]
226 fn test_try_new_invalid_range() {
227 let result = RangeFilter::try_new(0x200, 0x100);
228 assert!(result.is_err());
229 }
230
231 #[test]
232 fn test_range_size() {
233 let filter = RangeFilter::new(0x100, 0x1FF);
234 assert_eq!(filter.range_size(), 256);
235 }
236
237 #[test]
238 fn test_priority() {
239 let single = RangeFilter::new(0x100, 0x100);
240 let small = RangeFilter::new(0x100, 0x10F);
241 let large = RangeFilter::new(0x100, 0x1FF);
242
243 assert!(single.priority() > small.priority());
244 assert!(small.priority() > large.priority());
245 }
246}