1use crate::{
8 and::And,
9 empty::Empty,
10 event::{Event, ToEvent},
11 or::Or,
12 props::ErasedProps,
13};
14
15pub trait Filter {
21 fn matches<E: ToEvent>(&self, evt: E) -> bool;
27
28 fn and_when<U>(self, other: U) -> And<Self, U>
34 where
35 Self: Sized,
36 {
37 And::new(self, other)
38 }
39
40 fn or_when<U>(self, other: U) -> Or<Self, U>
46 where
47 Self: Sized,
48 {
49 Or::new(self, other)
50 }
51}
52
53impl<'a, F: Filter + ?Sized> Filter for &'a F {
54 fn matches<E: ToEvent>(&self, evt: E) -> bool {
55 (**self).matches(evt)
56 }
57}
58
59#[cfg(feature = "alloc")]
60impl<'a, F: Filter + ?Sized + 'a> Filter for alloc::boxed::Box<F> {
61 fn matches<E: ToEvent>(&self, evt: E) -> bool {
62 (**self).matches(evt)
63 }
64}
65
66#[cfg(feature = "alloc")]
67impl<'a, F: Filter + ?Sized + 'a> Filter for alloc::sync::Arc<F> {
68 fn matches<E: ToEvent>(&self, evt: E) -> bool {
69 (**self).matches(evt)
70 }
71}
72
73impl<F: Filter> Filter for Option<F> {
74 fn matches<E: ToEvent>(&self, evt: E) -> bool {
75 match self {
76 Some(filter) => filter.matches(evt),
77 None => Empty.matches(evt),
78 }
79 }
80}
81
82impl Filter for Empty {
83 fn matches<E: ToEvent>(&self, _: E) -> bool {
84 true
85 }
86}
87
88impl Filter for fn(Event<&dyn ErasedProps>) -> bool {
89 fn matches<E: ToEvent>(&self, evt: E) -> bool {
90 (self)(evt.to_event().erase())
91 }
92}
93
94pub struct FromFn<F = fn(Event<&dyn ErasedProps>) -> bool>(F);
100
101impl<F> FromFn<F> {
102 pub const fn new(filter: F) -> FromFn<F> {
106 FromFn(filter)
107 }
108}
109
110impl<F: Fn(Event<&dyn ErasedProps>) -> bool> Filter for FromFn<F> {
111 fn matches<E: ToEvent>(&self, evt: E) -> bool {
112 (self.0)(evt.to_event().erase())
113 }
114}
115
116pub const fn from_fn<F: Fn(Event<&dyn ErasedProps>) -> bool>(f: F) -> FromFn<F> {
120 FromFn(f)
121}
122
123pub struct Always {}
127
128impl Always {
129 pub const fn new() -> Always {
133 Always {}
134 }
135}
136
137impl Filter for Always {
138 fn matches<E: ToEvent>(&self, _: E) -> bool {
139 true
140 }
141}
142
143pub const fn always() -> Always {
147 Always::new()
148}
149
150impl<T: Filter, U: Filter> Filter for And<T, U> {
151 fn matches<E: ToEvent>(&self, evt: E) -> bool {
152 let evt = evt.to_event();
153
154 self.left().matches(&evt) && self.right().matches(&evt)
155 }
156}
157
158impl<T: Filter, U: Filter> Filter for Or<T, U> {
159 fn matches<E: ToEvent>(&self, evt: E) -> bool {
160 let evt = evt.to_event();
161
162 self.left().matches(&evt) || self.right().matches(&evt)
163 }
164}
165
166mod internal {
167 use crate::{event::Event, props::ErasedProps};
168
169 pub trait DispatchFilter {
170 fn dispatch_matches(&self, evt: &Event<&dyn ErasedProps>) -> bool;
171 }
172
173 pub trait SealedFilter {
174 fn erase_filter(&self) -> crate::internal::Erased<&dyn DispatchFilter>;
175 }
176}
177
178pub trait ErasedFilter: internal::SealedFilter {}
184
185impl<T: Filter> ErasedFilter for T {}
186
187impl<T: Filter> internal::SealedFilter for T {
188 fn erase_filter(&self) -> crate::internal::Erased<&dyn internal::DispatchFilter> {
189 crate::internal::Erased(self)
190 }
191}
192
193impl<T: Filter> internal::DispatchFilter for T {
194 fn dispatch_matches(&self, evt: &Event<&dyn ErasedProps>) -> bool {
195 self.matches(evt)
196 }
197}
198
199impl<'a> Filter for dyn ErasedFilter + 'a {
200 fn matches<E: ToEvent>(&self, evt: E) -> bool {
201 self.erase_filter()
202 .0
203 .dispatch_matches(&evt.to_event().erase())
204 }
205}
206
207impl<'a> Filter for dyn ErasedFilter + Send + Sync + 'a {
208 fn matches<E: ToEvent>(&self, evt: E) -> bool {
209 (self as &(dyn ErasedFilter + 'a)).matches(evt)
210 }
211}
212
213#[cfg(test)]
214mod tests {
215 use crate::{path::Path, template::Template};
216
217 use super::*;
218
219 struct MyFilter {
220 matches: bool,
221 }
222
223 impl Filter for MyFilter {
224 fn matches<E: ToEvent>(&self, _: E) -> bool {
225 self.matches
226 }
227 }
228
229 #[test]
230 fn option_filter() {
231 for (case, matches) in [(Some(MyFilter { matches: false }), false), (None, true)] {
232 assert_eq!(
233 matches,
234 case.matches(Event::new(
235 Path::new_raw("module"),
236 Template::literal("Event"),
237 Empty,
238 Empty,
239 ))
240 );
241 }
242 }
243
244 #[test]
245 fn and_filter() {
246 for a in [true, false] {
247 for b in [true, false] {
248 let fa = MyFilter { matches: a };
249 let fb = MyFilter { matches: b };
250
251 assert_eq!(
252 a && b,
253 fa.and_when(fb).matches(Event::new(
254 Path::new_raw("module"),
255 Template::literal("Event"),
256 Empty,
257 Empty,
258 ))
259 );
260 }
261 }
262 }
263
264 #[test]
265 fn or_filter() {
266 for a in [true, false] {
267 for b in [true, false] {
268 let fa = MyFilter { matches: a };
269 let fb = MyFilter { matches: b };
270
271 assert_eq!(
272 a || b,
273 fa.or_when(fb).matches(Event::new(
274 Path::new_raw("module"),
275 Template::literal("Event"),
276 Empty,
277 Empty,
278 ))
279 );
280 }
281 }
282 }
283
284 #[test]
285 fn from_fn_filter() {
286 let f = from_fn(|evt| evt.mdl() == Path::new_raw("module"));
287
288 assert!(f.matches(Event::new(
289 Path::new_raw("module"),
290 Template::literal("Event"),
291 Empty,
292 Empty,
293 )));
294
295 assert!(!f.matches(Event::new(
296 Path::new_raw("not_module"),
297 Template::literal("Event"),
298 Empty,
299 Empty,
300 )));
301 }
302
303 #[test]
304 fn always_filter() {
305 let f = always();
306
307 assert!(f.matches(Event::new(
308 Path::new_raw("module"),
309 Template::literal("Event"),
310 Empty,
311 Empty,
312 )));
313 }
314
315 #[test]
316 fn erased_filter() {
317 let f = MyFilter { matches: true };
318 let f = &f as &dyn ErasedFilter;
319
320 assert!(f.matches(Event::new(
321 Path::new_raw("module"),
322 Template::literal("Event"),
323 Empty,
324 Empty,
325 )));
326
327 let f = MyFilter { matches: false };
328 let f = &f as &dyn ErasedFilter;
329
330 assert!(!f.matches(Event::new(
331 Path::new_raw("module"),
332 Template::literal("Event"),
333 Empty,
334 Empty,
335 )));
336 }
337}