Skip to content

Commit 4e1d03c

Browse files
authored
Merge pull request #134 from rshearman/owned-ord
feat: Allow predicates to own object and evaluate against borrowed types
2 parents ee57a38 + 7934a3a commit 4e1d03c

File tree

2 files changed

+66
-139
lines changed

2 files changed

+66
-139
lines changed

src/iter.rs

Lines changed: 35 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ where
6060
/// assert_eq!(true, predicate_fn.eval("a"));
6161
/// assert_eq!(false, predicate_fn.eval("b"));
6262
/// assert_eq!(true, predicate_fn.eval("c"));
63+
///
64+
/// let predicate_fn = predicate::in_iter(vec![String::from("a"), String::from("c"), String::from("e")]).sort();
65+
/// assert_eq!(true, predicate_fn.eval("a"));
66+
/// assert_eq!(false, predicate_fn.eval("b"));
67+
/// assert_eq!(true, predicate_fn.eval("c"));
6368
/// ```
6469
pub fn sort(self) -> OrdInPredicate<T> {
6570
let mut items = self.inner.debug;
@@ -70,33 +75,16 @@ where
7075
}
7176
}
7277

73-
impl<T> Predicate<T> for InPredicate<T>
74-
where
75-
T: PartialEq + fmt::Debug,
76-
{
77-
fn eval(&self, variable: &T) -> bool {
78-
self.inner.debug.contains(variable)
79-
}
80-
81-
fn find_case<'a>(&'a self, expected: bool, variable: &T) -> Option<reflection::Case<'a>> {
82-
utils::default_find_case(self, expected, variable).map(|case| {
83-
case.add_product(reflection::Product::new(
84-
"var",
85-
utils::DebugAdapter::new(variable).to_string(),
86-
))
87-
})
88-
}
89-
}
90-
91-
impl<'a, T> Predicate<T> for InPredicate<&'a T>
78+
impl<P, T> Predicate<P> for InPredicate<T>
9279
where
93-
T: PartialEq + fmt::Debug + ?Sized,
80+
T: std::borrow::Borrow<P> + PartialEq + fmt::Debug,
81+
P: PartialEq + fmt::Debug + ?Sized,
9482
{
95-
fn eval(&self, variable: &T) -> bool {
96-
self.inner.debug.contains(&variable)
83+
fn eval(&self, variable: &P) -> bool {
84+
self.inner.debug.iter().any(|x| x.borrow() == variable)
9785
}
9886

99-
fn find_case<'b>(&'b self, expected: bool, variable: &T) -> Option<reflection::Case<'b>> {
87+
fn find_case<'a>(&'a self, expected: bool, variable: &P) -> Option<reflection::Case<'a>> {
10088
utils::default_find_case(self, expected, variable).map(|case| {
10189
case.add_product(reflection::Product::new(
10290
"var",
@@ -160,6 +148,11 @@ where
160148
/// assert_eq!(true, predicate_fn.eval("a"));
161149
/// assert_eq!(false, predicate_fn.eval("b"));
162150
/// assert_eq!(true, predicate_fn.eval("c"));
151+
///
152+
/// let predicate_fn = predicate::in_iter(vec![String::from("a"), String::from("c"), String::from("e")]);
153+
/// assert_eq!(true, predicate_fn.eval("a"));
154+
/// assert_eq!(false, predicate_fn.eval("b"));
155+
/// assert_eq!(true, predicate_fn.eval("c"));
163156
/// ```
164157
pub fn in_iter<I, T>(iter: I) -> InPredicate<T>
165158
where
@@ -188,33 +181,19 @@ where
188181
inner: utils::DebugAdapter<Vec<T>>,
189182
}
190183

191-
impl<T> Predicate<T> for OrdInPredicate<T>
184+
impl<P, T> Predicate<P> for OrdInPredicate<T>
192185
where
193-
T: Ord + fmt::Debug,
186+
T: std::borrow::Borrow<P> + Ord + fmt::Debug,
187+
P: Ord + fmt::Debug + ?Sized,
194188
{
195-
fn eval(&self, variable: &T) -> bool {
196-
self.inner.debug.binary_search(variable).is_ok()
189+
fn eval(&self, variable: &P) -> bool {
190+
self.inner
191+
.debug
192+
.binary_search_by(|x| x.borrow().cmp(variable))
193+
.is_ok()
197194
}
198195

199-
fn find_case<'a>(&'a self, expected: bool, variable: &T) -> Option<reflection::Case<'a>> {
200-
utils::default_find_case(self, expected, variable).map(|case| {
201-
case.add_product(reflection::Product::new(
202-
"var",
203-
utils::DebugAdapter::new(variable).to_string(),
204-
))
205-
})
206-
}
207-
}
208-
209-
impl<'a, T> Predicate<T> for OrdInPredicate<&'a T>
210-
where
211-
T: Ord + fmt::Debug + ?Sized,
212-
{
213-
fn eval(&self, variable: &T) -> bool {
214-
self.inner.debug.binary_search(&variable).is_ok()
215-
}
216-
217-
fn find_case<'b>(&'b self, expected: bool, variable: &T) -> Option<reflection::Case<'b>> {
196+
fn find_case<'a>(&'a self, expected: bool, variable: &P) -> Option<reflection::Case<'a>> {
218197
utils::default_find_case(self, expected, variable).map(|case| {
219198
case.add_product(reflection::Product::new(
220199
"var",
@@ -267,33 +246,16 @@ where
267246
inner: utils::DebugAdapter<HashSet<T>>,
268247
}
269248

270-
impl<T> Predicate<T> for HashableInPredicate<T>
249+
impl<P, T> Predicate<P> for HashableInPredicate<T>
271250
where
272-
T: Hash + Eq + fmt::Debug,
251+
T: std::borrow::Borrow<P> + Hash + Eq + fmt::Debug,
252+
P: Hash + Eq + fmt::Debug + ?Sized,
273253
{
274-
fn eval(&self, variable: &T) -> bool {
254+
fn eval(&self, variable: &P) -> bool {
275255
self.inner.debug.contains(variable)
276256
}
277257

278-
fn find_case<'a>(&'a self, expected: bool, variable: &T) -> Option<reflection::Case<'a>> {
279-
utils::default_find_case(self, expected, variable).map(|case| {
280-
case.add_product(reflection::Product::new(
281-
"var",
282-
utils::DebugAdapter::new(variable).to_string(),
283-
))
284-
})
285-
}
286-
}
287-
288-
impl<'a, T> Predicate<T> for HashableInPredicate<&'a T>
289-
where
290-
T: Hash + Eq + fmt::Debug + ?Sized,
291-
{
292-
fn eval(&self, variable: &T) -> bool {
293-
self.inner.debug.contains(&variable)
294-
}
295-
296-
fn find_case<'b>(&'b self, expected: bool, variable: &T) -> Option<reflection::Case<'b>> {
258+
fn find_case<'a>(&'a self, expected: bool, variable: &P) -> Option<reflection::Case<'a>> {
297259
utils::default_find_case(self, expected, variable).map(|case| {
298260
case.add_product(reflection::Product::new(
299261
"var",
@@ -351,6 +313,11 @@ where
351313
/// assert_eq!(true, predicate_fn.eval("a"));
352314
/// assert_eq!(false, predicate_fn.eval("b"));
353315
/// assert_eq!(true, predicate_fn.eval("c"));
316+
///
317+
/// let predicate_fn = predicate::in_hash(vec![String::from("a"), String::from("c"), String::from("e")]);
318+
/// assert_eq!(true, predicate_fn.eval("a"));
319+
/// assert_eq!(false, predicate_fn.eval("b"));
320+
/// assert_eq!(true, predicate_fn.eval("c"));
354321
/// ```
355322
pub fn in_hash<I, T>(iter: I) -> HashableInPredicate<T>
356323
where

src/ord.rs

Lines changed: 31 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) 2018 The predicates-rs Project Developers.
1+
// Copyright (c) 2018, 2022 The predicates-rs Project Developers.
22
//
33
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
44
// http://www.apache.org/license/LICENSE-2.0> or the MIT license
@@ -35,26 +35,24 @@ impl fmt::Display for EqOps {
3535
///
3636
/// This is created by the `predicate::{eq, ne}` functions.
3737
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
38-
pub struct EqPredicate<T>
39-
where
40-
T: fmt::Debug + PartialEq,
41-
{
38+
pub struct EqPredicate<T> {
4239
constant: T,
4340
op: EqOps,
4441
}
4542

46-
impl<T> Predicate<T> for EqPredicate<T>
43+
impl<P, T> Predicate<P> for EqPredicate<T>
4744
where
48-
T: fmt::Debug + PartialEq,
45+
T: std::borrow::Borrow<P> + fmt::Debug,
46+
P: fmt::Debug + PartialEq + ?Sized,
4947
{
50-
fn eval(&self, variable: &T) -> bool {
48+
fn eval(&self, variable: &P) -> bool {
5149
match self.op {
52-
EqOps::Equal => variable.eq(&self.constant),
53-
EqOps::NotEqual => variable.ne(&self.constant),
50+
EqOps::Equal => variable.eq(self.constant.borrow()),
51+
EqOps::NotEqual => variable.ne(self.constant.borrow()),
5452
}
5553
}
5654

57-
fn find_case<'a>(&'a self, expected: bool, variable: &T) -> Option<reflection::Case<'a>> {
55+
fn find_case<'a>(&'a self, expected: bool, variable: &P) -> Option<reflection::Case<'a>> {
5856
utils::default_find_case(self, expected, variable).map(|case| {
5957
case.add_product(reflection::Product::new(
6058
"var",
@@ -64,32 +62,11 @@ where
6462
}
6563
}
6664

67-
impl<'a, T> Predicate<T> for EqPredicate<&'a T>
68-
where
69-
T: fmt::Debug + PartialEq + ?Sized,
70-
{
71-
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-
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 {}
65+
impl<T> reflection::PredicateReflection for EqPredicate<T> where T: fmt::Debug {}
8966

9067
impl<T> fmt::Display for EqPredicate<T>
9168
where
92-
T: fmt::Debug + PartialEq,
69+
T: fmt::Debug,
9370
{
9471
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9572
let palette = crate::Palette::current();
@@ -120,6 +97,10 @@ where
12097
/// let predicate_fn = predicate::eq("Hello");
12198
/// assert_eq!(true, predicate_fn.eval("Hello"));
12299
/// assert_eq!(false, predicate_fn.eval("Goodbye"));
100+
///
101+
/// let predicate_fn = predicate::eq(String::from("Hello"));
102+
/// assert_eq!(true, predicate_fn.eval("Hello"));
103+
/// assert_eq!(false, predicate_fn.eval("Goodbye"));
123104
/// ```
124105
pub fn eq<T>(constant: T) -> EqPredicate<T>
125106
where
@@ -178,28 +159,26 @@ impl fmt::Display for OrdOps {
178159
///
179160
/// This is created by the `predicate::{gt, ge, lt, le}` functions.
180161
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
181-
pub struct OrdPredicate<T>
182-
where
183-
T: fmt::Debug + PartialOrd,
184-
{
162+
pub struct OrdPredicate<T> {
185163
constant: T,
186164
op: OrdOps,
187165
}
188166

189-
impl<T> Predicate<T> for OrdPredicate<T>
167+
impl<P, T> Predicate<P> for OrdPredicate<T>
190168
where
191-
T: fmt::Debug + PartialOrd,
169+
T: std::borrow::Borrow<P> + fmt::Debug,
170+
P: fmt::Debug + PartialOrd + ?Sized,
192171
{
193-
fn eval(&self, variable: &T) -> bool {
172+
fn eval(&self, variable: &P) -> bool {
194173
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),
174+
OrdOps::LessThan => variable.lt(self.constant.borrow()),
175+
OrdOps::LessThanOrEqual => variable.le(self.constant.borrow()),
176+
OrdOps::GreaterThanOrEqual => variable.ge(self.constant.borrow()),
177+
OrdOps::GreaterThan => variable.gt(self.constant.borrow()),
199178
}
200179
}
201180

202-
fn find_case<'a>(&'a self, expected: bool, variable: &T) -> Option<reflection::Case<'a>> {
181+
fn find_case<'a>(&'a self, expected: bool, variable: &P) -> Option<reflection::Case<'a>> {
203182
utils::default_find_case(self, expected, variable).map(|case| {
204183
case.add_product(reflection::Product::new(
205184
"var",
@@ -209,34 +188,11 @@ where
209188
}
210189
}
211190

212-
impl<'a, T> Predicate<T> for OrdPredicate<&'a T>
213-
where
214-
T: fmt::Debug + PartialOrd + ?Sized,
215-
{
216-
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-
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 {}
191+
impl<T> reflection::PredicateReflection for OrdPredicate<T> where T: fmt::Debug {}
236192

237193
impl<T> fmt::Display for OrdPredicate<T>
238194
where
239-
T: fmt::Debug + PartialOrd,
195+
T: fmt::Debug,
240196
{
241197
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
242198
let palette = crate::Palette::current();
@@ -267,6 +223,10 @@ where
267223
/// let predicate_fn = predicate::lt("b");
268224
/// assert_eq!(true, predicate_fn.eval("a"));
269225
/// assert_eq!(false, predicate_fn.eval("c"));
226+
///
227+
/// let predicate_fn = predicate::lt(String::from("b"));
228+
/// assert_eq!(true, predicate_fn.eval("a"));
229+
/// assert_eq!(false, predicate_fn.eval("c"));
270230
/// ```
271231
pub fn lt<T>(constant: T) -> OrdPredicate<T>
272232
where

0 commit comments

Comments
 (0)