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