• 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 in the matchers module.
17 #![doc(hidden)]
18 
19 /// Matches a value according to a pattern of matchers.
20 ///
21 /// This takes as an argument a specification similar to a struct or enum
22 /// initialiser, where each value is a [`Matcher`][crate::matcher::Matcher]
23 /// which is applied to the corresponding field.
24 ///
25 /// This can be used to match arbitrary combinations of fields on structures
26 /// using arbitrary matchers:
27 ///
28 /// ```
29 /// # use googletest::prelude::*;
30 /// #[derive(Debug)]
31 /// struct MyStruct {
32 ///     a_field: String,
33 ///     another_field: String,
34 /// }
35 ///
36 /// let my_struct = MyStruct {
37 ///     a_field: "Something to believe in".into(),
38 ///     another_field: "Something else".into()
39 /// };
40 /// verify_that!(my_struct, matches_pattern!(MyStruct {
41 ///     a_field: starts_with("Something"),
42 ///     another_field: ends_with("else"),
43 /// }))
44 /// #     .unwrap();
45 /// ```
46 ///
47 /// It is not required to include all named fields in the specification. Omitted
48 /// fields have no effect on the output of the matcher.
49 ///
50 /// ```
51 /// # use googletest::prelude::*;
52 /// # #[derive(Debug)]
53 /// # struct MyStruct {
54 /// #     a_field: String,
55 /// #     another_field: String,
56 /// # }
57 /// #
58 /// # let my_struct = MyStruct {
59 /// #     a_field: "Something to believe in".into(),
60 /// #     another_field: "Something else".into()
61 /// # };
62 /// verify_that!(my_struct, matches_pattern!(MyStruct {
63 ///     a_field: starts_with("Something"),
64 ///     // another_field is missing, so it may be anything.
65 /// }))
66 /// #     .unwrap();
67 /// ```
68 ///
69 /// One can use it recursively to match nested structures:
70 ///
71 /// ```
72 /// # use googletest::prelude::*;
73 /// #[derive(Debug)]
74 /// struct MyStruct {
75 ///     a_nested_struct: MyInnerStruct,
76 /// }
77 ///
78 /// #[derive(Debug)]
79 /// struct MyInnerStruct {
80 ///     a_field: String,
81 /// }
82 ///
83 /// let my_struct = MyStruct {
84 ///     a_nested_struct: MyInnerStruct { a_field: "Something to believe in".into() },
85 /// };
86 /// verify_that!(my_struct, matches_pattern!(MyStruct {
87 ///      a_nested_struct: matches_pattern!(MyInnerStruct {
88 ///         a_field: starts_with("Something"),
89 ///     }),
90 /// }))
91 /// #     .unwrap();
92 /// ```
93 ///
94 /// One can use the alias [`pat`][crate::matchers::pat] to make this less
95 /// verbose:
96 ///
97 /// ```
98 /// # use googletest::prelude::*;
99 /// # #[derive(Debug)]
100 /// # struct MyStruct {
101 /// #     a_nested_struct: MyInnerStruct,
102 /// # }
103 /// #
104 /// # #[derive(Debug)]
105 /// # struct MyInnerStruct {
106 /// #     a_field: String,
107 /// # }
108 /// #
109 /// # let my_struct = MyStruct {
110 /// #     a_nested_struct: MyInnerStruct { a_field: "Something to believe in".into() },
111 /// # };
112 /// verify_that!(my_struct, matches_pattern!(MyStruct {
113 ///     a_nested_struct: pat!(MyInnerStruct {
114 ///         a_field: starts_with("Something"),
115 ///     }),
116 /// }))
117 /// #     .unwrap();
118 /// ```
119 ///
120 /// In addition to fields, one can match on the outputs of methods
121 /// ("properties"):
122 ///
123 /// ```
124 /// # use googletest::prelude::*;
125 /// #[derive(Debug)]
126 /// struct MyStruct {
127 ///     a_field: String,
128 /// }
129 ///
130 /// impl MyStruct {
131 ///     fn get_a_field(&self) -> String { self.a_field.clone() }
132 /// }
133 ///
134 /// let my_struct = MyStruct { a_field: "Something to believe in".into() };
135 /// verify_that!(my_struct, matches_pattern!(MyStruct {
136 ///     get_a_field(): starts_with("Something"),
137 /// }))
138 /// #     .unwrap();
139 /// ```
140 ///
141 /// If an inner matcher is `eq(...)`, it can be omitted:
142 ///
143 /// ```
144 /// # use googletest::prelude::*;
145 /// #[derive(Debug)]
146 /// struct MyStruct {
147 ///     a_field: String,
148 ///     another_field: String,
149 /// }
150 ///
151 /// let my_struct = MyStruct {
152 ///     a_field: "this".into(),
153 ///     another_field: "that".into()
154 /// };
155 /// verify_that!(my_struct, matches_pattern!(MyStruct {
156 ///     a_field: "this",
157 ///     another_field: "that",
158 /// }))
159 /// #     .unwrap();
160 /// ```
161 ///
162 /// **Important**: The method should be pure function with a deterministic
163 /// output and no side effects. In particular, in the event of an assertion
164 /// failure, it will be invoked a second time, with the assertion failure output
165 /// reflecting the *second* invocation.
166 ///
167 /// These may also include extra litteral parameters you pass in:
168 ///
169 /// ```
170 /// # use googletest::prelude::*;
171 /// # #[derive(Debug)]
172 /// # struct MyStruct {
173 /// #     a_field: String,
174 /// # }
175 /// #
176 /// impl MyStruct {
177 ///     fn append_to_a_field(&self, suffix: &str) -> String { self.a_field.clone() + suffix }
178 /// }
179 ///
180 /// # let my_struct = MyStruct { a_field: "Something to believe in".into() };
181 /// verify_that!(my_struct, matches_pattern!(&MyStruct {
182 ///     append_to_a_field("a suffix"): ref ends_with("a suffix"),
183 /// }))
184 /// #     .unwrap();
185 /// ```
186 ///
187 /// You can precede both field and property matchers with a `ref` to match the
188 /// result by reference:
189 ///
190 /// ```
191 /// # use googletest::prelude::*;
192 /// # #[derive(Debug)]
193 /// # struct MyStruct {
194 /// #     a_field: String,
195 /// # }
196 /// #
197 /// impl MyStruct {
198 ///     fn get_a_field_ref(&self) -> String { self.a_field.clone() }
199 /// }
200 ///
201 /// # let my_struct = MyStruct { a_field: "Something to believe in".into() };
202 /// verify_that!(my_struct, matches_pattern!(&MyStruct {
203 ///     get_a_field_ref(): ref starts_with("Something"),
204 /// }))
205 /// #    .unwrap();
206 /// ```
207 ///
208 /// Note that if the `actual` is of type `&ActualT` and the pattern type is
209 /// `ActualT`, this is automatically performed. This behavior is similar to the
210 /// reference binding mode in pattern matching.
211 ///
212 /// ```
213 /// # use googletest::prelude::*;
214 /// # #[derive(Debug)]
215 /// # struct MyStruct {
216 /// #     a_field: String,
217 /// # }
218 /// #
219 /// impl MyStruct {
220 ///     fn get_a_field_ref(&self) -> String { self.a_field.clone() }
221 /// }
222 ///
223 /// # let my_struct = MyStruct { a_field: "Something to believe in".into() };
224 /// verify_that!(my_struct, matches_pattern!(MyStruct {
225 ///     get_a_field_ref(): starts_with("Something"),
226 /// }))
227 /// #    .unwrap();
228 /// ```
229 ///
230 /// One can also match tuple structs with up to 10 fields. In this case, all
231 /// fields must have matchers:
232 ///
233 /// ```
234 /// # use googletest::prelude::*;
235 /// #[derive(Debug)]
236 /// struct MyTupleStruct(String, String);
237 ///
238 /// let my_struct = MyTupleStruct("Something".into(), "Some other thing".into());
239 /// verify_that!(
240 ///     my_struct,
241 ///     matches_pattern!(&MyTupleStruct(ref eq("Something"), ref eq("Some other thing")))
242 /// )
243 /// #    .unwrap();
244 /// ```
245 ///
246 /// One can also match enum values:
247 ///
248 /// ```
249 /// # use googletest::prelude::*;
250 /// #[derive(Debug)]
251 /// enum MyEnum {
252 ///     A(u32),
253 ///     B,
254 /// }
255 ///
256 /// # fn should_pass() -> Result<()> {
257 /// verify_that!(MyEnum::A(123), matches_pattern!(&MyEnum::A(eq(123))))?; // Passes
258 /// #     Ok(())
259 /// # }
260 /// # fn should_fail() -> Result<()> {
261 /// verify_that!(MyEnum::B, matches_pattern!(&MyEnum::A(eq(123))))?; // Fails - wrong enum variant
262 /// #     Ok(())
263 /// # }
264 /// # should_pass().unwrap();
265 /// # should_fail().unwrap_err();
266 /// ```
267 ///
268 /// This macro does not support plain (non-struct) tuples. But it should not be
269 /// necessary as tuple of matchers are matchers of tuple. In other words, if
270 /// `MatcherU: Matcher<U>` and `MatcherT: Matcher<T>`, then `(MatcherU,
271 /// MatcherT): Matcher<(U, T)>`.
272 ///
273 /// Trailing commas are allowed (but not required) in both ordinary and tuple
274 /// structs.
275 ///
276 /// Note that the default format (rustfmt) can format macros if the macro
277 /// argument is parseable Rust code. This is mostly true for this macro with two
278 /// exceptions:
279 ///  * property matching
280 ///  * `ref` keyword with named fields
281 ///
282 /// An option for formatting large is to avoid these exceptions (by removing the
283 /// parenthesis of properties and the `ref` keywords), run `rustfmt` and add
284 /// them back.
285 #[macro_export]
286 #[doc(hidden)]
287 macro_rules! __matches_pattern {
288     ($($t:tt)*) => { $crate::matches_pattern_internal!($($t)*) }
289 }
290 
291 // Internal-only macro created so that the macro definition does not appear in
292 // generated documentation.
293 #[doc(hidden)]
294 #[macro_export]
295 macro_rules! matches_pattern_internal {
296     (
297         @name [$($struct_name:tt)*],
298         { $field_name:ident : ref $matcher:expr $(,)? }
299     ) => {
300         $crate::matchers::__internal_unstable_do_not_depend_on_these::is(
301             stringify!($($struct_name)*),
302             all!(field!($($struct_name)*.$field_name, ref $matcher))
303         )
304     };
305 
306     (
307         @name [$($struct_name:tt)*],
308         { $field_name:ident : $matcher:expr $(,)? }
309     ) => {
310         $crate::matchers::__internal_unstable_do_not_depend_on_these::is(
311             stringify!($($struct_name)*),
312             all!(field!($($struct_name)*.$field_name, $matcher))
313         )
314     };
315 
316     (
317         @name [$($struct_name:tt)*],
318         { $property_name:ident($($argument:expr),* $(,)?) : ref $matcher:expr $(,)? }
319     ) => {
320         $crate::matchers::__internal_unstable_do_not_depend_on_these::is(
321             stringify!($($struct_name)*),
322             all!(property!($($struct_name)*.$property_name($($argument),*), ref $matcher))
323         )
324     };
325 
326     (
327         @name [$($struct_name:tt)*],
328         { $property_name:ident($($argument:expr),* $(,)?) : $matcher:expr $(,)? }
329     ) => {
330         $crate::matchers::__internal_unstable_do_not_depend_on_these::is(
331             stringify!($($struct_name)*),
332             all!(property!($($struct_name)*.$property_name($($argument),*), $matcher))
333         )
334     };
335 
336     (
337         @name [$($struct_name:tt)*],
338         { $field_name:ident : ref $matcher:expr, $($rest:tt)* }
339     ) => {
340         $crate::matches_pattern_internal!(
341             @fields (field!($($struct_name)*.$field_name, ref $matcher)),
342             [$($struct_name)*],
343             { $($rest)* }
344         )
345     };
346 
347     (
348         @name [$($struct_name:tt)*],
349         { $field_name:ident : $matcher:expr, $($rest:tt)* }
350     ) => {
351         $crate::matches_pattern_internal!(
352             @fields (field!($($struct_name)*.$field_name, $matcher)),
353             [$($struct_name)*],
354             { $($rest)* }
355         )
356     };
357 
358     (
359         @name [$($struct_name:tt)*],
360         { $property_name:ident($($argument:expr),* $(,)?) : ref $matcher:expr, $($rest:tt)* }
361     ) => {
362         $crate::matches_pattern_internal!(
363             @fields (property!($($struct_name)*.$property_name($($argument),*), ref $matcher)),
364             [$($struct_name)*],
365             { $($rest)* }
366         )
367     };
368 
369     (
370         @name [$($struct_name:tt)*],
371         { $property_name:ident($($argument:expr),* $(,)?) : $matcher:expr, $($rest:tt)* }
372     ) => {
373         $crate::matches_pattern_internal!(
374             @fields (property!($($struct_name)*.$property_name($($argument),*), $matcher)),
375             [$($struct_name)*],
376             { $($rest)* }
377         )
378     };
379 
380     (
381         @fields ($($processed:tt)*),
382         [$($struct_name:tt)*],
383         { $field_name:ident : ref $matcher:expr $(,)? }
384     ) => {
385         $crate::matchers::__internal_unstable_do_not_depend_on_these::is(
386             stringify!($($struct_name)*),
387             all!(
388                 $($processed)*,
389                 field!($($struct_name)*.$field_name, ref $matcher)
390             ))
391     };
392 
393     (
394         @fields ($($processed:tt)*),
395         [$($struct_name:tt)*],
396         { $field_name:ident : $matcher:expr $(,)? }
397     ) => {
398         $crate::matchers::__internal_unstable_do_not_depend_on_these::is(
399             stringify!($($struct_name)*),
400             all!(
401                 $($processed)*,
402                 field!($($struct_name)*.$field_name, $matcher)
403             ))
404     };
405 
406     (
407         @fields ($($processed:tt)*),
408         [$($struct_name:tt)*],
409         { $property_name:ident($($argument:expr),* $(,)?) : ref $matcher:expr $(,)? }
410     ) => {
411         $crate::matchers::__internal_unstable_do_not_depend_on_these::is(
412             stringify!($($struct_name)*),
413             all!(
414                 $($processed)*,
415                 property!($($struct_name)*.$property_name($($argument),*), ref $matcher)
416             ))
417     };
418 
419     (
420         @fields ($($processed:tt)*),
421         [$($struct_name:tt)*],
422         { $property_name:ident($($argument:expr),* $(,)?) : $matcher:expr $(,)? }
423     ) => {
424         $crate::matchers::__internal_unstable_do_not_depend_on_these::is(
425             stringify!($($struct_name)*),
426             all!(
427                 $($processed)*,
428                 property!($($struct_name)*.$property_name($($argument),*), $matcher)
429             ))
430     };
431 
432     (
433         @fields ($($processed:tt)*),
434         [$($struct_name:tt)*],
435         { $field_name:ident : ref $matcher:expr, $($rest:tt)* }
436     ) => {
437         $crate::matches_pattern_internal!(
438             @fields (
439                 $($processed)*,
440                 field!($($struct_name)*.$field_name, ref $matcher)
441             ),
442             [$($struct_name)*],
443             { $($rest)* }
444         )
445     };
446 
447     (
448         @fields ($($processed:tt)*),
449         [$($struct_name:tt)*],
450         { $field_name:ident : $matcher:expr, $($rest:tt)* }
451     ) => {
452         $crate::matches_pattern_internal!(
453             @fields (
454                 $($processed)*,
455                 field!($($struct_name)*.$field_name, $matcher)
456             ),
457             [$($struct_name)*],
458             { $($rest)* }
459         )
460     };
461 
462     (
463         @fields ($($processed:tt)*),
464         [$($struct_name:tt)*],
465         { $property_name:ident($($argument:expr),* $(,)?) : ref $matcher:expr, $($rest:tt)* }
466     ) => {
467         $crate::matches_pattern_internal!(
468             @fields (
469                 $($processed)*,
470                 property!(ref $($struct_name)*.$property_name($($argument),*), $matcher)
471             ),
472             [$($struct_name)*],
473             { $($rest)* }
474         )
475     };
476 
477     (
478         @fields ($($processed:tt)*),
479         [$($struct_name:tt)*],
480         { $property_name:ident($($argument:expr),* $(,)?) : $matcher:expr, $($rest:tt)* }
481     ) => {
482         $crate::matches_pattern_internal!(
483             @fields (
484                 $($processed)*,
485                 property!($($struct_name)*.$property_name($($argument),*), $matcher)
486             ),
487             [$($struct_name)*],
488             { $($rest)* }
489         )
490     };
491 
492     (
493         @name [$($struct_name:tt)*],
494     ) => {
495         $crate::matchers::__internal_unstable_do_not_depend_on_these::pattern_only(
496             |v| matches!(v, $($struct_name)*),
497             concat!("is ", stringify!($($struct_name)*)),
498             concat!("is not ", stringify!($($struct_name)*)))
499     };
500 
501     (
502         @name [$($struct_name:tt)*],
503         (ref $matcher:expr $(,)?)
504     ) => {
505         $crate::matchers::__internal_unstable_do_not_depend_on_these::is(
506             stringify!($($struct_name)*),
507             all!(field!($($struct_name)*.0, ref $matcher))
508         )
509     };
510 
511     (
512         @name [$($struct_name:tt)*],
513         ($matcher:expr $(,)?)
514     ) => {
515         $crate::matchers::__internal_unstable_do_not_depend_on_these::is(
516             stringify!($($struct_name)*),
517             all!(field!($($struct_name)*.0, $matcher))
518         )
519     };
520 
521     (
522         @name [$($struct_name:tt)*],
523         (ref $matcher:expr, $($rest:tt)*)
524     ) => {
525         $crate::matches_pattern_internal!(
526             @fields (
527                 field!($($struct_name)*.0, ref $matcher)
528             ),
529             [$($struct_name)*],
530             1,
531             ($($rest)*)
532         )
533     };
534 
535     (
536         @name [$($struct_name:tt)*],
537         ($matcher:expr, $($rest:tt)*)
538     ) => {
539         $crate::matches_pattern_internal!(
540             @fields (
541                 field!($($struct_name)*.0, $matcher)
542             ),
543             [$($struct_name)*],
544             1,
545             ($($rest)*)
546         )
547     };
548 
549     (
550         @fields ($($processed:tt)*),
551         [$($struct_name:tt)*],
552         $field:tt,
553         (ref $matcher:expr $(,)?)
554     ) => {
555         $crate::matchers::__internal_unstable_do_not_depend_on_these::is(
556             stringify!($($struct_name)*),
557             all!(
558                 $($processed)*,
559                 field!($($struct_name)*.$field, ref $matcher)
560             ))
561     };
562 
563     (
564         @fields ($($processed:tt)*),
565         [$($struct_name:tt)*],
566         $field:tt,
567         ($matcher:expr $(,)?)
568     ) => {
569         $crate::matchers::__internal_unstable_do_not_depend_on_these::is(
570             stringify!($($struct_name)*),
571             all!(
572                 $($processed)*,
573                 field!($($struct_name)*.$field, $matcher)
574             ))
575     };
576 
577     // We need to repeat this once for every supported field position, unfortunately. There appears
578     // to be no way in declarative macros to compute $field + 1 and have the result evaluated to a
579     // token which can be used as a tuple index.
580     (
581         @fields ($($processed:tt)*),
582         [$($struct_name:tt)*],
583         1,
584         (ref $matcher:expr, $($rest:tt)*)
585     ) => {
586         $crate::matches_pattern_internal!(
587             @fields (
588                 $($processed)*,
589                 field!($($struct_name)*.1, ref $matcher)
590             ),
591             [$($struct_name)*],
592             2,
593             ($($rest)*)
594         )
595     };
596 
597     (
598         @fields ($($processed:tt)*),
599         [$($struct_name:tt)*],
600         1,
601         ($matcher:expr, $($rest:tt)*)
602     ) => {
603         $crate::matches_pattern_internal!(
604             @fields (
605                 $($processed)*,
606                 field!($($struct_name)*.1, $matcher)
607             ),
608             [$($struct_name)*],
609             2,
610             ($($rest)*)
611         )
612     };
613 
614     (
615         @fields ($($processed:tt)*),
616         [$($struct_name:tt)*],
617         2,
618         (ref $matcher:expr, $($rest:tt)*)
619     ) => {
620         $crate::matches_pattern_internal!(
621             @fields (
622                 $($processed)*,
623                 field!($($struct_name)*.2, ref $matcher)
624             ),
625             [$($struct_name)*],
626             3,
627             ($($rest)*)
628         )
629     };
630 
631     (
632         @fields ($($processed:tt)*),
633         [$($struct_name:tt)*],
634         2,
635         ($matcher:expr, $($rest:tt)*)
636     ) => {
637         $crate::matches_pattern_internal!(
638             @fields (
639                 $($processed)*,
640                 field!($($struct_name)*.2, $matcher)
641             ),
642             [$($struct_name)*],
643             3,
644             ($($rest)*)
645         )
646     };
647 
648     (
649         @fields ($($processed:tt)*),
650         [$($struct_name:tt)*],
651         3,
652         (ref $matcher:expr, $($rest:tt)*)
653     ) => {
654         $crate::matches_pattern_internal!(
655             @fields (
656                 $($processed)*,
657                 field!($($struct_name)*.3, ref $matcher)
658             ),
659             [$($struct_name)*],
660             4,
661             ($($rest)*)
662         )
663     };
664 
665     (
666         @fields ($($processed:tt)*),
667         [$($struct_name:tt)*],
668         3,
669         ($matcher:expr, $($rest:tt)*)
670     ) => {
671         $crate::matches_pattern_internal!(
672             @fields (
673                 $($processed)*,
674                 field!($($struct_name)*.3, $matcher)
675             ),
676             [$($struct_name)*],
677             4,
678             ($($rest)*)
679         )
680     };
681 
682     (
683         @fields ($($processed:tt)*),
684         [$($struct_name:tt)*],
685         4,
686         (ref $matcher:expr, $($rest:tt)*)
687     ) => {
688         $crate::matches_pattern_internal!(
689             @fields (
690                 $($processed)*,
691                 field!($($struct_name)*.4, ref $matcher)
692             ),
693             [$($struct_name)*],
694             5,
695             ($($rest)*)
696         )
697     };
698 
699     (
700         @fields ($($processed:tt)*),
701         [$($struct_name:tt)*],
702         4,
703         ($matcher:expr, $($rest:tt)*)
704     ) => {
705         $crate::matches_pattern_internal!(
706             @fields (
707                 $($processed)*,
708                 field!($($struct_name)*.4, $matcher)
709             ),
710             [$($struct_name)*],
711             5,
712             ($($rest)*)
713         )
714     };
715 
716     (
717         @fields ($($processed:tt)*),
718         [$($struct_name:tt)*],
719         5,
720         (ref $matcher:expr, $($rest:tt)*)
721     ) => {
722         $crate::matches_pattern_internal!(
723             @fields (
724                 $($processed)*,
725                 field!($($struct_name)*.5, ref $matcher)
726             ),
727             [$($struct_name)*],
728             6,
729             ($($rest)*)
730         )
731     };
732 
733     (
734         @fields ($($processed:tt)*),
735         [$($struct_name:tt)*],
736         5,
737         ($matcher:expr, $($rest:tt)*)
738     ) => {
739         $crate::matches_pattern_internal!(
740             @fields (
741                 $($processed)*,
742                 field!($($struct_name)*.5, $matcher)
743             ),
744             [$($struct_name)*],
745             6,
746             ($($rest)*)
747         )
748     };
749 
750     (
751         @fields ($($processed:tt)*),
752         [$($struct_name:tt)*],
753         6,
754         (ref $matcher:expr, $($rest:tt)*)
755     ) => {
756         $crate::matches_pattern_internal!(
757             @fields (
758                 $($processed)*,
759                 field!($($struct_name)*.6, ref $matcher)
760             ),
761             [$($struct_name)*],
762             7,
763             ($($rest)*)
764         )
765     };
766 
767     (
768         @fields ($($processed:tt)*),
769         [$($struct_name:tt)*],
770         6,
771         ($matcher:expr, $($rest:tt)*)
772     ) => {
773         $crate::matches_pattern_internal!(
774             @fields (
775                 $($processed)*,
776                 field!($($struct_name)*.6, $matcher)
777             ),
778             [$($struct_name)*],
779             7,
780             ($($rest)*)
781         )
782     };
783 
784     (
785         @fields ($($processed:tt)*),
786         [$($struct_name:tt)*],
787         7,
788         (ref $matcher:expr, $($rest:tt)*)
789     ) => {
790         $crate::matches_pattern_internal!(
791             @fields (
792                 $($processed)*,
793                 field!($($struct_name)*.7, ref $matcher)
794             ),
795             [$($struct_name)*],
796             8,
797             ($($rest)*)
798         )
799     };
800 
801     (
802         @fields ($($processed:tt)*),
803         [$($struct_name:tt)*],
804         7,
805         ($matcher:expr, $($rest:tt)*)
806     ) => {
807         $crate::matches_pattern_internal!(
808             @fields (
809                 $($processed)*,
810                 field!($($struct_name)*.7, $matcher)
811             ),
812             [$($struct_name)*],
813             8,
814             ($($rest)*)
815         )
816     };
817 
818     (
819         @fields ($($processed:tt)*),
820         [$($struct_name:tt)*],
821         8,
822         (ref $matcher:expr, $($rest:tt)*)
823     ) => {
824         $crate::matches_pattern_internal!(
825             @fields (
826                 $($processed)*,
827                 field!($($struct_name)*.8, ref $matcher)
828             ),
829             [$($struct_name)*],
830             9,
831             ($($rest)*)
832         )
833     };
834 
835     (
836         @fields ($($processed:tt)*),
837         [$($struct_name:tt)*],
838         8,
839         ($matcher:expr, $($rest:tt)*)
840     ) => {
841         $crate::matches_pattern_internal!(
842             @fields (
843                 $($processed)*,
844                 field!($($struct_name)*.8, $matcher)
845             ),
846             [$($struct_name)*],
847             9,
848             ($($rest)*)
849         )
850     };
851 
852     (@name [$($struct_name:tt)*], $first:tt $($rest:tt)*) => {
853         $crate::matches_pattern_internal!(@name [$($struct_name)* $first], $($rest)*)
854     };
855 
856     ($first:tt $($rest:tt)*) => {{
857         #[allow(unused)]
858         use $crate::matchers::{all, field, property};
859         $crate::matches_pattern_internal!(@name [$first], $($rest)*)
860     }};
861 }
862 
863 /// An alias for [`matches_pattern`][crate::matchers::matches_pattern!].
864 #[macro_export]
865 #[doc(hidden)]
866 macro_rules! __pat {
867     ($($t:tt)*) => { $crate::matches_pattern_internal!($($t)*) }
868 }
869 
870 #[doc(hidden)]
871 pub mod internal {
872     use crate::matcher::{Matcher, MatcherBase};
873     use std::fmt::Debug;
874 
875     // Specialized implementation of the `predicate` matcher to support ref binding
876     // mode for `matches_pattern`.
pattern_only<T>( matcher_function: fn(&T) -> bool, match_description: &'static str, no_match_description: &'static str, ) -> PatternOnlyMatcher<T>877     pub fn pattern_only<T>(
878         matcher_function: fn(&T) -> bool,
879         match_description: &'static str,
880         no_match_description: &'static str,
881     ) -> PatternOnlyMatcher<T> {
882         PatternOnlyMatcher { matcher_function, match_description, no_match_description }
883     }
884 
885     #[derive(MatcherBase)]
886     #[doc(hidden)]
887     pub struct PatternOnlyMatcher<T> {
888         matcher_function: fn(&T) -> bool,
889         match_description: &'static str,
890         no_match_description: &'static str,
891     }
892 
893     impl<'a, T: Debug> Matcher<&'a T> for PatternOnlyMatcher<T> {
matches(&self, actual: &'a T) -> crate::matcher::MatcherResult894         fn matches(&self, actual: &'a T) -> crate::matcher::MatcherResult {
895             (self.matcher_function)(actual).into()
896         }
897 
describe( &self, matcher_result: crate::matcher::MatcherResult, ) -> crate::description::Description898         fn describe(
899             &self,
900             matcher_result: crate::matcher::MatcherResult,
901         ) -> crate::description::Description {
902             match matcher_result {
903                 crate::matcher::MatcherResult::Match => self.match_description.into(),
904                 crate::matcher::MatcherResult::NoMatch => self.no_match_description.into(),
905             }
906         }
907     }
908 
909     impl<T: Debug + Copy> Matcher<T> for PatternOnlyMatcher<T> {
matches(&self, actual: T) -> crate::matcher::MatcherResult910         fn matches(&self, actual: T) -> crate::matcher::MatcherResult {
911             (self.matcher_function)(&actual).into()
912         }
913 
describe( &self, matcher_result: crate::matcher::MatcherResult, ) -> crate::description::Description914         fn describe(
915             &self,
916             matcher_result: crate::matcher::MatcherResult,
917         ) -> crate::description::Description {
918             match matcher_result {
919                 crate::matcher::MatcherResult::Match => self.match_description.into(),
920                 crate::matcher::MatcherResult::NoMatch => self.no_match_description.into(),
921             }
922         }
923     }
924 }
925