@@ -16,7 +16,7 @@ use crate::matcher::{MatchExplanation, Matcher, MatcherResult};
16
16
#[ cfg( google3) ]
17
17
use googletest:: * ;
18
18
use std:: fmt:: Debug ;
19
- use std:: iter :: zip ;
19
+ use std:: marker :: PhantomData ;
20
20
21
21
/// Matches a container equal (in the sense of `==`) to `expected`.
22
22
///
@@ -85,119 +85,61 @@ use std::iter::zip;
85
85
// ContainerEqMatcher has some specialisations for slice types (see
86
86
// documentation above). Returning impl Matcher would hide those from the
87
87
// compiler.
88
- pub fn container_eq < ContainerT : PartialEq + Debug > (
89
- expected : ContainerT ,
90
- ) -> ContainerEqMatcher < ContainerT > {
91
- ContainerEqMatcher { expected }
88
+ pub fn container_eq < ActualContainerT , ExpectedContainerT > (
89
+ expected : ExpectedContainerT ,
90
+ ) -> ContainerEqMatcher < ActualContainerT , ExpectedContainerT >
91
+ where
92
+ ActualContainerT : PartialEq < ExpectedContainerT > + Debug + ?Sized ,
93
+ ExpectedContainerT : Debug ,
94
+ {
95
+ ContainerEqMatcher { expected, phantom : Default :: default ( ) }
92
96
}
93
97
94
- pub struct ContainerEqMatcher < T : Debug > {
95
- expected : T ,
98
+ pub struct ContainerEqMatcher < ActualContainerT : ?Sized , ExpectedContainerT > {
99
+ expected : ExpectedContainerT ,
100
+ phantom : PhantomData < ActualContainerT > ,
96
101
}
97
102
98
- impl < T : PartialEq + Debug , ContainerT : PartialEq + Debug > Matcher < ContainerT >
99
- for ContainerEqMatcher < ContainerT >
103
+ impl < ActualElementT , ActualContainerT , ExpectedElementT , ExpectedContainerT >
104
+ Matcher < ActualContainerT > for ContainerEqMatcher < ActualContainerT , ExpectedContainerT >
100
105
where
101
- for < ' a > & ' a ContainerT : IntoIterator < Item = & ' a T > ,
106
+ ActualElementT : PartialEq < ExpectedElementT > + Debug + ?Sized ,
107
+ ActualContainerT : PartialEq < ExpectedContainerT > + Debug + ?Sized ,
108
+ ExpectedElementT : Debug ,
109
+ ExpectedContainerT : Debug ,
110
+ for < ' a > & ' a ActualContainerT : IntoIterator < Item = & ' a ActualElementT > ,
111
+ for < ' a > & ' a ExpectedContainerT : IntoIterator < Item = & ' a ExpectedElementT > ,
102
112
{
103
- fn matches ( & self , actual : & ContainerT ) -> MatcherResult {
113
+ fn matches ( & self , actual : & ActualContainerT ) -> MatcherResult {
104
114
( * actual == self . expected ) . into ( )
105
115
}
106
116
107
- fn explain_match ( & self , actual : & ContainerT ) -> MatchExplanation {
108
- self . explain_match_impl ( actual)
109
- }
110
-
111
- fn describe ( & self , matcher_result : MatcherResult ) -> String {
112
- self . describe_impl ( matcher_result)
113
- }
114
- }
115
-
116
- impl < T : PartialEq + Debug , const N : usize > Matcher < Vec < T > > for ContainerEqMatcher < [ T ; N ] > {
117
- fn matches ( & self , actual : & Vec < T > ) -> MatcherResult {
118
- ( actual. as_slice ( ) == self . expected ) . into ( )
119
- }
120
-
121
- fn explain_match ( & self , actual : & Vec < T > ) -> MatchExplanation {
122
- self . explain_match_impl ( actual)
123
- }
124
-
125
- fn describe ( & self , matcher_result : MatcherResult ) -> String {
126
- self . describe_impl ( matcher_result)
127
- }
128
- }
129
-
130
- impl < T : PartialEq + Debug , const N : usize > Matcher < [ T ] > for ContainerEqMatcher < [ T ; N ] > {
131
- fn matches ( & self , actual : & [ T ] ) -> MatcherResult {
132
- ( actual == self . expected ) . into ( )
133
- }
134
-
135
- fn explain_match ( & self , actual : & [ T ] ) -> MatchExplanation {
136
- self . explain_match_impl ( actual)
117
+ fn explain_match ( & self , actual : & ActualContainerT ) -> MatchExplanation {
118
+ build_explanation ( self . get_missing_items ( actual) , self . get_unexpected_items ( actual) )
137
119
}
138
120
139
121
fn describe ( & self , matcher_result : MatcherResult ) -> String {
140
- self . describe_impl ( matcher_result)
141
- }
142
- }
143
-
144
- impl < const N : usize > Matcher < Vec < String > > for ContainerEqMatcher < [ & str ; N ] > {
145
- fn matches ( & self , actual : & Vec < String > ) -> MatcherResult {
146
- if actual. len ( ) != self . expected . len ( ) {
147
- return MatcherResult :: DoesNotMatch ;
148
- }
149
- for ( actual_element, expected_element) in zip ( actual, self . expected ) {
150
- if actual_element. as_str ( ) != expected_element {
151
- return MatcherResult :: DoesNotMatch ;
152
- }
122
+ match matcher_result {
123
+ MatcherResult :: Matches => format ! ( "is equal to {:?}" , self . expected) ,
124
+ MatcherResult :: DoesNotMatch => format ! ( "isn't equal to {:?}" , self . expected) ,
153
125
}
154
- MatcherResult :: Matches
155
- }
156
-
157
- fn explain_match ( & self , actual : & Vec < String > ) -> MatchExplanation {
158
- build_explanation (
159
- self . get_missing_str_items ( actual) ,
160
- self . get_unexpected_string_items ( actual) ,
161
- )
162
- }
163
-
164
- fn describe ( & self , matcher_result : MatcherResult ) -> String {
165
- self . describe_impl ( matcher_result)
166
126
}
167
127
}
168
128
169
- impl < T : PartialEq + Debug , ExpectedT : Debug > ContainerEqMatcher < ExpectedT >
129
+ impl < ActualElementT , ActualContainerT , ExpectedElementT , ExpectedContainerT >
130
+ ContainerEqMatcher < ActualContainerT , ExpectedContainerT >
170
131
where
171
- for < ' a > & ' a ExpectedT : IntoIterator < Item = & ' a T > ,
132
+ ActualElementT : PartialEq < ExpectedElementT > + ?Sized ,
133
+ ActualContainerT : PartialEq < ExpectedContainerT > + ?Sized ,
134
+ for < ' a > & ' a ActualContainerT : IntoIterator < Item = & ' a ActualElementT > ,
135
+ for < ' a > & ' a ExpectedContainerT : IntoIterator < Item = & ' a ExpectedElementT > ,
172
136
{
173
- fn explain_match_impl < ActualT : ?Sized > ( & self , actual : & ActualT ) -> MatchExplanation
174
- where
175
- for < ' a > & ' a ActualT : IntoIterator < Item = & ' a T > + Debug ,
176
- {
177
- build_explanation ( self . get_missing_items ( actual) , self . get_unexpected_items ( actual) )
178
- }
179
-
180
- fn get_missing_items < ActualT : ?Sized > ( & self , actual : & ActualT ) -> Vec < & T >
181
- where
182
- for < ' a > & ' a ActualT : IntoIterator < Item = & ' a T > ,
183
- {
137
+ fn get_missing_items ( & self , actual : & ActualContainerT ) -> Vec < & ExpectedElementT > {
184
138
self . expected . into_iter ( ) . filter ( |& i| !actual. into_iter ( ) . any ( |j| j == i) ) . collect ( )
185
139
}
186
140
187
- fn get_unexpected_items < ' a , ActualT : ?Sized > ( & self , actual : & ' a ActualT ) -> Vec < & ' a T >
188
- where
189
- for < ' b > & ' b ActualT : IntoIterator < Item = & ' b T > ,
190
- {
191
- actual. into_iter ( ) . filter ( |& i| !self . expected . into_iter ( ) . any ( |j| j == i) ) . collect ( )
192
- }
193
- }
194
-
195
- impl < ExpectedT : Debug > ContainerEqMatcher < ExpectedT > {
196
- fn describe_impl ( & self , matcher_result : MatcherResult ) -> String {
197
- match matcher_result {
198
- MatcherResult :: Matches => format ! ( "is equal to {:?}" , self . expected) ,
199
- MatcherResult :: DoesNotMatch => format ! ( "isn't equal to {:?}" , self . expected) ,
200
- }
141
+ fn get_unexpected_items < ' a > ( & self , actual : & ' a ActualContainerT ) -> Vec < & ' a ActualElementT > {
142
+ actual. into_iter ( ) . filter ( |& i| !self . expected . into_iter ( ) . any ( |j| i == j) ) . collect ( )
201
143
}
202
144
}
203
145
@@ -234,16 +176,6 @@ fn build_explanation<T: Debug, U: Debug>(missing: Vec<T>, unexpected: Vec<U>) ->
234
176
}
235
177
}
236
178
237
- impl < const N : usize > ContainerEqMatcher < [ & str ; N ] > {
238
- fn get_missing_str_items ( & self , actual : & [ String ] ) -> Vec < & str > {
239
- self . expected . into_iter ( ) . filter ( |i| !actual. iter ( ) . any ( |j| j == i) ) . collect ( )
240
- }
241
-
242
- fn get_unexpected_string_items < ' a > ( & self , actual : & ' a [ String ] ) -> Vec < & ' a String > {
243
- actual. iter ( ) . filter ( |i| !self . expected . into_iter ( ) . any ( |j| j == i. as_str ( ) ) ) . collect ( )
244
- }
245
- }
246
-
247
179
#[ cfg( test) ]
248
180
mod tests {
249
181
use super :: container_eq;
0 commit comments