rs_filter/
lib.rs

1#[cfg(feature = "macros")]
2pub use rs_filter_macros::*;
3
4pub trait Filterable<Filter> {
5    fn is_match(&self, filter: &Filter) -> bool;
6}
7
8#[derive(Default, Clone, PartialEq)]
9pub enum EqFilter<T: PartialEq> {
10    #[default]
11    Any,
12    None,
13    Eq(T),
14    Neq(T),
15}
16
17impl<T: PartialEq> Filterable<EqFilter<T>> for T {
18    fn is_match(&self, filter: &EqFilter<T>) -> bool {
19        match filter {
20            EqFilter::Any => true,
21            EqFilter::None => false,
22            EqFilter::Eq(val) => self == val,
23            EqFilter::Neq(val) => self != val,
24        }
25    }
26}
27
28impl<T: PartialEq> Filterable<EqFilter<T>> for Option<T> {
29    fn is_match(&self, filter: &EqFilter<T>) -> bool {
30        match filter {
31            EqFilter::Any => true,
32            EqFilter::None => self.is_none(),
33            EqFilter::Eq(val) => self.as_ref().is_some_and(|inner| inner == val),
34            EqFilter::Neq(val) => self.as_ref().is_some_and(|inner| inner != val),
35        }
36    }
37}
38
39#[derive(Default, Clone, PartialEq)]
40pub enum OrdFilter<T: PartialOrd> {
41    #[default]
42    Any,
43    None,
44    Eq(T),
45    Neq(T),
46    Gt(T),
47    Gte(T),
48    Lt(T),
49    Lte(T),
50}
51
52impl<T: PartialOrd> Filterable<OrdFilter<T>> for T {
53    fn is_match(&self, filter: &OrdFilter<T>) -> bool {
54        match filter {
55            OrdFilter::Any => true,
56            OrdFilter::None => false,
57            OrdFilter::Eq(val) => self == val,
58            OrdFilter::Neq(val) => self != val,
59            OrdFilter::Gt(val) => self > val,
60            OrdFilter::Gte(val) => self >= val,
61            OrdFilter::Lt(val) => self < val,
62            OrdFilter::Lte(val) => self <= val,
63        }
64    }
65}
66
67impl<T: PartialOrd> Filterable<OrdFilter<T>> for Option<T> {
68    fn is_match(&self, filter: &OrdFilter<T>) -> bool {
69        match filter {
70            OrdFilter::Any => true,
71            OrdFilter::None => self.is_none(),
72            OrdFilter::Eq(val) => self.as_ref().is_some_and(|inner| inner == val),
73            OrdFilter::Neq(val) => self.as_ref().is_some_and(|inner| inner != val),
74            OrdFilter::Gt(val) => self.as_ref().is_some_and(|inner| inner > val),
75            OrdFilter::Gte(val) => self.as_ref().is_some_and(|inner| inner >= val),
76            OrdFilter::Lt(val) => self.as_ref().is_some_and(|inner| inner < val),
77            OrdFilter::Lte(val) => self.as_ref().is_some_and(|inner| inner <= val),
78        }
79    }
80}
81
82#[derive(Default, Clone, PartialEq)]
83pub enum StringFilter {
84    #[default]
85    Any,
86    None,
87    Eq(String),
88    Neq(String),
89    Contains(String),
90    StartsWith(String),
91    EndsWith(String),
92}
93
94trait NotOption {}
95impl NotOption for String {}
96impl NotOption for &str {}
97
98impl<T: NotOption + AsRef<str>> Filterable<StringFilter> for T {
99    fn is_match(&self, filter: &StringFilter) -> bool {
100        match filter {
101            StringFilter::Any => true,
102            StringFilter::None => false,
103            StringFilter::Eq(val) => self.as_ref() == val,
104            StringFilter::Neq(val) => self.as_ref() != val,
105            StringFilter::Contains(val) => self.as_ref().contains(val),
106            StringFilter::StartsWith(val) => self.as_ref().starts_with(val),
107            StringFilter::EndsWith(val) => self.as_ref().ends_with(val),
108        }
109    }
110}
111
112impl<T: AsRef<str>> Filterable<StringFilter> for Option<T> {
113    fn is_match(&self, filter: &StringFilter) -> bool {
114        match filter {
115            StringFilter::Any => true,
116            StringFilter::None => self.is_none(),
117            StringFilter::Eq(val) => self.as_ref().is_some_and(|inner| inner.as_ref() == val),
118            StringFilter::Neq(val) => self.as_ref().is_some_and(|inner| inner.as_ref() != val),
119            StringFilter::Contains(val) => self
120                .as_ref()
121                .is_some_and(|inner| inner.as_ref().contains(val)),
122            StringFilter::StartsWith(val) => self
123                .as_ref()
124                .is_some_and(|inner| inner.as_ref().starts_with(val)),
125            StringFilter::EndsWith(val) => self
126                .as_ref()
127                .is_some_and(|inner| inner.as_ref().ends_with(val)),
128        }
129    }
130}