filters/failable/
filter.rs

1//
2// This Source Code Form is subject to the terms of the Mozilla Public
3// License, v. 2.0. If a copy of the MPL was not distributed with this
4// file, You can obtain one at http://mozilla.org/MPL/2.0/.
5//
6
7use std::borrow::Borrow;
8
9pub use failable::ops::and::FailableAnd;
10pub use failable::ops::bool::FailableBool;
11pub use failable::ops::not::FailableNot;
12pub use failable::ops::xor::FailableXOr;
13pub use failable::ops::or::FailableOr;
14pub use failable::ops::map::{FailableMapInput, FailableMapErr};
15
16/// Trait for converting something into a Filter
17pub trait IntoFailableFilter<N> {
18    type IntoFilt: FailableFilter<N>;
19
20    fn into_failable_filter(self) -> Self::IntoFilt;
21}
22
23/// All Filters can be turned into Filters
24impl<N, I: FailableFilter<N>> IntoFailableFilter<N> for I {
25    type IntoFilt = I;
26
27    fn into_failable_filter(self) -> Self::IntoFilt {
28        self
29    }
30}
31
32pub trait FailableFilter<N> {
33    type Error: Sized;
34
35    /// The function which is used to filter something
36    fn filter(&self, &N) -> Result<bool, Self::Error>;
37
38    /// Helper to invert a filter.
39    ///
40    /// ```
41    /// # #[derive(Debug)]
42    /// # struct ErrorStub { }
43    /// #
44    /// use filters::failable::filter::FailableFilter;
45    ///
46    /// let f = (|&a: &usize| -> Result<bool, ErrorStub> { Ok(a == 1) }).not();
47    ///
48    /// assert!(f.filter(&2).unwrap());
49    /// ```
50    fn not(self) -> FailableNot<Self>
51        where Self: Sized
52    {
53        FailableNot::new(self)
54    }
55
56    /// Helper to connect two filters via logical OR
57    ///
58    /// ```
59    /// # #[derive(Debug)]
60    /// # struct ErrorStub { }
61    /// #
62    /// use filters::failable::filter::FailableFilter;
63    ///
64    /// let a = (|&a: &usize| -> Result<bool, ErrorStub> { Ok(a == 1) });
65    /// let b = (|&a: &usize| -> Result<bool, ErrorStub> { Ok(a == 2) });
66    /// let c = a.or(b);
67    ///
68    /// assert!(c.filter(&1).unwrap());
69    /// assert!(c.filter(&2).unwrap());
70    /// assert!(!c.filter(&7).unwrap());
71    /// ```
72    fn or<F>(self, other: F) -> FailableOr<Self, F::IntoFilt>
73        where Self: Sized,
74              F: IntoFailableFilter<N> + Sized
75    {
76        FailableOr::new(self, other.into_failable_filter())
77    }
78
79    /// Helper to connect two filters via logical OR and NOT
80    ///
81    /// ```
82    /// # #[derive(Debug)]
83    /// # struct ErrorStub { }
84    /// #
85    /// use filters::failable::filter::FailableFilter;
86    ///
87    /// let a = (|&a: &usize| -> Result<bool, ErrorStub> { Ok(a == 1) });
88    /// let b = (|&a: &usize| -> Result<bool, ErrorStub> { Ok(a == 2) });
89    /// let c = a.or_not(b);
90    ///
91    /// assert!(c.filter(&1).unwrap());
92    /// assert!(!c.filter(&2).unwrap());
93    /// assert!(c.filter(&7).unwrap());
94    /// ```
95    fn or_not<F>(self, other: F) -> FailableOr<Self, FailableNot<F::IntoFilt>>
96        where Self: Sized,
97              F: IntoFailableFilter<N> + Sized,
98    {
99        self.or(FailableNot::new(other.into_failable_filter()))
100    }
101
102    /// Helper to connect three filters via logical OR
103    ///
104    /// ```
105    /// # #[derive(Debug)]
106    /// # struct ErrorStub { }
107    /// #
108    /// use filters::failable::filter::FailableFilter;
109    ///
110    /// let a = (|&a: &usize| -> Result<bool, ErrorStub> { Ok(a == 1) });
111    /// let b = (|&a: &usize| -> Result<bool, ErrorStub> { Ok(a == 2) });
112    /// let c = (|&a: &usize| -> Result<bool, ErrorStub> { Ok(a == 3) });
113    /// let d = a.or3(b, c);
114    ///
115    /// assert!(d.filter(&1).unwrap());
116    /// assert!(d.filter(&2).unwrap());
117    /// assert!(d.filter(&3).unwrap());
118    /// assert!(!d.filter(&4).unwrap());
119    /// ```
120    fn or3<F, F2>(self, other: F, other2: F2) -> FailableOr<Self, FailableOr<F::IntoFilt, F2::IntoFilt>>
121        where Self: Sized,
122              F: IntoFailableFilter<N> + Sized,
123              F2: IntoFailableFilter<N> + Sized
124    {
125        FailableOr::new(self, FailableOr::new(other.into_failable_filter(), other2.into_failable_filter()))
126    }
127
128    /// Helper to connect two filters via logical NOR
129    ///
130    /// ```
131    /// # #[derive(Debug)]
132    /// # struct ErrorStub { }
133    /// #
134    /// use filters::failable::filter::FailableFilter;
135    ///
136    /// let a = (|&a: &usize| -> Result<bool, ErrorStub> { Ok(a == 1) });
137    /// let b = (|&a: &usize| -> Result<bool, ErrorStub> { Ok(a == 2) });
138    /// let c = a.nor(b); /* !(a == 1 || a == 2) */
139    ///
140    /// assert!(!c.filter(&1).unwrap());
141    /// assert!(!c.filter(&2).unwrap());
142    /// assert!(c.filter(&3).unwrap());
143    /// assert!(c.filter(&4).unwrap());
144    /// ```
145    fn nor<F>(self, other: F) -> FailableNot<FailableOr<Self, F>>
146        where Self: Sized,
147    {
148        FailableNot::new(FailableOr::new(self, other))
149    }
150
151    /// Helper to connect two filters via logical XOR
152    ///
153    /// ```
154    /// # #[derive(Debug)]
155    /// # struct ErrorStub { }
156    /// #
157    /// use filters::failable::filter::FailableFilter;
158    ///
159    /// let a = (|&a: &usize| -> Result<bool, ErrorStub> { Ok(a > 3) });
160    /// let b = (|&a: &usize| -> Result<bool, ErrorStub> { Ok(a < 7) });
161    /// let c = a.xor(b);
162    ///
163    /// assert!(c.filter(&1).unwrap());
164    /// assert!(c.filter(&3).unwrap());
165    /// assert!(!c.filter(&4).unwrap());
166    /// assert!(!c.filter(&6).unwrap());
167    /// assert!(c.filter(&9).unwrap());
168    /// ```
169    fn xor<F>(self, other: F) -> FailableXOr<Self, F>
170        where Self: Sized,
171    {
172        FailableXOr::new(self, other)
173    }
174
175    /// Helper to connect two filters via logical AND
176    ///
177    /// ```
178    /// # #[derive(Debug)]
179    /// # struct ErrorStub { }
180    /// #
181    /// use filters::failable::filter::FailableFilter;
182    ///
183    /// let a = (|&a: &usize| -> Result<bool, ErrorStub> { Ok(a > 1) });
184    /// let b = (|&a: &usize| -> Result<bool, ErrorStub> { Ok(a < 7) });
185    /// let c = a.and(b);
186    ///
187    /// assert!(!c.filter(&1).unwrap());
188    /// assert!(c.filter(&3).unwrap());
189    /// assert!(c.filter(&4).unwrap());
190    /// assert!(c.filter(&6).unwrap());
191    /// assert!(!c.filter(&9).unwrap());
192    /// ```
193    fn and<F>(self, other: F) -> FailableAnd<Self, F::IntoFilt>
194        where Self: Sized,
195              F: IntoFailableFilter<N> + Sized
196    {
197        FailableAnd::new(self, other.into_failable_filter())
198    }
199
200    /// Helper to connect three filters via logical AND
201    ///
202    /// ```
203    /// # #[derive(Debug)]
204    /// # struct ErrorStub { }
205    /// #
206    /// use filters::failable::filter::FailableFilter;
207    ///
208    /// let a = (|&a: &usize| -> Result<bool, ErrorStub> { Ok(a > 1) });
209    /// let b = (|&a: &usize| -> Result<bool, ErrorStub> { Ok(a < 20) });
210    /// let c = (|&a: &usize| -> Result<bool, ErrorStub> { Ok(a % 2 == 0) });
211    /// let d = a.and3(b, c);
212    ///
213    /// assert!(!d.filter(&1).unwrap());
214    /// assert!(!d.filter(&3).unwrap());
215    /// assert!(d.filter(&8).unwrap());
216    /// assert!(d.filter(&10).unwrap());
217    /// assert!(d.filter(&14).unwrap());
218    /// assert!(!d.filter(&15).unwrap());
219    /// assert!(!d.filter(&19).unwrap());
220    /// ```
221    fn and3<F, F2>(self, other: F, other2: F2) -> FailableAnd<Self, FailableAnd<F::IntoFilt, F2::IntoFilt>>
222        where Self: Sized,
223              F: IntoFailableFilter<N> + Sized,
224              F2: IntoFailableFilter<N> + Sized
225    {
226        FailableAnd::new(self, FailableAnd::new(other.into_failable_filter(), other2.into_failable_filter()))
227    }
228
229    /// Helper to connect two filters via logical AND and NOT
230    ///
231    /// ```
232    /// # #[derive(Debug)]
233    /// # struct ErrorStub { }
234    /// #
235    /// use filters::failable::filter::FailableFilter;
236    ///
237    /// let a = (|&a: &usize| -> Result<bool, ErrorStub> { Ok(a > 10) });
238    /// let b = (|&a: &usize| -> Result<bool, ErrorStub> { Ok(a < 20) });
239    /// let c = a.and_not(b);
240    ///
241    /// assert!(!c.filter(&1).unwrap());
242    /// assert!(!c.filter(&3).unwrap());
243    /// assert!(!c.filter(&8).unwrap());
244    /// assert!(!c.filter(&11).unwrap());
245    /// assert!(c.filter(&24).unwrap());
246    /// assert!(c.filter(&25).unwrap());
247    /// assert!(c.filter(&29).unwrap());
248    /// ```
249    fn and_not<F>(self, other: F) -> FailableAnd<Self, FailableNot<F::IntoFilt>>
250        where Self: Sized,
251              F: IntoFailableFilter<N> + Sized
252    {
253        self.and(FailableNot::new(other.into_failable_filter()))
254    }
255
256    /// Helper to connect two filters via logical NAND
257    ///
258    /// ```
259    /// # #[derive(Debug)]
260    /// # struct ErrorStub { }
261    /// #
262    /// use filters::failable::filter::FailableFilter;
263    ///
264    /// let a = (|&a: &usize| -> Result<bool, ErrorStub> { Ok(a > 10) });
265    /// let b = (|&a: &usize| -> Result<bool, ErrorStub> { Ok(a < 20) });
266    /// let c = a.nand(b);
267    ///
268    /// assert!(c.filter(&1).unwrap());
269    /// assert!(c.filter(&3).unwrap());
270    /// assert!(c.filter(&8).unwrap());
271    /// assert!(!c.filter(&11).unwrap());
272    /// assert!(!c.filter(&14).unwrap());
273    /// assert!(c.filter(&25).unwrap());
274    /// assert!(c.filter(&29).unwrap());
275    /// ```
276    fn nand<F>(self, other: F) -> FailableNot<FailableAnd<Self, F>>
277        where Self: Sized,
278    {
279        FailableNot::new(FailableAnd::new(self, other))
280    }
281
282    /// Helper to transform the input of a filter
283    ///
284    /// ```
285    /// # #[derive(Debug)]
286    /// # struct ErrorStub { }
287    /// #
288    /// use filters::failable::filter::FailableFilter;
289    ///
290    /// let a = (|&a: &usize| -> Result<bool, ErrorStub> { Ok(a > 1) });
291    /// let b = (|&a: &i64| -> Result<bool, ErrorStub> { Ok(a < 7) });
292    /// let b = b.map_input(|&x: &usize| x as i64);
293    /// let c = a.and(b);
294    ///
295    /// assert!(!c.filter(&1).unwrap());
296    /// assert!(c.filter(&3).unwrap());
297    /// assert!(c.filter(&4).unwrap());
298    /// assert!(c.filter(&6).unwrap());
299    /// assert!(!c.filter(&9).unwrap());
300    /// ```
301    fn map_input<O, B, T, M>(self, map: M) -> FailableMapInput<Self, M, O, B>
302        where Self: Sized,
303              M: Fn(&T) -> N,
304              B: Borrow<O> + Sized
305    {
306        FailableMapInput::new(self, map)
307    }
308
309    /// Helper to transform the input of a filter
310    ///
311    /// ```
312    /// # use std::fmt;
313    /// # #[derive(Debug)]
314    /// # struct ErrorStub { }
315    /// #
316    /// use filters::failable::filter::FailableFilter;
317    ///
318    /// let a = (|&a: &usize| -> Result<bool, ErrorStub> { Ok(a > 1) });
319    /// let b = (|&a: &usize| -> Result<bool, fmt::Error> { Ok(a < 7) });
320    /// let b = b.map_err(|_: fmt::Error| ErrorStub {});
321    /// let c = a.and(b);
322    ///
323    /// assert!(!c.filter(&1).unwrap());
324    /// assert!(c.filter(&3).unwrap());
325    /// assert!(c.filter(&4).unwrap());
326    /// assert!(c.filter(&6).unwrap());
327    /// assert!(!c.filter(&9).unwrap());
328    /// ```
329    fn map_err<M, OE>(self, map: M) -> FailableMapErr<Self, M, OE>
330        where Self: Sized,
331              M: Fn(Self::Error) -> OE
332    {
333        FailableMapErr::new(self, map)
334    }
335
336}
337
338/// All closures that take a ref to something and return Result<bool, E> are failable filters
339impl<I, E, T> FailableFilter<I> for T
340    where T: Fn(&I) -> Result<bool, E>
341{
342    type Error = E;
343
344    fn filter(&self, other: &I) -> Result<bool, Self::Error> {
345        self(other)
346    }
347}
348
349#[cfg(test)]
350mod tests {
351    use super::*;
352
353    #[derive(Debug)]
354    struct StupError { }
355
356    #[test]
357    fn compile_test() {
358        let a = |_: &i32| -> Result<bool, StupError> { Ok(true) };
359
360        assert!(a.filter(&1).unwrap());
361    }
362
363    #[test]
364    fn test_error_return() {
365        let a = |_: &i32| -> Result<bool, StupError> { Err(StupError {}) };
366
367        assert!(a.filter(&1).is_err());
368    }
369
370    #[test]
371    fn test_error_return_and_chained() {
372        let a = |_: &i32| -> Result<bool, StupError> { Err(StupError {}) };
373        let b = |_: &i32| -> Result<bool, StupError> { Ok(true) };
374        let c = |_: &i32| -> Result<bool, StupError> { Ok(true) };
375        let d = |_: &i32| -> Result<bool, StupError> { Ok(true) };
376
377        let e = d.and(b).and(c).and(a);
378
379        assert!(e.filter(&1).is_err());
380    }
381
382    #[test]
383    fn test_error_return_or_chained() {
384        let a = |_: &i32| -> Result<bool, StupError> { Err(StupError {}) };
385        let b = |_: &i32| -> Result<bool, StupError> { Ok(true) };
386        let c = |_: &i32| -> Result<bool, StupError> { Ok(true) };
387        let d = |_: &i32| -> Result<bool, StupError> { Ok(true) };
388
389        let e = a.or(b).or(c).or(d);
390
391        assert!(e.filter(&1).is_err());
392    }
393
394    #[test]
395    fn test_both_filter_types() {
396        use filter::Filter;
397
398        let a = |_: &i32| -> Result<bool, StupError> { Ok(true) };
399        let b = |_: &i32| -> bool { true };
400        let c = |_: &i32| -> Result<bool, StupError> { Ok(true) };
401        let d = |_: &i32| -> bool { false };
402
403        let e = a                                               // true
404            .and(b.into_failable().map_err(|_| StupError {}))   // true
405            .xor(c)                                             // true
406            .or(d.into_failable().map_err(|_| StupError {}));   // true
407
408        assert!(!e.filter(&1).unwrap());
409    }
410
411
412    #[test]
413    fn test_both_filter_types_in_one_scope() {
414        use filter::Filter;
415        use failable::filter::FailableFilter;
416
417        let failable   = |_: &i32| -> Result<bool, StupError> { Ok(true) };
418        let unfailable = |_: &i32| -> bool { true };
419
420        assert!(failable.filter(&1).unwrap());
421        assert!(unfailable.filter(&1));
422
423    }
424}
425