258 lines
6.3 KiB
Rust
258 lines
6.3 KiB
Rust
// 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<T> {
|
|
pub end_wrapper: RangeEndWrapper<T>,
|
|
}
|
|
|
|
impl<T> RangeStartWrapper<T> {
|
|
pub fn new(range: Range<T>) -> RangeStartWrapper<T> {
|
|
RangeStartWrapper {
|
|
end_wrapper: RangeEndWrapper::new(range),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T> PartialEq for RangeStartWrapper<T>
|
|
where
|
|
T: PartialEq,
|
|
{
|
|
fn eq(&self, other: &RangeStartWrapper<T>) -> bool {
|
|
self.start == other.start
|
|
}
|
|
}
|
|
|
|
impl<T> Eq for RangeStartWrapper<T> where T: Eq {}
|
|
|
|
impl<T> Ord for RangeStartWrapper<T>
|
|
where
|
|
T: Ord,
|
|
{
|
|
fn cmp(&self, other: &RangeStartWrapper<T>) -> Ordering {
|
|
self.start.cmp(&other.start)
|
|
}
|
|
}
|
|
|
|
impl<T> PartialOrd for RangeStartWrapper<T>
|
|
where
|
|
T: PartialOrd,
|
|
{
|
|
fn partial_cmp(&self, other: &RangeStartWrapper<T>) -> Option<Ordering> {
|
|
self.start.partial_cmp(&other.start)
|
|
}
|
|
}
|
|
|
|
impl<T> core::borrow::Borrow<RangeEndWrapper<T>> for RangeStartWrapper<T> {
|
|
fn borrow(&self) -> &RangeEndWrapper<T> {
|
|
&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<T> Deref for RangeStartWrapper<T> {
|
|
type Target = RangeEndWrapper<T>;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.end_wrapper
|
|
}
|
|
}
|
|
|
|
//
|
|
// Range end wrapper
|
|
//
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct RangeEndWrapper<T> {
|
|
pub range: Range<T>,
|
|
}
|
|
|
|
impl<T> RangeEndWrapper<T> {
|
|
pub fn new(range: Range<T>) -> RangeEndWrapper<T> {
|
|
RangeEndWrapper { range }
|
|
}
|
|
}
|
|
|
|
impl<T> PartialEq for RangeEndWrapper<T>
|
|
where
|
|
T: PartialEq,
|
|
{
|
|
fn eq(&self, other: &RangeEndWrapper<T>) -> bool {
|
|
self.end == other.end
|
|
}
|
|
}
|
|
|
|
impl<T> Eq for RangeEndWrapper<T> where T: Eq {}
|
|
|
|
impl<T> Ord for RangeEndWrapper<T>
|
|
where
|
|
T: Ord,
|
|
{
|
|
fn cmp(&self, other: &RangeEndWrapper<T>) -> Ordering {
|
|
self.end.cmp(&other.end)
|
|
}
|
|
}
|
|
|
|
impl<T> PartialOrd for RangeEndWrapper<T>
|
|
where
|
|
T: PartialOrd,
|
|
{
|
|
fn partial_cmp(&self, other: &RangeEndWrapper<T>) -> Option<Ordering> {
|
|
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<T> Deref for RangeEndWrapper<T> {
|
|
type Target = Range<T>;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.range
|
|
}
|
|
}
|
|
|
|
//
|
|
// RangeInclusive start wrapper
|
|
//
|
|
|
|
#[derive(Eq, Debug, Clone)]
|
|
pub struct RangeInclusiveStartWrapper<T> {
|
|
pub end_wrapper: RangeInclusiveEndWrapper<T>,
|
|
}
|
|
|
|
impl<T> RangeInclusiveStartWrapper<T> {
|
|
pub fn new(range: RangeInclusive<T>) -> RangeInclusiveStartWrapper<T> {
|
|
RangeInclusiveStartWrapper {
|
|
end_wrapper: RangeInclusiveEndWrapper::new(range),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T> PartialEq for RangeInclusiveStartWrapper<T>
|
|
where
|
|
T: PartialEq,
|
|
{
|
|
fn eq(&self, other: &RangeInclusiveStartWrapper<T>) -> bool {
|
|
self.start() == other.start()
|
|
}
|
|
}
|
|
|
|
impl<T> Ord for RangeInclusiveStartWrapper<T>
|
|
where
|
|
T: Ord,
|
|
{
|
|
fn cmp(&self, other: &RangeInclusiveStartWrapper<T>) -> Ordering {
|
|
self.start().cmp(other.start())
|
|
}
|
|
}
|
|
|
|
impl<T> PartialOrd for RangeInclusiveStartWrapper<T>
|
|
where
|
|
T: PartialOrd,
|
|
{
|
|
fn partial_cmp(&self, other: &RangeInclusiveStartWrapper<T>) -> Option<Ordering> {
|
|
self.start().partial_cmp(other.start())
|
|
}
|
|
}
|
|
|
|
impl<T> core::borrow::Borrow<RangeInclusiveEndWrapper<T>> for RangeInclusiveStartWrapper<T> {
|
|
fn borrow(&self) -> &RangeInclusiveEndWrapper<T> {
|
|
&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<T> Deref for RangeInclusiveStartWrapper<T> {
|
|
type Target = RangeInclusiveEndWrapper<T>;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.end_wrapper
|
|
}
|
|
}
|
|
|
|
//
|
|
// RangeInclusive end wrapper
|
|
//
|
|
|
|
#[derive(Eq, Debug, Clone)]
|
|
pub struct RangeInclusiveEndWrapper<T> {
|
|
pub range: RangeInclusive<T>,
|
|
}
|
|
|
|
impl<T> RangeInclusiveEndWrapper<T> {
|
|
pub fn new(range: RangeInclusive<T>) -> RangeInclusiveEndWrapper<T> {
|
|
RangeInclusiveEndWrapper { range }
|
|
}
|
|
}
|
|
|
|
impl<T> PartialEq for RangeInclusiveEndWrapper<T>
|
|
where
|
|
T: PartialEq,
|
|
{
|
|
fn eq(&self, other: &RangeInclusiveEndWrapper<T>) -> bool {
|
|
self.end() == other.end()
|
|
}
|
|
}
|
|
|
|
impl<T> Ord for RangeInclusiveEndWrapper<T>
|
|
where
|
|
T: Ord,
|
|
{
|
|
fn cmp(&self, other: &RangeInclusiveEndWrapper<T>) -> Ordering {
|
|
self.end().cmp(other.end())
|
|
}
|
|
}
|
|
|
|
impl<T> PartialOrd for RangeInclusiveEndWrapper<T>
|
|
where
|
|
T: PartialOrd,
|
|
{
|
|
fn partial_cmp(&self, other: &RangeInclusiveEndWrapper<T>) -> Option<Ordering> {
|
|
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<T> Deref for RangeInclusiveEndWrapper<T> {
|
|
type Target = RangeInclusive<T>;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.range
|
|
}
|
|
}
|