Skip to main content

assert_rs/assertion/
collected.rs

1use super::{Assertion, Debug, Display};
2
3/// A group of assertions, where the first one to fail will short-circuit.
4///
5/// This can be created using its [`FromIterator`] implementation or the [`AssertAll`] extension trait.
6pub struct CollectedAssertion<A: Assertion>(pub Option<A>);
7
8impl<A: Assertion> Display for CollectedAssertion<A> {
9    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
10        match self.0 {
11            Some(ref a) => Display::fmt(a, f),
12            None => Ok(()),
13        }
14    }
15}
16
17impl<A: Assertion> Debug for CollectedAssertion<A> {
18    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
19        Display::fmt(self, f)
20    }
21}
22
23impl<A: Assertion> FromIterator<A> for CollectedAssertion<A> {
24    fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
25        Self(iter.into_iter().find(|a| !a.test()))
26    }
27}
28
29#[cfg(feature = "std")]
30impl<A: Assertion> std::process::Termination for CollectedAssertion<A> {
31    fn report(self) -> std::process::ExitCode {
32        if self.test() {
33            std::process::ExitCode::SUCCESS
34        } else {
35            println!("{self}");
36            std::process::ExitCode::FAILURE
37        }
38    }
39}
40
41impl<A: Assertion> Assertion for CollectedAssertion<A> {
42    fn test(&self) -> bool {
43        self.0.as_ref().is_none_or(Assertion::test)
44    }
45}
46
47/// Extension trait, blanked implemented for [`Iterator`]s of [`Assertion`]s.
48///
49/// Adds the [`assert_all`](AssertAll::assert_all) method,
50/// which calls the [`collect`](Iterator::collect) method (with fewer generics and turbofish).
51pub trait AssertAll {
52    type Output: Assertion;
53
54    /// Collect this iterator of [`Assertion`]s into a [`CollectedAssertion`].
55    fn assert_all(self) -> CollectedAssertion<Self::Output>
56    where
57        Self: Sized;
58}
59
60impl<I, A> AssertAll for I
61where
62    I: IntoIterator<Item = A>,
63    A: Assertion,
64{
65    type Output = A;
66
67    fn assert_all(self) -> CollectedAssertion<Self::Output>
68    where
69        Self: Sized,
70    {
71        self.into_iter().collect()
72    }
73}