From 06904cfb0c477fc1dc3831cdacf4f7addb338a1b Mon Sep 17 00:00:00 2001 From: ripytide Date: Wed, 5 Apr 2023 13:45:10 +0100 Subject: [PATCH] implemented gaps --- src/range_bounds_map.rs | 79 +++++++++++++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 19 deletions(-) diff --git a/src/range_bounds_map.rs b/src/range_bounds_map.rs index d8cfaaa..ecec1e1 100644 --- a/src/range_bounds_map.rs +++ b/src/range_bounds_map.rs @@ -32,7 +32,9 @@ use serde::ser::SerializeMap; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use crate::bound_ord::BoundOrd; -use crate::helpers::{cmp_range_with_bound_ord, cut_range, overlaps}; +use crate::helpers::{ + cmp_range_with_bound_ord, cut_range, flip_bound, is_valid_range, overlaps, +}; use crate::TryFromBounds; /// An ordered map of non-overlapping [`RangeBounds`] based on [`BTreeMap`]. @@ -789,15 +791,55 @@ where /// ] /// ); /// ``` - //pub fn gaps<'a, Q>( - //&'a self, - //outer_range_bounds: Q, - //) -> impl Iterator, Bound)> + '_ - //where - //Q: 'a + RangeBounds + Clone, - //I: Clone, - //{ - //} + pub fn gaps<'a, Q>( + &'a self, + outer_range: Q, + ) -> impl Iterator, Bound)> + '_ + where + Q: NiceRange + 'a, + { + // I'm in love with how clean/mindblowing this entire function is + let overlapping = self + .overlapping(outer_range) + .map(|(key, _)| (key.start(), key.end())); + + // If the start or end point of outer_range_bounds is not + // contained within a RangeBounds in the map then we need to + // generate a artificial RangeBounds to use instead. + // + // We also have to flip the artificial ones ahead of time as + // we actually want the range_bounds endpoints included + // not excluded unlike with other bounds in artificials + + let artificial_start = ( + flip_bound(outer_range.start()), + flip_bound(outer_range.start()), + ); + let artificial_end = + (flip_bound(outer_range.end()), flip_bound(outer_range.end())); + let mut artificials = once(artificial_start) + .chain(overlapping) + .chain(once(artificial_end)); + + let start_contained = + self.inner.contains_key(comp_start(outer_range.start())); + let end_contained = + self.inner.contains_key(comp_end(outer_range.end())); + + if start_contained { + artificials.next(); + } + if end_contained { + artificials.next_back(); + } + + return artificials + .tuple_windows() + .map(|((_, first_end), (second_start, _))| { + (flip_bound(first_end), flip_bound(second_start)) + }) + .filter(|range| is_valid_range(*range)); + } /// Returns `true` if the map covers every point in the given /// `RangeBounds`, and `false` if it doesn't. @@ -824,14 +866,13 @@ where /// assert_eq!(map.contains_range_bounds(&(2..6)), false); /// assert_eq!(map.contains_range_bounds(&(6..50)), true); /// ``` - //pub fn contains_range_bounds(&self, range_bounds: Q) -> bool - //where - //Q: RangeBounds + Clone, - //I: Clone, - //{ - //// Soooo clean and mathematical 🥰! - //self.gaps(range_bounds).next().is_none() - //} + pub fn contains_range_bounds(&self, range_bounds: Q) -> bool + where + Q: NiceRange, + { + // Soooo clean and mathematical 🥰! + self.gaps(range_bounds).next().is_none() + } /// Adds a new (`RangeBounds`, `Value`) entry to the map without /// modifying other entries. @@ -866,7 +907,7 @@ where return Err(OverlapError); } - self.inner.insert(range, value, double_comp()); + self.insert_unchecked(range, value); return Ok(()); }