use super::{Assertion, Debug, Display};
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]
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,)+
])
};
}