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}