hitbox_core/predicate/
combinators.rs1use async_trait::async_trait;
20
21use super::{Predicate, PredicateResult};
22
23#[derive(Debug)]
28pub struct Not<P> {
29 predicate: P,
30}
31
32impl<P> Not<P> {
33 pub fn new(predicate: P) -> Self {
35 Self { predicate }
36 }
37}
38
39#[async_trait]
40impl<P> Predicate for Not<P>
41where
42 P: Predicate + Send + Sync,
43 P::Subject: Send,
44{
45 type Subject = P::Subject;
46
47 async fn check(&self, subject: Self::Subject) -> PredicateResult<Self::Subject> {
48 match self.predicate.check(subject).await {
49 PredicateResult::Cacheable(s) => PredicateResult::NonCacheable(s),
50 PredicateResult::NonCacheable(s) => PredicateResult::Cacheable(s),
51 }
52 }
53}
54
55#[derive(Debug)]
60pub struct And<L, R> {
61 left: L,
62 right: R,
63}
64
65impl<L, R> And<L, R> {
66 pub fn new(left: L, right: R) -> Self {
68 Self { left, right }
69 }
70}
71
72#[async_trait]
73impl<L, R> Predicate for And<L, R>
74where
75 L: Predicate + Send + Sync,
76 R: Predicate<Subject = L::Subject> + Send + Sync,
77 L::Subject: Send,
78{
79 type Subject = L::Subject;
80
81 async fn check(&self, subject: Self::Subject) -> PredicateResult<Self::Subject> {
82 match self.left.check(subject).await {
83 PredicateResult::Cacheable(s) => self.right.check(s).await,
84 non_cacheable => non_cacheable,
85 }
86 }
87}
88
89#[derive(Debug)]
94pub struct Or<L, R> {
95 left: L,
96 right: R,
97}
98
99impl<L, R> Or<L, R> {
100 pub fn new(left: L, right: R) -> Self {
102 Self { left, right }
103 }
104}
105
106#[async_trait]
107impl<L, R> Predicate for Or<L, R>
108where
109 L: Predicate + Send + Sync,
110 R: Predicate<Subject = L::Subject> + Send + Sync,
111 L::Subject: Send,
112{
113 type Subject = L::Subject;
114
115 async fn check(&self, subject: Self::Subject) -> PredicateResult<Self::Subject> {
116 match self.left.check(subject).await {
117 PredicateResult::NonCacheable(s) => self.right.check(s).await,
118 cacheable => cacheable,
119 }
120 }
121}
122
123pub trait PredicateExt: Predicate + Sized {
125 fn and<R>(self, right: R) -> And<Self, R>
129 where
130 R: Predicate<Subject = Self::Subject>,
131 {
132 And::new(self, right)
133 }
134
135 fn or<R>(self, right: R) -> Or<Self, R>
139 where
140 R: Predicate<Subject = Self::Subject>,
141 {
142 Or::new(self, right)
143 }
144
145 fn not(self) -> Not<Self> {
149 Not::new(self)
150 }
151
152 fn boxed(self) -> Box<dyn Predicate<Subject = Self::Subject> + Send + Sync>
157 where
158 Self: Send + Sync + 'static,
159 {
160 Box::new(self)
161 }
162}
163
164impl<T: Predicate + Sized> PredicateExt for T {}