From 4519109ac5939d487b45dc220c89ed2f3a936780 Mon Sep 17 00:00:00 2001 From: Waffle Date: Fri, 13 Sep 2019 14:57:02 +0300 Subject: [PATCH] Implement wrapper for filters that adds `|`, `&` operators --- src/dispatcher/filter.rs | 68 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/src/dispatcher/filter.rs b/src/dispatcher/filter.rs index 57eb6c84..ac3b1f67 100644 --- a/src/dispatcher/filter.rs +++ b/src/dispatcher/filter.rs @@ -241,3 +241,71 @@ macro_rules! any { ) }; } + + +/// Simple wrapper around `Filter` that adds `|` and `&` operators. +/// +/// ## Examples +/// ``` +/// use async_telegram_bot::dispatcher::filter::{Filter, f, F, And, Or}; +/// +/// let flt1 = |i: &i32| -> bool { *i > 17 }; +/// let flt2 = |i: &i32| -> bool { *i < 42 }; +/// let flt3 = |i: &i32| -> bool { *i % 2 == 0 }; +/// +/// let and = f(flt1) & flt2; +/// assert!(and.test(&19)); // both filters pass +/// +/// assert_eq!(and.test(&50), false); // `flt2` doesn't pass +/// assert_eq!(and.test(&16), false); // `flt1` doesn't pass +/// +/// +/// let or = f(flt1) | flt3; +/// assert!(or.test(&19)); // `flt1` passes +/// assert!(or.test(&16)); // `flt2` passes +/// assert!(or.test(&20)); // both pass +/// +/// assert_eq!(or.test(&17), false); // both don't pass +/// +/// +/// // Note: only first filter in chain should be wrapped in `f(...)` +/// let complicated: F, _>>= f(flt1) & flt2 | flt3; +/// assert!(complicated.test(&2)); // `flt3` passes +/// assert!(complicated.test(&21)); // `flt1` and `flt2` pass +/// +/// assert_eq!(complicated.test(&15), false); // `flt1` and `flt3` don't pass +/// assert_eq!(complicated.test(&43), false); // `flt2` and `flt3` don't pass +/// ``` +pub struct F(A); + +/// Constructor fn for [F] +/// +/// [F]: crate::dispatcher::filter::F; +pub fn f(a: A) -> F { + F(a) +} + +impl Filter for F +where + A: Filter +{ + fn test(&self, value: &T) -> bool { + self.0.test(value) + } +} + +impl std::ops::BitAnd for F { + type Output = F>; + + fn bitand(self, other: B) -> Self::Output { + f(and(self.0, other)) + } +} + +impl std::ops::BitOr for F { + type Output = F>; + + fn bitor(self, other: B) -> Self::Output { + f(or(self.0, other)) + } +}