diff --git a/Cargo.lock b/Cargo.lock index cb83bf0..2e32590 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -36,7 +36,7 @@ checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] name = "discrete_range_map" -version = "0.4.2" +version = "0.4.3" dependencies = [ "btree_monstrousity", "either", diff --git a/src/discrete_range_map.rs b/src/discrete_range_map.rs index 68f0ca2..89a7ff2 100644 --- a/src/discrete_range_map.rs +++ b/src/discrete_range_map.rs @@ -21,6 +21,7 @@ use std::cmp::Ordering; use std::fmt::{self, Debug}; use std::iter::once; use std::marker::PhantomData; +use std::ops::RangeBounds; use btree_monstrousity::btree_map::{ IntoIter as BTreeMapIntoIter, SearchBoundCustom, @@ -33,7 +34,7 @@ use serde::ser::SerializeSeq; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use crate::discrete_finite::DiscreteFinite; -use crate::interval::Interval; +use crate::interval::InclusiveInterval; use crate::utils::{cmp_point_with_range, cut_range, is_valid_range, overlaps}; /// An ordered map of non-overlapping ranges based on [`BTreeMap`]. @@ -90,7 +91,7 @@ pub struct OverlapError; impl DiscreteRangeMap where I: Ord + Copy + DiscreteFinite, - K: FiniteRange + Copy + From>, + K: InclusiveRange + Copy + From>, { /// Returns `true` if the given range overlaps any of the /// other ranges in the map, and `false` if not. @@ -118,7 +119,7 @@ where /// ``` pub fn overlaps(&self, range: Q) -> bool where - Q: FiniteRange + Copy, + Q: InclusiveRange + Copy, { invalid_range_panic(range); @@ -158,7 +159,7 @@ where range: Q, ) -> impl DoubleEndedIterator where - Q: FiniteRange + Copy, + Q: InclusiveRange + Copy, { invalid_range_panic(range); @@ -206,7 +207,7 @@ where range: Q, ) -> impl DoubleEndedIterator where - Q: FiniteRange + Copy, + Q: InclusiveRange + Copy, { invalid_range_panic(range); @@ -315,7 +316,7 @@ where .get_key_value(overlapping_comp(point)) .ok_or_else(|| K::from(self.get_gap_at_raw(point))) } - fn get_gap_at_raw(&self, point: I) -> Interval { + fn get_gap_at_raw(&self, point: I) -> InclusiveInterval { let lower = self .inner .upper_bound(overlapping_comp(point), SearchBoundCustom::Included); @@ -323,7 +324,7 @@ where .inner .lower_bound(overlapping_comp(point), SearchBoundCustom::Included); - Interval { + InclusiveInterval { start: lower .key() .map_or(I::MIN, |lower| lower.end().up().unwrap()), @@ -371,7 +372,7 @@ where range: Q, ) -> impl Iterator + '_ where - Q: FiniteRange + Copy + 'a, + Q: InclusiveRange + Copy + 'a, { invalid_range_panic(range); @@ -435,7 +436,7 @@ where range: Q, ) -> impl Iterator + '_ where - Q: FiniteRange + Copy + 'a, + Q: InclusiveRange + Copy + 'a, V: Clone, { invalid_range_panic(range); @@ -466,7 +467,7 @@ where single_overlapping_range: K, ) -> impl Iterator where - Q: FiniteRange + Copy, + Q: InclusiveRange + Copy, V: Clone, { invalid_range_panic(range); @@ -494,7 +495,7 @@ where right_overlapping: Option, ) -> impl Iterator + '_ where - Q: FiniteRange + Copy + 'a, + Q: InclusiveRange + Copy + 'a, V: Clone, { invalid_range_panic(range); @@ -547,7 +548,7 @@ where .into_iter() .chain(self.remove_overlapping(range).map(|(key, value)| { ( - K::from(Interval { + K::from(InclusiveInterval { start: key.start(), end: key.end(), }), @@ -587,7 +588,7 @@ where /// ``` pub fn gaps<'a, Q>(&'a self, outer_range: Q) -> impl Iterator + '_ where - Q: FiniteRange + Copy + 'a, + Q: InclusiveRange + Copy + 'a, { invalid_range_panic(outer_range); @@ -636,7 +637,7 @@ where let inner_gaps = overlapping .tuple_windows() .map(|(first, second)| { - K::from(Interval { + K::from(InclusiveInterval { start: first.1.up().unwrap(), end: second.0.down().unwrap(), }) @@ -678,7 +679,7 @@ where /// ``` pub fn contains_range(&self, range: Q) -> bool where - Q: FiniteRange + Copy, + Q: InclusiveRange + Copy, { invalid_range_panic(range); @@ -749,15 +750,17 @@ where let matching_end = get_end(self, &value); let returning = match (matching_start, matching_end) { - (Some(matching_start), Some(matching_end)) => K::from(Interval { - start: matching_start.start(), - end: matching_end.end(), - }), - (Some(matching_start), None) => K::from(Interval { + (Some(matching_start), Some(matching_end)) => { + K::from(InclusiveInterval { + start: matching_start.start(), + end: matching_end.end(), + }) + } + (Some(matching_start), None) => K::from(InclusiveInterval { start: matching_start.start(), end: range.end(), }), - (None, Some(matching_end)) => K::from(Interval { + (None, Some(matching_end)) => K::from(InclusiveInterval { start: range.start(), end: matching_end.end(), }), @@ -1210,9 +1213,9 @@ impl DiscreteRangeMap { /// /// # Examples /// ``` - /// use discrete_range_map::{DiscreteRangeMap, Interval}; + /// use discrete_range_map::{DiscreteRangeMap, InclusiveInterval}; /// - /// let map: DiscreteRangeMap, bool> = + /// let map: DiscreteRangeMap, bool> = /// DiscreteRangeMap::new(); /// ``` pub fn new() -> Self { @@ -1359,7 +1362,7 @@ impl DiscreteRangeMap { fn invalid_range_panic(range: Q) where - Q: FiniteRange, + Q: InclusiveRange, I: Ord, { if !is_valid_range(range) { @@ -1371,7 +1374,7 @@ where fn double_comp() -> impl FnMut(&K, &K) -> Ordering where - K: FiniteRange, + K: InclusiveRange, I: Ord + DiscreteFinite, { |inner_range: &K, new_range: &K| new_range.start().cmp(&inner_range.start()) @@ -1379,14 +1382,14 @@ where fn overlapping_comp(point: I) -> impl FnMut(&K) -> Ordering where I: Ord + Copy, - K: FiniteRange + Copy, + K: InclusiveRange + Copy, { move |inner_range: &K| cmp_point_with_range(point, *inner_range) } fn touching_start_comp(start: I) -> impl FnMut(&K) -> Ordering where I: Ord + Copy + DiscreteFinite, - K: FiniteRange, + K: InclusiveRange, { move |inner_range: &K| match inner_range.end().up() { Some(touching_position) => start.cmp(&touching_position), @@ -1396,7 +1399,7 @@ where fn touching_end_comp(end: I) -> impl FnMut(&K) -> Ordering where I: Ord + Copy + DiscreteFinite, - K: FiniteRange, + K: InclusiveRange, { move |inner_range: &K| match inner_range.start().down() { Some(touching_position) => end.cmp(&touching_position), @@ -1404,10 +1407,37 @@ where } } -/// A range that has Finite **Inclusive** end-points. -pub trait FiniteRange { +/// A range that has **Inclusive** end-points. +pub trait InclusiveRange: RangeBounds { fn start(&self) -> I; fn end(&self) -> I; + + ///requires that self comes before other and they don't overlap + fn touches_ordered(&self, other: &Self) -> bool + where + I: DiscreteFinite + Ord, + { + self.end() == other.start().down().unwrap() + } + + ///requires that self comes before other + fn overlaps_ordered(&self, other: &Self) -> bool + where + I: DiscreteFinite + Ord, + { + self.contains(&other.start()) || self.contains(&other.end()) + } + + ///requires that self comes before other + fn merge_ordered(&self, other: &Self) -> Self + where + Self: From>, + { + Self::from(InclusiveInterval { + start: self.start(), + end: other.end(), + }) + } } // Trait Impls ========================== @@ -1470,7 +1500,7 @@ where impl<'de, I, K, V> Deserialize<'de> for DiscreteRangeMap where I: Ord + Copy + DiscreteFinite, - K: FiniteRange + Copy + From> + Deserialize<'de>, + K: InclusiveRange + Copy + From> + Deserialize<'de>, V: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result @@ -1494,7 +1524,7 @@ struct DiscreteRangeMapVisitor { impl<'de, I, K, V> Visitor<'de> for DiscreteRangeMapVisitor where I: Ord + Copy + DiscreteFinite, - K: FiniteRange + Copy + From> + Deserialize<'de>, + K: InclusiveRange + Copy + From> + Deserialize<'de>, V: Deserialize<'de>, { type Value = DiscreteRangeMap; @@ -1531,7 +1561,7 @@ mod tests { pub(crate) const NUMBERS_DOMAIN: &'static [i8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; - fn basic() -> DiscreteRangeMap, bool> { + fn basic() -> DiscreteRangeMap, bool> { DiscreteRangeMap::from_slice_strict([ (ui(4), false), (ee(5, 7), true), @@ -1540,7 +1570,7 @@ mod tests { ]) .unwrap() } - fn basic_slice() -> [(Interval, bool); 4] { + fn basic_slice() -> [(InclusiveInterval, bool); 4] { [ (ui(4), false), (ee(5, 7), true), @@ -1583,10 +1613,10 @@ mod tests { ); } fn assert_insert_strict( - mut before: DiscreteRangeMap, bool>, - to_insert: (Interval, bool), + mut before: DiscreteRangeMap, bool>, + to_insert: (InclusiveInterval, bool), result: Result<(), OverlapError>, - after: [(Interval, bool); N], + after: [(InclusiveInterval, bool); N], ) { assert_eq!(before.insert_strict(to_insert.0, to_insert.1), result); assert_eq!(before, DiscreteRangeMap::from_slice_strict(after).unwrap()) @@ -1598,7 +1628,7 @@ mod tests { for overlap_range in all_valid_test_bounds() { //you can't overlap nothing assert!( - DiscreteRangeMap::, ()>::new() + DiscreteRangeMap::, ()>::new() .overlapping(overlap_range) .next() .is_none() @@ -1702,10 +1732,10 @@ mod tests { ); } fn assert_remove_overlapping( - mut before: DiscreteRangeMap, bool>, - to_remove: Interval, - result: [(Interval, bool); N], - after: [(Interval, bool); Y], + mut before: DiscreteRangeMap, bool>, + to_remove: InclusiveInterval, + result: [(InclusiveInterval, bool); N], + after: [(InclusiveInterval, bool); Y], ) { assert_eq!( before.remove_overlapping(to_remove).collect::>(), @@ -1752,10 +1782,10 @@ mod tests { ); } fn assert_cut( - mut before: DiscreteRangeMap, bool>, - to_cut: Interval, - result: [(Interval, bool); Y], - after: [(Interval, bool); N], + mut before: DiscreteRangeMap, bool>, + to_cut: InclusiveInterval, + result: [(InclusiveInterval, bool); Y], + after: [(InclusiveInterval, bool); N], ) { assert_eq!(before.cut(to_cut).collect::>(), result); assert_eq!(before, DiscreteRangeMap::from_slice_strict(after).unwrap()); @@ -1791,9 +1821,9 @@ mod tests { ); } fn assert_gaps( - map: DiscreteRangeMap, bool>, - outer_range: Interval, - result: [Interval; N], + map: DiscreteRangeMap, bool>, + outer_range: InclusiveInterval, + result: [InclusiveInterval; N], ) { assert_eq!(map.gaps(outer_range).collect::>(), result); } @@ -1841,10 +1871,10 @@ mod tests { ); } fn assert_insert_merge_touching( - mut before: DiscreteRangeMap, bool>, - to_insert: (Interval, bool), - result: Result, OverlapError>, - after: [(Interval, bool); N], + mut before: DiscreteRangeMap, bool>, + to_insert: (InclusiveInterval, bool), + result: Result, OverlapError>, + after: [(InclusiveInterval, bool); N], ) { assert_eq!( before.insert_merge_touching(to_insert.0, to_insert.1), @@ -1897,10 +1927,10 @@ mod tests { ); } fn assert_insert_merge_touching_if_values_equal( - mut before: DiscreteRangeMap, bool>, - to_insert: (Interval, bool), - result: Result, OverlapError>, - after: [(Interval, bool); N], + mut before: DiscreteRangeMap, bool>, + to_insert: (InclusiveInterval, bool), + result: Result, OverlapError>, + after: [(InclusiveInterval, bool); N], ) { assert_eq!( before.insert_merge_touching_if_values_equal( @@ -1961,10 +1991,10 @@ mod tests { ); } fn assert_insert_merge_overlapping( - mut before: DiscreteRangeMap, bool>, - to_insert: (Interval, bool), - result: Interval, - after: [(Interval, bool); N], + mut before: DiscreteRangeMap, bool>, + to_insert: (InclusiveInterval, bool), + result: InclusiveInterval, + after: [(InclusiveInterval, bool); N], ) { assert_eq!( before.insert_merge_overlapping(to_insert.0, to_insert.1), @@ -2037,10 +2067,10 @@ mod tests { ); } fn assert_insert_merge_touching_or_overlapping( - mut before: DiscreteRangeMap, bool>, - to_insert: (Interval, bool), - result: Interval, - after: [(Interval, bool); N], + mut before: DiscreteRangeMap, bool>, + to_insert: (InclusiveInterval, bool), + result: InclusiveInterval, + after: [(InclusiveInterval, bool); N], ) { assert_eq!( before @@ -2138,7 +2168,7 @@ mod tests { } } } - fn con(x: Option>, point: &i8) -> bool { + fn con(x: Option>, point: &i8) -> bool { match x { Some(y) => contains_point(y, *point), None => false, @@ -2172,7 +2202,7 @@ mod tests { // Test Helper Functions //====================== fn all_non_overlapping_test_bound_entries() - -> Vec<(Interval, Interval)> { + -> Vec<(InclusiveInterval, InclusiveInterval)> { let mut output = Vec::new(); for test_bounds1 in all_valid_test_bounds() { for test_bounds2 in all_valid_test_bounds() { @@ -2185,12 +2215,12 @@ mod tests { return output; } - fn all_valid_test_bounds() -> Vec> { + fn all_valid_test_bounds() -> Vec> { let mut output = Vec::new(); for i in NUMBERS { for j in NUMBERS { if i <= j { - output.push(Interval { start: *i, end: *j }); + output.push(InclusiveInterval { start: *i, end: *j }); } } } diff --git a/src/discrete_range_set.rs b/src/discrete_range_set.rs index a8f0b50..3fb6c94 100644 --- a/src/discrete_range_set.rs +++ b/src/discrete_range_set.rs @@ -7,9 +7,9 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; use crate::discrete_finite::DiscreteFinite; use crate::discrete_range_map::{ - FiniteRange, IntoIter as DiscreteRangeMapIntoIter, + InclusiveRange, IntoIter as DiscreteRangeMapIntoIter, }; -use crate::interval::Interval; +use crate::interval::InclusiveInterval; use crate::{DiscreteRangeMap, OverlapError}; /// An ordered set of non-overlapping ranges based on [`DiscreteRangeMap`]. @@ -31,12 +31,12 @@ pub struct DiscreteRangeSet { impl DiscreteRangeSet where I: Ord + Copy + DiscreteFinite, - K: FiniteRange + Copy + From>, + K: InclusiveRange + Copy + From>, { /// See [`DiscreteRangeMap::overlaps()`] for more details. pub fn overlaps(&self, range: Q) -> bool where - Q: FiniteRange + Copy, + Q: InclusiveRange + Copy, { self.inner.overlaps(range) } @@ -46,7 +46,7 @@ where range: Q, ) -> impl DoubleEndedIterator where - Q: FiniteRange + Copy, + Q: InclusiveRange + Copy, { self.inner.overlapping(range).map(first) } @@ -64,28 +64,28 @@ where range: Q, ) -> impl Iterator + '_ where - Q: FiniteRange + Copy + 'a, + Q: InclusiveRange + Copy + 'a, { self.inner.remove_overlapping(range).map(first) } /// See [`DiscreteRangeMap::cut()`] for more details. pub fn cut<'a, Q>(&'a mut self, range: Q) -> impl Iterator + '_ where - Q: FiniteRange + Copy + 'a, + Q: InclusiveRange + Copy + 'a, { self.inner.cut(range).map(first) } /// See [`DiscreteRangeMap::gaps()`] for more details. pub fn gaps<'a, Q>(&'a self, range: Q) -> impl Iterator + '_ where - Q: FiniteRange + Copy + 'a, + Q: InclusiveRange + Copy + 'a, { self.inner.gaps(range) } /// See [`DiscreteRangeMap::contains_range()`] for more details. pub fn contains_range(&self, range: Q) -> bool where - Q: FiniteRange + Copy, + Q: InclusiveRange + Copy, { self.inner.contains_range(range) } @@ -218,7 +218,7 @@ where impl<'de, I, K> Deserialize<'de> for DiscreteRangeSet where I: Ord + Copy + DiscreteFinite, - K: FiniteRange + Copy + From> + Deserialize<'de>, + K: InclusiveRange + Copy + From> + Deserialize<'de>, { fn deserialize(deserializer: D) -> Result where @@ -239,7 +239,7 @@ struct DiscreteRangeSetVisitor { impl<'de, I, K> Visitor<'de> for DiscreteRangeSetVisitor where I: Ord + Copy + DiscreteFinite, - K: FiniteRange + Copy + From> + Deserialize<'de>, + K: InclusiveRange + Copy + From> + Deserialize<'de>, { type Value = DiscreteRangeSet; diff --git a/src/interval.rs b/src/interval.rs index 6b91bbf..289bcea 100644 --- a/src/interval.rs +++ b/src/interval.rs @@ -17,44 +17,35 @@ You should have received a copy of the GNU Affero General Public License along with discrete_range_map. If not, see . */ -use crate::discrete_range_map::FiniteRange; +use std::ops::{Bound, RangeBounds}; + +use serde::{Deserialize, Serialize}; + +use crate::discrete_range_map::InclusiveRange; use crate::DiscreteFinite; -///both ends are always included -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct Interval { +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct InclusiveInterval { pub start: I, pub end: I, } -impl Interval +impl InclusiveInterval where I: Ord + DiscreteFinite + Copy {} + +impl RangeBounds for InclusiveInterval where - I: Ord + DiscreteFinite + Copy, + I: Copy, { - pub fn contains(&self, point: I) -> bool { - point >= self.start && point <= self.end + fn start_bound(&self) -> Bound<&I> { + Bound::Included(&self.start) } - ///requires that self comes before other and they don't overlap - pub fn touches_ordered(&self, other: &Self) -> bool { - self.end == other.start.down().unwrap() - } - - ///requires that self comes before other - pub fn overlaps_ordered(&self, other: &Self) -> bool { - self.contains(other.start) || self.contains(other.end) - } - - ///requires that self comes before other - pub fn merge_ordered(self, other: &Self) -> Self { - Interval { - start: self.start, - end: other.end, - } + fn end_bound(&self) -> Bound<&I> { + Bound::Included(&self.end) } } -impl FiniteRange for Interval +impl InclusiveRange for InclusiveInterval where I: Copy, { diff --git a/src/lib.rs b/src/lib.rs index 4c735f7..4abf85d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,21 +46,40 @@ along with discrete_range_map. If not, see . //! ## Example using a custom range type //! //! ```rust +//! use std::ops::{Bound, RangeBounds}; //! use discrete_range_map::test_ranges::ie; //! use discrete_range_map::{ -//! DiscreteFinite, DiscreteRangeMap, FiniteRange, Interval, +//! DiscreteFinite, DiscreteRangeMap, InclusiveInterval, +//! InclusiveRange, //! }; //! //! #[derive(Debug, Copy, Clone)] //! enum Reservation { -//! // Start, End (Inclusive-Exclusive) +//! // Start, End (Inclusive-Inclusive) //! Finite(i8, i8), -//! // Start (Inclusive-Forever) +//! // Start (Inclusive-Infinity) //! Infinite(i8), //! } //! -//! // First, we need to implement FiniteRange -//! impl FiniteRange for Reservation { +//! // First, we need to implement RangeBounds since its a super-trait +//! // of InclusiveRange +//! impl RangeBounds for Reservation { +//! fn start_bound(&self) -> Bound<&i8> { +//! match self { +//! Reservation::Finite(start, _) => Bound::Included(start), +//! Reservation::Infinite(start) => Bound::Included(start), +//! } +//! } +//! fn end_bound(&self) -> Bound<&i8> { +//! match self { +//! Reservation::Finite(_, end) => Bound::Included(end), +//! Reservation::Infinite(_) => Bound::Included(&i8::MAX), +//! } +//! } +//! } +//! +//! // First, we need to implement InclusiveRange +//! impl InclusiveRange for Reservation { //! fn start(&self) -> i8 { //! match self { //! Reservation::Finite(start, _) => *start, @@ -69,23 +88,21 @@ along with discrete_range_map. If not, see . //! } //! fn end(&self) -> i8 { //! match self { -//! //the end is exclusive so we take off 1 with checking -//! //for compile time error overflow detection -//! Reservation::Finite(_, end) => end.down().unwrap(), +//! Reservation::Finite(_, end) => *end, //! Reservation::Infinite(_) => i8::MAX, //! } //! } //! } //! -//! // Second, we need to implement From> -//! impl From> for Reservation { -//! fn from(bounds: Interval) -> Self { -//! if bounds.end == i8::MAX { -//! Reservation::Infinite(bounds.start) +//! // Second, we need to implement From> +//! impl From> for Reservation { +//! fn from(value: InclusiveInterval) -> Self { +//! if value.end == i8::MAX { +//! Reservation::Infinite(value.start) //! } else { //! Reservation::Finite( -//! bounds.start, -//! bounds.end.up().unwrap(), +//! value.start, +//! value.end.up().unwrap(), //! ) //! } //! } @@ -94,7 +111,7 @@ along with discrete_range_map. If not, see . //! // Next we can create a custom typed DiscreteRangeMap //! let reservation_map = DiscreteRangeMap::from_slice_strict([ //! (Reservation::Finite(10, 20), "Ferris".to_string()), -//! (Reservation::Infinite(20), "Corro".to_string()), +//! (Reservation::Infinite(21), "Corro".to_string()), //! ]) //! .unwrap(); //! @@ -277,7 +294,7 @@ pub mod discrete_range_set; pub use crate::discrete_finite::DiscreteFinite; pub use crate::discrete_range_map::{ - DiscreteRangeMap, FiniteRange, OverlapError, + DiscreteRangeMap, InclusiveRange, OverlapError, }; pub use crate::discrete_range_set::DiscreteRangeSet; -pub use crate::interval::Interval; +pub use crate::interval::InclusiveInterval; diff --git a/src/test_ranges.rs b/src/test_ranges.rs index 3a85ee6..57ffef2 100644 --- a/src/test_ranges.rs +++ b/src/test_ranges.rs @@ -1,26 +1,26 @@ use crate::discrete_finite::DiscreteFinite; -use crate::interval::Interval; +use crate::interval::InclusiveInterval; -pub fn uu() -> Interval { - Interval { +pub fn uu() -> InclusiveInterval { + InclusiveInterval { start: i8::MIN, end: i8::MAX, } } -pub fn ui(x: i8) -> Interval { - Interval { +pub fn ui(x: i8) -> InclusiveInterval { + InclusiveInterval { start: i8::MIN, end: x, } } -pub fn ue(x: i8) -> Interval { - Interval { +pub fn ue(x: i8) -> InclusiveInterval { + InclusiveInterval { start: i8::MIN, end: x.down().unwrap(), } } -pub fn iu(x: i8) -> Interval { - Interval { +pub fn iu(x: i8) -> InclusiveInterval { + InclusiveInterval { start: x, end: i8::MAX, } @@ -28,23 +28,23 @@ pub fn iu(x: i8) -> Interval { //fn eu(x: i8) -> TestBounds { //(Bound::Excluded(x), Bound::Unbounded) //} -pub fn ii(x1: i8, x2: i8) -> Interval { - Interval { start: x1, end: x2 } +pub fn ii(x1: i8, x2: i8) -> InclusiveInterval { + InclusiveInterval { start: x1, end: x2 } } -pub fn ie(x1: i8, x2: i8) -> Interval { - Interval { +pub fn ie(x1: i8, x2: i8) -> InclusiveInterval { + InclusiveInterval { start: x1, end: x2.down().unwrap(), } } -pub fn ei(x1: i8, x2: i8) -> Interval { - Interval { +pub fn ei(x1: i8, x2: i8) -> InclusiveInterval { + InclusiveInterval { start: x1.up().unwrap(), end: x2, } } -pub fn ee(x1: i8, x2: i8) -> Interval { - Interval { +pub fn ee(x1: i8, x2: i8) -> InclusiveInterval { + InclusiveInterval { start: x1.up().unwrap(), end: x2.down().unwrap(), } diff --git a/src/utils.rs b/src/utils.rs index b1d8f6e..d7eb2e2 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -20,13 +20,13 @@ along with discrete_range_map. If not, see . use std::cmp::Ordering; use crate::discrete_finite::DiscreteFinite; -use crate::discrete_range_map::FiniteRange; -use crate::interval::Interval; +use crate::discrete_range_map::InclusiveRange; +use crate::interval::InclusiveInterval; pub(crate) fn cmp_point_with_range(point: I, range: K) -> Ordering where I: Ord, - K: FiniteRange, + K: InclusiveRange, { if point < range.start() { Ordering::Less @@ -49,8 +49,8 @@ pub(crate) enum Config { } pub(crate) fn config(a: A, b: B) -> Config where - A: FiniteRange + Copy, - B: FiniteRange + Copy, + A: InclusiveRange + Copy, + B: InclusiveRange + Copy, I: Ord, { if a.start() < b.start() { @@ -71,21 +71,21 @@ where } enum SortedConfig { - NonOverlapping(Interval, Interval), - PartialOverlap(Interval, Interval), - Swallowed(Interval, Interval), + NonOverlapping(InclusiveInterval, InclusiveInterval), + PartialOverlap(InclusiveInterval, InclusiveInterval), + Swallowed(InclusiveInterval, InclusiveInterval), } fn sorted_config(a: A, b: B) -> SortedConfig where - A: FiniteRange + Copy, - B: FiniteRange + Copy, + A: InclusiveRange + Copy, + B: InclusiveRange + Copy, I: Ord, { - let ae = Interval { + let ae = InclusiveInterval { start: a.start(), end: a.end(), }; - let be = Interval { + let be = InclusiveInterval { start: b.start(), end: b.end(), }; @@ -106,7 +106,7 @@ where pub(crate) fn contains_point(range: A, point: I) -> bool where - A: FiniteRange, + A: InclusiveRange, I: Ord, { cmp_point_with_range(point, range).is_eq() @@ -114,14 +114,14 @@ where #[derive(Debug)] pub(crate) struct CutResult { - pub(crate) before_cut: Option>, - pub(crate) inside_cut: Option>, - pub(crate) after_cut: Option>, + pub(crate) before_cut: Option>, + pub(crate) inside_cut: Option>, + pub(crate) after_cut: Option>, } pub(crate) fn cut_range(base: B, cut: C) -> CutResult where - B: FiniteRange + Copy, - C: FiniteRange + Copy, + B: InclusiveRange + Copy, + C: InclusiveRange + Copy, I: Ord + Copy + DiscreteFinite, { let mut result = CutResult { @@ -132,34 +132,34 @@ where match config(base, cut) { Config::LeftFirstNonOverlapping => { - result.before_cut = Some(Interval { + result.before_cut = Some(InclusiveInterval { start: base.start(), end: base.end(), }); } Config::LeftFirstPartialOverlap => { - result.before_cut = Some(Interval { + result.before_cut = Some(InclusiveInterval { start: base.start(), end: cut.start().down().unwrap(), }); - result.inside_cut = Some(Interval { + result.inside_cut = Some(InclusiveInterval { start: cut.start(), end: base.end(), }); } Config::LeftContainsRight => { - result.before_cut = Some(Interval { + result.before_cut = Some(InclusiveInterval { start: base.start(), end: cut.start().down().unwrap(), }); - result.inside_cut = Some(Interval { + result.inside_cut = Some(InclusiveInterval { start: cut.start(), end: cut.end(), }); //if cut is already max then we don't need to have an //after_cut if let Some(upped_end) = cut.end().up() { - result.after_cut = Some(Interval { + result.after_cut = Some(InclusiveInterval { start: upped_end, end: base.end(), }); @@ -167,23 +167,23 @@ where } Config::RightFirstNonOverlapping => { - result.after_cut = Some(Interval { + result.after_cut = Some(InclusiveInterval { start: base.start(), end: base.end(), }); } Config::RightFirstPartialOverlap => { - result.after_cut = Some(Interval { + result.after_cut = Some(InclusiveInterval { start: cut.end().up().unwrap(), end: base.end(), }); - result.inside_cut = Some(Interval { + result.inside_cut = Some(InclusiveInterval { start: base.start(), end: cut.end(), }); } Config::RightContainsLeft => { - result.inside_cut = Some(Interval { + result.inside_cut = Some(InclusiveInterval { start: base.start(), end: base.end(), }); @@ -201,15 +201,15 @@ where pub(crate) fn is_valid_range(range: K) -> bool where I: Ord, - K: FiniteRange, + K: InclusiveRange, { range.start() <= range.end() } pub(crate) fn overlaps(a: A, b: B) -> bool where - A: FiniteRange + Copy, - B: FiniteRange + Copy, + A: InclusiveRange + Copy, + B: InclusiveRange + Copy, I: Ord, { !matches!(sorted_config(a, b), SortedConfig::NonOverlapping(_, _))