1use crate::Record;
2use crate::RecordKind;
3use itertools::Itertools;
4use std::fmt;
5
6pub trait RecordFilter: Send + 'static {
18 fn check(&self, record: &Record) -> bool;
23
24 fn fmt_debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29 f.write_str("UnknownFilter")
30 }
31}
32
33impl<T: RecordFilter + ?Sized> RecordFilter for Box<T> {
34 fn check(&self, record: &Record) -> bool {
35 (**self).check(record)
36 }
37
38 fn fmt_debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 (**self).fmt_debug(f)
40 }
41}
42
43#[derive(Debug, Clone, Copy, Default)]
52pub struct DefaultFilter;
53
54impl RecordFilter for DefaultFilter {
55 #[inline]
56 fn check(&self, _record: &Record) -> bool {
57 true
58 }
59
60 fn fmt_debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 fmt::Debug::fmt(self, f)
62 }
63}
64
65#[derive(Debug)]
76pub struct RecordKindFilter {
77 allowed_kinds: Vec<RecordKind>,
78}
79
80impl RecordKindFilter {
81 pub fn new(kinds: &'static [RecordKind]) -> Self {
83 Self {
84 allowed_kinds: kinds.iter().copied().unique().collect(),
85 }
86 }
87}
88
89impl RecordFilter for RecordKindFilter {
90 #[inline]
91 fn check(&self, record: &Record) -> bool {
92 self.allowed_kinds.contains(&record.kind)
93 }
94
95 fn fmt_debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
96 fmt::Debug::fmt(self, f)
97 }
98}
99
100pub struct AllFilter {
131 filters: Vec<Box<dyn RecordFilter>>,
132}
133
134impl fmt::Debug for AllFilter {
135 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136 f.debug_struct("AllFilter")
137 .field("filters", &RecordFiltersDebug(&self.filters))
138 .finish()
139 }
140}
141
142impl AllFilter {
143 pub fn new(filters: Vec<Box<dyn RecordFilter>>) -> Self {
160 Self { filters }
161 }
162}
163
164impl RecordFilter for AllFilter {
165 #[inline]
166 fn check(&self, record: &Record) -> bool {
167 self.filters.iter().all(|filter| filter.check(record))
168 }
169
170 fn fmt_debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
171 fmt::Debug::fmt(self, f)
172 }
173}
174
175pub struct AnyFilter {
210 filters: Vec<Box<dyn RecordFilter>>,
211}
212
213impl fmt::Debug for AnyFilter {
214 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
215 f.debug_struct("AnyFilter")
216 .field("filters", &RecordFiltersDebug(&self.filters))
217 .finish()
218 }
219}
220
221impl AnyFilter {
222 pub fn new(filters: Vec<Box<dyn RecordFilter>>) -> Self {
239 Self { filters }
240 }
241}
242
243impl RecordFilter for AnyFilter {
244 #[inline]
245 fn check(&self, record: &Record) -> bool {
246 self.filters.iter().any(|filter| filter.check(record))
247 }
248
249 fn fmt_debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
250 fmt::Debug::fmt(self, f)
251 }
252}
253
254struct RecordFilterDebug<'a>(&'a dyn RecordFilter);
260
261impl fmt::Debug for RecordFilterDebug<'_> {
262 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
263 self.0.fmt_debug(f)
264 }
265}
266
267struct RecordFiltersDebug<'a>(&'a [Box<dyn RecordFilter>]);
269
270impl fmt::Debug for RecordFiltersDebug<'_> {
271 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
272 let mut list = f.debug_list();
273 for filter in self.0.iter() {
274 list.entry(&RecordFilterDebug(filter.as_ref()));
275 }
276 list.finish()
277 }
278}
279
280#[cfg(test)]
285mod tests {
286 use crate::filter::AllFilter;
287 use crate::filter::AnyFilter;
288 use crate::filter::DefaultFilter;
289 use crate::filter::RecordFilter;
290 use crate::filter::RecordKindFilter;
291 use crate::record::Record;
292 use crate::record::RecordKind;
293 use std::fmt;
294
295 fn assert_unpin<T: Unpin>() {}
296
297 #[test]
298 fn test_unpin() {
299 assert_unpin::<DefaultFilter>();
300 assert_unpin::<RecordKindFilter>();
301 assert_unpin::<AllFilter>();
302 assert_unpin::<AnyFilter>();
303 }
304
305 #[test]
306 fn test_default_filter() {
307 assert!(DefaultFilter.check(&Record::new(
308 RecordKind::Read,
309 String::from("01:02:03:04:05:06")
310 )));
311 assert!(DefaultFilter.check(&Record::new(
312 RecordKind::Write,
313 String::from("01:02:03:04:05:06")
314 )));
315 assert!(DefaultFilter.check(&Record::new(RecordKind::Drop, String::from("deallocated"))));
316 assert!(DefaultFilter.check(&Record::new(
317 RecordKind::Shutdown,
318 String::from("write shutdown request")
319 )));
320 }
321
322 #[test]
323 fn test_record_kind_filter() {
324 let filter = RecordKindFilter::new(&[RecordKind::Read]);
325 assert!(filter.check(&Record::new(
326 RecordKind::Read,
327 String::from("01:02:03:04:05:06")
328 )));
329 assert!(!filter.check(&Record::new(
330 RecordKind::Write,
331 String::from("01:02:03:04:05:06")
332 )));
333 assert!(!filter.check(&Record::new(RecordKind::Drop, String::from("deallocated"))));
334 assert!(!filter.check(&Record::new(
335 RecordKind::Shutdown,
336 String::from("write shutdown request")
337 )));
338 }
339
340 #[test]
341 fn test_all_filter_empty() {
342 let filter = AllFilter::new(vec![]);
343 assert!(filter.check(&Record::new(RecordKind::Read, String::from("test"))));
345 assert!(filter.check(&Record::new(RecordKind::Write, String::from("test"))));
346 assert!(filter.check(&Record::new(RecordKind::Error, String::from("test"))));
347 }
348
349 #[test]
350 fn test_all_filter_single() {
351 let filter = AllFilter::new(vec![Box::new(RecordKindFilter::new(&[RecordKind::Read]))]);
352
353 assert!(filter.check(&Record::new(RecordKind::Read, String::from("data"))));
354 assert!(!filter.check(&Record::new(RecordKind::Write, String::from("data"))));
355 assert!(!filter.check(&Record::new(RecordKind::Error, String::from("error"))));
356 }
357
358 #[test]
359 fn test_all_filter_multiple_all_pass() {
360 let filter = AllFilter::new(vec![
362 Box::new(RecordKindFilter::new(&[
363 RecordKind::Read,
364 RecordKind::Write,
365 ])),
366 Box::new(RecordKindFilter::new(&[
367 RecordKind::Read,
368 RecordKind::Error,
369 ])),
370 ]);
371
372 assert!(filter.check(&Record::new(RecordKind::Read, String::from("data"))));
373 }
374
375 #[test]
376 fn test_all_filter_multiple_one_fails() {
377 let filter = AllFilter::new(vec![
379 Box::new(RecordKindFilter::new(&[
380 RecordKind::Read,
381 RecordKind::Write,
382 ])),
383 Box::new(RecordKindFilter::new(&[
384 RecordKind::Read,
385 RecordKind::Error,
386 ])),
387 ]);
388
389 assert!(!filter.check(&Record::new(RecordKind::Write, String::from("data"))));
390 }
391
392 #[test]
393 fn test_all_filter_multiple_all_fail() {
394 let filter = AllFilter::new(vec![
395 Box::new(RecordKindFilter::new(&[RecordKind::Read])),
396 Box::new(RecordKindFilter::new(&[RecordKind::Write])),
397 ]);
398
399 assert!(!filter.check(&Record::new(RecordKind::Error, String::from("error"))));
400 }
401
402 #[test]
403 fn test_all_filter_with_default() {
404 let filter = AllFilter::new(vec![
406 Box::new(DefaultFilter),
407 Box::new(RecordKindFilter::new(&[RecordKind::Read])),
408 ]);
409
410 assert!(filter.check(&Record::new(RecordKind::Read, String::from("data"))));
411 assert!(!filter.check(&Record::new(RecordKind::Write, String::from("data"))));
412 }
413
414 #[test]
415 fn test_any_filter_empty() {
416 let filter = AnyFilter::new(vec![]);
417 assert!(!filter.check(&Record::new(RecordKind::Read, String::from("test"))));
419 assert!(!filter.check(&Record::new(RecordKind::Write, String::from("test"))));
420 assert!(!filter.check(&Record::new(RecordKind::Error, String::from("test"))));
421 }
422
423 #[test]
424 fn test_any_filter_single() {
425 let filter = AnyFilter::new(vec![Box::new(RecordKindFilter::new(&[RecordKind::Read]))]);
426
427 assert!(filter.check(&Record::new(RecordKind::Read, String::from("data"))));
428 assert!(!filter.check(&Record::new(RecordKind::Write, String::from("data"))));
429 assert!(!filter.check(&Record::new(RecordKind::Error, String::from("error"))));
430 }
431
432 #[test]
433 fn test_any_filter_multiple_first_passes() {
434 let filter = AnyFilter::new(vec![
435 Box::new(RecordKindFilter::new(&[RecordKind::Read])),
436 Box::new(RecordKindFilter::new(&[RecordKind::Write])),
437 ]);
438
439 assert!(filter.check(&Record::new(RecordKind::Read, String::from("data"))));
440 }
441
442 #[test]
443 fn test_any_filter_multiple_second_passes() {
444 let filter = AnyFilter::new(vec![
445 Box::new(RecordKindFilter::new(&[RecordKind::Read])),
446 Box::new(RecordKindFilter::new(&[RecordKind::Write])),
447 ]);
448
449 assert!(filter.check(&Record::new(RecordKind::Write, String::from("data"))));
450 }
451
452 #[test]
453 fn test_any_filter_multiple_all_pass() {
454 let filter = AnyFilter::new(vec![
455 Box::new(RecordKindFilter::new(&[
456 RecordKind::Read,
457 RecordKind::Write,
458 ])),
459 Box::new(RecordKindFilter::new(&[
460 RecordKind::Read,
461 RecordKind::Error,
462 ])),
463 ]);
464
465 assert!(filter.check(&Record::new(RecordKind::Read, String::from("data"))));
466 }
467
468 #[test]
469 fn test_any_filter_multiple_all_fail() {
470 let filter = AnyFilter::new(vec![
471 Box::new(RecordKindFilter::new(&[RecordKind::Read])),
472 Box::new(RecordKindFilter::new(&[RecordKind::Write])),
473 ]);
474
475 assert!(!filter.check(&Record::new(RecordKind::Error, String::from("error"))));
476 }
477
478 #[test]
479 fn test_any_filter_with_default() {
480 let filter = AnyFilter::new(vec![
482 Box::new(RecordKindFilter::new(&[RecordKind::Read])),
483 Box::new(DefaultFilter),
484 ]);
485
486 assert!(filter.check(&Record::new(RecordKind::Read, String::from("data"))));
488 assert!(filter.check(&Record::new(RecordKind::Write, String::from("data"))));
489 assert!(filter.check(&Record::new(RecordKind::Error, String::from("error"))));
490 }
491
492 #[test]
493 fn test_nested_composite_filters() {
494 let filter = AllFilter::new(vec![Box::new(AnyFilter::new(vec![
497 Box::new(RecordKindFilter::new(&[RecordKind::Read])),
498 Box::new(RecordKindFilter::new(&[RecordKind::Write])),
499 ]))]);
500
501 assert!(filter.check(&Record::new(RecordKind::Read, String::from("data"))));
502 assert!(filter.check(&Record::new(RecordKind::Write, String::from("data"))));
503 assert!(!filter.check(&Record::new(RecordKind::Drop, String::from("dropped"))));
504 assert!(!filter.check(&Record::new(RecordKind::Error, String::from("error"))));
505 }
506
507 #[test]
508 fn test_complex_nested_filters() {
509 let filter = AllFilter::new(vec![
513 Box::new(AnyFilter::new(vec![
514 Box::new(RecordKindFilter::new(&[RecordKind::Read])),
515 Box::new(RecordKindFilter::new(&[RecordKind::Write])),
516 ])),
517 Box::new(AnyFilter::new(vec![
518 Box::new(RecordKindFilter::new(&[RecordKind::Read])),
519 Box::new(RecordKindFilter::new(&[RecordKind::Error])),
520 ])),
521 ]);
522
523 assert!(filter.check(&Record::new(RecordKind::Read, String::from("data"))));
524 assert!(!filter.check(&Record::new(RecordKind::Write, String::from("data"))));
525 assert!(!filter.check(&Record::new(RecordKind::Error, String::from("error"))));
526 assert!(!filter.check(&Record::new(RecordKind::Drop, String::from("dropped"))));
527 }
528
529 #[test]
530 fn test_trait_object_safety() {
531 let default: Box<dyn RecordFilter> = Box::<DefaultFilter>::default();
533 let record_kind: Box<dyn RecordFilter> = Box::new(RecordKindFilter::new(&[]));
534 let all: Box<dyn RecordFilter> = Box::new(AllFilter::new(vec![]));
535 let any: Box<dyn RecordFilter> = Box::new(AnyFilter::new(vec![]));
536
537 let record = Record::new(RecordKind::Open, String::from("test log record"));
538
539 _ = default.check(&record);
541 _ = record_kind.check(&record);
542 _ = all.check(&record);
543 _ = any.check(&record);
544 }
545
546 fn assert_record_filter<T: RecordFilter>() {}
547
548 #[test]
549 fn test_box() {
550 assert_record_filter::<Box<dyn RecordFilter>>();
551 assert_record_filter::<Box<RecordKindFilter>>();
552 assert_record_filter::<Box<DefaultFilter>>();
553 assert_record_filter::<Box<AllFilter>>();
554 assert_record_filter::<Box<AnyFilter>>();
555 }
556
557 fn assert_send<T: Send>() {}
558
559 #[test]
560 fn test_send() {
561 assert_send::<RecordKindFilter>();
562 assert_send::<DefaultFilter>();
563 assert_send::<AllFilter>();
564 assert_send::<AnyFilter>();
565
566 assert_send::<Box<dyn RecordFilter>>();
567 assert_send::<Box<RecordKindFilter>>();
568 assert_send::<Box<DefaultFilter>>();
569 assert_send::<Box<AllFilter>>();
570 assert_send::<Box<AnyFilter>>();
571 }
572
573 fn assert_debug<T: fmt::Debug>() {}
574
575 #[test]
576 fn test_debug() {
577 assert_debug::<DefaultFilter>();
578 assert_debug::<RecordKindFilter>();
579 assert_debug::<AllFilter>();
580 assert_debug::<AnyFilter>();
581
582 assert_debug::<Box<DefaultFilter>>();
583 assert_debug::<Box<RecordKindFilter>>();
584 assert_debug::<Box<AllFilter>>();
585 assert_debug::<Box<AnyFilter>>();
586 }
587
588 #[test]
589 fn test_debug_output() {
590 assert_eq!(format!("{:?}", DefaultFilter), "DefaultFilter");
592
593 let record_kind_filter = RecordKindFilter::new(&[RecordKind::Read, RecordKind::Write]);
595 let debug_str = format!("{:?}", record_kind_filter);
596 assert!(debug_str.contains("RecordKindFilter"));
597 assert!(debug_str.contains("Read"));
598 assert!(debug_str.contains("Write"));
599
600 let all_filter_empty = AllFilter::new(vec![]);
602 let debug_str = format!("{:?}", all_filter_empty);
603 assert!(debug_str.contains("AllFilter"));
604 assert!(debug_str.contains("filters: []"));
605
606 let all_filter = AllFilter::new(vec![
608 Box::new(RecordKindFilter::new(&[RecordKind::Read])),
609 Box::new(DefaultFilter),
610 ]);
611 let debug_str = format!("{:?}", all_filter);
612 assert!(debug_str.contains("AllFilter"));
613 assert!(debug_str.contains("RecordKindFilter"));
614 assert!(debug_str.contains("Read"));
615 assert!(debug_str.contains("DefaultFilter"));
616
617 let any_filter_empty = AnyFilter::new(vec![]);
619 let debug_str = format!("{:?}", any_filter_empty);
620 assert!(debug_str.contains("AnyFilter"));
621 assert!(debug_str.contains("filters: []"));
622
623 let any_filter = AnyFilter::new(vec![
625 Box::new(RecordKindFilter::new(&[RecordKind::Write])),
626 Box::new(DefaultFilter),
627 ]);
628 let debug_str = format!("{:?}", any_filter);
629 assert!(debug_str.contains("AnyFilter"));
630 assert!(debug_str.contains("RecordKindFilter"));
631 assert!(debug_str.contains("Write"));
632 assert!(debug_str.contains("DefaultFilter"));
633
634 let nested = AllFilter::new(vec![Box::new(AnyFilter::new(vec![Box::new(
636 RecordKindFilter::new(&[RecordKind::Read]),
637 )]))]);
638 let debug_str = format!("{:?}", nested);
639 assert!(debug_str.contains("AllFilter"));
640 assert!(debug_str.contains("AnyFilter"));
641 assert!(debug_str.contains("RecordKindFilter"));
642 assert!(debug_str.contains("Read"));
643 }
644}