diff --git a/src/discrete_bounds.rs b/src/discrete_bounds.rs index 4e372cc..6a3d910 100644 --- a/src/discrete_bounds.rs +++ b/src/discrete_bounds.rs @@ -22,13 +22,13 @@ use std::ops::{Bound, RangeBounds}; use crate::bound_ord::DiscreteBoundOrd; use crate::stepable::Stepable; -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct DiscreteBounds { start: DiscreteBound, end: DiscreteBound, } -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum DiscreteBound { Included(I), Unbounded, diff --git a/src/lib.rs b/src/lib.rs index da1fe59..f64a048 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -230,6 +230,7 @@ pub(crate) mod utils; pub mod stepable; pub mod discrete_bounds; +pub mod try_from_discrete_bounds; pub mod range_bounds_map; pub mod range_bounds_set; diff --git a/src/range_bounds_map.rs b/src/range_bounds_map.rs index 7a25fdf..a0f4ef4 100644 --- a/src/range_bounds_map.rs +++ b/src/range_bounds_map.rs @@ -21,7 +21,7 @@ use std::cmp::Ordering; use std::fmt::{self, Debug}; use std::iter::once; use std::marker::PhantomData; -use std::ops::{Bound, RangeBounds}; +use std::ops::RangeBounds; use btree_monstrousity::btree_map::{IntoIter as BTreeMapIntoIter, SearchBoundCustom}; use btree_monstrousity::BTreeMap; @@ -33,9 +33,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; use crate::bound_ord::DiscreteBoundOrd; use crate::discrete_bounds::{DiscreteBound, DiscreteBounds}; use crate::stepable::Stepable; -use crate::utils::{ - cmp_range_with_discrete_bound_ord, cut_range, is_valid_range, overlaps, -}; +use crate::utils::{cmp_range_with_discrete_bound_ord, cut_range, is_valid_range, overlaps}; /// An ordered map of non-overlapping ranges based on [`BTreeMap`]. /// @@ -739,7 +737,7 @@ where where Q: DiscreteRange + Copy + 'a, K: TryFrom>, - TryFromBoundsError: From, + TryFromBoundsError: From, V: Clone, { invalid_range_panic(range); @@ -770,9 +768,9 @@ where single_overlapping_range: K, ) -> Result, V)>, TryFromBoundsError> where - Q: DiscreteRange + Copy, + Q: DiscreteRange + Copy, K: TryFrom>, - TryFromBoundsError: From, + TryFromBoundsError: From, V: Clone, { invalid_range_panic(range); @@ -787,10 +785,7 @@ where None => None, }; - let value = self - .inner - .remove(overlapping_comp(range.start())) - .unwrap(); + let value = self.inner.remove(overlapping_comp(range.start())).unwrap(); if let Some(before) = returning_before_cut { self.insert_unchecked(before, value.clone()); @@ -810,7 +805,7 @@ where where Q: DiscreteRange + Copy + 'a, K: TryFrom>, - TryFromBoundsError: From, + TryFromBoundsError: From, V: Clone, { invalid_range_panic(range); @@ -864,10 +859,15 @@ where return Ok(keeping_before_entry .into_iter() - .chain( - self.remove_overlapping(range) - .map(|(key, value)| ((DiscreteBounds::from(key)), value)), - ) + .chain(self.remove_overlapping(range).map(|(key, value)| { + ( + (DiscreteBounds { + start: key.start().into(), + end: key.end().into(), + }), + value, + ) + })) .chain(keeping_after_entry.into_iter())); } @@ -908,7 +908,7 @@ where /// ] /// ); /// ``` - pub fn gaps(&self, outer_range: Q) -> impl DoubleEndedIterator, Bound)> + pub fn gaps(&self, outer_range: Q) -> impl DoubleEndedIterator> where Q: DiscreteRange + Copy, { @@ -927,21 +927,17 @@ where // we actually want the range 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())); + //todo check if stepable first before adding artificials + let artificial_start = (outer_range.start(), outer_range.start().down_if_finite()); + let artificial_end = (outer_range.end().up_if_finite(), outer_range.start()); let mut artificials = once(artificial_start) .chain(overlapping) .chain(once(artificial_end)); let start_contained = self .inner - .contains_key(overlapping_start_comp(outer_range.start())); - let end_contained = self - .inner - .contains_key(overlapping_end_comp(outer_range.end())); + .contains_key(overlapping_comp(outer_range.start())); + let end_contained = self.inner.contains_key(overlapping_comp(outer_range.end())); if start_contained { artificials.next(); @@ -956,7 +952,10 @@ where //find one at the time of writing .collect::>() .windows(2) - .map(|windows| (flip_bound(windows[0].1), flip_bound(windows[1].0))) + .map(|windows| DiscreteBounds { + start: windows[0].1.up_if_finite().into(), + end: windows[1].0.down_if_finite().into(), + }) .filter(|range| is_valid_range(*range)) //optimisation this would also then be unneccessary .collect::>() @@ -990,7 +989,7 @@ where /// ``` pub fn contains_range(&self, range: Q) -> bool where - Q: DiscreteRange, + Q: DiscreteRange + Copy, { invalid_range_panic(range); @@ -1047,7 +1046,7 @@ where ) -> Result where K: TryFrom>, - TryFromBoundsError: From, + TryFromBoundsError: From, G1: FnOnce(&Self, &V) -> Option, G2: FnOnce(&Self, &V) -> Option, R1: FnOnce(&mut Self, &V), @@ -1059,13 +1058,18 @@ where let matching_end = get_end(self, &value); let returning = match (matching_start, matching_end) { - (Some(matching_start), Some(matching_end)) => { - K::try_from_bounds(matching_start.start(), matching_end.end())? - } - (Some(matching_start), None) => { - K::try_from_bounds(matching_start.start(), range.end())? - } - (None, Some(matching_end)) => K::try_from_bounds(range.start(), matching_end.end())?, + (Some(matching_start), Some(matching_end)) => K::try_from(DiscreteBounds { + start: matching_start.start().into(), + end: matching_end.end().into(), + })?, + (Some(matching_start), None) => K::try_from(DiscreteBounds { + start: matching_start.start().into(), + end: range.end().into(), + })?, + (None, Some(matching_end)) => K::try_from(DiscreteBounds { + start: range.start().into(), + end: matching_end.end().into(), + })?, (None, None) => range, }; @@ -1146,7 +1150,7 @@ where ) -> Result where K: TryFrom>, - TryFromBoundsError: From, + TryFromBoundsError: From, { invalid_range_panic(range); @@ -1246,7 +1250,7 @@ where ) -> Result where K: TryFrom>, - TryFromBoundsError: From, + TryFromBoundsError: From, V: Eq, { invalid_range_panic(range); @@ -1349,7 +1353,7 @@ where pub fn insert_merge_overlapping(&mut self, range: K, value: V) -> Result where K: TryFrom>, - TryFromBoundsError: From, + TryFromBoundsError: From, { invalid_range_panic(range); @@ -1359,14 +1363,14 @@ where |selfy, _| { selfy .inner - .get_key_value(overlapping_start_comp(range.start())) + .get_key_value(overlapping_comp(range.start())) .map(|(key, _)| key) .copied() }, |selfy, _| { selfy .inner - .get_key_value(overlapping_end_comp(range.end())) + .get_key_value(overlapping_comp(range.end())) .map(|(key, _)| key) .copied() }, @@ -1437,7 +1441,7 @@ where ) -> Result where K: TryFrom>, - TryFromBoundsError: From, + TryFromBoundsError: From, { invalid_range_panic(range); @@ -1451,7 +1455,7 @@ where .map(|(key, _)| key) .or(selfy .inner - .get_key_value(overlapping_start_comp(range.start())) + .get_key_value(overlapping_comp(range.start())) .map(|(key, _)| key)) .copied() }, @@ -1462,7 +1466,7 @@ where .map(|(key, _)| key) .or(selfy .inner - .get_key_value(overlapping_end_comp(range.end())) + .get_key_value(overlapping_comp(range.end())) .map(|(key, _)| key)) .copied() }, @@ -1511,7 +1515,7 @@ where pub fn insert_overwrite(&mut self, range: K, value: V) -> Result<(), TryFromBoundsError> where K: TryFrom>, - TryFromBoundsError: From, + TryFromBoundsError: From, V: Clone, { invalid_range_panic(range); @@ -1743,8 +1747,8 @@ impl Default for RangeBoundsMap { impl Serialize for RangeBoundsMap where - I: Ord + Copy, - K: DiscreteRange + Serialize, + I: Ord + Copy + Stepable, + K: DiscreteRange + Copy + Serialize, V: Serialize, { fn serialize(&self, serializer: S) -> Result @@ -1761,8 +1765,8 @@ where impl<'de, I, K, V> Deserialize<'de> for RangeBoundsMap where - I: Ord + Copy, - K: DiscreteRange + Deserialize<'de>, + I: Ord + Copy + Stepable, + K: DiscreteRange + Copy + Deserialize<'de>, V: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result @@ -1785,8 +1789,8 @@ struct RangeBoundsMapVisitor { impl<'de, I, K, V> Visitor<'de> for RangeBoundsMapVisitor where - I: Ord + Copy, - K: DiscreteRange + Deserialize<'de>, + I: Ord + Copy + Stepable, + K: DiscreteRange + Copy + Deserialize<'de>, V: Deserialize<'de>, { type Value = RangeBoundsMap; @@ -1815,8 +1819,7 @@ mod tests { use pretty_assertions::assert_eq; use super::*; - use crate::bound_ord::DiscreteBoundOrd; - use crate::test_ranges::{ee, ei, ie, ii, iu, u, ue, ui, uu, AnyRange}; + use crate::test_ranges::{ee, ei, ie, ii, iu, u, ue, ui, uu}; use crate::utils::{config, Config, CutResult}; //only every other number to allow mathematical_overlapping_definition @@ -1825,7 +1828,7 @@ mod tests { //go a bit around on either side to compensate for Unbounded pub(crate) const NUMBERS_DOMAIN: &'static [i8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; - fn basic() -> RangeBoundsMap { + fn basic() -> RangeBoundsMap, bool> { RangeBoundsMap::from_slice_strict([ (ui(4), false), (ee(5, 7), true), @@ -1913,10 +1916,10 @@ mod tests { ); } fn assert_insert_strict( - mut before: RangeBoundsMap, - to_insert: (AnyRange, bool), + mut before: RangeBoundsMap, bool>, + to_insert: (DiscreteBounds, bool), result: Result<(), OverlapError>, - after: Option<[(AnyRange, bool); N]>, + after: Option<[(DiscreteBounds, bool); N]>, ) { let clone = before.clone(); assert_eq!(before.insert_strict(to_insert.0, to_insert.1), result); @@ -1933,7 +1936,7 @@ mod tests { //case zero for overlap_range in all_valid_test_bounds() { //you can't overlap nothing - assert!(RangeBoundsMap::::new() + assert!(RangeBoundsMap::, ()>::new() .overlapping(overlap_range) .next() .is_none()); @@ -1980,9 +1983,7 @@ mod tests { } //make our expected_overlapping the correct order if expected_overlapping.len() > 1 { - if DiscreteBoundOrd::start(expected_overlapping[0].start()) - > DiscreteBoundOrd::start(expected_overlapping[1].start()) - { + if expected_overlapping[0].start() > expected_overlapping[1].start() { expected_overlapping.swap(0, 1); } } @@ -2030,10 +2031,10 @@ mod tests { ); } fn assert_remove_overlapping( - mut before: RangeBoundsMap, - to_remove: AnyRange, - result: [(AnyRange, bool); N], - after: Option<[(AnyRange, bool); Y]>, + mut before: RangeBoundsMap, bool>, + to_remove: DiscreteBounds, + result: [(DiscreteBounds, bool); N], + after: Option<[(DiscreteBounds, bool); Y]>, ) { let clone = before.clone(); assert_eq!( @@ -2122,13 +2123,13 @@ mod tests { fn assert_cut( mut before: RangeBoundsMap, to_cut: Q, - result: Result<[((Bound, Bound), V); Y], TryFromBoundsError>, + result: Result<[(DiscreteBounds, V); Y], TryFromBoundsError>, after: Option<[(K, V); N]>, ) where - I: Ord + Debug + Copy, - K: DiscreteRange + TryFrom> + PartialEq + Debug, - TryFromBoundsError: From, - Q: DiscreteRange, + I: Ord + Debug + Copy + Stepable, + K: DiscreteRange + TryFrom> + PartialEq + Debug + Copy, + TryFromBoundsError: From, + Q: DiscreteRange + Copy, V: PartialEq + Debug + Clone, { let clone = before.clone(); @@ -2269,9 +2270,9 @@ mod tests { result: Result, after: Option<[(K, V); N]>, ) where - I: Ord + Debug + Copy, - K: DiscreteRange + TryFrom> + PartialEq + Debug, - TryFromBoundsError: From, + I: Ord + Debug + Copy + Stepable, + K: DiscreteRange + TryFrom> + PartialEq + Debug + Copy, + TryFromBoundsError: From, V: PartialEq + Debug + Clone, { let clone = before.clone(); @@ -2390,9 +2391,9 @@ mod tests { result: Result, after: Option<[(K, V); N]>, ) where - I: Ord + Debug + Copy, - K: DiscreteRange + TryFrom> + PartialEq + Debug, - TryFromBoundsError: From, + I: Ord + Debug + Copy + Stepable, + K: DiscreteRange + TryFrom> + PartialEq + Debug + Copy, + TryFromBoundsError: From, V: Eq + Debug + Clone, { let clone = before.clone(); @@ -2488,9 +2489,9 @@ mod tests { result: Result, after: Option<[(K, V); N]>, ) where - I: Ord + Debug + Copy, - K: DiscreteRange + TryFrom> + PartialEq + Debug, - TryFromBoundsError: From, + I: Ord + Debug + Copy + Stepable, + K: DiscreteRange + TryFrom> + PartialEq + Debug + Copy, + TryFromBoundsError: From, V: PartialEq + Debug + Clone, { let clone = before.clone(); @@ -2620,9 +2621,9 @@ mod tests { result: Result, after: Option<[(K, V); N]>, ) where - I: Ord + Debug + Copy, + I: Ord + Debug + Copy + Stepable, K: DiscreteRange + TryFrom> + PartialEq + Debug, - TryFromBoundsError: From, + TryFromBoundsError: From, V: PartialEq + Debug + Clone, { let clone = before.clone(); diff --git a/src/test_ranges.rs b/src/test_ranges.rs index 6867092..9e6a951 100644 --- a/src/test_ranges.rs +++ b/src/test_ranges.rs @@ -1,59 +1,60 @@ -use std::ops::{Bound, RangeBounds}; +use std::ops::Bound; -use crate::{TryFromBoundsError}; +use crate::discrete_bounds::{DiscreteBound, DiscreteBounds}; +use crate::stepable::Stepable; -pub type AnyRange = (Bound, Bound); - -pub fn uu() -> AnyRange { - (Bound::Unbounded, Bound::Unbounded) +pub fn uu() -> DiscreteBounds { + DiscreteBounds { + start: DiscreteBound::Unbounded, + end: DiscreteBound::Unbounded, + } } -pub fn ui(x: i8) -> AnyRange { - (Bound::Unbounded, Bound::Included(x)) +pub fn ui(x: i8) -> DiscreteBounds { + DiscreteBounds { + start: DiscreteBound::Unbounded, + end: DiscreteBound::Included(x), + } } -pub fn ue(x: i8) -> AnyRange { - (Bound::Unbounded, Bound::Excluded(x)) +pub fn ue(x: i8) -> DiscreteBounds { + DiscreteBounds { + start: DiscreteBound::Unbounded, + end: DiscreteBound::Included(x.down().unwrap()), + } } -pub fn iu(x: i8) -> AnyRange { - (Bound::Included(x), Bound::Unbounded) +pub fn iu(x: i8) -> DiscreteBounds { + DiscreteBounds { + start: DiscreteBound::Included(x), + end: DiscreteBound::Unbounded, + } } //fn eu(x: i8) -> TestBounds { //(Bound::Excluded(x), Bound::Unbounded) //} -pub fn ii(x1: i8, x2: i8) -> AnyRange { - (Bound::Included(x1), Bound::Included(x2)) +pub fn ii(x1: i8, x2: i8) -> DiscreteBounds { + DiscreteBounds { + start: DiscreteBound::Included(x1), + end: DiscreteBound::Included(x2), + } } -pub fn ie(x1: i8, x2: i8) -> AnyRange { - (Bound::Included(x1), Bound::Excluded(x2)) +pub fn ie(x1: i8, x2: i8) -> DiscreteBounds { + DiscreteBounds { + start: DiscreteBound::Included(x1), + end: DiscreteBound::Included(x2.down().unwrap()), + } } -pub fn ei(x1: i8, x2: i8) -> AnyRange { - (Bound::Excluded(x1), Bound::Included(x2)) +pub fn ei(x1: i8, x2: i8) -> DiscreteBounds { + DiscreteBounds { + start: DiscreteBound::Included(x1.up().unwrap()), + end: DiscreteBound::Included(x2), + } } -pub fn ee(x1: i8, x2: i8) -> AnyRange { - (Bound::Excluded(x1), Bound::Excluded(x2)) +pub fn ee(x1: i8, x2: i8) -> DiscreteBounds { + DiscreteBounds { + start: DiscreteBound::Included(x1.up().unwrap()), + end: DiscreteBound::Included(x2.down().unwrap()), + } } pub fn u() -> Bound { Bound::Unbounded } - -/// a..b Inclusive-Exclusive range struct -/// since the builtin range isn't Copy for some reason -#[allow(dead_code)] -#[derive(Debug, Copy, Clone, PartialEq)] -pub struct InExRange { - start: i8, - end: i8, -} - -pub fn ie_strict(start: i8, end: i8) -> InExRange { - InExRange { start, end } -} - -impl RangeBounds for InExRange { - fn start_bound(&self) -> Bound<&i8> { - Bound::Included(&self.start) - } - fn end_bound(&self) -> Bound<&i8> { - Bound::Excluded(&self.end) - } -} diff --git a/src/try_from_discrete_bounds.rs b/src/try_from_discrete_bounds.rs new file mode 100644 index 0000000..100bd47 --- /dev/null +++ b/src/try_from_discrete_bounds.rs @@ -0,0 +1,10 @@ +use crate::discrete_bounds::DiscreteBound; + +pub trait TryFromDiscreteBounds { + fn try_from_discrete_bounds( + start: DiscreteBound, + end: DiscreteBound, + ) -> Result + where + Self: Sized; +}