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 {
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     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 {
eval(&self, variable: &P) -> bool48     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 
find_case<'a>(&'a self, expected: bool, variable: &P) -> Option<reflection::Case<'a>>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 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result71     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72         let palette = crate::Palette::new(f.alternate());
73         write!(
74             f,
75             "{} {} {}",
76             palette.var("var"),
77             palette.description(self.op),
78             palette.expected(utils::DebugAdapter::new(&self.constant)),
79         )
80     }
81 }
82 
83 /// Creates a new predicate that will return `true` when the given `variable` is
84 /// equal to a pre-defined value.
85 ///
86 /// # Examples
87 ///
88 /// ```
89 /// use predicates::prelude::*;
90 ///
91 /// let predicate_fn = predicate::eq(5);
92 /// assert_eq!(true, predicate_fn.eval(&5));
93 /// assert_eq!(false, predicate_fn.eval(&10));
94 ///
95 /// let predicate_fn = predicate::eq("Hello");
96 /// assert_eq!(true, predicate_fn.eval("Hello"));
97 /// assert_eq!(false, predicate_fn.eval("Goodbye"));
98 ///
99 /// let predicate_fn = predicate::eq(String::from("Hello"));
100 /// assert_eq!(true, predicate_fn.eval("Hello"));
101 /// assert_eq!(false, predicate_fn.eval("Goodbye"));
102 /// ```
eq<T>(constant: T) -> EqPredicate<T> where T: fmt::Debug + PartialEq,103 pub fn eq<T>(constant: T) -> EqPredicate<T>
104 where
105     T: fmt::Debug + PartialEq,
106 {
107     EqPredicate {
108         constant,
109         op: EqOps::Equal,
110     }
111 }
112 
113 /// Creates a new predicate that will return `true` when the given `variable` is
114 /// _not_ equal to a pre-defined value.
115 ///
116 /// # Examples
117 ///
118 /// ```
119 /// use predicates::prelude::*;
120 ///
121 /// let predicate_fn = predicate::ne(5);
122 /// assert_eq!(false, predicate_fn.eval(&5));
123 /// assert_eq!(true, predicate_fn.eval(&10));
124 /// ```
ne<T>(constant: T) -> EqPredicate<T> where T: PartialEq + fmt::Debug,125 pub fn ne<T>(constant: T) -> EqPredicate<T>
126 where
127     T: PartialEq + fmt::Debug,
128 {
129     EqPredicate {
130         constant,
131         op: EqOps::NotEqual,
132     }
133 }
134 
135 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
136 enum OrdOps {
137     LessThan,
138     LessThanOrEqual,
139     GreaterThanOrEqual,
140     GreaterThan,
141 }
142 
143 impl fmt::Display for OrdOps {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result144     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145         let op = match *self {
146             OrdOps::LessThan => "<",
147             OrdOps::LessThanOrEqual => "<=",
148             OrdOps::GreaterThanOrEqual => ">=",
149             OrdOps::GreaterThan => ">",
150         };
151         write!(f, "{}", op)
152     }
153 }
154 
155 /// Predicate that returns `true` if `variable` matches the pre-defined `Ord`
156 /// value, otherwise returns `false`.
157 ///
158 /// This is created by the `predicate::{gt, ge, lt, le}` functions.
159 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
160 pub struct OrdPredicate<T> {
161     constant: T,
162     op: OrdOps,
163 }
164 
165 impl<P, T> Predicate<P> for OrdPredicate<T>
166 where
167     T: std::borrow::Borrow<P> + fmt::Debug,
168     P: fmt::Debug + PartialOrd + ?Sized,
169 {
eval(&self, variable: &P) -> bool170     fn eval(&self, variable: &P) -> bool {
171         match self.op {
172             OrdOps::LessThan => variable.lt(self.constant.borrow()),
173             OrdOps::LessThanOrEqual => variable.le(self.constant.borrow()),
174             OrdOps::GreaterThanOrEqual => variable.ge(self.constant.borrow()),
175             OrdOps::GreaterThan => variable.gt(self.constant.borrow()),
176         }
177     }
178 
find_case<'a>(&'a self, expected: bool, variable: &P) -> Option<reflection::Case<'a>>179     fn find_case<'a>(&'a self, expected: bool, variable: &P) -> Option<reflection::Case<'a>> {
180         utils::default_find_case(self, expected, variable).map(|case| {
181             case.add_product(reflection::Product::new(
182                 "var",
183                 utils::DebugAdapter::new(variable).to_string(),
184             ))
185         })
186     }
187 }
188 
189 impl<T> reflection::PredicateReflection for OrdPredicate<T> where T: fmt::Debug {}
190 
191 impl<T> fmt::Display for OrdPredicate<T>
192 where
193     T: fmt::Debug,
194 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result195     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
196         let palette = crate::Palette::new(f.alternate());
197         write!(
198             f,
199             "{} {} {}",
200             palette.var("var"),
201             palette.description(self.op),
202             palette.expected(utils::DebugAdapter::new(&self.constant)),
203         )
204     }
205 }
206 
207 /// Creates a new predicate that will return `true` when the given `variable` is
208 /// less than a pre-defined value.
209 ///
210 /// # Examples
211 ///
212 /// ```
213 /// use predicates::prelude::*;
214 ///
215 /// let predicate_fn = predicate::lt(5);
216 /// assert_eq!(true, predicate_fn.eval(&4));
217 /// assert_eq!(false, predicate_fn.eval(&6));
218 ///
219 /// let predicate_fn = predicate::lt("b");
220 /// assert_eq!(true, predicate_fn.eval("a"));
221 /// assert_eq!(false, predicate_fn.eval("c"));
222 ///
223 /// let predicate_fn = predicate::lt(String::from("b"));
224 /// assert_eq!(true, predicate_fn.eval("a"));
225 /// assert_eq!(false, predicate_fn.eval("c"));
226 /// ```
lt<T>(constant: T) -> OrdPredicate<T> where T: fmt::Debug + PartialOrd,227 pub fn lt<T>(constant: T) -> OrdPredicate<T>
228 where
229     T: fmt::Debug + PartialOrd,
230 {
231     OrdPredicate {
232         constant,
233         op: OrdOps::LessThan,
234     }
235 }
236 
237 /// Creates a new predicate that will return `true` when the given `variable` is
238 /// less than or equal to a pre-defined value.
239 ///
240 /// # Examples
241 ///
242 /// ```
243 /// use predicates::prelude::*;
244 ///
245 /// let predicate_fn = predicate::le(5);
246 /// assert_eq!(true, predicate_fn.eval(&4));
247 /// assert_eq!(true, predicate_fn.eval(&5));
248 /// assert_eq!(false, predicate_fn.eval(&6));
249 /// ```
le<T>(constant: T) -> OrdPredicate<T> where T: PartialOrd + fmt::Debug,250 pub fn le<T>(constant: T) -> OrdPredicate<T>
251 where
252     T: PartialOrd + fmt::Debug,
253 {
254     OrdPredicate {
255         constant,
256         op: OrdOps::LessThanOrEqual,
257     }
258 }
259 
260 /// Creates a new predicate that will return `true` when the given `variable` is
261 /// greater than or equal to a pre-defined value.
262 ///
263 /// # Examples
264 ///
265 /// ```
266 /// use predicates::prelude::*;
267 ///
268 /// let predicate = predicate::ge(5);
269 /// assert_eq!(false, predicate.eval(&4));
270 /// assert_eq!(true, predicate.eval(&5));
271 /// assert_eq!(true, predicate.eval(&6));
272 /// ```
ge<T>(constant: T) -> OrdPredicate<T> where T: PartialOrd + fmt::Debug,273 pub fn ge<T>(constant: T) -> OrdPredicate<T>
274 where
275     T: PartialOrd + fmt::Debug,
276 {
277     OrdPredicate {
278         constant,
279         op: OrdOps::GreaterThanOrEqual,
280     }
281 }
282 
283 /// Creates a new predicate that will return `true` when the given `variable` is
284 /// greater than a pre-defined value.
285 ///
286 /// # Examples
287 ///
288 /// ```
289 /// use predicates::prelude::*;
290 ///
291 /// let predicate_fn = predicate::gt(5);
292 /// assert_eq!(false, predicate_fn.eval(&4));
293 /// assert_eq!(false, predicate_fn.eval(&5));
294 /// assert_eq!(true, predicate_fn.eval(&6));
295 /// ```
gt<T>(constant: T) -> OrdPredicate<T> where T: PartialOrd + fmt::Debug,296 pub fn gt<T>(constant: T) -> OrdPredicate<T>
297 where
298     T: PartialOrd + fmt::Debug,
299 {
300     OrdPredicate {
301         constant,
302         op: OrdOps::GreaterThan,
303     }
304 }
305