1 | // Copyright (c) 2018, 2022 The predicates-rs Project Developers. |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
4 | // http://www.apache.org/license/LICENSE-2.0> or the MIT license |
5 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your |
6 | // option. This file may not be copied, modified, or distributed |
7 | // except according to those terms. |
8 | |
9 | //! Definition of `Predicate`s for comparisons over `Ord` and `Eq` types. |
10 | |
11 | use std::fmt; |
12 | |
13 | use crate::reflection; |
14 | use crate::utils; |
15 | use crate::Predicate; |
16 | |
17 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] |
18 | enum EqOps { |
19 | Equal, |
20 | NotEqual, |
21 | } |
22 | |
23 | impl fmt::Display for EqOps { |
24 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
25 | let op = match *self { |
26 | EqOps::Equal => "==" , |
27 | EqOps::NotEqual => "!=" , |
28 | }; |
29 | write!(f, "{}" , op) |
30 | } |
31 | } |
32 | |
33 | /// Predicate that returns `true` if `variable` matches the pre-defined `Eq` |
34 | /// value, otherwise returns `false`. |
35 | /// |
36 | /// This is created by the `predicate::{eq, ne}` functions. |
37 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
38 | pub struct EqPredicate<T> { |
39 | constant: T, |
40 | op: EqOps, |
41 | } |
42 | |
43 | impl<P, T> Predicate<P> for EqPredicate<T> |
44 | where |
45 | T: std::borrow::Borrow<P> + fmt::Debug, |
46 | P: fmt::Debug + PartialEq + ?Sized, |
47 | { |
48 | fn eval(&self, variable: &P) -> bool { |
49 | match self.op { |
50 | EqOps::Equal => variable.eq(self.constant.borrow()), |
51 | EqOps::NotEqual => variable.ne(self.constant.borrow()), |
52 | } |
53 | } |
54 | |
55 | fn find_case<'a>(&'a self, expected: bool, variable: &P) -> Option<reflection::Case<'a>> { |
56 | utils::default_find_case(self, expected, variable).map(|case| { |
57 | case.add_product(reflection::Product::new( |
58 | "var" , |
59 | utils::DebugAdapter::new(variable).to_string(), |
60 | )) |
61 | }) |
62 | } |
63 | } |
64 | |
65 | impl<T> reflection::PredicateReflection for EqPredicate<T> where T: fmt::Debug {} |
66 | |
67 | impl<T> fmt::Display for EqPredicate<T> |
68 | where |
69 | T: fmt::Debug, |
70 | { |
71 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
72 | let palette = crate::Palette::current(); |
73 | write!( |
74 | f, |
75 | "{} {} {}" , |
76 | palette.var.paint("var" ), |
77 | palette.description.paint(self.op), |
78 | palette |
79 | .expected |
80 | .paint(utils::DebugAdapter::new(&self.constant)), |
81 | ) |
82 | } |
83 | } |
84 | |
85 | /// Creates a new predicate that will return `true` when the given `variable` is |
86 | /// equal to a pre-defined value. |
87 | /// |
88 | /// # Examples |
89 | /// |
90 | /// ``` |
91 | /// use predicates::prelude::*; |
92 | /// |
93 | /// let predicate_fn = predicate::eq(5); |
94 | /// assert_eq!(true, predicate_fn.eval(&5)); |
95 | /// assert_eq!(false, predicate_fn.eval(&10)); |
96 | /// |
97 | /// let predicate_fn = predicate::eq("Hello" ); |
98 | /// assert_eq!(true, predicate_fn.eval("Hello" )); |
99 | /// assert_eq!(false, predicate_fn.eval("Goodbye" )); |
100 | /// |
101 | /// let predicate_fn = predicate::eq(String::from("Hello" )); |
102 | /// assert_eq!(true, predicate_fn.eval("Hello" )); |
103 | /// assert_eq!(false, predicate_fn.eval("Goodbye" )); |
104 | /// ``` |
105 | pub fn eq<T>(constant: T) -> EqPredicate<T> |
106 | where |
107 | T: fmt::Debug + PartialEq, |
108 | { |
109 | EqPredicate { |
110 | constant, |
111 | op: EqOps::Equal, |
112 | } |
113 | } |
114 | |
115 | /// Creates a new predicate that will return `true` when the given `variable` is |
116 | /// _not_ equal to a pre-defined value. |
117 | /// |
118 | /// # Examples |
119 | /// |
120 | /// ``` |
121 | /// use predicates::prelude::*; |
122 | /// |
123 | /// let predicate_fn = predicate::ne(5); |
124 | /// assert_eq!(false, predicate_fn.eval(&5)); |
125 | /// assert_eq!(true, predicate_fn.eval(&10)); |
126 | /// ``` |
127 | pub fn ne<T>(constant: T) -> EqPredicate<T> |
128 | where |
129 | T: PartialEq + fmt::Debug, |
130 | { |
131 | EqPredicate { |
132 | constant, |
133 | op: EqOps::NotEqual, |
134 | } |
135 | } |
136 | |
137 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] |
138 | enum OrdOps { |
139 | LessThan, |
140 | LessThanOrEqual, |
141 | GreaterThanOrEqual, |
142 | GreaterThan, |
143 | } |
144 | |
145 | impl fmt::Display for OrdOps { |
146 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
147 | let op = match *self { |
148 | OrdOps::LessThan => "<" , |
149 | OrdOps::LessThanOrEqual => "<=" , |
150 | OrdOps::GreaterThanOrEqual => ">=" , |
151 | OrdOps::GreaterThan => ">" , |
152 | }; |
153 | write!(f, "{}" , op) |
154 | } |
155 | } |
156 | |
157 | /// Predicate that returns `true` if `variable` matches the pre-defined `Ord` |
158 | /// value, otherwise returns `false`. |
159 | /// |
160 | /// This is created by the `predicate::{gt, ge, lt, le}` functions. |
161 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
162 | pub struct OrdPredicate<T> { |
163 | constant: T, |
164 | op: OrdOps, |
165 | } |
166 | |
167 | impl<P, T> Predicate<P> for OrdPredicate<T> |
168 | where |
169 | T: std::borrow::Borrow<P> + fmt::Debug, |
170 | P: fmt::Debug + PartialOrd + ?Sized, |
171 | { |
172 | fn eval(&self, variable: &P) -> bool { |
173 | match self.op { |
174 | OrdOps::LessThan => variable.lt(self.constant.borrow()), |
175 | OrdOps::LessThanOrEqual => variable.le(self.constant.borrow()), |
176 | OrdOps::GreaterThanOrEqual => variable.ge(self.constant.borrow()), |
177 | OrdOps::GreaterThan => variable.gt(self.constant.borrow()), |
178 | } |
179 | } |
180 | |
181 | fn find_case<'a>(&'a self, expected: bool, variable: &P) -> Option<reflection::Case<'a>> { |
182 | utils::default_find_case(self, expected, variable).map(|case| { |
183 | case.add_product(reflection::Product::new( |
184 | "var" , |
185 | utils::DebugAdapter::new(variable).to_string(), |
186 | )) |
187 | }) |
188 | } |
189 | } |
190 | |
191 | impl<T> reflection::PredicateReflection for OrdPredicate<T> where T: fmt::Debug {} |
192 | |
193 | impl<T> fmt::Display for OrdPredicate<T> |
194 | where |
195 | T: fmt::Debug, |
196 | { |
197 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
198 | let palette = crate::Palette::current(); |
199 | write!( |
200 | f, |
201 | "{} {} {}" , |
202 | palette.var.paint("var" ), |
203 | palette.description.paint(self.op), |
204 | palette |
205 | .expected |
206 | .paint(utils::DebugAdapter::new(&self.constant)), |
207 | ) |
208 | } |
209 | } |
210 | |
211 | /// Creates a new predicate that will return `true` when the given `variable` is |
212 | /// less than a pre-defined value. |
213 | /// |
214 | /// # Examples |
215 | /// |
216 | /// ``` |
217 | /// use predicates::prelude::*; |
218 | /// |
219 | /// let predicate_fn = predicate::lt(5); |
220 | /// assert_eq!(true, predicate_fn.eval(&4)); |
221 | /// assert_eq!(false, predicate_fn.eval(&6)); |
222 | /// |
223 | /// let predicate_fn = predicate::lt("b" ); |
224 | /// assert_eq!(true, predicate_fn.eval("a" )); |
225 | /// assert_eq!(false, predicate_fn.eval("c" )); |
226 | /// |
227 | /// let predicate_fn = predicate::lt(String::from("b" )); |
228 | /// assert_eq!(true, predicate_fn.eval("a" )); |
229 | /// assert_eq!(false, predicate_fn.eval("c" )); |
230 | /// ``` |
231 | pub fn lt<T>(constant: T) -> OrdPredicate<T> |
232 | where |
233 | T: fmt::Debug + PartialOrd, |
234 | { |
235 | OrdPredicate { |
236 | constant, |
237 | op: OrdOps::LessThan, |
238 | } |
239 | } |
240 | |
241 | /// Creates a new predicate that will return `true` when the given `variable` is |
242 | /// less than or equal to a pre-defined value. |
243 | /// |
244 | /// # Examples |
245 | /// |
246 | /// ``` |
247 | /// use predicates::prelude::*; |
248 | /// |
249 | /// let predicate_fn = predicate::le(5); |
250 | /// assert_eq!(true, predicate_fn.eval(&4)); |
251 | /// assert_eq!(true, predicate_fn.eval(&5)); |
252 | /// assert_eq!(false, predicate_fn.eval(&6)); |
253 | /// ``` |
254 | pub fn le<T>(constant: T) -> OrdPredicate<T> |
255 | where |
256 | T: PartialOrd + fmt::Debug, |
257 | { |
258 | OrdPredicate { |
259 | constant, |
260 | op: OrdOps::LessThanOrEqual, |
261 | } |
262 | } |
263 | |
264 | /// Creates a new predicate that will return `true` when the given `variable` is |
265 | /// greater than or equal to a pre-defined value. |
266 | /// |
267 | /// # Examples |
268 | /// |
269 | /// ``` |
270 | /// use predicates::prelude::*; |
271 | /// |
272 | /// let predicate = predicate::ge(5); |
273 | /// assert_eq!(false, predicate.eval(&4)); |
274 | /// assert_eq!(true, predicate.eval(&5)); |
275 | /// assert_eq!(true, predicate.eval(&6)); |
276 | /// ``` |
277 | pub fn ge<T>(constant: T) -> OrdPredicate<T> |
278 | where |
279 | T: PartialOrd + fmt::Debug, |
280 | { |
281 | OrdPredicate { |
282 | constant, |
283 | op: OrdOps::GreaterThanOrEqual, |
284 | } |
285 | } |
286 | |
287 | /// Creates a new predicate that will return `true` when the given `variable` is |
288 | /// greater than a pre-defined value. |
289 | /// |
290 | /// # Examples |
291 | /// |
292 | /// ``` |
293 | /// use predicates::prelude::*; |
294 | /// |
295 | /// let predicate_fn = predicate::gt(5); |
296 | /// assert_eq!(false, predicate_fn.eval(&4)); |
297 | /// assert_eq!(false, predicate_fn.eval(&5)); |
298 | /// assert_eq!(true, predicate_fn.eval(&6)); |
299 | /// ``` |
300 | pub fn gt<T>(constant: T) -> OrdPredicate<T> |
301 | where |
302 | T: PartialOrd + fmt::Debug, |
303 | { |
304 | OrdPredicate { |
305 | constant, |
306 | op: OrdOps::GreaterThan, |
307 | } |
308 | } |
309 | |