use {
crate::{Sigma, Test},
core::{fmt, marker::PhantomData},
};
pub trait CanBeInfinite {
fn check_finite(&self) -> bool;
}
pub type Finite<Input> = Sigma<Input, FiniteInvariant<Input>>;
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct FiniteInvariant<Input: fmt::Debug + CanBeInfinite>(PhantomData<Input>);
impl<Input: fmt::Debug + CanBeInfinite> Test<Input, 1> for FiniteInvariant<Input> {
const ADJECTIVE: &str = "finite";
type Error<'i>
= NotFinite
where
Input: 'i;
#[inline(always)]
fn test([input]: [&Input; 1]) -> Result<(), Self::Error<'_>> {
if input.check_finite() {
Ok(())
} else {
Err(NotFinite)
}
}
}
#[non_exhaustive]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct NotFinite;
impl fmt::Display for NotFinite {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "`CanBeInfinite::check_finite(..)` returned `false`")
}
}
impl CanBeInfinite for f32 {
#[inline(always)]
fn check_finite(&self) -> bool {
self.is_finite()
}
}
impl CanBeInfinite for f64 {
#[inline(always)]
fn check_finite(&self) -> bool {
self.is_finite()
}
}