burbomath 0.0.1

Burbokop's rust math library
Documentation
use core::fmt::{Display, Formatter};
use core::ops::{Bound, RangeBounds};

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Range<Idx> {
    pub start: Idx,
    pub end: Idx,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct RangeInclusive<Idx> {
    pub start: Idx,
    pub end: Idx,
}

impl<T> From<core::ops::Range<T>> for Range<T> {
    fn from(value: core::ops::Range<T>) -> Self {
        Self {
            start: value.start,
            end: value.end,
        }
    }
}

impl<T> From<core::ops::RangeInclusive<T>> for RangeInclusive<T> {
    fn from(value: core::ops::RangeInclusive<T>) -> Self {
        let (start, end) = value.into_inner();
        RangeInclusive { start, end }
    }
}

impl<T> RangeBounds<T> for Range<T> {
    fn start_bound(&self) -> Bound<&T> {
        Bound::Included(&self.start)
    }
    fn end_bound(&self) -> Bound<&T> {
        Bound::Excluded(&self.end)
    }
}

impl<T> RangeBounds<T> for Range<&T> {
    fn start_bound(&self) -> Bound<&T> {
        Bound::Included(self.start)
    }
    fn end_bound(&self) -> Bound<&T> {
        Bound::Excluded(self.end)
    }
}

impl<Idx: PartialOrd<Idx>> Range<Idx> {
    #[inline]
    pub fn contains<U>(&self, item: &U) -> bool
    where
        Idx: PartialOrd<U>,
        U: ?Sized + PartialOrd<Idx>,
    {
        <Self as RangeBounds<Idx>>::contains(self, item)
    }

    #[inline]
    pub fn is_valid(&self) -> bool {
        self.start <= self.end
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        !(self.start < self.end)
    }
}

impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
    #[inline]
    pub fn contains<U>(&self, item: &U) -> bool
    where
        Idx: PartialOrd<U>,
        U: ?Sized + PartialOrd<Idx>,
    {
        <Self as RangeBounds<Idx>>::contains(self, item)
    }

    #[inline]
    pub fn is_valid(&self) -> bool {
        self.start <= self.end
    }

    // Commented because inclusive ranges cannot be empty
    // #[inline]
    // pub fn is_empty(&self) -> bool {
    //     !(self.start <= self.end)
    // }
}

impl<T> RangeBounds<T> for RangeInclusive<T> {
    fn start_bound(&self) -> Bound<&T> {
        Bound::Included(&self.start)
    }
    fn end_bound(&self) -> Bound<&T> {
        Bound::Included(&self.end)
    }
}

impl<T> RangeBounds<T> for RangeInclusive<&T> {
    fn start_bound(&self) -> Bound<&T> {
        Bound::Included(self.start)
    }
    fn end_bound(&self) -> Bound<&T> {
        Bound::Included(self.end)
    }
}

impl<T: Display> Display for Range<T> {
    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
        write!(f, "{}..{}", self.start, self.end)
    }
}

impl<T: Display> Display for RangeInclusive<T> {
    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
        write!(f, "{}..={}", self.start, self.end)
    }
}