use core::{fmt, marker::PhantomData};
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct AllPairs<Invariant: crate::Test<Input::Item, 2>, Input: IntoIterator + fmt::Debug>(
PhantomData<Invariant>,
PhantomData<Input>,
)
where
Input::Item: fmt::Debug,
for<'i> &'i Input: IntoIterator<Item = &'i Input::Item>;
impl<Invariant: crate::Test<Input::Item, 2>, Input: IntoIterator + fmt::Debug> crate::Test<Input, 1>
for AllPairs<Invariant, Input>
where
Input::Item: fmt::Debug,
for<'i> &'i Input: IntoIterator<Item = &'i Input::Item>,
{
const ADJECTIVE: &str = "all pairwise valid";
type Error<'i>
= NotAllPairs<'i, Input::Item, Invariant>
where
Input: 'i;
#[inline]
fn test([input]: [&Input; 1]) -> Result<(), Self::Error<'_>> {
let mut iter = input.into_iter();
let mut last_ptr: *const _ = {
let Some(last_ref) = iter.next() else {
return Ok(());
};
last_ref
};
for (index_of_fst, current) in iter.enumerate() {
let last = unsafe { &*last_ptr };
match Invariant::test([last, current]) {
Ok(()) => {}
Err(error) => {
return Err(NotAllPairs {
elem_fst: last,
elem_snd: current,
error,
index_of_fst,
});
}
}
last_ptr = current;
}
Ok(())
}
}
#[non_exhaustive]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct NotAllPairs<'i, Item: fmt::Debug, Invariant: crate::Test<Item, 2>> {
elem_fst: &'i Item,
elem_snd: &'i Item,
error: Invariant::Error<'i>,
index_of_fst: usize,
}
impl<Item: fmt::Debug, Invariant: crate::Test<Item, 2>> fmt::Display
for NotAllPairs<'_, Item, Invariant>
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
#![expect(
clippy::use_debug,
reason = "Intentional and informative, not just forgotten print-debugging"
)]
let Self {
elem_fst,
elem_snd,
ref error,
index_of_fst,
} = *self;
write!(f, "Elements #{index_of_fst} and #")?;
if let Some(index_of_snd) = index_of_fst.checked_add(1) {
fmt::Display::fmt(&index_of_snd, f)
} else {
write!(f, "[`usize` overflow]")
}?;
write!(
f,
" ({elem_fst:#?} and {elem_snd:#?}) were not {}: {error}",
Invariant::ADJECTIVE,
)
}
}