5555#[ macro_export]
5656#[ doc( hidden) ]
5757macro_rules! __any {
58- ( $( $matcher: expr) ,* $( , ) ?) => { {
59- use $crate:: matchers:: __internal_unstable_do_not_depend_on_these:: AnyMatcher ;
60- AnyMatcher :: new( [ $( Box :: new( $matcher) ) ,* ] )
58+ ( $( , ) ?) => { {
59+ std:: compile_error!( "any![...] expects at least one argument" ) ;
60+ } } ;
61+ ( $matcher: expr $( , ) ?) => { {
62+ $matcher
63+ } } ;
64+ ( $head: expr, $head2: expr $( , ) ?) => { {
65+ $crate:: matchers:: __internal_unstable_do_not_depend_on_these:: DisjunctionMatcher :: new( $head, $head2)
66+ } } ;
67+ ( $head: expr, $head2: expr, $( $tail: expr) ,+ $( , ) ?) => { {
68+ $crate:: __any![
69+ $crate:: matchers:: __internal_unstable_do_not_depend_on_these:: DisjunctionMatcher :: new( $head, $head2) ,
70+ $( $tail) ,+
71+ ]
6172 } }
6273}
6374
64- /// Functionality needed by the [`any`] macro.
65- ///
66- /// For internal use only. API stablility is not guaranteed!
67- #[ doc( hidden) ]
68- pub mod internal {
69- use crate :: description:: Description ;
70- use crate :: matcher:: { Matcher , MatcherResult } ;
71- use crate :: matchers:: anything;
72- use std:: fmt:: Debug ;
73-
74- /// A matcher which matches an input value matched by all matchers in the
75- /// array `components`.
76- ///
77- /// For internal use only. API stablility is not guaranteed!
78- #[ doc( hidden) ]
79- pub struct AnyMatcher < ' a , T : Debug + ?Sized , const N : usize > {
80- components : [ Box < dyn Matcher < ActualT = T > + ' a > ; N ] ,
81- }
82-
83- impl < ' a , T : Debug + ?Sized , const N : usize > AnyMatcher < ' a , T , N > {
84- /// Constructs an [`AnyMatcher`] with the given component matchers.
85- ///
86- /// Intended for use only by the [`all`] macro.
87- pub fn new ( components : [ Box < dyn Matcher < ActualT = T > + ' a > ; N ] ) -> Self {
88- Self { components }
89- }
90- }
91-
92- impl < ' a , T : Debug + ?Sized , const N : usize > Matcher for AnyMatcher < ' a , T , N > {
93- type ActualT = T ;
94-
95- fn matches ( & self , actual : & Self :: ActualT ) -> MatcherResult {
96- MatcherResult :: from ( self . components . iter ( ) . any ( |c| c. matches ( actual) . is_match ( ) ) )
97- }
98-
99- fn explain_match ( & self , actual : & Self :: ActualT ) -> Description {
100- match N {
101- 0 => format ! ( "which {}" , anything:: <T >( ) . describe( MatcherResult :: NoMatch ) ) . into ( ) ,
102- 1 => self . components [ 0 ] . explain_match ( actual) ,
103- _ => {
104- let failures = self
105- . components
106- . iter ( )
107- . filter ( |component| component. matches ( actual) . is_no_match ( ) )
108- . collect :: < Vec < _ > > ( ) ;
109-
110- if failures. len ( ) == 1 {
111- failures[ 0 ] . explain_match ( actual)
112- } else {
113- Description :: new ( )
114- . collect (
115- failures
116- . into_iter ( )
117- . map ( |component| component. explain_match ( actual) ) ,
118- )
119- . bullet_list ( )
120- }
121- }
122- }
123- }
124-
125- fn describe ( & self , matcher_result : MatcherResult ) -> Description {
126- match N {
127- 0 => anything :: < T > ( ) . describe ( matcher_result) ,
128- 1 => self . components [ 0 ] . describe ( matcher_result) ,
129- _ => {
130- let properties = self
131- . components
132- . iter ( )
133- . map ( |m| m. describe ( matcher_result) )
134- . collect :: < Description > ( )
135- . bullet_list ( )
136- . indent ( ) ;
137- format ! (
138- "{}:\n {properties}" ,
139- if matcher_result. into( ) {
140- "has at least one of the following properties"
141- } else {
142- "has none of the following properties"
143- }
144- )
145- . into ( )
146- }
147- }
148- }
149- }
150- }
151-
15275#[ cfg( test) ]
15376mod tests {
154- use super :: internal;
15577 use crate :: matcher:: { Matcher , MatcherResult } ;
15678 use crate :: prelude:: * ;
15779 use indoc:: indoc;
15880
15981 #[ test]
16082 fn description_shows_more_than_one_matcher ( ) -> Result < ( ) > {
161- let first_matcher = starts_with ( "A" ) ;
83+ let first_matcher: StrMatcher < String , & str > = starts_with ( "A" ) ;
16284 let second_matcher = ends_with ( "string" ) ;
163- let matcher: internal :: AnyMatcher < String , 2 > = any ! ( first_matcher, second_matcher) ;
85+ let matcher = any ! ( first_matcher, second_matcher) ;
16486
16587 verify_that ! (
16688 matcher. describe( MatcherResult :: Match ) ,
@@ -175,8 +97,8 @@ mod tests {
17597
17698 #[ test]
17799 fn description_shows_one_matcher_directly ( ) -> Result < ( ) > {
178- let first_matcher = starts_with ( "A" ) ;
179- let matcher: internal :: AnyMatcher < String , 1 > = any ! ( first_matcher) ;
100+ let first_matcher: StrMatcher < String , & str > = starts_with ( "A" ) ;
101+ let matcher = any ! ( first_matcher) ;
180102
181103 verify_that ! (
182104 matcher. describe( MatcherResult :: Match ) ,
@@ -189,7 +111,7 @@ mod tests {
189111 {
190112 let first_matcher = starts_with ( "Another" ) ;
191113 let second_matcher = ends_with ( "string" ) ;
192- let matcher: internal :: AnyMatcher < str , 2 > = any ! ( first_matcher, second_matcher) ;
114+ let matcher = any ! ( first_matcher, second_matcher) ;
193115
194116 verify_that ! (
195117 matcher. explain_match( "A string" ) ,
@@ -200,7 +122,7 @@ mod tests {
200122 #[ test]
201123 fn mismatch_description_is_simple_when_only_one_constituent ( ) -> Result < ( ) > {
202124 let first_matcher = starts_with ( "Another" ) ;
203- let matcher: internal :: AnyMatcher < str , 1 > = any ! ( first_matcher) ;
125+ let matcher = any ! ( first_matcher) ;
204126
205127 verify_that ! (
206128 matcher. explain_match( "A string" ) ,
0 commit comments