Skip to content

Commit efd199b

Browse files
authored
Merge pull request #38 from epage/eval
Implement `Display` support in lead up to #7
2 parents e550a91 + d02cc4c commit efd199b

17 files changed

+382
-22
lines changed

src/boolean.rs

+33
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
//! Definition of boolean logic combinators over `Predicate`s.
1010
1111
use std::marker::PhantomData;
12+
use std::fmt;
1213

1314
use Predicate;
1415

@@ -54,6 +55,17 @@ where
5455
}
5556
}
5657

58+
impl<M1, M2, Item> fmt::Display for AndPredicate<M1, M2, Item>
59+
where
60+
M1: Predicate<Item>,
61+
M2: Predicate<Item>,
62+
Item: ?Sized,
63+
{
64+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
65+
write!(f, "({} && {})", self.a, self.b)
66+
}
67+
}
68+
5769
/// Predicate that combines two `Predicate`s, returning the OR of the results.
5870
///
5971
/// This is created by the `Predicate::or` function.
@@ -96,6 +108,17 @@ where
96108
}
97109
}
98110

111+
impl<M1, M2, Item> fmt::Display for OrPredicate<M1, M2, Item>
112+
where
113+
M1: Predicate<Item>,
114+
M2: Predicate<Item>,
115+
Item: ?Sized,
116+
{
117+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
118+
write!(f, "({} || {})", self.a, self.b)
119+
}
120+
}
121+
99122
/// Predicate that returns a `Predicate` taking the logical NOT of the result.
100123
///
101124
/// This is created by the `Predicate::not` function.
@@ -133,6 +156,16 @@ where
133156
}
134157
}
135158

159+
impl<M, Item> fmt::Display for NotPredicate<M, Item>
160+
where
161+
M: Predicate<Item>,
162+
Item: ?Sized,
163+
{
164+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
165+
write!(f, "(! {})", self.inner)
166+
}
167+
}
168+
136169
/// `Predicate` extension that adds boolean logic.
137170
pub trait PredicateBooleanExt<Item: ?Sized>
138171
where

src/boxed.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ where
4545
Item: ?Sized,
4646
{
4747
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
48-
write!(f, "BoxPredicate")
48+
write!(f, "{}", self.0)
4949
}
5050
}
5151

src/constant.rs

+7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
//! Definition of a constant (always true or always false) `Predicate`.
1010
1111
use std::marker::PhantomData;
12+
use std::fmt;
1213

1314
use Predicate;
1415

@@ -27,6 +28,12 @@ impl<Item> Predicate<Item> for BooleanPredicate<Item> {
2728
}
2829
}
2930

31+
impl<Item> fmt::Display for BooleanPredicate<Item> {
32+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
33+
write!(f, "{}", self.retval)
34+
}
35+
}
36+
3037
/// Creates a new `Predicate` that always returns `true`.
3138
///
3239
/// # Examples

src/core.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@
66
// option. This file may not be copied, modified, or distributed
77
// except according to those terms.
88

9+
use std::fmt;
10+
911
/// Trait for generically evaluating a type against a dynamically created
1012
/// predicate function.
1113
///
1214
/// The exact meaning of `eval` depends on the situation, but will usually
1315
/// mean that the evaluated item is in some sort of pre-defined set. This is
1416
/// different from `Ord` and `Eq` in that an `item` will almost never be the
1517
/// same type as the implementing `Predicate` type.
16-
pub trait Predicate<Item: ?Sized> {
18+
pub trait Predicate<Item: ?Sized>: fmt::Display {
1719
/// Execute this `Predicate` against `variable`, returning the resulting
1820
/// boolean.
1921
fn eval(&self, variable: &Item) -> bool;

src/float/close.rs

+12
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
// option. This file may not be copied, modified, or distributed
77
// except according to those terms.
88

9+
use std::fmt;
10+
911
use float_cmp::ApproxEq;
1012
use float_cmp::Ulps;
1113

@@ -84,6 +86,16 @@ impl Predicate<f64> for IsClosePredicate {
8486
}
8587
}
8688

89+
impl fmt::Display for IsClosePredicate {
90+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
91+
write!(
92+
f,
93+
"var ~= {} +/- {} ({})",
94+
self.target, self.epsilon, self.ulps
95+
)
96+
}
97+
}
98+
8799
/// Create a new `Predicate` that ensures two numbers are "close" enough, understanding that
88100
/// rounding errors occur.
89101
///

