Skip to content

Commit 1d99a84

Browse files
hovinenbcopybara-github
authored andcommitted
Consolidate the implementations of the trait Matcher for ContainerEqMatcher.
Previously, there were several separate implementations to be used against different actual value types. This will no longer be possible in the future when the type parameter of `Matcher` is changed to an associated type. This change consolidates the various implementations into a single one which already covers all cases. It makes use of the optional type parameter of `PartialEq` to do this. It also renames the type parameters around `ContainerEqMatcher` to be more descriptive and consistent. The struct itself now has the type of the actual container as a type parameter. This is not strictly required at this stage, but will be necessary in the following step when `Matcher` is modified. PiperOrigin-RevId: 527875014
1 parent 58506d2 commit 1d99a84

File tree

1 file changed

+35
-103
lines changed

1 file changed

+35
-103
lines changed

googletest/src/matchers/container_eq_matcher.rs

Lines changed: 35 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::matcher::{MatchExplanation, Matcher, MatcherResult};
1616
#[cfg(google3)]
1717
use googletest::*;
1818
use std::fmt::Debug;
19-
use std::iter::zip;
19+
use std::marker::PhantomData;
2020

2121
/// Matches a container equal (in the sense of `==`) to `expected`.
2222
///
@@ -85,119 +85,61 @@ use std::iter::zip;
8585
// ContainerEqMatcher has some specialisations for slice types (see
8686
// documentation above). Returning impl Matcher would hide those from the
8787
// compiler.
88-
pub fn container_eq<ContainerT: PartialEq + Debug>(
89-
expected: ContainerT,
90-
) -> ContainerEqMatcher<ContainerT> {
91-
ContainerEqMatcher { expected }
88+
pub fn container_eq<ActualContainerT, ExpectedContainerT>(
89+
expected: ExpectedContainerT,
90+
) -> ContainerEqMatcher<ActualContainerT, ExpectedContainerT>
91+
where
92+
ActualContainerT: PartialEq<ExpectedContainerT> + Debug + ?Sized,
93+
ExpectedContainerT: Debug,
94+
{
95+
ContainerEqMatcher { expected, phantom: Default::default() }
9296
}
9397

94-
pub struct ContainerEqMatcher<T: Debug> {
95-
expected: T,
98+
pub struct ContainerEqMatcher<ActualContainerT: ?Sized, ExpectedContainerT> {
99+
expected: ExpectedContainerT,
100+
phantom: PhantomData<ActualContainerT>,
96101
}
97102

98-
impl<T: PartialEq + Debug, ContainerT: PartialEq + Debug> Matcher<ContainerT>
99-
for ContainerEqMatcher<ContainerT>
103+
impl<ActualElementT, ActualContainerT, ExpectedElementT, ExpectedContainerT>
104+
Matcher<ActualContainerT> for ContainerEqMatcher<ActualContainerT, ExpectedContainerT>
100105
where
101-
for<'a> &'a ContainerT: IntoIterator<Item = &'a T>,
106+
ActualElementT: PartialEq<ExpectedElementT> + Debug + ?Sized,
107+
ActualContainerT: PartialEq<ExpectedContainerT> + Debug + ?Sized,
108+
ExpectedElementT: Debug,
109+
ExpectedContainerT: Debug,
110+
for<'a> &'a ActualContainerT: IntoIterator<Item = &'a ActualElementT>,
111+
for<'a> &'a ExpectedContainerT: IntoIterator<Item = &'a ExpectedElementT>,
102112
{
103-
fn matches(&self, actual: &ContainerT) -> MatcherResult {
113+
fn matches(&self, actual: &ActualContainerT) -> MatcherResult {
104114
(*actual == self.expected).into()
105115
}
106116

107-
fn explain_match(&self, actual: &ContainerT) -> MatchExplanation {
108-
self.explain_match_impl(actual)
109-
}
110-
111-
fn describe(&self, matcher_result: MatcherResult) -> String {
112-
self.describe_impl(matcher_result)
113-
}
114-
}
115-
116-
impl<T: PartialEq + Debug, const N: usize> Matcher<Vec<T>> for ContainerEqMatcher<[T; N]> {
117-
fn matches(&self, actual: &Vec<T>) -> MatcherResult {
118-
(actual.as_slice() == self.expected).into()
119-
}
120-
121-
fn explain_match(&self, actual: &Vec<T>) -> MatchExplanation {
122-
self.explain_match_impl(actual)
123-
}
124-
125-
fn describe(&self, matcher_result: MatcherResult) -> String {
126-
self.describe_impl(matcher_result)
127-
}
128-
}
129-
130-
impl<T: PartialEq + Debug, const N: usize> Matcher<[T]> for ContainerEqMatcher<[T; N]> {
131-
fn matches(&self, actual: &[T]) -> MatcherResult {
132-
(actual == self.expected).into()
133-
}
134-
135-
fn explain_match(&self, actual: &[T]) -> MatchExplanation {
136-
self.explain_match_impl(actual)
117+
fn explain_match(&self, actual: &ActualContainerT) -> MatchExplanation {
118+
build_explanation(self.get_missing_items(actual), self.get_unexpected_items(actual))
137119
}
138120

139121
fn describe(&self, matcher_result: MatcherResult) -> String {
140-
self.describe_impl(matcher_result)
141-
}
142-
}
143-
144-
impl<const N: usize> Matcher<Vec<String>> for ContainerEqMatcher<[&str; N]> {
145-
fn matches(&self, actual: &Vec<String>) -> MatcherResult {
146-
if actual.len() != self.expected.len() {
147-
return MatcherResult::DoesNotMatch;
148-
}
149-
for (actual_element, expected_element) in zip(actual, self.expected) {
150-
if actual_element.as_str() != expected_element {
151-
return MatcherResult::DoesNotMatch;
152-
}
122+
match matcher_result {
123+
MatcherResult::Matches => format!("is equal to {:?}", self.expected),
124+
MatcherResult::DoesNotMatch => format!("isn't equal to {:?}", self.expected),
153125
}
154-
MatcherResult::Matches
155-
}
156-
157-
fn explain_match(&self, actual: &Vec<String>) -> MatchExplanation {
158-
build_explanation(
159-
self.get_missing_str_items(actual),
160-
self.get_unexpected_string_items(actual),
161-
)
162-
}
163-
164-
fn describe(&self, matcher_result: MatcherResult) -> String {
165-
self.describe_impl(matcher_result)
166126
}
167127
}
168128

169-
impl<T: PartialEq + Debug, ExpectedT: Debug> ContainerEqMatcher<ExpectedT>
129+
impl<ActualElementT, ActualContainerT, ExpectedElementT, ExpectedContainerT>
130+
ContainerEqMatcher<ActualContainerT, ExpectedContainerT>
170131
where
171-
for<'a> &'a ExpectedT: IntoIterator<Item = &'a T>,
132+
ActualElementT: PartialEq<ExpectedElementT> + ?Sized,
133+
ActualContainerT: PartialEq<ExpectedContainerT> + ?Sized,
134+
for<'a> &'a ActualContainerT: IntoIterator<Item = &'a ActualElementT>,
135+
for<'a> &'a ExpectedContainerT: IntoIterator<Item = &'a ExpectedElementT>,
172136
{
173-
fn explain_match_impl<ActualT: ?Sized>(&self, actual: &ActualT) -> MatchExplanation
174-
where
175-
for<'a> &'a ActualT: IntoIterator<Item = &'a T> + Debug,
176-
{
177-
build_explanation(self.get_missing_items(actual), self.get_unexpected_items(actual))
178-
}
179-
180-
fn get_missing_items<ActualT: ?Sized>(&self, actual: &ActualT) -> Vec<&T>
181-
where
182-
for<'a> &'a ActualT: IntoIterator<Item = &'a T>,
183-
{
137+
fn get_missing_items(&self, actual: &ActualContainerT) -> Vec<&ExpectedElementT> {
184138
self.expected.into_iter().filter(|&i| !actual.into_iter().any(|j| j == i)).collect()
185139
}
186140

187-
fn get_unexpected_items<'a, ActualT: ?Sized>(&self, actual: &'a ActualT) -> Vec<&'a T>
188-
where
189-
for<'b> &'b ActualT: IntoIterator<Item = &'b T>,
190-
{
191-
actual.into_iter().filter(|&i| !self.expected.into_iter().any(|j| j == i)).collect()
192-
}
193-
}
194-
195-
impl<ExpectedT: Debug> ContainerEqMatcher<ExpectedT> {
196-
fn describe_impl(&self, matcher_result: MatcherResult) -> String {
197-
match matcher_result {
198-
MatcherResult::Matches => format!("is equal to {:?}", self.expected),
199-
MatcherResult::DoesNotMatch => format!("isn't equal to {:?}", self.expected),
200-
}
141+
fn get_unexpected_items<'a>(&self, actual: &'a ActualContainerT) -> Vec<&'a ActualElementT> {
142+
actual.into_iter().filter(|&i| !self.expected.into_iter().any(|j| i == j)).collect()
201143
}
202144
}
203145

@@ -234,16 +176,6 @@ fn build_explanation<T: Debug, U: Debug>(missing: Vec<T>, unexpected: Vec<U>) ->
234176
}
235177
}
236178

237-
impl<const N: usize> ContainerEqMatcher<[&str; N]> {
238-
fn get_missing_str_items(&self, actual: &[String]) -> Vec<&str> {
239-
self.expected.into_iter().filter(|i| !actual.iter().any(|j| j == i)).collect()
240-
}
241-
242-
fn get_unexpected_string_items<'a>(&self, actual: &'a [String]) -> Vec<&'a String> {
243-
actual.iter().filter(|i| !self.expected.into_iter().any(|j| j == i.as_str())).collect()
244-
}
245-
}
246-
247179
#[cfg(test)]
248180
mod tests {
249181
use super::container_eq;

0 commit comments

Comments
 (0)