saturation 0.2.3

Real-time saturation and clipping designed for use with vst's
Documentation
use core::{cmp::Ordering, fmt::Debug, ops::{Add, Deref, Div, Mul, Rem, Sub}};

use num::Float;

#[allow(clippy::derive_ord_xor_partial_ord)]
#[derive(Clone, Copy, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize)]
#[serde(transparent)]
#[repr(transparent)]
pub struct Finite<F>(F)
where
    F: Float;
impl<F> Finite<F>
where
    F: Float
{
    pub fn new(value: F) -> Option<Self>
    {
        if value.is_finite()
        {
            Some(Self(value))
        }
        else
        {
            None
        }
    }
}
impl<F> Debug for Finite<F>
where
    F: Float + Debug
{
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
    {
        self.0.fmt(f)
    }
}
impl<F> PartialEq<F> for Finite<F>
where
    F: Float
{
    fn eq(&self, other: &F) -> bool
    {
        &**self == other
    }
    #[allow(clippy::partialeq_ne_impl)]
    fn ne(&self, other: &F) -> bool
    {
        &**self != other
    }
}
impl<F> PartialOrd<F> for Finite<F>
where
    F: Float
{
    fn partial_cmp(&self, other: &F) -> Option<Ordering>
    {
        (**self).partial_cmp(other)
    }

    fn lt(&self, other: &F) -> bool
    {
        (**self).lt(other)
    }

    fn le(&self, other: &F) -> bool
    {
        (**self).le(other)
    }

    fn gt(&self, other: &F) -> bool
    {
        (**self).gt(other)
    }

    fn ge(&self, other: &F) -> bool
    {
        (**self).ge(other)
    }
}
impl<F> Eq for Finite<F>
where
    F: Float
{
    
}
impl<F> Ord for Finite<F>
where
    F: Float
{
    fn cmp(&self, other: &Self) -> Ordering
    {
        unsafe {
            self.partial_cmp(other).unwrap_unchecked()
        }
    }
}
impl<F> Deref for Finite<F>
where
    F: Float
{
    type Target = F;

    fn deref(&self) -> &Self::Target
    {
        &self.0
    }
}

macro_rules! binop {
    ($($trait:ident :: $f:ident)*) => {
        $(
            impl<F> $trait<F> for Finite<F>
            where
                F: Float
            {
                type Output = F;
            
                #[inline]
                fn $f(self, rhs: F) -> Self::Output
                {
                    (*self).$f(rhs)
                }
            }
            impl<F> $trait for Finite<F>
            where
                F: Float
            {
                type Output = F;
            
                #[inline]
                fn $f(self, rhs: Self) -> Self::Output
                {
                    self.$f(*rhs)
                }
            }
        )*
    };
}

binop!(
    Add::add
    Sub::sub
    Mul::mul
    Div::div
    Rem::rem
);