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