use crate::{
accum::Finished,
error::{InvalidIndex, InvalidPair, Unequal},
};
pub trait Verifier<Item> {
type Error<'a>
where
Self: 'a,
Item: 'a;
fn verify_item<'a>(
&'a self,
accum: Finished<'a, Item>,
index: isize,
) -> Result<(), Self::Error<'a>>;
}
impl<Item: PartialEq> Verifier<Item> for [Item] {
type Error<'a>
= Unequal<'a, Item>
where
Item: 'a;
fn verify_item<'b>(
&'b self,
accum: Finished<'b, Item>,
index: isize,
) -> Result<(), Unequal<'b, Item>> {
let (index, actual) = accum.get_unsigned_indexed(index).unwrap();
let Some(expected) = self.get(index) else {
return Err(Unequal {
expected: None,
actual,
});
};
if actual == expected {
Ok(())
} else {
Err(Unequal {
expected: Some(expected),
actual,
})
}
}
}
#[derive(Copy, Clone, Debug)]
pub struct CheckAdjacent<F>(pub F);
impl<Item, F> Verifier<Item> for CheckAdjacent<F>
where
for<'a> F: Fn(&'a Item, &'a Item) -> bool,
{
type Error<'a>
= InvalidPair<'a, Item>
where
Self: 'a,
Item: 'a;
fn verify_item<'a>(
&'a self,
accum: Finished<'a, Item>,
index: isize,
) -> Result<(), InvalidPair<'a, Item>> {
let (unsigned_index, mid) = accum.get_unsigned_indexed(index).unwrap();
if index < 0 {
if unsigned_index == 0 {
return Ok(());
}
let hi = accum.get_unsigned(unsigned_index + 1).unwrap();
if self.0(mid, hi) {
Ok(())
} else {
Err(InvalidPair {
pair: (mid, hi),
index_is_negative: true,
})
}
} else {
if unsigned_index == accum.len().saturating_sub(1) {
return Ok(());
}
let lo = accum.get_unsigned(unsigned_index - 1).unwrap();
if self.0(lo, mid) {
Ok(())
} else {
Err(InvalidPair {
pair: (lo, mid),
index_is_negative: false,
})
}
}
}
}
#[derive(Copy, Clone, Debug)]
pub struct CheckIndex<F>(pub F);
impl<Item, F> Verifier<Item> for CheckIndex<F>
where
for<'a> F: Fn(usize, &'a Item) -> bool,
{
type Error<'a>
= InvalidIndex<'a, Item>
where
Self: 'a,
Item: 'a;
fn verify_item<'a>(
&'a self,
accum: Finished<'a, Item>,
index: isize,
) -> Result<(), InvalidIndex<'a, Item>> {
let (index, item) = accum.get_unsigned_indexed(index).unwrap();
if self.0(index, item) {
Ok(())
} else {
Err(InvalidIndex { item, index })
}
}
}