ranges 0.3.3

This crate provides a generic alternative to core/std ranges, set-operations to work with them and a range set that can efficiently store them with the least amount of memory possible.
Documentation
use core::ops::Sub;

use crate::{Arrangement, Domain, GenericRange, OperationResult};

impl<T: Domain> GenericRange<T> {
    /// Returns the difference of two ranges.
    ///
    /// # Examples
    ///```
    /// use ranges::{GenericRange, OperationResult};
    ///
    /// let range = GenericRange::from(1..=5);
    /// let range2 = range;
    /// assert_eq!(range - range2, OperationResult::Empty);
    ///```
    ///```
    /// use ranges::{GenericRange, OperationResult};
    ///
    /// let range = GenericRange::from(1..=5);
    /// let range2 = 1..3;
    /// assert_eq!(range - range2, OperationResult::Single((3..=5).into()));
    ///```
    ///```
    /// use ranges::{GenericRange, OperationResult};
    ///
    /// let range = GenericRange::from(1..=10);
    /// let range2 = 3..5;
    /// assert_eq!(range - range2, OperationResult::Double((1..3).into(), (5..=10).into()));
    ///```
    pub fn difference(self, other: Self) -> OperationResult<T> {
        match self.arrangement(&other) {
            Arrangement::Disjoint { .. } | Arrangement::Touching { .. } => OperationResult::Single(self),
            Arrangement::Overlapping { self_less: true, .. }
            | Arrangement::Ending {
                self_shorter: false, ..
            } => OperationResult::Single(Self {
                start: self.start,
                end: Self::invert_border(other.start),
            }),
            Arrangement::Overlapping { self_less: false, .. }
            | Arrangement::Starting {
                self_shorter: false, ..
            } => OperationResult::Single(Self {
                start: Self::invert_border(other.end),
                end: self.end,
            }),
            Arrangement::Containing { self_shorter: true }
            | Arrangement::Starting { self_shorter: true, .. }
            | Arrangement::Ending { self_shorter: true, .. }
            | Arrangement::Equal => OperationResult::Empty,
            Arrangement::Containing { self_shorter: false } => OperationResult::Double(
                Self {
                    start: self.start,
                    end: Self::invert_border(other.start),
                },
                Self {
                    start: Self::invert_border(other.end),
                    end: self.end,
                },
            ),
            Arrangement::Empty { self_empty: Some(true) } | Arrangement::Empty { self_empty: None } => {
                // ∅ \ A = ∅
                OperationResult::Empty
            }
            Arrangement::Empty {
                self_empty: Some(false),
            } => {
                // A \ ∅ = A
                OperationResult::Single(self)
            }
        }
    }
}

/// This calls [`self.difference(other)`](#method.difference).
impl<T, I> Sub<I> for GenericRange<T>
where
    I: Into<GenericRange<T>>,
    T: Domain,
{
    type Output = OperationResult<T>;

    #[must_use]
    fn sub(self, rhs: I) -> Self::Output {
        self.difference(rhs.into())
    }
}

#[cfg(test)]
mod tests {
    use crate::{GenericRange, OperationResult};

    #[test]
    fn disjoint() {
        let range = GenericRange::new_less_than(5);
        let range2 = GenericRange::new_at_least(10);

        assert_eq!(range.difference(range2), OperationResult::Single(range));
        assert_eq!(range2.difference(range), OperationResult::Single(range2));

        assert_eq!(range - range2, OperationResult::Single(range));
        assert_eq!(range2 - range, OperationResult::Single(range2));
    }

    #[test]
    fn touching() {
        let range = GenericRange::from(0..10);
        let range2 = GenericRange::from(10..=20);

        assert_eq!(range.difference(range2), OperationResult::Single(range));
        assert_eq!(range2.difference(range), OperationResult::Single(range2));

        assert_eq!(range - range2, OperationResult::Single(range));
        assert_eq!(range2 - range, OperationResult::Single(range2));
    }

    #[test]
    fn overlapping() {
        let range = GenericRange::from(0..10);
        let range2 = GenericRange::from(5..=15);

        assert_eq!(
            range.difference(range2),
            OperationResult::Single(GenericRange::from(0..5))
        );
        assert_eq!(
            range2.difference(range),
            OperationResult::Single(GenericRange::from(10..=15))
        );

        assert_eq!(range - range2, OperationResult::Single(GenericRange::from(0..5)));
        assert_eq!(range2 - range, OperationResult::Single(GenericRange::from(10..=15)));
    }

    #[test]
    fn containing() {
        let range = GenericRange::from(0..10);
        let range2 = GenericRange::from(5..=8);

        assert_eq!(
            range.difference(range2),
            OperationResult::Double(GenericRange::from(0..5), GenericRange::new_open(8, 10))
        );
        assert_eq!(range2.difference(range), OperationResult::Empty);

        assert_eq!(
            range - range2,
            OperationResult::Double(GenericRange::from(0..5), GenericRange::new_open(8, 10))
        );
        assert_eq!(range2 - range, OperationResult::Empty);
    }

    #[test]
    fn starting() {
        let range = GenericRange::from(0..10);
        let range2 = GenericRange::from(0..=8);

        assert_eq!(
            range.difference(range2),
            OperationResult::Single(GenericRange::new_open(8, 10))
        );
        assert_eq!(range2.difference(range), OperationResult::Empty);

        assert_eq!(range - range2, OperationResult::Single(GenericRange::new_open(8, 10)));
        assert_eq!(range2 - range, OperationResult::Empty);
    }

    #[test]
    fn ending() {
        let range = GenericRange::from(3..=10);
        let range2 = GenericRange::from(5..=10);

        assert_eq!(
            range.difference(range2),
            OperationResult::Single(GenericRange::from(3..5))
        );
        assert_eq!(range2.difference(range), OperationResult::Empty);

        assert_eq!(range - range2, OperationResult::Single(GenericRange::from(3..5)));
        assert_eq!(range2 - range, OperationResult::Empty);
    }

    #[test]
    fn equal() {
        let range = GenericRange::from(5..=10);
        let range2 = range;

        assert_eq!(range.difference(range2), OperationResult::Empty);
        assert_eq!(range2.difference(range), OperationResult::Empty);

        assert_eq!(range - range2, OperationResult::Empty);
        assert_eq!(range2 - range, OperationResult::Empty);
    }
}