5353#[ macro_export]
5454#[ doc( hidden) ]
5555macro_rules! __all {
56- ( $( $matcher: expr) ,* $( , ) ?) => { {
57- use $crate:: matchers:: __internal_unstable_do_not_depend_on_these:: AllMatcher ;
58- AllMatcher :: new( [ $( Box :: new( $matcher) ) ,* ] )
56+ ( $( , ) ?) => { {
57+ $crate:: matchers:: anything( )
58+ } } ;
59+ ( $matcher: expr $( , ) ?) => { {
60+ $matcher
61+ } } ;
62+ ( $head: expr, $head2: expr $( , ) ?) => { {
63+ $crate:: matchers:: __internal_unstable_do_not_depend_on_these:: ConjunctionMatcher :: new( $head, $head2)
64+ } } ;
65+ ( $head: expr, $head2: expr, $( $tail: expr) ,+ $( , ) ?) => { {
66+ $crate:: __all![
67+ $crate:: matchers:: __internal_unstable_do_not_depend_on_these:: ConjunctionMatcher :: new( $head, $head2) ,
68+ $( $tail) ,+
69+ ]
5970 } }
6071}
6172
62- /// Functionality needed by the [`all`] macro.
63- ///
64- /// For internal use only. API stablility is not guaranteed!
65- #[ doc( hidden) ]
66- pub mod internal {
67- use crate :: description:: Description ;
68- use crate :: matcher:: { Matcher , MatcherResult } ;
69- use crate :: matchers:: anything;
70- use std:: fmt:: Debug ;
71-
72- /// A matcher which matches an input value matched by all matchers in the
73- /// array `components`.
74- ///
75- /// For internal use only. API stablility is not guaranteed!
76- #[ doc( hidden) ]
77- pub struct AllMatcher < ' a , T : Debug + ?Sized , const N : usize > {
78- components : [ Box < dyn Matcher < ActualT = T > + ' a > ; N ] ,
79- }
80-
81- impl < ' a , T : Debug + ?Sized , const N : usize > AllMatcher < ' a , T , N > {
82- /// Constructs an [`AllMatcher`] with the given component matchers.
83- ///
84- /// Intended for use only by the [`all`] macro.
85- pub fn new ( components : [ Box < dyn Matcher < ActualT = T > + ' a > ; N ] ) -> Self {
86- Self { components }
87- }
88- }
89-
90- impl < ' a , T : Debug + ?Sized , const N : usize > Matcher for AllMatcher < ' a , T , N > {
91- type ActualT = T ;
92-
93- fn matches ( & self , actual : & Self :: ActualT ) -> MatcherResult {
94- for component in & self . components {
95- match component. matches ( actual) {
96- MatcherResult :: NoMatch => {
97- return MatcherResult :: NoMatch ;
98- }
99- MatcherResult :: Match => { }
100- }
101- }
102- MatcherResult :: Match
103- }
104-
105- fn explain_match ( & self , actual : & Self :: ActualT ) -> Description {
106- match N {
107- 0 => anything :: < T > ( ) . explain_match ( actual) ,
108- 1 => self . components [ 0 ] . explain_match ( actual) ,
109- _ => {
110- let failures = self
111- . components
112- . iter ( )
113- . filter ( |component| component. matches ( actual) . is_no_match ( ) )
114- . collect :: < Vec < _ > > ( ) ;
115-
116- if failures. len ( ) == 1 {
117- failures[ 0 ] . explain_match ( actual)
118- } else {
119- Description :: new ( )
120- . collect (
121- failures
122- . into_iter ( )
123- . map ( |component| component. explain_match ( actual) ) ,
124- )
125- . bullet_list ( )
126- }
127- }
128- }
129- }
130-
131- fn describe ( & self , matcher_result : MatcherResult ) -> Description {
132- match N {
133- 0 => anything :: < T > ( ) . describe ( matcher_result) ,
134- 1 => self . components [ 0 ] . describe ( matcher_result) ,
135- _ => {
136- let header = if matcher_result. into ( ) {
137- "has all the following properties:"
138- } else {
139- "has at least one of the following properties:"
140- } ;
141- Description :: new ( ) . text ( header) . nested (
142- Description :: new ( )
143- . bullet_list ( )
144- . collect ( self . components . iter ( ) . map ( |m| m. describe ( matcher_result) ) ) ,
145- )
146- }
147- }
148- }
149- }
150- }
151-
15273#[ cfg( test) ]
15374mod tests {
154- use super :: internal;
15575 use crate :: matcher:: { Matcher , MatcherResult } ;
15676 use crate :: prelude:: * ;
15777 use indoc:: indoc;
15878
15979 #[ test]
16080 fn description_shows_more_than_one_matcher ( ) -> Result < ( ) > {
161- let first_matcher = starts_with ( "A" ) ;
81+ let first_matcher: StrMatcher < String , _ > = starts_with ( "A" ) ;
16282 let second_matcher = ends_with ( "string" ) ;
163- let matcher: internal :: AllMatcher < String , 2 > = all ! ( first_matcher, second_matcher) ;
83+ let matcher = all ! ( first_matcher, second_matcher) ;
16484
16585 verify_that ! (
16686 matcher. describe( MatcherResult :: Match ) ,
@@ -175,8 +95,8 @@ mod tests {
17595
17696 #[ test]
17797 fn description_shows_one_matcher_directly ( ) -> Result < ( ) > {
178- let first_matcher = starts_with ( "A" ) ;
179- let matcher: internal :: AllMatcher < String , 1 > = all ! ( first_matcher) ;
98+ let first_matcher: StrMatcher < String , _ > = starts_with ( "A" ) ;
99+ let matcher = all ! ( first_matcher) ;
180100
181101 verify_that ! (
182102 matcher. describe( MatcherResult :: Match ) ,
@@ -187,9 +107,9 @@ mod tests {
187107 #[ test]
188108 fn mismatch_description_shows_which_matcher_failed_if_more_than_one_constituent ( ) -> Result < ( ) >
189109 {
190- let first_matcher = starts_with ( "Another" ) ;
110+ let first_matcher: StrMatcher < str , _ > = starts_with ( "Another" ) ;
191111 let second_matcher = ends_with ( "string" ) ;
192- let matcher: internal :: AllMatcher < str , 2 > = all ! ( first_matcher, second_matcher) ;
112+ let matcher = all ! ( first_matcher, second_matcher) ;
193113
194114 verify_that ! (
195115 matcher. explain_match( "A string" ) ,
@@ -200,7 +120,7 @@ mod tests {
200120 #[ test]
201121 fn mismatch_description_is_simple_when_only_one_consistuent ( ) -> Result < ( ) > {
202122 let first_matcher = starts_with ( "Another" ) ;
203- let matcher: internal :: AllMatcher < str , 1 > = all ! ( first_matcher) ;
123+ let matcher = all ! ( first_matcher) ;
204124
205125 verify_that ! (
206126 matcher. explain_match( "A string" ) ,
0 commit comments