xpct/matchers/collections/
every.rs1use std::fmt;
2
3use crate::core::{DynTransformMatch, MatchOutcome, Matcher, TransformMatch};
4use crate::matchers::SomeFailures;
5
6pub struct EveryMatcher<'a, PosOut, NegOut, IntoIter>
10where
11 IntoIter: IntoIterator + 'a,
12{
13 match_func: Box<dyn Fn() -> Matcher<'a, IntoIter::Item, PosOut, NegOut> + 'a>,
14}
15
16impl<'a, PosOut, NegOut, IntoIter> fmt::Debug for EveryMatcher<'a, PosOut, NegOut, IntoIter>
17where
18 IntoIter: IntoIterator + 'a,
19{
20 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21 f.debug_struct("EveryMatcher").finish_non_exhaustive()
22 }
23}
24
25impl<'a, PosOut, NegOut, IntoIter> EveryMatcher<'a, PosOut, NegOut, IntoIter>
26where
27 IntoIter: IntoIterator + 'a,
28{
29 pub fn new(match_func: impl Fn() -> Matcher<'a, IntoIter::Item, PosOut, NegOut> + 'a) -> Self {
31 Self {
32 match_func: Box::new(match_func),
33 }
34 }
35}
36
37impl<'a, PosOut, NegOut, IntoIter> TransformMatch for EveryMatcher<'a, PosOut, NegOut, IntoIter>
38where
39 IntoIter: IntoIterator + 'a,
40{
41 type In = IntoIter;
42
43 type PosOut = Vec<PosOut>;
44 type NegOut = Vec<NegOut>;
45
46 type PosFail = SomeFailures;
47 type NegFail = SomeFailures;
48
49 fn match_pos(
50 self,
51 actual: Self::In,
52 ) -> crate::Result<MatchOutcome<Self::PosOut, Self::PosFail>> {
53 let mut failures = Vec::new();
54 let mut successes = Vec::new();
55
56 for input in actual {
57 match Box::new((self.match_func)()).match_pos(input)? {
58 MatchOutcome::Success(success) => {
59 failures.push(None);
60 successes.push(success);
61 }
62 MatchOutcome::Fail(fail) => {
63 failures.push(Some(fail));
64 }
65 }
66 }
67
68 if failures.iter().any(Option::is_some) {
69 return Ok(MatchOutcome::Fail(failures));
70 }
71
72 Ok(MatchOutcome::Success(successes))
73 }
74
75 fn match_neg(
76 self,
77 actual: Self::In,
78 ) -> crate::Result<MatchOutcome<Self::NegOut, Self::NegFail>> {
79 let mut failures = Vec::new();
80 let mut successes = Vec::new();
81
82 for input in actual {
83 match Box::new((self.match_func)()).match_neg(input)? {
84 MatchOutcome::Success(success) => {
85 failures.push(None);
86 successes.push(success);
87 }
88 MatchOutcome::Fail(fail) => {
89 failures.push(Some(fail));
90 }
91 }
92 }
93
94 if failures.iter().any(Option::is_none) {
95 return Ok(MatchOutcome::Success(successes));
96 }
97
98 Ok(MatchOutcome::Fail(failures))
99 }
100}