// Wrappers to allow storing (and sorting/searching) // ranges as the keys of a `BTreeMap`. // // This wraps the range in two layers: one that lets us // order ranges by their start (`RangeStartWrapper`), // and then within that, one that lets us order them by // their end (`RangeEndWrapper`). Ordinarily we'll use // the former, but there are a couple of cases where we // want to be able to do the latter for performance/convenience. // // This is made possible by a sneaky `Borrow` implementation // which skirts the law about the borrowed representation // having identical implementations of `Ord` etc., but shouldn't // be a problem in practice because users of the crate can't // access these special wrappers, and we are careful to uphold // invariants that prevent observing any states where the // differing implementations would produce different results. // // Specifically, we maintain the invariants // that the order of range starts is the same as the order // of range ends, and that no two stored ranges have the // same start or end as each other. // // NOTE: Be very careful not to accidentally use these // if you really do want to compare equality of the // inner range! use core::cmp::Ordering; use core::ops::{Deref, Range, RangeInclusive}; // // Range start wrapper // #[derive(Debug, Clone)] pub struct RangeStartWrapper { pub end_wrapper: RangeEndWrapper, } impl RangeStartWrapper { pub fn new(range: Range) -> RangeStartWrapper { RangeStartWrapper { end_wrapper: RangeEndWrapper::new(range), } } } impl PartialEq for RangeStartWrapper where T: PartialEq, { fn eq(&self, other: &RangeStartWrapper) -> bool { self.start == other.start } } impl Eq for RangeStartWrapper where T: Eq {} impl Ord for RangeStartWrapper where T: Ord, { fn cmp(&self, other: &RangeStartWrapper) -> Ordering { self.start.cmp(&other.start) } } impl PartialOrd for RangeStartWrapper where T: PartialOrd, { fn partial_cmp(&self, other: &RangeStartWrapper) -> Option { self.start.partial_cmp(&other.start) } } impl core::borrow::Borrow> for RangeStartWrapper { fn borrow(&self) -> &RangeEndWrapper { &self.end_wrapper } } // Avoid the need to tediously plumb through the layers of wrapper structs // when you're just trying to access members of the inner range itself. impl Deref for RangeStartWrapper { type Target = RangeEndWrapper; fn deref(&self) -> &Self::Target { &self.end_wrapper } } // // Range end wrapper // #[derive(Debug, Clone)] pub struct RangeEndWrapper { pub range: Range, } impl RangeEndWrapper { pub fn new(range: Range) -> RangeEndWrapper { RangeEndWrapper { range } } } impl PartialEq for RangeEndWrapper where T: PartialEq, { fn eq(&self, other: &RangeEndWrapper) -> bool { self.end == other.end } } impl Eq for RangeEndWrapper where T: Eq {} impl Ord for RangeEndWrapper where T: Ord, { fn cmp(&self, other: &RangeEndWrapper) -> Ordering { self.end.cmp(&other.end) } } impl PartialOrd for RangeEndWrapper where T: PartialOrd, { fn partial_cmp(&self, other: &RangeEndWrapper) -> Option { self.end.partial_cmp(&other.end) } } // Avoid the need to tediously plumb through the layers of wrapper structs // when you're just trying to access members of the inner range itself. impl Deref for RangeEndWrapper { type Target = Range; fn deref(&self) -> &Self::Target { &self.range } } // // RangeInclusive start wrapper // #[derive(Eq, Debug, Clone)] pub struct RangeInclusiveStartWrapper { pub end_wrapper: RangeInclusiveEndWrapper, } impl RangeInclusiveStartWrapper { pub fn new(range: RangeInclusive) -> RangeInclusiveStartWrapper { RangeInclusiveStartWrapper { end_wrapper: RangeInclusiveEndWrapper::new(range), } } } impl PartialEq for RangeInclusiveStartWrapper where T: PartialEq, { fn eq(&self, other: &RangeInclusiveStartWrapper) -> bool { self.start() == other.start() } } impl Ord for RangeInclusiveStartWrapper where T: Ord, { fn cmp(&self, other: &RangeInclusiveStartWrapper) -> Ordering { self.start().cmp(other.start()) } } impl PartialOrd for RangeInclusiveStartWrapper where T: PartialOrd, { fn partial_cmp(&self, other: &RangeInclusiveStartWrapper) -> Option { self.start().partial_cmp(other.start()) } } impl core::borrow::Borrow> for RangeInclusiveStartWrapper { fn borrow(&self) -> &RangeInclusiveEndWrapper { &self.end_wrapper } } // Avoid the need to tediously plumb through the layers of wrapper structs // when you're just trying to access members of the inner range itself. impl Deref for RangeInclusiveStartWrapper { type Target = RangeInclusiveEndWrapper; fn deref(&self) -> &Self::Target { &self.end_wrapper } } // // RangeInclusive end wrapper // #[derive(Eq, Debug, Clone)] pub struct RangeInclusiveEndWrapper { pub range: RangeInclusive, } impl RangeInclusiveEndWrapper { pub fn new(range: RangeInclusive) -> RangeInclusiveEndWrapper { RangeInclusiveEndWrapper { range } } } impl PartialEq for RangeInclusiveEndWrapper where T: PartialEq, { fn eq(&self, other: &RangeInclusiveEndWrapper) -> bool { self.end() == other.end() } } impl Ord for RangeInclusiveEndWrapper where T: Ord, { fn cmp(&self, other: &RangeInclusiveEndWrapper) -> Ordering { self.end().cmp(other.end()) } } impl PartialOrd for RangeInclusiveEndWrapper where T: PartialOrd, { fn partial_cmp(&self, other: &RangeInclusiveEndWrapper) -> Option { self.end().partial_cmp(other.end()) } } // Avoid the need to tediously plumb through the layers of wrapper structs // when you're just trying to access members of the inner range itself. impl Deref for RangeInclusiveEndWrapper { type Target = RangeInclusive; fn deref(&self) -> &Self::Target { &self.range } }