assert-rs 0.1.1

An assertion library that uses types and data to fail tests instead of panicking.
Documentation
use super::{Assertion, Debug, Display};

/// A group of assertions, all tested simultaneously.
///
/// These can be created using the [`multi_assert!`](crate::multi_assert) macro.
/// See its docs for more.
pub struct MultiAssertion<A: Assertion, const N: usize>([A; N]);

impl<A: Assertion, const N: usize> Display for MultiAssertion<A, N> {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        write!(f, "assertion failures in a multi-assert:")?;
        for (i, assertion) in self.0.iter().enumerate() {
            if assertion.test() {
                write!(f, "\n{i}. [ok]")?;
            } else {
                writeln!(f, "\n{i}. {assertion}")?;
            }
        }
        Ok(())
    }
}

impl<A: Assertion, const N: usize> MultiAssertion<A, N> {
    #[must_use]
    /// You can use [`multi_assert!`](crate::multi_assert) instead, but it's not required.
    pub const fn new(assertions: [A; N]) -> Self {
        Self(assertions)
    }
}

#[cfg(feature = "std")]
impl<A: Assertion, const N: usize> std::process::Termination for MultiAssertion<A, N> {
    fn report(self) -> std::process::ExitCode {
        if self.test() {
            std::process::ExitCode::SUCCESS
        } else {
            println!("{self}");
            std::process::ExitCode::FAILURE
        }
    }
}

impl<A: Assertion, const N: usize> Assertion for MultiAssertion<A, N> {
    fn test(&self) -> bool {
        self.0.iter().all(Assertion::test)
    }
}

impl<A: Assertion, const N: usize> Debug for MultiAssertion<A, N> {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        Display::fmt(self, f)
    }
}

#[cfg(feature = "alloc")]
#[cfg_attr(doc, doc = include_str!("../multi_assert_doc.md"))]
#[macro_export]
macro_rules! multi_assert {
    [#[dyn] $($this:expr),+ $(,)?] => {
        $crate::assertion::MultiDynAssertion::new([
            $(Box::new($this),)+
        ])
    };
    [$($this:expr),+ $(,)?] => {
        $crate::assertion::MultiAssertion::new([
            $($this,)+
        ])
    };
}

#[cfg(not(feature = "alloc"))]
#[cfg_attr(doc, doc = include_str!("../multi_assert_doc.md"))]
#[macro_export]
macro_rules! multi_assert {
    [#[dyn] $($this:expr),+ $(,)?] => {
        compile_error!("cannot use #[dyn] if the no_alloc feature is enabled")
    };
    [$($this:expr),+ $(,)?] => {
        $crate::assertion::MultiAssertion::new([
            $($this,)+
        ])
    };
}