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