predicates/
ord.rs

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
11use std::fmt;
12
13use crate::reflection;
14use crate::utils;
15use crate::Predicate;
16
17#[derive(Clone, Copy, Debug, PartialEq, Eq)]
18enum EqOps {
19    Equal,
20    NotEqual,
21}
22
23impl fmt::Display for EqOps {
24    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)]
38pub struct EqPredicate<T>
39where
40    T: fmt::Debug + PartialEq,
41{
42    constant: T,
43    op: EqOps,
44}
45
46impl<T> Predicate<T> for EqPredicate<T>
47where
48    T: fmt::Debug + PartialEq,
49{
50    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
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
62impl<'a, T> Predicate<T> for EqPredicate<&'a T>
63where
64    T: fmt::Debug + PartialEq + ?Sized,
65{
66    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
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
78impl<T> reflection::PredicateReflection for EqPredicate<T> where T: fmt::Debug + PartialEq {}
79
80impl<T> fmt::Display for EqPredicate<T>
81where
82    T: fmt::Debug + PartialEq,
83{
84    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/// ```
105pub fn eq<T>(constant: T) -> EqPredicate<T>
106where
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/// ```
127pub fn ne<T>(constant: T) -> EqPredicate<T>
128where
129    T: PartialEq + fmt::Debug,
130{
131    EqPredicate {
132        constant,
133        op: EqOps::NotEqual,
134    }
135}
136
137#[derive(Clone, Copy, Debug, PartialEq, Eq)]
138enum OrdOps {
139    LessThan,
140    LessThanOrEqual,
141    GreaterThanOrEqual,
142    GreaterThan,
143}
144
145impl fmt::Display for OrdOps {
146    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)]
162pub struct OrdPredicate<T>
163where
164    T: fmt::Debug + PartialOrd,
165{
166    constant: T,
167    op: OrdOps,
168}
169
170impl<T> Predicate<T> for OrdPredicate<T>
171where
172    T: fmt::Debug + PartialOrd,
173{
174    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
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
188impl<'a, T> Predicate<T> for OrdPredicate<&'a T>
189where
190    T: fmt::Debug + PartialOrd + ?Sized,
191{
192    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
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
206impl<T> reflection::PredicateReflection for OrdPredicate<T> where T: fmt::Debug + PartialOrd {}
207
208impl<T> fmt::Display for OrdPredicate<T>
209where
210    T: fmt::Debug + PartialOrd,
211{
212    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/// ```
233pub fn lt<T>(constant: T) -> OrdPredicate<T>
234where
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/// ```
256pub fn le<T>(constant: T) -> OrdPredicate<T>
257where
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/// ```
279pub fn ge<T>(constant: T) -> OrdPredicate<T>
280where
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/// ```
302pub fn gt<T>(constant: T) -> OrdPredicate<T>
303where
304    T: PartialOrd + fmt::Debug,
305{
306    OrdPredicate {
307        constant,
308        op: OrdOps::GreaterThan,
309    }
310}