jaaptools 0.1.14

I really just wanted to try publishing a package, but this contains stuff I find useful in many circumstances.
Documentation
use core::ops::Add;

impl<RHS, T: Add<RHS> + Sized + Copy> BoundedAdd<RHS> for T where
    <Self as Add<RHS>>::Output: PartialOrd
{
}

pub trait BoundedAdd<RHS>: Add<RHS> + Sized + Copy
where
    <Self as Add<RHS>>::Output: PartialOrd,
{
    /// Add number with explicit bounds
    /// Panics:
    ///   - When lower > upper
    ///   - When output cannot be compared to the bounds (eg: NaN)
    /// ```
    /// use jaaptools::ops::BoundedAdd;
    ///
    /// assert_eq!(4.bounded_add(3, 0, 10), 7);
    /// assert_eq!(4.bounded_add(3, 0, 6), 6);
    /// assert_eq!(4.bounded_add(-5, 0, 6), 0);
    /// ```
    fn bounded_add(
        self,
        rhs: RHS,
        lower: <Self as Add<RHS>>::Output,
        upper: <Self as Add<RHS>>::Output,
    ) -> <Self as Add<RHS>>::Output {
        if lower > upper {
            panic!("lower bound exceeds upper bound!");
        }
        let out = self + rhs;
        if out < lower {
            lower
        } else if out > upper {
            upper
        } else {
            out
        }
    }
}

impl<RHS, T: PartialOrd + BoundedAdd<RHS> + Add<RHS, Output = T>> BoundedAddAssign<RHS> for T {}

pub trait BoundedAddAssign<RHS>: BoundedAdd<RHS> + Add<RHS, Output = Self>
where
    Self: PartialOrd,
{
    /// Same as `bounded_add` but assigns directly to self
    fn bounded_add_assign(&mut self, rhs: RHS, lower: Self, upper: Self) {
        *self = self.bounded_add(rhs, lower, upper);
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_bounded_add() {
        assert_eq!(4.bounded_add(3, 0, 10), 7);
        assert_eq!(4.bounded_add(3, 0, 6), 6);
        assert_eq!(4.bounded_add(-5, 0, 6), 0);

        let mut x = 3.0;
        x.bounded_add_assign(4., 0., 5.);
        assert!((4.999..5.001).contains(&x));
    }
}