1 // Copyright (c) 2018 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 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result24     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 where
40     T: fmt::Debug + PartialEq,
41 {
42     constant: T,
43     op: EqOps,
44 }
45 
46 impl<T> Predicate<T> for EqPredicate<T>
47 where
48     T: fmt::Debug + PartialEq,
49 {
eval(&self, variable: &T) -> bool50     fn eval(&self, variable: &T) -> bool {
51         match self.op {
52             EqOps::Equal => variable.eq(&self.constant),
53             EqOps::NotEqual => variable.ne(&self.constant),
54         }
55     }
56 
find_case<'a>(&'a self, expected: bool, variable: &T) -> Option<reflection::Case<'a>>57     fn find_case<'a>(&'a self, expected: bool, variable: &T) -> Option<reflection::Case<'a>> {
58         utils::default_find_case(self, expected, variable)
59     }
60 }
61 
62 impl<'a, T> Predicate<T> for EqPredicate<&'a T>
63 where
64     T: fmt::Debug + PartialEq + ?Sized,
65 {
eval(&self, variable: &T) -> bool66     fn eval(&self, variable: &T) -> bool {
67         match self.op {
68             EqOps::Equal => variable.eq(self.constant),
69             EqOps::NotEqual => variable.ne(self.constant),
70         }
71     }
72 
find_case<'b>(&'b self, expected: bool, variable: &T) -> Option<reflection::Case<'b>>73     fn find_case<'b>(&'b self, expected: bool, variable: &T) -> Option<reflection::Case<'b>> {
74         utils::default_find_case(self, expected, variable)
75     }
76 }
77 
78 impl<T> reflection::PredicateReflection for EqPredicate<T> where T: fmt::Debug + PartialEq {}
79 
80 impl<T> fmt::Display for EqPredicate<T>
81 where
82     T: fmt::Debug + PartialEq,
83 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result84     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85         write!(f, "var {} {:?}", self.op, self.constant)
86     }
87 }
88 
89 /// Creates a new predicate that will return `true` when the given `variable` is
90 /// equal to a pre-defined value.
91 ///
92 /// # Examples
93 ///
94 /// ```
95 /// use predicates::prelude::*;
96 ///
97 /// let predicate_fn = predicate::eq(5);
98 /// assert_eq!(true, predicate_fn.eval(&5));
99 /// assert_eq!(false, predicate_fn.eval(&10));
100 ///
101 /// let predicate_fn = predicate::eq("Hello");
102 /// assert_eq!(true, predicate_fn.eval("Hello"));
103 /// assert_eq!(false, predicate_fn.eval("Goodbye"));
104 /// ```
eq<T>(constant: T) -> EqPredicate<T> where T: fmt::Debug + PartialEq,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 /// ```
ne<T>(constant: T) -> EqPredicate<T> where T: PartialEq + fmt::Debug,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 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result146     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 where
164     T: fmt::Debug + PartialOrd,
165 {
166     constant: T,
167     op: OrdOps,
168 }
169 
170 impl<T> Predicate<T> for OrdPredicate<T>
171 where
172     T: fmt::Debug + PartialOrd,
173 {
eval(&self, variable: &T) -> bool174     fn eval(&self, variable: &T) -> bool {
175         match self.op {
176             OrdOps::LessThan => variable.lt(&self.constant),
177             OrdOps::LessThanOrEqual => variable.le(&self.constant),
178             OrdOps::GreaterThanOrEqual => variable.ge(&self.constant),
179             OrdOps::GreaterThan => variable.gt(&self.constant),
180         }
181     }
182 
find_case<'a>(&'a self, expected: bool, variable: &T) -> Option<reflection::Case<'a>>183     fn find_case<'a>(&'a self, expected: bool, variable: &T) -> Option<reflection::Case<'a>> {
184         utils::default_find_case(self, expected, variable)
185     }
186 }
187 
188 impl<'a, T> Predicate<T> for OrdPredicate<&'a T>
189 where
190     T: fmt::Debug + PartialOrd + ?Sized,
191 {
eval(&self, variable: &T) -> bool192     fn eval(&self, variable: &T) -> bool {
193         match self.op {
194             OrdOps::LessThan => variable.lt(self.constant),
195             OrdOps::LessThanOrEqual => variable.le(self.constant),
196             OrdOps::GreaterThanOrEqual => variable.ge(self.constant),
197             OrdOps::GreaterThan => variable.gt(self.constant),
198         }
199     }
200 
find_case<'b>(&'b self, expected: bool, variable: &T) -> Option<reflection::Case<'b>>201     fn find_case<'b>(&'b self, expected: bool, variable: &T) -> Option<reflection::Case<'b>> {
202         utils::default_find_case(self, expected, variable)
203     }
204 }
205 
206 impl<T> reflection::PredicateReflection for OrdPredicate<T> where T: fmt::Debug + PartialOrd {}
207 
208 impl<T> fmt::Display for OrdPredicate<T>
209 where
210     T: fmt::Debug + PartialOrd,
211 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result212     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
213         write!(f, "var {} {:?}", self.op, self.constant)
214     }
215 }
216 
217 /// Creates a new predicate that will return `true` when the given `variable` is
218 /// less than a pre-defined value.
219 ///
220 /// # Examples
221 ///
222 /// ```
223 /// use predicates::prelude::*;
224 ///
225 /// let predicate_fn = predicate::lt(5);
226 /// assert_eq!(true, predicate_fn.eval(&4));
227 /// assert_eq!(false, predicate_fn.eval(&6));
228 ///
229 /// let predicate_fn = predicate::lt("b");
230 /// assert_eq!(true, predicate_fn.eval("a"));
231 /// assert_eq!(false, predicate_fn.eval("c"));
232 /// ```
lt<T>(constant: T) -> OrdPredicate<T> where T: fmt::Debug + PartialOrd,233 pub fn lt<T>(constant: T) -> OrdPredicate<T>
234 where
235     T: fmt::Debug + PartialOrd,
236 {
237     OrdPredicate {
238         constant,
239         op: OrdOps::LessThan,
240     }
241 }
242 
243 /// Creates a new predicate that will return `true` when the given `variable` is
244 /// less than or equal to a pre-defined value.
245 ///
246 /// # Examples
247 ///
248 /// ```
249 /// use predicates::prelude::*;
250 ///
251 /// let predicate_fn = predicate::le(5);
252 /// assert_eq!(true, predicate_fn.eval(&4));
253 /// assert_eq!(true, predicate_fn.eval(&5));
254 /// assert_eq!(false, predicate_fn.eval(&6));
255 /// ```
le<T>(constant: T) -> OrdPredicate<T> where T: PartialOrd + fmt::Debug,256 pub fn le<T>(constant: T) -> OrdPredicate<T>
257 where
258     T: PartialOrd + fmt::Debug,
259 {
260     OrdPredicate {
261         constant,
262         op: OrdOps::LessThanOrEqual,
263     }
264 }
265 
266 /// Creates a new predicate that will return `true` when the given `variable` is
267 /// greater than or equal to a pre-defined value.
268 ///
269 /// # Examples
270 ///
271 /// ```
272 /// use predicates::prelude::*;
273 ///
274 /// let predicate = predicate::ge(5);
275 /// assert_eq!(false, predicate.eval(&4));
276 /// assert_eq!(true, predicate.eval(&5));
277 /// assert_eq!(true, predicate.eval(&6));
278 /// ```
ge<T>(constant: T) -> OrdPredicate<T> where T: PartialOrd + fmt::Debug,279 pub fn ge<T>(constant: T) -> OrdPredicate<T>
280 where
281     T: PartialOrd + fmt::Debug,
282 {
283     OrdPredicate {
284         constant,
285         op: OrdOps::GreaterThanOrEqual,
286     }
287 }
288 
289 /// Creates a new predicate that will return `true` when the given `variable` is
290 /// greater than a pre-defined value.
291 ///
292 /// # Examples
293 ///
294 /// ```
295 /// use predicates::prelude::*;
296 ///
297 /// let predicate_fn = predicate::gt(5);
298 /// assert_eq!(false, predicate_fn.eval(&4));
299 /// assert_eq!(false, predicate_fn.eval(&5));
300 /// assert_eq!(true, predicate_fn.eval(&6));
301 /// ```
gt<T>(constant: T) -> OrdPredicate<T> where T: PartialOrd + fmt::Debug,302 pub fn gt<T>(constant: T) -> OrdPredicate<T>
303 where
304     T: PartialOrd + fmt::Debug,
305 {
306     OrdPredicate {
307         constant,
308         op: OrdOps::GreaterThan,
309     }
310 }
311