diff --git a/src/helpers.rs b/src/helpers.rs index 2d8bbc7..b7fcfe2 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -23,6 +23,7 @@ use std::ops::{Bound, RangeBounds}; use labels::{tested, trivial}; use crate::bound_ord::BoundOrd; +use crate::{TryFromBounds, TryFromBoundsError}; pub(crate) fn cmp_range_bounds_with_bound_ord( range_bounds: &A, @@ -117,7 +118,10 @@ where } #[trivial] -pub(crate) fn contains_bound_ord(range_bounds: &A, bound_ord: BoundOrd<&I>) -> bool +pub(crate) fn contains_bound_ord( + range_bounds: &A, + bound_ord: BoundOrd<&I>, +) -> bool where A: RangeBounds, I: Ord, @@ -266,3 +270,54 @@ pub(crate) fn flip_bound(bound: Bound) -> Bound { Bound::Unbounded => Bound::Unbounded, } } + +//assumes the bound overlaps the range_bounds +pub(crate) fn split_off_right_section( + range_bounds: &&K, + with_bound: Bound, +) -> (Option>, (Bound, Bound)) +where + I: Clone + Ord, + K: RangeBounds + TryFromBounds, +{ + let (start_bound, end_bound) = + (range_bounds.start_bound(), range_bounds.end_bound()); + + let keeping_section = (with_bound, end_bound.cloned()); + + let returning_section = (start_bound.cloned(), flip_bound(with_bound)); + + if is_valid_range_bounds(&returning_section) { + return ( + Some(K::try_from_bounds(returning_section.0, returning_section.1)), + keeping_section, + ); + } else { + return (None, keeping_section); + } +} +//assumes the bound overlaps the range_bounds +pub(crate) fn split_off_left_section( + with_bound: Bound, + range_bounds: &K, +) -> (Option>, (Bound, Bound)) +where + I: Clone + Ord, + K: RangeBounds + TryFromBounds, +{ + let (start_bound, end_bound) = + (range_bounds.start_bound(), range_bounds.end_bound()); + + let keeping_section = (start_bound.cloned(), with_bound); + + let returning_section = (flip_bound(with_bound), end_bound.cloned()); + + if is_valid_range_bounds(&returning_section) { + return ( + Some(K::try_from_bounds(returning_section.0, returning_section.1)), + keeping_section, + ); + } else { + return (None, keeping_section); + } +} diff --git a/src/range_bounds_map.rs b/src/range_bounds_map.rs index 5761002..bbe684e 100644 --- a/src/range_bounds_map.rs +++ b/src/range_bounds_map.rs @@ -34,7 +34,8 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; use crate::bound_ord::BoundOrd; use crate::helpers::{ cmp_range_bounds_with_bound_ord, contains_bound_ord, cut_range_bounds, - flip_bound, is_valid_range_bounds, overlaps, touches, + flip_bound, is_valid_range_bounds, overlaps, split_off_right_section, + touches, }; use crate::TryFromBounds; @@ -627,29 +628,92 @@ where /// assert!(base.cut(&(60..=80)).is_err()); /// ``` #[tested] - pub fn cut<'a, Q>( - &'a mut self, + pub fn cut( + &mut self, range_bounds: Q, - ) -> Result + '_, TryFromBoundsError> + ) -> Result< + impl Iterator, Bound), V)>, + TryFromBoundsError, + > where - Q: 'a + RangeBounds, + Q: RangeBounds, I: Clone, K: TryFromBounds, V: Clone, { - // This is so clean and mathematically pleasing omg i'm in love with it - match range_bounds.start_bound() { - Bound::Included(point) => self.bisect_at_point(point, false)?, - Bound::Excluded(point) => self.bisect_at_point(point, true)?, - Bound::Unbounded => {} - } - match range_bounds.end_bound() { - Bound::Included(point) => self.bisect_at_point(point, true)?, - Bound::Excluded(point) => self.bisect_at_point(point, false)?, - Bound::Unbounded => {} + let left = self + .inner + .get_key_value(comp_start(range_bounds.start_bound())) + .map(|(key, _)| { + (key.start_bound().cloned(), key.end_bound().cloned()) + }); + let right = self + .inner + .get_key_value(comp_end(range_bounds.end_bound())) + .map(|(key, _)| { + (key.start_bound().cloned(), key.end_bound().cloned()) + }); + + let mut returning_left = None; + let mut keeping_left = None; + + let mut returning_right = None; + let mut keeping_right = None; + + if let Some(left) = left { + let (r_left, k_left) = split_off_right_section( + &&left, + range_bounds.start_bound().cloned(), + ); + + keeping_left = Some(k_left); + + if let Some(r_left) = r_left { + returning_left = Some(r_left?); + } } - return Ok(self.remove_overlapping(range_bounds)); + if let Some(right) = right { + let (r_right, k_right) = split_off_right_section( + &&right, + range_bounds.start_bound().cloned(), + ); + + keeping_right = Some(k_right); + + if let Some(r_right) = r_right { + returning_right = Some(r_right?); + } + } + + if let Some(l_value) = + self.inner.remove(comp_start(range_bounds.start_bound())) + { + self.insert_strict(returning_left.unwrap(), l_value); + } + if let Some(r_value) = + self.inner.remove(comp_end(range_bounds.end_bound())) + { + self.insert_strict(returning_right.unwrap(), r_value); + } + + if let Some((left, _)) = left && let Some((right, _)) = right { + if left.start_bound() == right.start_bound() { + let mega_cut = (keeping_left.unwrap().0.0,keeping_right.unwrap().0.1); + keeping_left = Some((mega_cut, keeping_left.unwrap().1)); + keeping_right = None; + } + } + + return Ok(keeping_left + .into_iter() + .chain(self.remove_overlapping(range_bounds).map(|(key, value)| { + ( + (key.start_bound().cloned(), key.end_bound().cloned()), + value, + ) + })) + .chain(keeping_right.into_iter())); } //does nothing if it hits a degenerate interval or if it would //leave invalid range_bounds within the structure @@ -968,10 +1032,10 @@ where range_bounds: K, value: V, ) -> Result<&K, OverlapOrTryFromBoundsError> { + todo!() } #[parent_tested] - fn touching_left(&self, range_bounds: &K) -> Option<&K> { - } + fn touching_left(&self, range_bounds: &K) -> Option<&K> {} #[parent_tested] fn touching_right(&self, range_bounds: &K) -> Option<&K> { todo!()