1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum CompareOp {
7 Equal,
9 NotEqual,
11 In,
13 NotIn,
15 Exists,
17 NotExists,
19 StartsWith,
21 EndsWith,
23 Contains,
25 GreaterThan,
27 GreaterThanOrEqual,
29 LessThan,
31 LessThanOrEqual,
33}
34
35impl CompareOp {
36 #[inline]
41 pub fn parse(s: &str) -> Option<Self> {
42 match s {
43 "eq" => Some(Self::Equal),
44 "neq" => Some(Self::NotEqual),
45 "in" => Some(Self::In),
46 "nin" => Some(Self::NotIn),
47 "ex" => Some(Self::Exists),
48 "nex" => Some(Self::NotExists),
49 "sw" => Some(Self::StartsWith),
50 "ew" => Some(Self::EndsWith),
51 "ct" => Some(Self::Contains),
52 "gt" => Some(Self::GreaterThan),
53 "gte" => Some(Self::GreaterThanOrEqual),
54 "lt" => Some(Self::LessThan),
55 "lte" => Some(Self::LessThanOrEqual),
56 _ => None,
57 }
58 }
59
60 #[inline]
62 pub const fn as_str(self) -> &'static str {
63 match self {
64 Self::Equal => "eq",
65 Self::NotEqual => "neq",
66 Self::In => "in",
67 Self::NotIn => "nin",
68 Self::Exists => "ex",
69 Self::NotExists => "nex",
70 Self::StartsWith => "sw",
71 Self::EndsWith => "ew",
72 Self::Contains => "ct",
73 Self::GreaterThan => "gt",
74 Self::GreaterThanOrEqual => "gte",
75 Self::LessThan => "lt",
76 Self::LessThanOrEqual => "lte",
77 }
78 }
79}
80
81impl std::fmt::Display for CompareOp {
83 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
84 write!(f, "{}", self.as_str())
85 }
86}
87
88impl std::str::FromStr for CompareOp {
90 type Err = String;
91
92 fn from_str(s: &str) -> Result<Self, Self::Err> {
93 Self::parse(s).ok_or_else(|| format!("Invalid comparison operator: {}", s))
94 }
95}
96
97#[derive(Debug, Clone, Copy, PartialEq, Eq)]
101pub enum LogicalOp {
102 And,
104 Or,
106 Not,
108}
109
110impl LogicalOp {
111 #[inline]
116 pub fn parse(s: &str) -> Option<Self> {
117 match s {
118 "and" => Some(Self::And),
119 "or" => Some(Self::Or),
120 "not" => Some(Self::Not),
121 _ => None,
122 }
123 }
124
125 #[inline]
127 pub const fn as_str(self) -> &'static str {
128 match self {
129 Self::And => "and",
130 Self::Or => "or",
131 Self::Not => "not",
132 }
133 }
134}
135
136impl std::fmt::Display for LogicalOp {
138 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
139 write!(f, "{}", self.as_str())
140 }
141}
142
143impl std::str::FromStr for LogicalOp {
145 type Err = String;
146
147 fn from_str(s: &str) -> Result<Self, Self::Err> {
148 Self::parse(s).ok_or_else(|| format!("Invalid logical operator: {}", s))
149 }
150}
151
152#[cfg(test)]
153mod tests {
154 use super::*;
155
156 #[test]
157 fn test_compare_op_from_str() {
158 assert_eq!(CompareOp::parse("eq"), Some(CompareOp::Equal));
159 assert_eq!(CompareOp::parse("neq"), Some(CompareOp::NotEqual));
160 assert_eq!(CompareOp::parse("in"), Some(CompareOp::In));
161 assert_eq!(CompareOp::parse("nin"), Some(CompareOp::NotIn));
162 assert_eq!(CompareOp::parse("ex"), Some(CompareOp::Exists));
163 assert_eq!(CompareOp::parse("nex"), Some(CompareOp::NotExists));
164 assert_eq!(CompareOp::parse("sw"), Some(CompareOp::StartsWith));
165 assert_eq!(CompareOp::parse("ew"), Some(CompareOp::EndsWith));
166 assert_eq!(CompareOp::parse("ct"), Some(CompareOp::Contains));
167 assert_eq!(CompareOp::parse("gt"), Some(CompareOp::GreaterThan));
168 assert_eq!(CompareOp::parse("gte"), Some(CompareOp::GreaterThanOrEqual));
169 assert_eq!(CompareOp::parse("lt"), Some(CompareOp::LessThan));
170 assert_eq!(CompareOp::parse("lte"), Some(CompareOp::LessThanOrEqual));
171 assert_eq!(CompareOp::parse("invalid"), None);
172 }
173
174 #[test]
175 fn test_compare_op_as_str() {
176 assert_eq!(CompareOp::Equal.as_str(), "eq");
177 assert_eq!(CompareOp::NotEqual.as_str(), "neq");
178 assert_eq!(CompareOp::In.as_str(), "in");
179 assert_eq!(CompareOp::NotIn.as_str(), "nin");
180 assert_eq!(CompareOp::Exists.as_str(), "ex");
181 assert_eq!(CompareOp::NotExists.as_str(), "nex");
182 assert_eq!(CompareOp::StartsWith.as_str(), "sw");
183 assert_eq!(CompareOp::EndsWith.as_str(), "ew");
184 assert_eq!(CompareOp::Contains.as_str(), "ct");
185 assert_eq!(CompareOp::GreaterThan.as_str(), "gt");
186 assert_eq!(CompareOp::GreaterThanOrEqual.as_str(), "gte");
187 assert_eq!(CompareOp::LessThan.as_str(), "lt");
188 assert_eq!(CompareOp::LessThanOrEqual.as_str(), "lte");
189 }
190
191 #[test]
192 fn test_logical_op_from_str() {
193 assert_eq!(LogicalOp::parse("and"), Some(LogicalOp::And));
194 assert_eq!(LogicalOp::parse("or"), Some(LogicalOp::Or));
195 assert_eq!(LogicalOp::parse("not"), Some(LogicalOp::Not));
196 assert_eq!(LogicalOp::parse("invalid"), None);
197 }
198
199 #[test]
200 fn test_logical_op_as_str() {
201 assert_eq!(LogicalOp::And.as_str(), "and");
202 assert_eq!(LogicalOp::Or.as_str(), "or");
203 assert_eq!(LogicalOp::Not.as_str(), "not");
204 }
205
206 #[test]
207 fn test_round_trip_compare_ops() {
208 let ops = [
209 CompareOp::Equal,
210 CompareOp::NotEqual,
211 CompareOp::In,
212 CompareOp::NotIn,
213 CompareOp::Exists,
214 CompareOp::NotExists,
215 CompareOp::StartsWith,
216 CompareOp::EndsWith,
217 CompareOp::Contains,
218 CompareOp::GreaterThan,
219 CompareOp::GreaterThanOrEqual,
220 CompareOp::LessThan,
221 CompareOp::LessThanOrEqual,
222 ];
223
224 for op in ops {
225 let s = op.as_str();
226 let parsed = CompareOp::parse(s);
227 assert_eq!(parsed, Some(op));
228 }
229 }
230
231 #[test]
232 fn test_round_trip_logical_ops() {
233 let ops = [LogicalOp::And, LogicalOp::Or, LogicalOp::Not];
234
235 for op in ops {
236 let s = op.as_str();
237 let parsed = LogicalOp::parse(s);
238 assert_eq!(parsed, Some(op));
239 }
240 }
241}