1 // Copyright 2023 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 #![doc(hidden)]
16 
17 use crate::{
18     description::Description,
19     matcher::{Matcher, MatcherResult},
20 };
21 use std::{fmt::Debug, marker::PhantomData};
22 
23 /// Matches precisely values matched by `inner`.
24 ///
25 /// The returned matcher produces a description prefixed by the string
26 /// `description`. This is useful in contexts where the test assertion failure
27 /// output must include the additional description.
is<'a, ActualT: Debug + 'a, InnerMatcherT: Matcher<ActualT = ActualT> + 'a>( description: &'a str, inner: InnerMatcherT, ) -> impl Matcher<ActualT = ActualT> + 'a28 pub fn is<'a, ActualT: Debug + 'a, InnerMatcherT: Matcher<ActualT = ActualT> + 'a>(
29     description: &'a str,
30     inner: InnerMatcherT,
31 ) -> impl Matcher<ActualT = ActualT> + 'a {
32     IsMatcher { description, inner, phantom: Default::default() }
33 }
34 
35 struct IsMatcher<'a, ActualT, InnerMatcherT> {
36     description: &'a str,
37     inner: InnerMatcherT,
38     phantom: PhantomData<ActualT>,
39 }
40 
41 impl<'a, ActualT: Debug, InnerMatcherT: Matcher<ActualT = ActualT>> Matcher
42     for IsMatcher<'a, ActualT, InnerMatcherT>
43 {
44     type ActualT = ActualT;
45 
matches(&self, actual: &Self::ActualT) -> MatcherResult46     fn matches(&self, actual: &Self::ActualT) -> MatcherResult {
47         self.inner.matches(actual)
48     }
49 
describe(&self, matcher_result: MatcherResult) -> Description50     fn describe(&self, matcher_result: MatcherResult) -> Description {
51         match matcher_result {
52             MatcherResult::Match => format!(
53                 "is {} which {}",
54                 self.description,
55                 self.inner.describe(MatcherResult::Match)
56             )
57             .into(),
58             MatcherResult::NoMatch => format!(
59                 "is not {} which {}",
60                 self.description,
61                 self.inner.describe(MatcherResult::Match)
62             )
63             .into(),
64         }
65     }
66 
explain_match(&self, actual: &Self::ActualT) -> Description67     fn explain_match(&self, actual: &Self::ActualT) -> Description {
68         self.inner.explain_match(actual)
69     }
70 }
71