tracing_capture/predicates/
combinators.rs

1//! Helper combinators for predicates.
2
3use predicates::{
4    reflection::{Case, PredicateReflection},
5    Predicate,
6};
7
8use std::fmt;
9
10/// Boolean "and" combinator for predicates. Produced by the bitwise and (`&`) operator
11/// on the base predicates from this module.
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub struct And<T, U> {
14    first: T,
15    second: U,
16}
17
18impl<T: PredicateReflection, U: PredicateReflection> And<T, U> {
19    pub(crate) fn new(first: T, second: U) -> Self {
20        Self { first, second }
21    }
22}
23
24impl<T: fmt::Display, U: fmt::Display> fmt::Display for And<T, U> {
25    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
26        write!(formatter, "({} && {})", self.first, self.second)
27    }
28}
29
30impl<T: PredicateReflection, U: PredicateReflection> PredicateReflection for And<T, U> {}
31
32impl<T, U, Item: ?Sized> Predicate<Item> for And<T, U>
33where
34    T: Predicate<Item>,
35    U: Predicate<Item>,
36{
37    fn eval(&self, variable: &Item) -> bool {
38        self.first.eval(variable) && self.second.eval(variable)
39    }
40
41    fn find_case(&self, expected: bool, variable: &Item) -> Option<Case<'_>> {
42        if expected {
43            // We need both child cases.
44            let first = self.first.find_case(expected, variable)?;
45            let second = self.second.find_case(expected, variable)?;
46            let case = Case::new(Some(self), expected)
47                .add_child(first)
48                .add_child(second);
49            Some(case)
50        } else {
51            // Return either of cases if present.
52            if let Some(child) = self.first.find_case(expected, variable) {
53                Some(Case::new(Some(self), expected).add_child(child))
54            } else {
55                self.second
56                    .find_case(expected, variable)
57                    .map(|child| Case::new(Some(self), expected).add_child(child))
58            }
59        }
60    }
61}
62
63/// Boolean "or" combinator for predicates. Produced by the bitwise or (`|`) operator
64/// on the base predicates from this module.
65#[derive(Debug, Clone, Copy, PartialEq, Eq)]
66pub struct Or<T, U> {
67    first: T,
68    second: U,
69}
70
71impl<T: PredicateReflection, U: PredicateReflection> Or<T, U> {
72    pub(crate) fn new(first: T, second: U) -> Self {
73        Self { first, second }
74    }
75}
76
77impl<T: fmt::Display, U: fmt::Display> fmt::Display for Or<T, U> {
78    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
79        write!(formatter, "({} || {})", self.first, self.second)
80    }
81}
82
83impl<T: PredicateReflection, U: PredicateReflection> PredicateReflection for Or<T, U> {}
84
85impl<T, U, Item: ?Sized> Predicate<Item> for Or<T, U>
86where
87    T: Predicate<Item>,
88    U: Predicate<Item>,
89{
90    fn eval(&self, variable: &Item) -> bool {
91        self.first.eval(variable) || self.second.eval(variable)
92    }
93
94    fn find_case(&self, expected: bool, variable: &Item) -> Option<Case<'_>> {
95        if expected {
96            // Return either of cases if present.
97            if let Some(child) = self.first.find_case(expected, variable) {
98                Some(Case::new(Some(self), expected).add_child(child))
99            } else {
100                self.second
101                    .find_case(expected, variable)
102                    .map(|child| Case::new(Some(self), expected).add_child(child))
103            }
104        } else {
105            // We need both child cases.
106            let first = self.first.find_case(expected, variable)?;
107            let second = self.second.find_case(expected, variable)?;
108            let case = Case::new(Some(self), expected)
109                .add_child(first)
110                .add_child(second);
111            Some(case)
112        }
113    }
114}
115
116macro_rules! impl_bool_ops {
117    ($name:ident <$($ty_var:ident),+>) => {
118        impl<Rhs, $($ty_var,)+> core::ops::BitAnd<Rhs> for $name<$($ty_var,)+>
119        where
120            Self: predicates::reflection::PredicateReflection,
121            Rhs: predicates::reflection::PredicateReflection,
122        {
123            type Output = $crate::predicates::And<Self, Rhs>;
124
125            fn bitand(self, rhs: Rhs) -> Self::Output {
126                $crate::predicates::And::new(self, rhs)
127            }
128        }
129
130        impl<Rhs, $($ty_var,)+> core::ops::BitOr<Rhs> for $name<$($ty_var,)+>
131        where
132            Self: predicates::reflection::PredicateReflection,
133            Rhs: predicates::reflection::PredicateReflection,
134        {
135            type Output = $crate::predicates::Or<Self, Rhs>;
136
137            fn bitor(self, rhs: Rhs) -> Self::Output {
138                $crate::predicates::Or::new(self, rhs)
139            }
140        }
141    };
142}
143
144impl_bool_ops!(And<T, U>);
145impl_bool_ops!(Or<T, U>);