src/function.rs

+38
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
//! Definition of `Predicate` for wrapping a `Fn(&T) -> bool`
1010
1111
use std::marker::PhantomData;
12+
use std::fmt;
1213

1314
use Predicate;
1415

@@ -20,9 +21,36 @@ where
2021
F: Fn(&T) -> bool,
2122
{
2223
function: F,
24+
name: &'static str,
2325
_phantom: PhantomData<T>,
2426
}
2527

28+
impl<F, T> FnPredicate<F, T>
29+
where
30+
F: Fn(&T) -> bool,
31+
{
32+
/// Provide a descriptive name for this function.
33+
///
34+
/// # Examples
35+
///
36+
/// ```
37+
/// use predicates::prelude::*;
38+
///
39+
/// struct Example {
40+
/// string: String,
41+
/// number: i32,
42+
/// }
43+
///
44+
/// let string_check = predicate::function(|x: &Example| x.string == "hello")
45+
/// .fn_name("is_hello");
46+
/// println!("predicate: {}", string_check);
47+
/// ```
48+
pub fn fn_name(mut self, name: &'static str) -> Self {
49+
self.name = name;
50+
self
51+
}
52+
}
53+
2654
impl<F, T> Predicate<T> for FnPredicate<F, T>
2755
where
2856
F: Fn(&T) -> bool,
@@ -32,6 +60,15 @@ where
3260
}
3361
}
3462

63+
impl<F, T> fmt::Display for FnPredicate<F, T>
64+
where
65+
F: Fn(&T) -> bool,
66+
{
67+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68+
write!(f, "{}(var)", self.name)
69+
}
70+
}
71+
3572
/// Creates a new predicate that wraps over the given function. The returned
3673
/// type implements `Predicate` and therefore has all combinators available to
3774
/// it.
@@ -60,6 +97,7 @@ where
6097
{
6198
FnPredicate {
6299
function: function,
100+
name: "fn",
63101
_phantom: PhantomData,
64102
}
65103
}

src/iter.rs

+37-9
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
//! Definition of `Predicate`s for comparisons of membership in a set.
1010
1111
use std::collections::HashSet;
12+
use std::fmt;
1213
use std::hash::Hash;
1314
use std::iter::FromIterator;
1415

@@ -26,14 +27,14 @@ use Predicate;
2627
#[derive(Debug)]
2728
pub struct InPredicate<T>
2829
where
29-
T: PartialEq,
30+
T: PartialEq + fmt::Debug,
3031
{
3132
inner: Vec<T>,
3233
}
3334

