From 4b80374d39ddb30621c94ebdc30c4843a99a3dcd Mon Sep 17 00:00:00 2001 From: ripytide Date: Thu, 6 Apr 2023 14:09:06 +0100 Subject: [PATCH] fixed all doctests in map.rs and deleted set.rs since I'm gonna re-make it just pointing to map.rs --- src/bound_ord.rs | 14 +- src/lib.rs | 20 +- src/range_bounds_map.rs | 127 +++--- src/range_bounds_set.rs | 843 ---------------------------------------- src/test_ranges.rs | 72 +++- 5 files changed, 140 insertions(+), 936 deletions(-) diff --git a/src/bound_ord.rs b/src/bound_ord.rs index 5eb3bae..3cff1b8 100644 --- a/src/bound_ord.rs +++ b/src/bound_ord.rs @@ -196,13 +196,13 @@ mod tests { assert!(BoundOrd::StartExcluded(2) < BoundOrd::EndUnbounded); //StartUnbounded - assert!(BoundOrd::StartUnbounded:: == BoundOrd::StartUnbounded); - assert!(BoundOrd::StartUnbounded:: <= BoundOrd::StartUnbounded); - assert!(BoundOrd::StartUnbounded:: >= BoundOrd::StartUnbounded); + assert!(BoundOrd::StartUnbounded:: == BoundOrd::StartUnbounded); + assert!(BoundOrd::StartUnbounded:: <= BoundOrd::StartUnbounded); + assert!(BoundOrd::StartUnbounded:: >= BoundOrd::StartUnbounded); assert!(BoundOrd::StartUnbounded < BoundOrd::EndExcluded(2)); - assert!(BoundOrd::StartUnbounded:: < BoundOrd::EndUnbounded); + assert!(BoundOrd::StartUnbounded:: < BoundOrd::EndUnbounded); //EndExcluded assert!(BoundOrd::EndExcluded(2) == BoundOrd::EndExcluded(2)); @@ -212,8 +212,8 @@ mod tests { assert!(BoundOrd::EndExcluded(2) > BoundOrd::EndExcluded(0)); //EndUnbounded - assert!(BoundOrd::EndUnbounded:: == BoundOrd::EndUnbounded); - assert!(BoundOrd::EndUnbounded:: <= BoundOrd::EndUnbounded); - assert!(BoundOrd::EndUnbounded:: >= BoundOrd::EndUnbounded); + assert!(BoundOrd::EndUnbounded:: == BoundOrd::EndUnbounded); + assert!(BoundOrd::EndUnbounded:: <= BoundOrd::EndUnbounded); + assert!(BoundOrd::EndUnbounded:: >= BoundOrd::EndUnbounded); } } diff --git a/src/lib.rs b/src/lib.rs index d5ecc03..de3ea05 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,13 +29,14 @@ along with range_bounds_map. If not, see . //! //! ```rust //! use range_bounds_map::RangeBoundsMap; +//! use range_bounds_map::test_ranges::ie; //! //! let mut map = RangeBoundsMap::new(); //! -//! map.insert_strict(0..5, true); -//! map.insert_strict(5..10, false); +//! map.insert_strict(ie(0, 5), true); +//! map.insert_strict(ie(5, 10), false); //! -//! assert_eq!(map.overlaps(-2..12), true); +//! assert_eq!(map.overlaps(ie(-2, 12)), true); //! assert_eq!(map.contains_point(20), false); //! assert_eq!(map.contains_point(5), true); //! ``` @@ -46,18 +47,19 @@ along with range_bounds_map. If not, see . //! use std::ops::{Bound, RangeBounds}; //! //! use range_bounds_map::RangeBoundsMap; +//! use range_bounds_map::test_ranges::ie; //! //! #[derive(Debug, Copy, Clone)] //! enum Reservation { //! // Start, End (Inclusive-Inclusive) -//! Finite(u8, u8), +//! Finite(i8, i8), //! // Start (Exclusive) -//! Infinite(u8), +//! Infinite(i8), //! } //! //! // First, we need to implement RangeBounds -//! impl RangeBounds for Reservation { -//! fn start_bound(&self) -> Bound<&u8> { +//! impl RangeBounds for Reservation { +//! fn start_bound(&self) -> Bound<&i8> { //! match self { //! Reservation::Finite(start, _) => { //! Bound::Included(start) @@ -67,7 +69,7 @@ along with range_bounds_map. If not, see . //! } //! } //! } -//! fn end_bound(&self) -> Bound<&u8> { +//! fn end_bound(&self) -> Bound<&i8> { //! match self { //! Reservation::Finite(_, end) => Bound::Included(end), //! Reservation::Infinite(_) => Bound::Unbounded, @@ -82,7 +84,7 @@ along with range_bounds_map. If not, see . //! ]) //! .unwrap(); //! -//! for (reservation, name) in reservation_map.overlapping(16..17) +//! for (reservation, name) in reservation_map.overlapping(ie(16, 17)) //! { //! println!( //! "{name} has reserved {reservation:?} inside the range 16..17" diff --git a/src/range_bounds_map.rs b/src/range_bounds_map.rs index f2b7168..a6da8b8 100644 --- a/src/range_bounds_map.rs +++ b/src/range_bounds_map.rs @@ -109,7 +109,7 @@ use crate::TryFromBounds; /// } /// } /// -/// // Now we can make a [`RangeBoundsMap`] of [`ExEx`]s to `u8` +/// // Now we can make a [`RangeBoundsMap`] of [`ExEx`]s to `i8` /// let mut map = RangeBoundsMap::new(); /// /// map.insert_strict(ExEx::new(0.0, 5.0), 8).unwrap(); @@ -118,7 +118,10 @@ use crate::TryFromBounds; /// assert_eq!(map.contains_point(NotNan::new(5.0).unwrap()), false); /// /// assert_eq!(map.get_at_point(NotNan::new(9.0).unwrap()), None); -/// assert_eq!(map.get_at_point(NotNan::new(7.0).unwrap()), Some(32)); +/// assert_eq!( +/// map.get_at_point(NotNan::new(7.0).unwrap()), +/// Some(&32) +/// ); /// /// assert_eq!( /// map.get_entry_at_point(NotNan::new(2.0).unwrap()), @@ -161,11 +164,11 @@ pub struct OverlapError; /// return Err(TryFromBoundsError). /// /// ``` -/// use range_bounds_map::test_ranges::{ie, ii}; +/// use range_bounds_map::test_ranges::{ii, ran}; /// use range_bounds_map::{RangeBoundsMap, TryFromBoundsError}; /// /// let mut map = -/// RangeBoundsMap::from_slice_strict([(ie(2, 8), true)]) +/// RangeBoundsMap::from_slice_strict([(ran(2, 8), true)]) /// .unwrap(); /// /// assert!(map.cut(ii(4, 6)).is_err()); @@ -203,12 +206,12 @@ pub struct OverlapError; /// /// #[derive(Debug, Copy, Clone, PartialEq)] /// enum MultiBounds { -/// Inclusive(u8, u8), -/// Exclusive(u8, u8), +/// Inclusive(i8, i8), +/// Exclusive(i8, i8), /// } /// -/// impl RangeBounds for MultiBounds { -/// fn start_bound(&self) -> Bound<&u8> { +/// impl RangeBounds for MultiBounds { +/// fn start_bound(&self) -> Bound<&i8> { /// match self { /// MultiBounds::Inclusive(start, _) => { /// Bound::Included(start) @@ -218,7 +221,7 @@ pub struct OverlapError; /// } /// } /// } -/// fn end_bound(&self) -> Bound<&u8> { +/// fn end_bound(&self) -> Bound<&i8> { /// match self { /// MultiBounds::Inclusive(_, end) => { /// Bound::Included(end) @@ -230,10 +233,10 @@ pub struct OverlapError; /// } /// } /// -/// impl TryFromBounds for MultiBounds { +/// impl TryFromBounds for MultiBounds { /// fn try_from_bounds( -/// start_bound: Bound, -/// end_bound: Bound, +/// start_bound: Bound, +/// end_bound: Bound, /// ) -> Result { /// match (start_bound, end_bound) { /// (Bound::Included(start), Bound::Included(end)) => { @@ -288,7 +291,7 @@ where /// use range_bounds_map::test_ranges::TestBounds; /// use range_bounds_map::RangeBoundsMap; /// - /// let map: RangeBoundsMap = + /// let map: RangeBoundsMap = /// RangeBoundsMap::new(); /// ``` pub fn new() -> Self { @@ -402,6 +405,10 @@ where where Q: NiceRange, { + if !is_valid_range(range) { + panic!("Invalid RangeBounds!"); + } + let lower_comp = overlapping_start_comp(range.start()); let upper_comp = overlapping_end_comp(range.end()); @@ -524,7 +531,7 @@ where /// /// assert_eq!(iter.next(), Some((&ie(1, 4), &false))); /// assert_eq!(iter.next(), Some((&ie(4, 8), &true))); - /// assert_eq!(iter.next(), Some((&ie(8, 0), &false))); + /// assert_eq!(iter.next(), Some((&ie(8, 100), &false))); /// assert_eq!(iter.next(), None); /// ``` pub fn iter(&self) -> impl DoubleEndedIterator { @@ -606,24 +613,24 @@ where /// ``` /// use std::ops::Bound; /// - /// use range_bounds_map::test_ranges::{ie, ii}; + /// use range_bounds_map::test_ranges::{ie, ii, ran}; /// use range_bounds_map::{RangeBoundsMap, TryFromBoundsError}; /// /// let mut base = RangeBoundsMap::from_slice_strict([ - /// (ie(1, 4), false), - /// (ie(4, 8), true), - /// (ie(8, 100), false), + /// (ran(1, 4), false), + /// (ran(4, 8), true), + /// (ran(8, 100), false), /// ]) /// .unwrap(); /// /// let after_cut = RangeBoundsMap::from_slice_strict([ - /// (ie(1, 2), false), - /// (ie(40, 100), false), + /// (ran(1, 2), false), + /// (ran(40, 100), false), /// ]) /// .unwrap(); /// /// assert_eq!( - /// base.cut(ie(2, 0)).unwrap().collect::>(), + /// base.cut(ie(2, 40)).unwrap().collect::>(), /// [ /// ((Bound::Included(2), Bound::Excluded(4)), false), /// ((Bound::Included(4), Bound::Excluded(8)), true), @@ -797,7 +804,7 @@ where /// ``` /// use std::ops::Bound; /// - /// use range_bounds_map::test_ranges::ie; + /// use range_bounds_map::test_ranges::{ie, iu}; /// use range_bounds_map::RangeBoundsMap; /// /// let map = RangeBoundsMap::from_slice_strict([ @@ -807,7 +814,7 @@ where /// ]) /// .unwrap(); /// - /// let mut gaps = map.gaps(2..); + /// let mut gaps = map.gaps(iu(2)); /// /// assert_eq!( /// gaps.collect::>(), @@ -894,7 +901,7 @@ where /// /// assert_eq!(map.contains_range_bounds(ie(1, 3)), true); /// assert_eq!(map.contains_range_bounds(ie(2, 6)), false); - /// assert_eq!(map.contains_range_bounds(ie(6, 0)), true); + /// assert_eq!(map.contains_range_bounds(ie(6, 100)), true); /// ``` pub fn contains_range_bounds(&self, range_bounds: Q) -> bool where @@ -1038,12 +1045,12 @@ where /// // Neither Touching or Overlapping /// assert_eq!( /// map.insert_merge_touching(ie(10, 16), false), - /// Ok(ie(0, 6)) + /// Ok(ie(10, 16)) /// ); /// /// assert_eq!( /// map.iter().collect::>(), - /// [(&ie(1, 6), &true), (&ie(10, 6), &false)] + /// [(&ie(1, 6), &true), (&ie(10, 16), &false)] /// ); /// ``` pub fn insert_merge_touching( @@ -1128,7 +1135,7 @@ where /// // Neither Touching or Overlapping /// assert_eq!( /// map.insert_merge_overlapping(ie(10, 16), false), - /// Ok(ie(0, 6)) + /// Ok(ie(10, 16)) /// ); /// /// assert_eq!( @@ -1136,7 +1143,7 @@ where /// [ /// (&ie(-4, 1), &true), /// (&ie(1, 8), &true), - /// (&ie(0, 6), &false) + /// (&ie(10, 16), &false) /// ] /// ); /// ``` @@ -1144,7 +1151,10 @@ where &mut self, range: K, value: V, - ) -> Result where K: TryFromBounds{ + ) -> Result + where + K: TryFromBounds, + { self.insert_merge_with_comps( range, value, @@ -1210,19 +1220,22 @@ where /// // Neither Touching or Overlapping /// assert_eq!( /// map.insert_merge_touching_or_overlapping(ie(10, 16), false), - /// Ok(ie(0, 6)) + /// Ok(ie(10, 16)) /// ); /// /// assert_eq!( /// map.iter().collect::>(), - /// [(&ie(-4, 8), &true), (&ie(0, 6), &false)] + /// [(&ie(-4, 8), &true), (&ie(10, 16), &false)] /// ); /// ``` pub fn insert_merge_touching_or_overlapping( &mut self, range: K, value: V, - ) -> Result where K: TryFromBounds{ + ) -> Result + where + K: TryFromBounds, + { self.insert_merge_with_comps( range, value, @@ -1300,7 +1313,7 @@ where value: V, ) -> Result<(), TryFromBoundsError> where - K: TryFromBounds, + K: TryFromBounds, V: Clone, { let _ = self.cut(range)?; @@ -1347,7 +1360,7 @@ where /// /// assert_eq!( /// map.last_entry(), - /// Some((&ie(8, 0), &false)) + /// Some((&ie(8, 100), &false)) /// ); pub fn last_entry(&self) -> Option<(&K, &V)> { self.inner.last_key_value() @@ -1479,12 +1492,12 @@ mod tests { //only every other number to allow mathematical_overlapping_definition //to test between bounds in finite using smaller intervalled finite - pub(crate) const NUMBERS: &'static [u8] = &[2, 4, 6, 8, 10]; + pub(crate) const NUMBERS: &'static [i8] = &[2, 4, 6, 8, 10]; //go a bit around on either side to compensate for Unbounded - pub(crate) const NUMBERS_DOMAIN: &'static [u8] = + 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 { RangeBoundsMap::from_slice_strict([ (ui(4), false), (ee(5, 7), true), @@ -1494,7 +1507,7 @@ mod tests { .unwrap() } - fn special() -> RangeBoundsMap { + fn special() -> RangeBoundsMap { RangeBoundsMap::from_slice_strict([ (mii(4, 6), false), (mee(7, 8), true), @@ -1505,35 +1518,35 @@ mod tests { #[derive(Debug, PartialEq, Copy, Clone)] enum MultiBounds { - Inclusive(u8, u8), - Exclusive(u8, u8), + Inclusive(i8, i8), + Exclusive(i8, i8), } - fn mii(start: u8, end: u8) -> MultiBounds { + fn mii(start: i8, end: i8) -> MultiBounds { MultiBounds::Inclusive(start, end) } - fn mee(start: u8, end: u8) -> MultiBounds { + fn mee(start: i8, end: i8) -> MultiBounds { MultiBounds::Exclusive(start, end) } - impl RangeBounds for MultiBounds { - fn start_bound(&self) -> Bound<&u8> { + impl RangeBounds for MultiBounds { + fn start_bound(&self) -> Bound<&i8> { match self { MultiBounds::Inclusive(start, _) => Bound::Included(start), MultiBounds::Exclusive(start, _) => Bound::Excluded(start), } } - fn end_bound(&self) -> Bound<&u8> { + fn end_bound(&self) -> Bound<&i8> { match self { MultiBounds::Inclusive(_, end) => Bound::Included(end), MultiBounds::Exclusive(_, end) => Bound::Excluded(end), } } } - impl TryFromBounds for MultiBounds { + impl TryFromBounds for MultiBounds { fn try_from_bounds( - start_bound: Bound, - end_bound: Bound, + start_bound: Bound, + end_bound: Bound, ) -> Result { match (start_bound, end_bound) { (Bound::Included(start), Bound::Included(end)) => { @@ -1593,7 +1606,7 @@ mod tests { ); } fn assert_insert_strict( - mut before: RangeBoundsMap, + mut before: RangeBoundsMap, to_insert: (TestBounds, bool), result: Result<(), OverlapError>, after: Option<[(TestBounds, bool); N]>, @@ -1617,7 +1630,7 @@ mod tests { for overlap_range in all_valid_test_bounds() { //you can't overlap nothing assert!( - RangeBoundsMap::::new() + RangeBoundsMap::::new() .overlapping(overlap_range) .next() .is_none() @@ -1721,7 +1734,7 @@ mod tests { ); } fn assert_remove_overlapping( - mut before: RangeBoundsMap, + mut before: RangeBoundsMap, to_remove: TestBounds, result: [(TestBounds, bool); N], after: Option<[(TestBounds, bool); Y]>, @@ -1858,7 +1871,7 @@ mod tests { assert_gaps(basic(), ii(8, 8), [ii(8, 8)]); } fn assert_gaps( - map: RangeBoundsMap, + map: RangeBoundsMap, outer_range_bounds: TestBounds, result: [TestBounds; N], ) { @@ -2313,7 +2326,7 @@ mod tests { } } } - fn con(x: Option<(Bound, Bound)>, point: &u8) -> bool { + fn con(x: Option<(Bound, Bound)>, point: &i8) -> bool { match x { Some(y) => y.contains(point), None => false, @@ -2321,7 +2334,7 @@ mod tests { } #[test] fn cut_range_bounds_should_return_valid_ranges() { - let result: CutResult = cut_range(ie(3, 8), ie(5, 8)); + let result: CutResult = cut_range(ie(3, 8), ie(5, 8)); if let Some(x) = result.before_cut { assert!(is_valid_range(x)); } @@ -2403,7 +2416,7 @@ mod tests { return output; } - fn all_finite_bounded_entries() -> Vec<(Bound, Bound)> { + fn all_finite_bounded_entries() -> Vec<(Bound, Bound)> { let mut output = Vec::new(); for i in NUMBERS { for j in NUMBERS { @@ -2422,7 +2435,7 @@ mod tests { return output; } - fn all_finite_bounded() -> Vec> { + fn all_finite_bounded() -> Vec> { let mut output = Vec::new(); for i in NUMBERS { for j in 0..=1 { @@ -2432,7 +2445,7 @@ mod tests { return output; } - fn finite_bound(x: u8, included: bool) -> Bound { + fn finite_bound(x: i8, included: bool) -> Bound { match included { false => Bound::Included(x), true => Bound::Excluded(x), diff --git a/src/range_bounds_set.rs b/src/range_bounds_set.rs index 04ee8fb..9d1f2f9 100644 --- a/src/range_bounds_set.rs +++ b/src/range_bounds_set.rs @@ -1,846 +1,3 @@ -/* -Copyright 2022 James Forster - -This file is part of range_bounds_map. - -range_bounds_map is free software: you can redistribute it and/or -modify it under the terms of the GNU Affero General Public License as -published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. - -range_bounds_map is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with range_bounds_map. If not, see . -*/ - -use std::fmt::{self, Debug}; -use std::marker::PhantomData; -use std::ops::{Bound, RangeBounds}; - -use labels::trivial; -use serde::de::{SeqAccess, Visitor}; -use serde::ser::SerializeSeq; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; - -use crate::range_bounds_map::IntoIter as MapIntoIter; -use crate::{ - OverlapError, OverlapOrTryFromBoundsError, RangeBoundsMap, TryFromBounds, - TryFromBoundsError, -}; - -/// An ordered set of non-overlapping [`RangeBounds`] based on [`RangeBoundsMap`]. -/// -/// `I` is the generic type parameter for the [`Ord`] type the `K` -/// type is [`RangeBounds`] over. -/// -/// `K` is the generic type parameter for the [`RangeBounds`] -/// implementing type in the set. -/// -/// # Examples -/// ``` -/// use range_bounds_map::RangeBoundsSet; -/// -/// // Make a new set -/// let mut set = -/// RangeBoundsSet::from_slice_strict([4..8, 8..18, 20..100]) -/// .unwrap(); -/// -/// if set.contains_point(&99) { -/// println!("Set contains value at 99 :)"); -/// } -/// -/// // Iterate over the entries in the set -/// for range in set.iter() { -/// println!("{range:?}"); -/// } -/// ``` -/// Example using a custom [`RangeBounds`] type: -/// ``` -/// use std::ops::{Bound, RangeBounds}; -/// -/// use ordered_float::NotNan; -/// use range_bounds_map::RangeBoundsSet; -/// -/// // An Exlusive-Exlusive range of [`f32`]s not provided by any -/// // std::ops ranges -/// // We use [`ordered_float::NotNan`]s as the inner type must be Ord -/// // similar to a normal [`BTreeSet`] -/// #[derive(Debug, PartialEq)] -/// struct ExEx { -/// start: NotNan, -/// end: NotNan, -/// } -/// # impl ExEx { -/// # fn new(start: f32, end: f32) -> ExEx { -/// # ExEx { -/// # start: NotNan::new(start).unwrap(), -/// # end: NotNan::new(end).unwrap(), -/// # } -/// # } -/// # } -/// -/// // Implement RangeBounds on our new type -/// impl RangeBounds> for ExEx { -/// fn start_bound(&self) -> Bound<&NotNan> { -/// Bound::Excluded(&self.start) -/// } -/// fn end_bound(&self) -> Bound<&NotNan> { -/// Bound::Excluded(&self.end) -/// } -/// } -/// -/// // Now we can make a [`RangeBoundsSet`] of [`ExEx`]s -/// let mut set = RangeBoundsSet::new(); -/// -/// set.insert_strict(ExEx::new(0.0, 5.0)).unwrap(); -/// set.insert_strict(ExEx::new(5.0, 7.5)).unwrap(); -/// -/// assert_eq!(set.contains_point(&NotNan::new(5.0).unwrap()), false); -/// -/// assert_eq!(set.get_at_point(&NotNan::new(9.0).unwrap()), None); -/// assert_eq!( -/// set.get_at_point(&NotNan::new(7.0).unwrap()), -/// Some(&ExEx::new(5.0, 7.5)) -/// ); -/// ``` -/// -/// [`RangeBounds`]: https://doc.rust-lang.org/std/ops/trait.RangeBounds.html -#[derive(Debug, Clone, PartialEq)] -pub struct RangeBoundsSet -where - I: Ord, -{ - map: RangeBoundsMap, -} - -impl RangeBoundsSet -where - K: RangeBounds, - I: Ord + Clone, -{ - /// Makes a new, empty `RangeBoundsSet`. - /// - /// # Examples - /// ``` - /// use std::ops::Range; - /// - /// use range_bounds_map::RangeBoundsSet; - /// - /// let set: RangeBoundsSet> = RangeBoundsSet::new(); - /// ``` - #[trivial] - pub fn new() -> Self { - RangeBoundsSet { - map: RangeBoundsMap::new(), - } - } - - /// Returns the number of `RangeBounds` in the set. - /// - /// # Examples - /// ``` - /// use range_bounds_map::RangeBoundsSet; - /// - /// let mut set = RangeBoundsSet::new(); - /// - /// assert_eq!(set.len(), 0); - /// set.insert_strict(0..1).unwrap(); - /// assert_eq!(set.len(), 1); - /// ``` - #[trivial] - pub fn len(&self) -> usize { - self.map.len() - } - - /// Returns `true` if the set contains no `RangeBounds`, and - /// `false` if it does. - /// - /// # Examples - /// ``` - /// use range_bounds_map::RangeBoundsSet; - /// - /// let mut set = RangeBoundsSet::new(); - /// - /// assert_eq!(set.is_empty(), true); - /// set.insert_strict(0..1).unwrap(); - /// assert_eq!(set.is_empty(), false); - /// ``` - #[trivial] - pub fn is_empty(&self) -> bool { - self.map.is_empty() - } - - /// Returns `true` if the given `RangeBounds` overlaps any of the - /// `RangeBounds` in the set, and `false` if not. - /// - /// # Panics - /// - /// Panics if the given `range_bounds` is an invalid - /// `RangeBounds`. See [`Invalid - /// RangeBounds`](https://docs.rs/range_bounds_map/latest/range_bounds_map/index.html#Invalid-RangeBounds) - /// for more details. - /// - /// # Examples - /// ``` - /// use range_bounds_map::RangeBoundsSet; - /// - /// let mut set = RangeBoundsSet::new(); - /// - /// set.insert_strict(5..10); - /// - /// assert_eq!(set.overlaps(&(1..=3)), false); - /// assert_eq!(set.overlaps(&(4..5)), false); - /// - /// assert_eq!(set.overlaps(&(4..=5)), true); - /// assert_eq!(set.overlaps(&(4..6)), true); - /// ``` - #[trivial] - pub fn overlaps(&self, range_bounds: &Q) -> bool - where - Q: RangeBounds, - { - self.map.overlaps(range_bounds) - } - - /// Returns an iterator over every `RangeBounds` in the set which - /// overlap the given `RangeBounds` in ascending order. - /// - /// # Panics - /// - /// Panics if the given `range_bounds` is an invalid - /// `RangeBounds`. See [`Invalid - /// RangeBounds`](https://docs.rs/range_bounds_map/latest/range_bounds_map/index.html#Invalid-RangeBounds) - /// for more details. - /// - /// # Examples - /// ``` - /// use range_bounds_map::RangeBoundsSet; - /// - /// let set = RangeBoundsSet::from_slice_strict([1..4, 4..8, 8..100]) - /// .unwrap(); - /// - /// let mut overlapping = set.overlapping(&(2..8)); - /// - /// assert_eq!( - /// overlapping.collect::>(), - /// [(&(1..4)), (&(4..8))] - /// ); - /// ``` - #[trivial] - pub fn overlapping( - &self, - range_bounds: &Q, - ) -> impl DoubleEndedIterator - where - Q: RangeBounds, - { - self.map.overlapping(range_bounds).map(|(key, _)| key) - } - - /// Returns a reference to the `RangeBounds` in the set that - /// overlaps the given point, if any. - /// - /// # Examples - /// ``` - /// use range_bounds_map::RangeBoundsSet; - /// - /// let set = RangeBoundsSet::from_slice_strict([1..4, 4..8, 8..100]) - /// .unwrap(); - /// - /// assert_eq!(set.get_at_point(&3), Some(&(1..4))); - /// assert_eq!(set.get_at_point(&4), Some(&(4..8))); - /// assert_eq!(set.get_at_point(&101), None); - /// ``` - #[trivial] - pub fn get_at_point(&self, point: &I) -> Option<&K> { - self.map.get_entry_at_point(point).map(|(key, _)| key) - } - - /// Returns `true` if the set contains a `RangeBounds` that - /// overlaps the given point, and `false` if not. - /// - /// # Examples - /// ``` - /// use range_bounds_map::RangeBoundsSet; - /// - /// let set = RangeBoundsSet::from_slice_strict([1..4, 4..8, 8..100]) - /// .unwrap(); - /// - /// assert_eq!(set.contains_point(&3), true); - /// assert_eq!(set.contains_point(&4), true); - /// assert_eq!(set.contains_point(&101), false); - /// ``` - #[trivial] - pub fn contains_point(&self, point: &I) -> bool { - self.map.contains_point(point) - } - - /// Returns an iterator over every `RangeBounds` in the set in - /// ascending order. - /// - /// # Examples - /// ``` - /// use range_bounds_map::RangeBoundsSet; - /// - /// let set = RangeBoundsSet::from_slice_strict([1..4, 4..8, 8..100]) - /// .unwrap(); - /// - /// let mut iter = set.iter(); - /// - /// assert_eq!(iter.next(), Some(&(1..4))); - /// assert_eq!(iter.next(), Some(&(4..8))); - /// assert_eq!(iter.next(), Some(&(8..100))); - /// assert_eq!(iter.next(), None); - /// ``` - #[trivial] - pub fn iter(&self) -> impl DoubleEndedIterator { - self.map.iter().map(|(key, _)| key) - } - - /// Removes every `RangeBounds` in the set which overlaps the - /// given `RangeBounds` and returns them in an iterator. - /// - /// # Panics - /// - /// Panics if the given `range_bounds` is an invalid - /// `RangeBounds`. See [`Invalid - /// RangeBounds`](https://docs.rs/range_bounds_map/latest/range_bounds_map/index.html#Invalid-RangeBounds) - /// for more details. - /// - /// # Examples - /// ``` - /// use range_bounds_map::RangeBoundsSet; - /// - /// let mut set = - /// RangeBoundsSet::from_slice_strict([1..4, 4..8, 8..100]) - /// .unwrap(); - /// - /// let mut removed = set.remove_overlapping(&(2..8)); - /// - /// assert_eq!(removed.collect::>(), [1..4, 4..8]); - /// - /// assert_eq!(set.iter().collect::>(), [&(8..100)]); - /// ``` - #[trivial] - pub fn remove_overlapping( - &mut self, - range_bounds: &Q, - ) -> impl DoubleEndedIterator - where - Q: RangeBounds, - { - self.map - .remove_overlapping(range_bounds) - .map(|(key, _)| key) - } - - /// Cuts a given `RangeBounds` out of the set and returns an - /// iterator of the full or partial `RangeBounds` that were cut in - /// as `(Bound, Bound)`. - /// - /// If the remaining `RangeBounds` left in the map after the cut - /// are not able be created with the [`TryFromBounds`] trait then - /// a [`TryFromBoundsError`] will be returned. - /// - /// # Panics - /// - /// Panics if the given `range_bounds` is an invalid - /// `RangeBounds`. See [`Invalid - /// RangeBounds`](https://docs.rs/range_bounds_map/latest/range_bounds_map/index.html#Invalid-RangeBounds) - /// for more details. - /// - /// # Examples - /// ``` - /// use std::ops::Bound; - /// - /// use range_bounds_map::{RangeBoundsSet, TryFromBoundsError}; - /// - /// let mut base = - /// RangeBoundsSet::from_slice_strict([1..4, 4..8, 8..100]) - /// .unwrap(); - /// - /// let after_cut = - /// RangeBoundsSet::from_slice_strict([1..2, 40..100]).unwrap(); - /// - /// assert_eq!( - /// base.cut(&(2..40)).unwrap().collect::>(), - /// [ - /// (Bound::Included(2), Bound::Excluded(4)), - /// (Bound::Included(4), Bound::Excluded(8)), - /// (Bound::Included(8), Bound::Excluded(40)), - /// ] - /// ); - /// assert_eq!(base, after_cut); - /// assert!(base.cut(&(60..=80)).is_err()); - /// ``` - #[trivial] - pub fn cut( - &mut self, - range_bounds: &Q, - ) -> Result< - impl DoubleEndedIterator, Bound)>, - TryFromBoundsError, - > - where - Q: RangeBounds, - K: TryFromBounds, - { - self.map.cut(range_bounds).map(|x| x.map(|(key, _)| key)) - } - - /// Returns an iterator of `(Bound<&I>, Bound<&I>)` over all the - /// maximally-sized gaps in the set that are also within the given - /// `outer_range_bounds`. - /// - /// To get all possible gaps call `gaps()` with an unbounded - /// `RangeBounds` such as `&(..)` or `&(Bound::Unbounded, - /// Bound::Unbounded)`. - /// - /// # Panics - /// - /// Panics if the given `outer_range_bounds` is an invalid - /// `RangeBounds`. See [`Invalid - /// RangeBounds`](https://docs.rs/range_bounds_map/latest/range_bounds_map/index.html#Invalid-RangeBounds) - /// for more details. - /// - /// # Examples - /// ``` - /// use std::ops::Bound; - /// - /// use range_bounds_map::RangeBoundsSet; - /// - /// let set = RangeBoundsSet::from_slice_strict([1..3, 5..7, 9..100]) - /// .unwrap(); - /// - /// let mut gaps = set.gaps(&(2..)); - /// - /// assert_eq!( - /// gaps.collect::>(), - /// [ - /// (Bound::Included(&3), Bound::Excluded(&5)), - /// (Bound::Included(&7), Bound::Excluded(&9)), - /// (Bound::Included(&100), Bound::Unbounded) - /// ] - /// ); - /// ``` - #[trivial] - pub fn gaps<'a, Q>( - &'a self, - outer_range_bounds: &'a Q, - ) -> impl Iterator, Bound<&I>)> - where - Q: RangeBounds, - { - self.map.gaps(outer_range_bounds) - } - - /// Returns `true` if the set covers every point in the given - /// `RangeBounds`, and `false` if it doesn't. - /// - /// # Panics - /// - /// Panics if the given `range_bounds` is an invalid - /// `RangeBounds`. See [`Invalid - /// RangeBounds`](https://docs.rs/range_bounds_map/latest/range_bounds_map/index.html#Invalid-RangeBounds) - /// for more details. - /// - /// # Examples - /// ``` - /// use range_bounds_map::RangeBoundsSet; - /// - /// let set = RangeBoundsSet::from_slice_strict([1..3, 5..8, 8..100]) - /// .unwrap(); - /// - /// assert_eq!(set.contains_range_bounds(&(1..3)), true); - /// assert_eq!(set.contains_range_bounds(&(2..6)), false); - /// assert_eq!(set.contains_range_bounds(&(6..50)), true); - /// ``` - #[trivial] - pub fn contains_range_bounds(&self, range_bounds: &Q) -> bool - where - Q: RangeBounds, - { - self.map.contains_range_bounds(range_bounds) - } - - /// Adds a new `RangeBounds` to the set without modifying other - /// `RangeBounds` in the set. - /// - /// If the given `RangeBounds` overlaps one or more `RangeBounds` - /// already in the set, then an [`OverlapError`] is returned and - /// the set is not updated. - /// - /// # Panics - /// - /// Panics if the given `range_bounds` is an invalid - /// `RangeBounds`. See [`Invalid - /// RangeBounds`](https://docs.rs/range_bounds_map/latest/range_bounds_map/index.html#Invalid-RangeBounds) - /// for more details. - /// - /// # Examples - /// ``` - /// use range_bounds_map::{OverlapError, RangeBoundsSet}; - /// - /// let mut set = RangeBoundsSet::new(); - /// - /// assert_eq!(set.insert_strict(5..10), Ok(())); - /// assert_eq!(set.insert_strict(5..10), Err(OverlapError)); - /// assert_eq!(set.len(), 1); - /// ``` - #[trivial] - pub fn insert_strict( - &mut self, - range_bounds: K, - ) -> Result<(), OverlapError> { - self.map.insert_strict(range_bounds, ()) - } - - /// Adds a new `RangeBounds` to the set and merges into other - /// `RangeBounds` in the set which touch it. - /// - /// If successful then a reference to the newly inserted - /// `RangeBounds` is returned. - /// - /// If the given `RangeBounds` overlaps one or more `RangeBounds` - /// already in the set, then an [`OverlapError`] is returned and - /// the set is not updated. - /// - /// If the merged `RangeBounds` cannot be created with the - /// [`TryFromBounds`] trait then a [`TryFromBoundsError`] will be - /// returned. - /// - /// # Panics - /// - /// Panics if the given `range_bounds` is an invalid - /// `RangeBounds`. See [`Invalid - /// RangeBounds`](https://docs.rs/range_bounds_map/latest/range_bounds_map/index.html#Invalid-RangeBounds) - /// for more details. - /// - /// # Examples - /// ``` - /// use range_bounds_map::{ - /// OverlapError, OverlapOrTryFromBoundsError, RangeBoundsSet, - /// }; - /// - /// let mut set = RangeBoundsSet::from_slice_strict([1..4]).unwrap(); - /// - /// // Touching - /// assert_eq!(set.insert_merge_touching(4..6), Ok(&(1..6))); - /// - /// // Overlapping - /// assert_eq!( - /// set.insert_merge_touching(4..8), - /// Err(OverlapOrTryFromBoundsError::Overlap(OverlapError)), - /// ); - /// - /// // Neither Touching or Overlapping - /// assert_eq!(set.insert_merge_touching(10..16), Ok(&(10..16))); - /// - /// assert_eq!(set.iter().collect::>(), [&(1..6), &(10..16)]); - /// ``` - #[trivial] - pub fn insert_merge_touching( - &mut self, - range_bounds: K, - ) -> Result<&K, OverlapOrTryFromBoundsError> - where - K: TryFromBounds, - { - self.map.insert_merge_touching(range_bounds, ()) - } - - /// Adds a new `RangeBounds` to the set and merges into other - /// `RangeBounds` in the set which overlap it. - /// - /// If successful then a reference to the newly inserted - /// `RangeBounds` is returned. - /// - /// If the merged `RangeBounds` cannot be created with the - /// [`TryFromBounds`] trait then a [`TryFromBoundsError`] will be - /// returned. - /// - /// # Panics - /// - /// Panics if the given `range_bounds` is an invalid - /// `RangeBounds`. See [`Invalid - /// RangeBounds`](https://docs.rs/range_bounds_map/latest/range_bounds_map/index.html#Invalid-RangeBounds) - /// for more details. - /// - /// # Examples - /// ``` - /// use range_bounds_map::RangeBoundsSet; - /// - /// let mut set = RangeBoundsSet::from_slice_strict([1..4]).unwrap(); - /// - /// // Touching - /// assert_eq!(set.insert_merge_overlapping(-4..1), Ok(&(-4..1))); - /// - /// // Overlapping - /// assert_eq!(set.insert_merge_overlapping(2..8), Ok(&(1..8))); - /// - /// // Neither Touching or Overlapping - /// assert_eq!(set.insert_merge_overlapping(10..16), Ok(&(10..16))); - /// - /// assert_eq!( - /// set.iter().collect::>(), - /// [&(-4..1), &(1..8), &(10..16)] - /// ); - /// ``` - #[trivial] - pub fn insert_merge_overlapping( - &mut self, - range_bounds: K, - ) -> Result<&K, TryFromBoundsError> - where - K: TryFromBounds, - { - self.map.insert_merge_overlapping(range_bounds, ()) - } - - /// Adds a new `RangeBounds` to the set and merges into other - /// `RangeBounds` in the set which touch or overlap it. - /// - /// If successful then a reference to the newly inserted - /// `RangeBounds` is returned. - /// - /// If the merged `RangeBounds` cannot be created with the - /// [`TryFromBounds`] trait then a [`TryFromBoundsError`] will be - /// returned. - /// - /// # Panics - /// - /// Panics if the given `range_bounds` is an invalid - /// `RangeBounds`. See [`Invalid - /// RangeBounds`](https://docs.rs/range_bounds_map/latest/range_bounds_map/index.html#Invalid-RangeBounds) - /// for more details. - /// - /// # Examples - /// ``` - /// use range_bounds_map::RangeBoundsSet; - /// - /// let mut set = RangeBoundsSet::from_slice_strict([1..4]).unwrap(); - /// - /// // Touching - /// assert_eq!( - /// set.insert_merge_touching_or_overlapping(-4..1), - /// Ok(&(-4..4)) - /// ); - /// - /// // Overlapping - /// assert_eq!( - /// set.insert_merge_touching_or_overlapping(2..8), - /// Ok(&(-4..8)) - /// ); - /// - /// // Neither Touching or Overlapping - /// assert_eq!( - /// set.insert_merge_touching_or_overlapping(10..16), - /// Ok(&(10..16)) - /// ); - /// - /// assert_eq!(set.iter().collect::>(), [&(-4..8), &(10..16)]); - /// ``` - #[trivial] - pub fn insert_merge_touching_or_overlapping( - &mut self, - range_bounds: K, - ) -> Result<&K, TryFromBoundsError> - where - K: TryFromBounds, - { - self.map - .insert_merge_touching_or_overlapping(range_bounds, ()) - } - - /// Adds a new `RangeBounds` to the set and overwrites any other - /// `RangeBounds` that overlap the given `RangeBounds`. - /// - /// This is equivalent to using [`RangeBoundsSet::cut()`] - /// followed by [`RangeBoundsSet::insert_strict()`]. - /// - /// If the remaining `RangeBounds` left after the cut are not able - /// to be created with the [`TryFromBounds`] trait then a - /// [`TryFromBoundsError`] will be returned. - /// - /// # Panics - /// - /// Panics if the given `range_bounds` is an invalid - /// `RangeBounds`. See [`Invalid - /// RangeBounds`](https://docs.rs/range_bounds_map/latest/range_bounds_map/index.html#Invalid-RangeBounds) - /// for more details. - /// - /// # Examples - /// ``` - /// use range_bounds_map::RangeBoundsSet; - /// - /// let mut set = RangeBoundsSet::from_slice_strict([2..8]).unwrap(); - /// - /// assert_eq!(set.insert_overwrite(4..6), Ok(())); - /// - /// assert_eq!( - /// set.iter().collect::>(), - /// [&(2..4), &(4..6), &(6..8)] - /// ); - /// ``` - #[trivial] - pub fn insert_overwrite( - &mut self, - range_bounds: K, - ) -> Result<(), TryFromBoundsError> - where - K: TryFromBounds, - { - self.map.insert_overwrite(range_bounds, ()) - } - - /// Returns the first `RangeBounds` in the set, if any. - /// - /// # Examples - /// ``` - /// use range_bounds_map::RangeBoundsSet; - /// - /// let set = RangeBoundsSet::from_slice_strict([1..4, 4..8, 8..100]) - /// .unwrap(); - /// - /// assert_eq!(set.first(), Some(&(1..4))); - /// ``` - #[trivial] - pub fn first(&self) -> Option<&K> { - self.map.first_entry().map(|(key, _)| key) - } - - /// Returns the last `RangeBounds` in the set, if any. - /// - /// # Examples - /// ``` - /// use range_bounds_map::RangeBoundsSet; - /// - /// let set = RangeBoundsSet::from_slice_strict([1..4, 4..8, 8..100]) - /// .unwrap(); - /// - /// assert_eq!(set.last(), Some(&(8..100))); - /// ``` - #[trivial] - pub fn last(&self) -> Option<&K> { - self.map.last_entry().map(|(key, _)| key) - } -} - -impl IntoIterator for RangeBoundsSet -where - K: RangeBounds, - I: Ord + Clone, -{ - type Item = K; - type IntoIter = IntoIter; - #[trivial] - fn into_iter(self) -> Self::IntoIter { - return IntoIter { - inner: self.map.into_iter(), - }; - } -} -/// An owning iterator over the entries of a [`RangeBoundsSet`]. -/// -/// This `struct` is created by the [`into_iter`] method on -/// [`RangeBoundsSet`] (provided by the [`IntoIterator`] trait). See -/// its documentation for more. -/// -/// [`into_iter`]: IntoIterator::into_iter -/// [`IntoIterator`]: core::iter::IntoIterator -pub struct IntoIter { - inner: MapIntoIter, -} -impl Iterator for IntoIter { - type Item = K; - #[trivial] - fn next(&mut self) -> Option { - self.inner.next().map(first) - } -} - -impl Default for RangeBoundsSet -where - I: Ord, -{ - #[trivial] - fn default() -> Self { - RangeBoundsSet { - map: RangeBoundsMap::default(), - } - } -} - -impl Serialize for RangeBoundsSet -where - I: Ord + Clone, - K: RangeBounds + Serialize, -{ - #[trivial] - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - let mut seq = serializer.serialize_seq(Some(self.len()))?; - for range_bounds in self.iter() { - seq.serialize_element(&range_bounds)?; - } - seq.end() - } -} - -impl<'de, I, K> Deserialize<'de> for RangeBoundsSet -where - K: Deserialize<'de> + RangeBounds, - I: Ord + Clone, -{ - #[trivial] - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - deserializer.deserialize_seq(RangeBoundsSetVisitor { - i: PhantomData, - k: PhantomData, - }) - } -} - -struct RangeBoundsSetVisitor { - i: PhantomData, - k: PhantomData, -} - -impl<'de, I, K> Visitor<'de> for RangeBoundsSetVisitor -where - I: Ord + Clone, - K: RangeBounds + Deserialize<'de>, -{ - type Value = RangeBoundsSet; - - #[trivial] - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a RangeBoundsSet") - } - - #[trivial] - fn visit_seq(self, mut access: A) -> Result - where - A: SeqAccess<'de>, - { - let mut set = RangeBoundsSet::new(); - while let Some(range_bounds) = access.next_element()? { - set.insert_strict(range_bounds) - .map_err(|_| serde::de::Error::custom("RangeBounds overlap"))?; - } - Ok(set) - } -} - #[trivial] fn first((a, _): (A, B)) -> A { a diff --git a/src/test_ranges.rs b/src/test_ranges.rs index 3f22de9..f1d7974 100644 --- a/src/test_ranges.rs +++ b/src/test_ranges.rs @@ -1,44 +1,76 @@ -use std::ops::Bound; +use std::ops::{Bound, RangeBounds}; -pub type TestBounds = (Bound, Bound); +use crate::{TryFromBounds, TryFromBoundsError}; + +pub type TestBounds = (Bound, Bound); -#[allow(dead_code)] pub fn uu() -> TestBounds { (Bound::Unbounded, Bound::Unbounded) } -#[allow(dead_code)] -pub fn ui(x: u8) -> TestBounds { +pub fn ui(x: i8) -> TestBounds { (Bound::Unbounded, Bound::Included(x)) } -#[allow(dead_code)] -pub fn ue(x: u8) -> TestBounds { +pub fn ue(x: i8) -> TestBounds { (Bound::Unbounded, Bound::Excluded(x)) } -#[allow(dead_code)] -pub fn iu(x: u8) -> TestBounds { +pub fn iu(x: i8) -> TestBounds { (Bound::Included(x), Bound::Unbounded) } -//fn eu(x: u8) -> TestBounds { +//fn eu(x: i8) -> TestBounds { //(Bound::Excluded(x), Bound::Unbounded) //} -#[allow(dead_code)] -pub fn ii(x1: u8, x2: u8) -> TestBounds { +pub fn ii(x1: i8, x2: i8) -> TestBounds { (Bound::Included(x1), Bound::Included(x2)) } -#[allow(dead_code)] -pub fn ie(x1: u8, x2: u8) -> TestBounds { +pub fn ie(x1: i8, x2: i8) -> TestBounds { (Bound::Included(x1), Bound::Excluded(x2)) } -#[allow(dead_code)] -pub fn ei(x1: u8, x2: u8) -> TestBounds { +pub fn ei(x1: i8, x2: i8) -> TestBounds { (Bound::Excluded(x1), Bound::Included(x2)) } -#[allow(dead_code)] -pub fn ee(x1: u8, x2: u8) -> TestBounds { +pub fn ee(x1: i8, x2: i8) -> TestBounds { (Bound::Excluded(x1), Bound::Excluded(x2)) } -#[allow(dead_code)] -pub fn u() -> Bound { +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 ran(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) + } +} + +impl TryFromBounds for InExRange { + fn try_from_bounds( + start_bound: Bound, + end_bound: Bound, + ) -> Result + where + Self: Sized, + { + match (start_bound, end_bound) { + (Bound::Included(start), Bound::Excluded(end)) => { + Ok(InExRange { start, end }) + } + _ => Err(TryFromBoundsError), + } + } +}