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