use core::{fmt, marker::PhantomData};
use refining_core::{
logical::{And, Not},
predicate::Predicate,
};
use crate::length::HasLength;
pub struct LengthEqual<const N: usize> {
private: PhantomData<()>,
}
impl<const N: usize, T: HasLength + ?Sized> Predicate<T> for LengthEqual<N> {
fn check(value: &T) -> bool {
value.length() == N
}
fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "value with length == {N}")
}
fn expect_code(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "length::eq<{N}>")
}
}
pub struct LengthNotEqual<const N: usize> {
private: PhantomData<()>,
}
impl<const N: usize, T: HasLength + ?Sized> Predicate<T> for LengthNotEqual<N> {
fn check(value: &T) -> bool {
value.length() != N
}
fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "value with length != {N}")
}
fn expect_code(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "length::ne<{N}>")
}
}
pub struct LengthLess<const N: usize> {
private: PhantomData<()>,
}
impl<const N: usize, T: HasLength + ?Sized> Predicate<T> for LengthLess<N> {
fn check(value: &T) -> bool {
value.length() < N
}
fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "value with length < {N}")
}
fn expect_code(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "length::lt<{N}>")
}
}
pub struct LengthGreater<const N: usize> {
private: PhantomData<()>,
}
impl<const N: usize, T: HasLength + ?Sized> Predicate<T> for LengthGreater<N> {
fn check(value: &T) -> bool {
value.length() > N
}
fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "value with length > {N}")
}
fn expect_code(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "length::gt<{N}>")
}
}
pub struct LengthLessOrEqual<const N: usize> {
private: PhantomData<()>,
}
impl<const N: usize, T: HasLength + ?Sized> Predicate<T> for LengthLessOrEqual<N> {
fn check(value: &T) -> bool {
value.length() <= N
}
fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "value with length <= {N}")
}
fn expect_code(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "length::le<{N}>")
}
}
pub struct LengthGreaterOrEqual<const N: usize> {
private: PhantomData<()>,
}
impl<const N: usize, T: HasLength + ?Sized> Predicate<T> for LengthGreaterOrEqual<N> {
fn check(value: &T) -> bool {
value.length() >= N
}
fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "value with length >= {N}")
}
fn expect_code(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "length::ge<{N}>")
}
}
pub type LengthOpen<const M: usize, const N: usize> = And<LengthGreater<M>, LengthLess<N>>;
pub type LengthClosedOpen<const M: usize, const N: usize> =
And<LengthGreaterOrEqual<M>, LengthLess<N>>;
pub type LengthOpenClosed<const M: usize, const N: usize> =
And<LengthGreater<M>, LengthLessOrEqual<N>>;
pub type LengthClosed<const M: usize, const N: usize> =
And<LengthGreaterOrEqual<M>, LengthLessOrEqual<N>>;
pub const ZERO: usize = 0;
pub type LengthZero = LengthEqual<ZERO>;
pub type LengthNonZero = LengthNotEqual<ZERO>;
pub struct LengthModulo<const D: usize, const M: usize> {
private: PhantomData<()>,
}
impl<const D: usize, const M: usize, T: HasLength + ?Sized> Predicate<T> for LengthModulo<D, M> {
fn check(value: &T) -> bool {
value.length() % D == M
}
fn expect(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "value with length % {D} == {M}")
}
fn expect_code(formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "length::mod<{D}, {M}>")
}
}
pub type LengthDivisible<const D: usize> = LengthModulo<D, ZERO>;
pub const TWO: usize = 2;
pub type LengthEven = LengthDivisible<TWO>;
pub type LengthOdd = Not<LengthEven>;