1use ltrait::{Filter, filter::FilterWrapper};
2use std::marker::PhantomData;
3
4impl<T> FilterExt for T
5where
6 T: Filter,
7 <T as Filter>::Context: Sync + Send,
8{
9}
10
11pub trait FilterExt: Filter + Sized
12where
13 <Self as Filter>::Context: Sync + Send,
14{
15 fn to_if<Cushion, F, TransF>(self, f: F, transformer: TransF) -> impl Filter<Context = Cushion>
16 where
18 Self: Sized,
19 Cushion: Sync + Send,
20 F: Fn(&Cushion) -> bool + Send,
21 TransF: Fn(&Cushion) -> <Self as Filter>::Context + Send,
22 {
23 FilterIf::new(self, f, transformer)
24 }
25
26 fn reverse(self) -> impl Filter<Context = <Self as Filter>::Context> {
27 ReversedFilter::new(self)
28 }
29
30 fn comb<Cushion, T, Ctx, F1, F2, F3>(
31 self,
32 transformer1: F1,
33 filter2: T,
34 transformer2: F2,
35 predicater: F3,
36 ) -> impl Filter<Context = Cushion>
37 where
38 Self: Sized,
39 T: Filter<Context = Ctx>,
40 F1: Fn(&Cushion) -> <Self as Filter>::Context + Send,
41 F2: Fn(&Cushion) -> Ctx + Send,
42 F3: Fn(bool, bool) -> bool + Send,
43 Cushion: Sync + Send,
44 {
45 FilterComb::new(self, transformer1, filter2, transformer2, predicater)
46 }
47}
48
49pub struct FilterComb<Cushion, T1, T2, C1, C2, F1, F2, F3>
50where
51 F1: Fn(&Cushion) -> C1 + Send,
52 F2: Fn(&Cushion) -> C2 + Send,
53 F3: Fn(bool, bool) -> bool + Send,
54 T1: Filter<Context = C1>,
55 T2: Filter<Context = C2>,
56 Cushion: Sync,
57{
58 filter1: T1,
59 filter2: T2,
60
61 transformer1: F1,
62 transformer2: F2,
63
64 predicater: F3,
65
66 _cushion: PhantomData<Cushion>,
67}
68
69impl<Cushion, T1, T2, C1, C2, F1, F2, F3> Filter for FilterComb<Cushion, T1, T2, C1, C2, F1, F2, F3>
70where
71 F1: Fn(&Cushion) -> C1 + Send,
72 F2: Fn(&Cushion) -> C2 + Send,
73 F3: Fn(bool, bool) -> bool + Send,
74 T1: Filter<Context = C1>,
75 T2: Filter<Context = C2>,
76 Cushion: Sync + Send,
77{
78 type Context = Cushion;
79
80 fn predicate(&self, ctx: &Self::Context, input: &str) -> bool {
81 (self.predicater)(
82 self.filter1.predicate(&(self.transformer1)(ctx), input),
83 self.filter2.predicate(&(self.transformer2)(ctx), input),
84 )
85 }
86}
87
88impl<Cushion, T1, T2, C1, C2, F1, F2, F3> FilterComb<Cushion, T1, T2, C1, C2, F1, F2, F3>
89where
90 F1: Fn(&Cushion) -> C1 + Send,
91 F2: Fn(&Cushion) -> C2 + Send,
92 F3: Fn(bool, bool) -> bool + Send,
93 T1: Filter<Context = C1>,
94 T2: Filter<Context = C2>,
95 Cushion: Sync,
96{
97 pub fn new(
98 filter1: T1,
99 transformer1: F1,
100 filter2: T2,
101 transformer2: F2,
102 predicater: F3,
103 ) -> Self {
104 Self {
105 filter1,
106 filter2,
107 transformer1,
108 transformer2,
109 predicater,
110 _cushion: PhantomData,
111 }
112 }
113}
114
115pub struct FilterIf<T, Ctx, F>
116where
117 T: Filter<Context = Ctx>,
118 F: Fn(&Ctx) -> bool + Send,
119 Ctx: Sync,
120{
121 filter: T,
122
123 f: F,
124
125 _ctx: PhantomData<Ctx>,
126}
127
128impl<Cushion, F, InnerF, TransF, Ctx>
129 FilterIf<FilterWrapper<Ctx, InnerF, TransF, Cushion>, Cushion, F>
130where
131 F: Fn(&Cushion) -> bool + Send,
132 Cushion: Sync + Send,
133 TransF: Fn(&Cushion) -> Ctx + Send,
134 InnerF: Filter<Context = Ctx>,
135 Ctx: Sync + Send,
136{
137 pub fn new(filter: InnerF, f: F, transformer: TransF) -> Self {
138 Self {
139 filter: FilterWrapper::new(filter, transformer),
140 f,
141 _ctx: PhantomData,
142 }
143 }
144}
145
146impl<T, Ctx, F> Filter for FilterIf<T, Ctx, F>
147where
148 T: Filter<Context = Ctx>,
149 F: Fn(&Ctx) -> bool + Send,
150 Ctx: Sync + Send,
151{
152 type Context = Ctx;
153
154 fn predicate(&self, ctx: &Self::Context, input: &str) -> bool {
155 if (self.f)(ctx) {
156 self.filter.predicate(ctx, input)
157 } else {
158 true
159 }
160 }
161}
162
163pub struct ReversedFilter<T, Ctx>
164where
165 T: Filter<Context = Ctx>,
166 Ctx: Sync,
167{
168 filter: T,
169
170 _ctx: PhantomData<Ctx>,
171}
172
173impl<T, Ctx> ReversedFilter<T, Ctx>
174where
175 T: Filter<Context = Ctx>,
176 Ctx: Sync,
177{
178 pub fn new(filter: T) -> Self {
179 Self {
180 filter,
181 _ctx: PhantomData,
182 }
183 }
184}
185
186impl<T, Ctx> Filter for ReversedFilter<T, Ctx>
187where
188 T: Filter<Context = Ctx>,
189 Ctx: Sync + Send,
190{
191 type Context = Ctx;
192
193 fn predicate(&self, ctx: &Self::Context, input: &str) -> bool {
194 !self.filter.predicate(ctx, input)
195 }
196}