canlink_hal/filter/
chain.rs1use crate::error::FilterError;
6use crate::message::CanMessage;
7
8use super::MessageFilter;
9
10pub struct FilterChain {
40 filters: Vec<Box<dyn MessageFilter>>,
42 max_hardware_filters: usize,
44 hardware_filter_count: usize,
46}
47
48impl FilterChain {
49 #[must_use]
55 pub fn new(max_hardware_filters: usize) -> Self {
56 Self {
57 filters: Vec::new(),
58 max_hardware_filters,
59 hardware_filter_count: 0,
60 }
61 }
62
63 pub fn add_filter(&mut self, filter: Box<dyn MessageFilter>) {
73 if filter.is_hardware() && self.hardware_filter_count < self.max_hardware_filters {
74 self.hardware_filter_count += 1;
75 }
76 self.filters.push(filter);
77 }
78
79 pub fn remove_filter(&mut self, index: usize) -> Result<Box<dyn MessageFilter>, FilterError> {
89 if index >= self.filters.len() {
90 return Err(FilterError::FilterNotFound { index });
91 }
92
93 let filter = self.filters.remove(index);
94 if filter.is_hardware() && self.hardware_filter_count > 0 {
95 self.hardware_filter_count -= 1;
96 }
97 Ok(filter)
98 }
99
100 pub fn clear(&mut self) {
102 self.filters.clear();
103 self.hardware_filter_count = 0;
104 }
105
106 #[must_use]
112 pub fn matches(&self, message: &CanMessage) -> bool {
113 if self.filters.is_empty() {
115 return true;
116 }
117
118 self.filters.iter().any(|f| f.matches(message))
120 }
121
122 #[must_use]
124 pub fn len(&self) -> usize {
125 self.filters.len()
126 }
127
128 #[must_use]
130 pub fn is_empty(&self) -> bool {
131 self.filters.is_empty()
132 }
133
134 #[must_use]
136 pub fn hardware_filter_count(&self) -> usize {
137 self.hardware_filter_count
138 }
139
140 #[must_use]
142 pub fn software_filter_count(&self) -> usize {
143 self.filters
144 .iter()
145 .filter(|f| !f.is_hardware() || self.hardware_filter_count >= self.max_hardware_filters)
146 .count()
147 }
148
149 #[must_use]
151 pub fn max_hardware_filters(&self) -> usize {
152 self.max_hardware_filters
153 }
154
155 #[must_use]
157 pub fn has_hardware_capacity(&self) -> bool {
158 self.hardware_filter_count < self.max_hardware_filters
159 }
160
161 #[must_use]
163 pub fn total_filter_count(&self) -> usize {
164 self.len()
165 }
166
167 pub fn iter(&self) -> impl Iterator<Item = &dyn MessageFilter> {
169 self.filters.iter().map(std::convert::AsRef::as_ref)
170 }
171}
172
173impl Default for FilterChain {
174 fn default() -> Self {
175 Self::new(4) }
177}
178
179#[cfg(test)]
180mod tests {
181 use super::*;
182 use crate::filter::{IdFilter, RangeFilter};
183 use crate::message::CanMessage;
184
185 fn make_message(id: u16) -> CanMessage {
186 CanMessage::new_standard(id, &[0u8; 8]).unwrap()
187 }
188
189 #[test]
190 fn test_empty_chain_passes_all() {
191 let chain = FilterChain::new(4);
192 assert!(chain.matches(&make_message(0x123)));
193 assert!(chain.matches(&make_message(0x456)));
194 }
195
196 #[test]
197 fn test_single_filter() {
198 let mut chain = FilterChain::new(4);
199 chain.add_filter(Box::new(IdFilter::new(0x123)));
200
201 assert!(chain.matches(&make_message(0x123)));
202 assert!(!chain.matches(&make_message(0x456)));
203 }
204
205 #[test]
206 fn test_multiple_filters_or_logic() {
207 let mut chain = FilterChain::new(4);
208 chain.add_filter(Box::new(IdFilter::new(0x123)));
209 chain.add_filter(Box::new(IdFilter::new(0x456)));
210
211 assert!(chain.matches(&make_message(0x123)));
212 assert!(chain.matches(&make_message(0x456)));
213 assert!(!chain.matches(&make_message(0x789)));
214 }
215
216 #[test]
217 fn test_mixed_filters() {
218 let mut chain = FilterChain::new(4);
219 chain.add_filter(Box::new(IdFilter::new(0x123)));
220 chain.add_filter(Box::new(RangeFilter::new(0x200, 0x2FF)));
221
222 assert!(chain.matches(&make_message(0x123)));
223 assert!(chain.matches(&make_message(0x250)));
224 assert!(!chain.matches(&make_message(0x300)));
225 }
226
227 #[test]
228 fn test_hardware_filter_count() {
229 let mut chain = FilterChain::new(2);
230
231 chain.add_filter(Box::new(IdFilter::new(0x100)));
233 assert_eq!(chain.hardware_filter_count(), 1);
234
235 chain.add_filter(Box::new(IdFilter::new(0x200)));
236 assert_eq!(chain.hardware_filter_count(), 2);
237
238 chain.add_filter(Box::new(RangeFilter::new(0x300, 0x3FF)));
240 assert_eq!(chain.hardware_filter_count(), 2);
241 }
242
243 #[test]
244 fn test_remove_filter() {
245 let mut chain = FilterChain::new(4);
246 chain.add_filter(Box::new(IdFilter::new(0x123)));
247 chain.add_filter(Box::new(IdFilter::new(0x456)));
248
249 assert_eq!(chain.len(), 2);
250
251 chain.remove_filter(0).unwrap();
252 assert_eq!(chain.len(), 1);
253
254 assert!(!chain.matches(&make_message(0x123)));
256 assert!(chain.matches(&make_message(0x456)));
257 }
258
259 #[test]
260 fn test_remove_invalid_index() {
261 let mut chain = FilterChain::new(4);
262 let result = chain.remove_filter(0);
263 assert!(result.is_err());
264 }
265
266 #[test]
267 fn test_clear() {
268 let mut chain = FilterChain::new(4);
269 chain.add_filter(Box::new(IdFilter::new(0x123)));
270 chain.add_filter(Box::new(IdFilter::new(0x456)));
271
272 chain.clear();
273 assert!(chain.is_empty());
274 assert_eq!(chain.hardware_filter_count(), 0);
275 }
276}