• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // There are no visible documentation elements in this module; the declarative
16 // macro is documented at the top level.
17 #![doc(hidden)]
18 
19 /// Functions for use only by the declarative macros in this module.
20 ///
21 /// **For internal use only. API stablility is not guaranteed!**
22 #[doc(hidden)]
23 pub mod internal {
24     use crate::{
25         description::Description,
26         matcher::{Matcher, MatcherBase, MatcherResult},
27     };
28     use std::fmt::Debug;
29 
30     impl MatcherBase for () {}
31 
32     // This implementation is provided for completeness, but is completely trivial.
33     // The only actual value which can be supplied is (), which must match.
34     impl Matcher<()> for () {
matches(&self, _: ()) -> MatcherResult35         fn matches(&self, _: ()) -> MatcherResult {
36             MatcherResult::Match
37         }
38 
describe(&self, matcher_result: MatcherResult) -> Description39         fn describe(&self, matcher_result: MatcherResult) -> Description {
40             match matcher_result {
41                 MatcherResult::Match => "is the empty tuple".into(),
42                 MatcherResult::NoMatch => "is not the empty tuple".into(),
43             }
44         }
45     }
46 
47     impl Matcher<&()> for () {
matches(&self, _: &()) -> MatcherResult48         fn matches(&self, _: &()) -> MatcherResult {
49             MatcherResult::Match
50         }
51 
describe(&self, matcher_result: MatcherResult) -> Description52         fn describe(&self, matcher_result: MatcherResult) -> Description {
53             <Self as Matcher<()>>::describe(self, matcher_result)
54         }
55     }
56 
57     /// Generates a tuple matcher for tuples of a specific length.
58     ///
59     /// **For internal use only. API stablility is not guaranteed!**
60     #[doc(hidden)]
61     macro_rules! tuple_matcher_n {
62         ($([$field_number:tt, $matcher_type:ident, $field_type:ident]),*) => {
63             impl<$($matcher_type: MatcherBase),*> MatcherBase for ($($matcher_type,)*){}
64 
65             impl<$($field_type: Debug + Copy, $matcher_type: Matcher<$field_type>),*>
66                 Matcher<($($field_type,)*)> for ($($matcher_type,)*)
67             {
68                 fn matches(&self, actual:  ($($field_type,)*)) -> MatcherResult {
69                     $(match self.$field_number.matches(actual.$field_number) {
70                         MatcherResult::Match => {},
71                         MatcherResult::NoMatch => {
72                             return MatcherResult::NoMatch;
73                         }
74                     })*
75                     MatcherResult::Match
76                 }
77 
78                 fn explain_match(&self, actual:  ($($field_type,)*)) -> Description  {
79                     let mut explanation = Description::new().text("which").nested(
80                         self.describe(self.matches(actual)));
81                     $(match self.$field_number.matches(actual.$field_number) {
82                         MatcherResult::Match => {},
83                         MatcherResult::NoMatch => {
84                             explanation = explanation
85                                 .text(format!(concat!("Element #", $field_number, " is {:?},"),
86                                     actual.$field_number))
87                                 .nested(self.$field_number.explain_match(actual.$field_number));
88                         }
89                     })*
90                     explanation
91                 }
92 
93                 fn describe(&self, matcher_result: MatcherResult) -> Description {
94                     match matcher_result {
95                         MatcherResult::Match => {
96                             let mut description = Description::new().text(
97                                 "is a tuple whose values respectively match:");
98                             $(description = description.nested(
99                                 self.$field_number.describe(matcher_result));)*
100                             description
101                         }
102                         MatcherResult::NoMatch => {
103                             let mut description = Description::new().text(
104                                 "is a tuple whose values do not respectively match:");
105                             $(description = description.nested(
106                                 self.$field_number.describe(MatcherResult::Match));)*
107                             description
108                         }
109                     }
110                 }
111             }
112             impl<'a, $($field_type: Debug, $matcher_type: Matcher<&'a $field_type>),*>
113                 Matcher<&'a ($($field_type,)*)> for ($($matcher_type,)*)
114             {
115                 fn matches(&self, actual:  &'a ($($field_type,)*)) -> MatcherResult {
116                     $(match self.$field_number.matches(&actual.$field_number) {
117                         MatcherResult::Match => {},
118                         MatcherResult::NoMatch => {
119                             return MatcherResult::NoMatch;
120                         }
121                     })*
122                     MatcherResult::Match
123                 }
124 
125                 fn explain_match(&self, actual:  &'a ($($field_type,)*)) -> Description  {
126                     let mut explanation = Description::new()
127                         .text("which")
128                         .nested(
129                             Matcher::<&'a ($($field_type,)*)>::describe(
130                                 self, self.matches(actual)));
131                     $(match self.$field_number.matches(&actual.$field_number) {
132                         MatcherResult::Match => {},
133                         MatcherResult::NoMatch => {
134                             explanation = explanation
135                                 .text(format!(
136                                     concat!(
137                                         "Element #",
138                                         $field_number,
139                                         " is {:?},"),
140                                         actual.$field_number))
141                                 .nested(self.$field_number.explain_match(&actual.$field_number));
142                         }
143                     })*
144                     explanation
145                 }
146 
147                 fn describe(&self, matcher_result: MatcherResult) -> Description {
148                     match matcher_result {
149                         MatcherResult::Match => {
150                             let mut description = Description::new().text(
151                                 "is a tuple whose values respectively match:");
152                             $(description = description.nested(
153                                 self.$field_number.describe(matcher_result));)*
154                             description
155                         }
156                         MatcherResult::NoMatch => {
157                             let mut description = Description::new().text(
158                                 "is a tuple whose values do not respectively match:");
159                             $(description = description.nested(
160                                 self.$field_number.describe(MatcherResult::Match));)*
161                             description
162                         }
163                     }
164                 }
165             }
166         };
167     }
168 
169     tuple_matcher_n!([0, I0, T0]);
170 
171     tuple_matcher_n!([0, I0, T0], [1, I1, T1]);
172 
173     tuple_matcher_n!([0, I0, T0], [1, I1, T1], [2, I2, T2]);
174 
175     tuple_matcher_n!([0, I0, T0], [1, I1, T1], [2, I2, T2], [3, I3, T3]);
176 
177     tuple_matcher_n!([0, I0, T0], [1, I1, T1], [2, I2, T2], [3, I3, T3], [4, I4, T4]);
178 
179     tuple_matcher_n!([0, I0, T0], [1, I1, T1], [2, I2, T2], [3, I3, T3], [4, I4, T4], [5, I5, T5]);
180 
181     tuple_matcher_n!(
182         [0, I0, T0],
183         [1, I1, T1],
184         [2, I2, T2],
185         [3, I3, T3],
186         [4, I4, T4],
187         [5, I5, T5],
188         [6, I6, T6]
189     );
190 
191     tuple_matcher_n!(
192         [0, I0, T0],
193         [1, I1, T1],
194         [2, I2, T2],
195         [3, I3, T3],
196         [4, I4, T4],
197         [5, I5, T5],
198         [6, I6, T6],
199         [7, I7, T7]
200     );
201 
202     tuple_matcher_n!(
203         [0, I0, T0],
204         [1, I1, T1],
205         [2, I2, T2],
206         [3, I3, T3],
207         [4, I4, T4],
208         [5, I5, T5],
209         [6, I6, T6],
210         [7, I7, T7],
211         [8, I8, T8]
212     );
213 
214     tuple_matcher_n!(
215         [0, I0, T0],
216         [1, I1, T1],
217         [2, I2, T2],
218         [3, I3, T3],
219         [4, I4, T4],
220         [5, I5, T5],
221         [6, I6, T6],
222         [7, I7, T7],
223         [8, I8, T8],
224         [9, I9, T9]
225     );
226 
227     tuple_matcher_n!(
228         [0, I0, T0],
229         [1, I1, T1],
230         [2, I2, T2],
231         [3, I3, T3],
232         [4, I4, T4],
233         [5, I5, T5],
234         [6, I6, T6],
235         [7, I7, T7],
236         [8, I8, T8],
237         [9, I9, T9],
238         [10, I10, T10]
239     );
240 
241     tuple_matcher_n!(
242         [0, I0, T0],
243         [1, I1, T1],
244         [2, I2, T2],
245         [3, I3, T3],
246         [4, I4, T4],
247         [5, I5, T5],
248         [6, I6, T6],
249         [7, I7, T7],
250         [8, I8, T8],
251         [9, I9, T9],
252         [10, I10, T10],
253         [11, I11, T11]
254     );
255 }
256