3435
impl<T> InPredicate<T>
3536
where
36-
T: Ord,
37+
T: Ord + fmt::Debug,
3738
{
3839
/// Creates a new predicate that will return `true` when the given `variable` is
3940
/// contained with the set of items provided.
@@ -64,13 +65,22 @@ where
6465

6566
impl<T> Predicate<T> for InPredicate<T>
6667
where
67-
T: PartialEq,
68+
T: PartialEq + fmt::Debug,
6869
{
6970
fn eval(&self, variable: &T) -> bool {
7071
self.inner.contains(variable)
7172
}
7273
}
7374

75+
impl<T> fmt::Display for InPredicate<T>
76+
where
77+
T: PartialEq + fmt::Debug,
78+
{
79+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
80+
write!(f, "var in {:?}", self.inner)
81+
}
82+
}
83+
7484
/// Creates a new predicate that will return `true` when the given `variable` is
7585
/// contained with the set of items provided.
7686
///
@@ -99,7 +109,7 @@ where
99109
/// ```
100110
pub fn in_iter<I, T>(iter: I) -> InPredicate<T>
101111
where
102-
T: PartialEq,
112+
T: PartialEq + fmt::Debug,
103113
I: IntoIterator<Item = T>,
104114
{
105115
InPredicate {
@@ -119,20 +129,29 @@ where
119129
#[derive(Debug)]
120130
pub struct OrdInPredicate<T>
121131
where
122-
T: Ord,
132+
T: Ord + fmt::Debug,
123133
{
124134
inner: Vec<T>,
125135
}
126136

127137
impl<T> Predicate<T> for OrdInPredicate<T>
128138
where
129-
T: Ord,
139+
T: Ord + fmt::Debug,
130140
{
131141
fn eval(&self, variable: &T) -> bool {
132142
self.inner.binary_search(variable).is_ok()
133143
}
134144
}
135145

146+
impl<T> fmt::Display for OrdInPredicate<T>
147+
where
148+
T: Ord + fmt::Debug,
149+
{
150+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
151+
write!(f, "var in {:?}", self.inner)
152+
}
153+
}
154+
136155
/// Predicate that returns `true` if `variable` is a member of the pre-defined
137156
/// `HashSet`, otherwise returns `false`.
138157
///
@@ -145,20 +164,29 @@ where
145164
#[derive(Debug)]
146165
pub struct HashableInPredicate<T>
147166
where
148-
T: Hash + Eq,
167+
T: Hash + Eq + fmt::Debug,
149168
{
150169
inner: HashSet<T>,
151170
}
152171

153172
impl<T> Predicate<T> for HashableInPredicate<T>
154173
where
155-
T: Hash + Eq,
174+
T: Hash + Eq + fmt::Debug,
156175
{
157176
fn eval(&self, variable: &T) -> bool {
158177
self.inner.contains(variable)
159178
}
160179
}
161180

181+
impl<T> fmt::Display for HashableInPredicate<T>
182+
where
183+
T: Hash + Eq + fmt::Debug,
184+
{
185+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
186+
write!(f, "var in {:?}", self.inner)
187+
}
188+
}
189+
162190
/// Creates a new predicate that will return `true` when the given `variable` is
163191
/// contained with the set of items provided.
164192
///
@@ -181,7 +209,7 @@ where
181209
/// ```
182210
pub fn in_hash<I, T>(iter: I) -> HashableInPredicate<T>
183211
where
184-
T: Hash + Eq,
212+
T: Hash + Eq + fmt::Debug,
185213
I: IntoIterator<Item = T>,
186214
{
187215
HashableInPredicate {

src/lib.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
//! ```
3535
//! use predicates::prelude::*;
3636
//!
37+
//! use std::fmt;
38+
//!
3739
//! // The simplest predicates are `always()` and `never()`, which always returns
3840
//! // `true` and always returns `false`, respectively. The values are simply
3941
//! // ignored when evaluating against these predicates:
@@ -57,7 +59,7 @@
5759
//! assert_eq!(false, between_5_and_10.eval(&11));
5860
//! assert_eq!(false, between_5_and_10.eval(&4));
5961
//!
60-
//! // The `Predicate` trait is pretty simple, requiring only the
62+
//! // The `Predicate` trait is pretty simple, the core of it is an
6163
//! // implementation of a `eval` function that takes a single argument and
6264
//! // returns a `bool`. Implementing a custom `Predicate` still allows all the
6365
//! // usual combinators of the `Predicate` trait to work!
@@ -67,6 +69,11 @@
6769
//! *variable == 42
6870
//! }
6971
//! }
72+
//! impl fmt::Display for IsTheAnswer {
73+
//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
74+
//! write!(f, "var.is_the_answer()")
75+
//! }
76+
//! }
7077
//!
7178
//! assert_eq!(true, IsTheAnswer.eval(&42));
7279
//! let almost_the_answer = IsTheAnswer.or(predicate::in_iter(vec![41, 43]));
@@ -103,6 +110,7 @@ pub mod constant;
103110
pub mod function;
104111
pub mod ord;
105112
pub mod iter;
113+
pub mod name;
106114

107115
// combinators
108116
pub mod boolean;

0 commit comments

Comments
 (0)