1use core::{fmt, marker::PhantomData};
4
5#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
7pub struct AllPairs<Invariant: crate::Test<Input::Item, 2>, Input: IntoIterator + fmt::Debug>(
8 PhantomData<Invariant>,
9 PhantomData<Input>,
10)
11where
12 Input::Item: fmt::Debug,
13 for<'i> &'i Input: IntoIterator<Item = &'i Input::Item>;
14
15impl<Invariant: crate::Test<Input::Item, 2>, Input: IntoIterator + fmt::Debug> crate::Test<Input, 1>
16 for AllPairs<Invariant, Input>
17where
18 Input::Item: fmt::Debug,
19 for<'i> &'i Input: IntoIterator<Item = &'i Input::Item>,
20{
21 const ADJECTIVE: &str = "all pairwise valid";
22
23 type Error<'i>
24 = NotAllPairs<'i, Input::Item, Invariant>
25 where
26 Input: 'i;
27
28 #[inline]
29 fn test([input]: [&Input; 1]) -> Result<(), Self::Error<'_>> {
30 let mut iter = input.into_iter();
31
32 let mut last_ptr: *const _ = {
35 let Some(last_ref) = iter.next() else {
36 return Ok(());
37 };
38 last_ref
39 };
40 for (index_of_fst, current) in iter.enumerate() {
41 let last = unsafe { &*last_ptr };
45 match Invariant::test([last, current]) {
46 Ok(()) => {}
47 Err(error) => {
48 return Err(NotAllPairs {
49 elem_fst: last,
50 elem_snd: current,
51 error,
52 index_of_fst,
53 });
54 }
55 }
56 last_ptr = current;
57 }
58 Ok(())
59 }
60}
61
62#[non_exhaustive]
64#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
65pub struct NotAllPairs<'i, Item: fmt::Debug, Invariant: crate::Test<Item, 2>> {
66 elem_fst: &'i Item,
68 elem_snd: &'i Item,
70 error: Invariant::Error<'i>,
72 index_of_fst: usize,
75}
76
77impl<Item: fmt::Debug, Invariant: crate::Test<Item, 2>> fmt::Display
78 for NotAllPairs<'_, Item, Invariant>
79{
80 #[inline]
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 #![expect(
83 clippy::use_debug,
84 reason = "Intentional and informative, not just forgotten print-debugging"
85 )]
86
87 let Self {
88 elem_fst,
89 elem_snd,
90 ref error,
91 index_of_fst,
92 } = *self;
93 write!(f, "Elements #{index_of_fst} and #")?;
94 if let Some(index_of_snd) = index_of_fst.checked_add(1) {
95 fmt::Display::fmt(&index_of_snd, f)
96 } else {
97 write!(f, "[`usize` overflow]")
98 }?;
99 write!(
100 f,
101 " ({elem_fst:#?} and {elem_snd:#?}) were not {}: {error}",
102 Invariant::ADJECTIVE,
103 )
104 }
105}