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, MatcherResult},
27     };
28     use std::fmt::Debug;
29 
30     // This implementation is provided for completeness, but is completely trivial.
31     // The only actual value which can be supplied is (), which must match.
32     impl Matcher for () {
33         type ActualT = ();
34 
matches(&self, _: &Self::ActualT) -> MatcherResult35         fn matches(&self, _: &Self::ActualT) -> 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     /// Generates a tuple matcher for tuples of a specific length.
48     ///
49     /// **For internal use only. API stablility is not guaranteed!**
50     #[doc(hidden)]
51     macro_rules! tuple_matcher_n {
52         ($([$field_number:tt, $matcher_type:ident, $field_type:ident]),*) => {
53             impl<$($field_type: Debug, $matcher_type: Matcher<ActualT = $field_type>),*>
54                 Matcher for ($($matcher_type,)*)
55             {
56                 type ActualT = ($($field_type,)*);
57 
58                 fn matches(&self, actual: &($($field_type,)*)) -> MatcherResult {
59                     $(match self.$field_number.matches(&actual.$field_number) {
60                         MatcherResult::Match => {},
61                         MatcherResult::NoMatch => {
62                             return MatcherResult::NoMatch;
63                         }
64                     })*
65                     MatcherResult::Match
66                 }
67 
68                 fn explain_match(&self, actual: &($($field_type,)*)) -> Description {
69                     let mut explanation = Description::new().text("which").nested(self.describe(self.matches(actual)));
70                     $(match self.$field_number.matches(&actual.$field_number) {
71                         MatcherResult::Match => {},
72                         MatcherResult::NoMatch => {
73                             explanation = explanation
74                                 .text(format!(concat!("Element #", $field_number, " is {:?},"), actual.$field_number))
75                                 .nested(self.$field_number.explain_match(&actual.$field_number));
76                         }
77                     })*
78                     explanation
79                 }
80 
81                 fn describe(&self, matcher_result: MatcherResult) -> Description {
82                     match matcher_result {
83                         MatcherResult::Match => {
84                             let mut description = Description::new().text("is a tuple whose values respectively match:");
85                             $(description = description.nested(self.$field_number.describe(matcher_result));)*
86                             description
87                         }
88                         MatcherResult::NoMatch => {
89                             let mut description = Description::new().text("is a tuple whose values do not respectively match:");
90                             $(description = description.nested(self.$field_number.describe(MatcherResult::Match));)*
91                             description
92                         }
93                     }
94                 }
95             }
96         };
97     }
98 
99     tuple_matcher_n!([0, I0, T0]);
100 
101     tuple_matcher_n!([0, I0, T0], [1, I1, T1]);
102 
103     tuple_matcher_n!([0, I0, T0], [1, I1, T1], [2, I2, T2]);
104 
105     tuple_matcher_n!([0, I0, T0], [1, I1, T1], [2, I2, T2], [3, I3, T3]);
106 
107     tuple_matcher_n!([0, I0, T0], [1, I1, T1], [2, I2, T2], [3, I3, T3], [4, I4, T4]);
108 
109     tuple_matcher_n!([0, I0, T0], [1, I1, T1], [2, I2, T2], [3, I3, T3], [4, I4, T4], [5, I5, T5]);
110 
111     tuple_matcher_n!(
112         [0, I0, T0],
113         [1, I1, T1],
114         [2, I2, T2],
115         [3, I3, T3],
116         [4, I4, T4],
117         [5, I5, T5],
118         [6, I6, T6]
119     );
120 
121     tuple_matcher_n!(
122         [0, I0, T0],
123         [1, I1, T1],
124         [2, I2, T2],
125         [3, I3, T3],
126         [4, I4, T4],
127         [5, I5, T5],
128         [6, I6, T6],
129         [7, I7, T7]
130     );
131 
132     tuple_matcher_n!(
133         [0, I0, T0],
134         [1, I1, T1],
135         [2, I2, T2],
136         [3, I3, T3],
137         [4, I4, T4],
138         [5, I5, T5],
139         [6, I6, T6],
140         [7, I7, T7],
141         [8, I8, T8]
142     );
143 
144     tuple_matcher_n!(
145         [0, I0, T0],
146         [1, I1, T1],
147         [2, I2, T2],
148         [3, I3, T3],
149         [4, I4, T4],
150         [5, I5, T5],
151         [6, I6, T6],
152         [7, I7, T7],
153         [8, I8, T8],
154         [9, I9, T9]
155     );
156 
157     tuple_matcher_n!(
158         [0, I0, T0],
159         [1, I1, T1],
160         [2, I2, T2],
161         [3, I3, T3],
162         [4, I4, T4],
163         [5, I5, T5],
164         [6, I6, T6],
165         [7, I7, T7],
166         [8, I8, T8],
167         [9, I9, T9],
168         [10, I10, T10]
169     );
170 
171     tuple_matcher_n!(
172         [0, I0, T0],
173         [1, I1, T1],
174         [2, I2, T2],
175         [3, I3, T3],
176         [4, I4, T4],
177         [5, I5, T5],
178         [6, I6, T6],
179         [7, I7, T7],
180         [8, I8, T8],
181         [9, I9, T9],
182         [10, I10, T10],
183         [11, I11, T11]
184     );
185 }
186