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