-
Notifications
You must be signed in to change notification settings - Fork 13
/
matcher.rs
101 lines (93 loc) · 2.92 KB
/
matcher.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//! Tools to check if an argument to a mocked method matches
//! expectations.
//!
//! See: [`pattern!`](crate::pattern) and [`from_fn!`](crate::from_fn)
//! for additional ways to create matchers.
//!
//! See [`faux::when!`](crate::when!) for how to use matchers within
//! the macro.
mod any;
mod eq;
mod from_fn;
mod invocation_matcher;
pub use any::any;
pub use eq::{eq, eq_against};
pub use from_fn::from_fn;
pub use invocation_matcher::{AnyInvocation, InvocationMatcher};
use std::fmt::{self, Formatter};
/// Matcher for single argument of a method.
///
/// Implementors provide an expectation to match an argument against.
///
/// `faux` provides some simple matchers: [`any()`], [`eq()`], and
/// [`eq_against()`]. Additionally, `faux` also provides two macros:
/// [`pattern!`](crate::pattern) for pattern matching and
/// [`from_fn!`](crate::from_fn) to provide a custom function.
///
/// You may define your own matcher for special use cases. The
/// [`fmt::Display`] implementation is used by [`InvocationMatcher`]
/// to display the expectation when any arguments failed to match.
///
/// # Examples
///
/// ```
/// use std::fmt::{self, Formatter};
/// use faux::ArgMatcher;
///
/// struct HasLength(usize);
///
/// // displayed as the expectation when any argument fails to match
/// // when used by an `InvocationMatcher`
/// impl fmt::Display for HasLength {
/// fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
/// write!(f, "_.len() == {}", self.0)
/// }
/// }
///
/// impl <T> ArgMatcher<&[T]> for HasLength {
/// // matches takes a reference to the argument
/// // the argument is &[T] so it takes &&[T]
/// fn matches(&self, argument: &&[T]) -> bool {
/// argument.len() == self.0
/// }
/// }
///
/// let has_three_length = HasLength(3);
/// let vec = vec![56, 78, 12, 43, 23];
/// assert!(has_three_length.matches(&&vec[..3]));
/// assert!(!has_three_length.matches(&&vec[1..]));
///
/// ```
pub trait ArgMatcher<Arg: ?Sized>: fmt::Display {
/// Checks if the argument matches the determined expectation.
///
/// ```
/// use faux::matcher::{self, ArgMatcher};
///
/// let eq_five = matcher::eq(5);
/// assert!(eq_five.matches(&5));
/// assert!(!eq_five.matches(&4));
/// ```
fn matches(&self, argument: &Arg) -> bool;
/// Converts the `Argmatcher<Arg>` into an `ArgMatcher<&Arg>` to
/// test against the reference of the argument.
fn into_ref_matcher(self) -> RefMatcher<Self>
where
Self: Sized,
{
RefMatcher(self)
}
}
/// Wraps an `ArgMatcher<Arg>` and implements `ArgMatcher<&Arg>`
/// instead.
pub struct RefMatcher<AM>(AM);
impl<Arg, AM: ArgMatcher<Arg>> ArgMatcher<&Arg> for RefMatcher<AM> {
fn matches(&self, actual: &&Arg) -> bool {
self.0.matches(*actual)
}
}
impl<AM: fmt::Display> fmt::Display for RefMatcher<AM> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "*{}", self.0)
}
}