rampart 0.1.1

Rampart determines how intervals relate to each other.
Documentation
use std::cmp::Ordering;

#[derive(Clone, Debug)]
pub struct Interval<T: Ord> {
    pub lesser: T,
    pub greater: T,
}

impl<T: Ord> Interval<T> {
    pub fn new(lesser: T, greater: T) -> Self {
        Self { lesser, greater }
    }
    pub fn relate(&self, y: &Self) -> Relation {
        let lxly = self.lesser.cmp(&y.lesser);
        let lxgy = self.lesser.cmp(&y.greater);
        let gxly = self.greater.cmp(&y.lesser);
        let gxgy = self.greater.cmp(&y.greater);
        match (lxly, lxgy, gxly, gxgy) {
            (Ordering::Equal, _, _, Ordering::Equal) => Relation::Equal,
            (_, _, Ordering::Less, _) => Relation::Before,
            (Ordering::Less, _, Ordering::Equal, Ordering::Less) => Relation::Meets,
            (_, _, Ordering::Equal, _) => Relation::Overlaps,
            (Ordering::Greater, Ordering::Equal, _, Ordering::Greater) => Relation::MetBy,
            (_, Ordering::Equal, _, _) => Relation::OverlappedBy,
            (_, Ordering::Greater, _, _) => Relation::After,
            (Ordering::Less, _, _, Ordering::Less) => Relation::Overlaps,
            (Ordering::Less, _, _, Ordering::Equal) => Relation::FinishedBy,
            (Ordering::Less, _, _, Ordering::Greater) => Relation::Contains,
            (Ordering::Equal, _, _, Ordering::Less) => Relation::Starts,
            (Ordering::Equal, _, _, Ordering::Greater) => Relation::StartedBy,
            (Ordering::Greater, _, _, Ordering::Less) => Relation::During,
            (Ordering::Greater, _, _, Ordering::Equal) => Relation::Finishes,
            (Ordering::Greater, _, _, Ordering::Greater) => Relation::OverlappedBy,
        }
    }
    pub fn is_empty(&self) -> bool {
        self.lesser.cmp(&self.greater) == Ordering::Equal
    }
    pub fn is_non_empty(&self) -> bool {
        !self.is_empty()
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Relation {
    Before,
    Meets,
    Overlaps,
    FinishedBy,
    Contains,
    Starts,
    Equal,
    StartedBy,
    During,
    Finishes,
    OverlappedBy,
    MetBy,
    After,
}

impl Relation {
    pub fn invert(&self) -> Self {
        match self {
            Self::After => Self::Before,
            Self::Before => Self::After,
            Self::Contains => Self::During,
            Self::During => Self::Contains,
            Self::Equal => Self::Equal,
            Self::FinishedBy => Self::Finishes,
            Self::Finishes => Self::FinishedBy,
            Self::Meets => Self::MetBy,
            Self::MetBy => Self::Meets,
            Self::OverlappedBy => Self::Overlaps,
            Self::Overlaps => Self::OverlappedBy,
            Self::StartedBy => Self::Starts,
            Self::Starts => Self::StartedBy,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{Interval, Relation};

    #[test]
    fn test_interval_new() {
        let interval = Interval::new(1, 2);
        assert_eq!(interval.lesser, 1);
        assert_eq!(interval.greater, 2);
    }

    #[test]
    fn test_relate() {
        let y = Interval::new(4, 8);
        assert_eq!(Relation::Before, Interval::new(1, 3).relate(&y));
        assert_eq!(Relation::Meets, Interval::new(2, 4).relate(&y));
        assert_eq!(Relation::Overlaps, Interval::new(3, 5).relate(&y));
        assert_eq!(Relation::FinishedBy, Interval::new(3, 8).relate(&y));
        assert_eq!(Relation::Contains, Interval::new(3, 9).relate(&y));
        assert_eq!(Relation::Starts, Interval::new(4, 6).relate(&y));
        assert_eq!(Relation::Equal, Interval::new(4, 8).relate(&y));
        assert_eq!(Relation::StartedBy, Interval::new(4, 9).relate(&y));
        assert_eq!(Relation::During, Interval::new(5, 7).relate(&y));
        assert_eq!(Relation::Finishes, Interval::new(6, 8).relate(&y));
        assert_eq!(Relation::OverlappedBy, Interval::new(7, 9).relate(&y));
        assert_eq!(Relation::MetBy, Interval::new(8, 10).relate(&y));
        assert_eq!(Relation::After, Interval::new(9, 11).relate(&y));
    }

    #[test]
    fn test_is_empty() {
        assert_eq!(Interval::new(1, 1).is_empty(), true);
        assert_eq!(Interval::new(1, 2).is_empty(), false);
    }

    #[test]
    fn test_is_non_empty() {
        assert_eq!(Interval::new(1, 1).is_non_empty(), false);
        assert_eq!(Interval::new(1, 2).is_non_empty(), true);
    }

    #[test]
    fn test_invert() {
        assert_eq!(Relation::Before, Relation::After.invert());
        assert_eq!(Relation::After, Relation::Before.invert());
        assert_eq!(Relation::During, Relation::Contains.invert());
        assert_eq!(Relation::Contains, Relation::During.invert());
        assert_eq!(Relation::Equal, Relation::Equal.invert());
        assert_eq!(Relation::Finishes, Relation::FinishedBy.invert());
        assert_eq!(Relation::FinishedBy, Relation::Finishes.invert());
        assert_eq!(Relation::MetBy, Relation::Meets.invert());
        assert_eq!(Relation::Meets, Relation::MetBy.invert());
        assert_eq!(Relation::Overlaps, Relation::OverlappedBy.invert());
        assert_eq!(Relation::OverlappedBy, Relation::Overlaps.invert());
        assert_eq!(Relation::Starts, Relation::StartedBy.invert());
        assert_eq!(Relation::StartedBy, Relation::Starts.invert());
    }
}