diff --git a/README.md b/README.md index 63568c9..6808e64 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,32 @@ assert_eq!( ## Key Definitions: +### Invalid RangeBounds + +Within this crate, not all `RangeBounds` are considered valid +`RangeBounds`. The definition of the validity of a `RangeBounds` used +within this crate is that a `RangeBounds` is only valid if it contains +at least one value of the underlying domain. + +For example, `4..6` is considered valid as it contains the values `4` +and `5`, however, `4..4` is considered invalid as it contains no +values. Another example of invalid `RangeBounds` are those with +`start_bound()`s with greater values than their `end_bound()`s, such +as `5..2` or `100..=40`. + +Here are a few examples of `RangeBounds` and whether they are valid: + +| `RangeBounds` | Valid | +| -------------- | ----- | +| 0..0 | NO | +| 0..1 | YES | +| 9..8 | NO | +| (0.4)..=(-0.2) | NO | +| ..(-3) | YES | +| 0.0003.. | YES | +| .. | YES | +| 400..=400 | YES | + ### Overlap Two `RangeBounds` are "overlapping" if there exists a point that is @@ -110,6 +136,11 @@ there exists no value between them. For example, `2..4` and When a `RangeBounds` "merges" other `RangeBounds` it absorbs them to become larger. +### Further Reading + +See Wikipedia's article on Intervals: + + # Improvements/Caveats - Missing some functions common to BTreeMap and BTreeSet like: diff --git a/src/lib.rs b/src/lib.rs index d3e9189..61a1e14 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -101,6 +101,32 @@ along with range_bounds_map. If not, see . //! //! ## Key Definitions: //! +//! ### Invalid RangeBounds +//! +//! Within this crate, not all `RangeBounds` are considered valid +//! `RangeBounds`. The definition of the validity of a `RangeBounds` used +//! within this crate is that a `RangeBounds` is only valid if it contains +//! at least one value of the underlying domain. +//! +//! For example, `4..6` is considered valid as it contains the values `4` +//! and `5`, however, `4..4` is considered invalid as it contains no +//! values. Another example of invalid `RangeBounds` are those with +//! `start_bound()`s with greater values than their `end_bound()`s, such +//! as `5..2` or `100..=40`. +//! +//! Here are a few examples of `RangeBounds` and whether they are valid: +//! +//! | `RangeBounds` | Valid | +//! | -------------- | ----- | +//! | 0..0 | NO | +//! | 0..1 | YES | +//! | 9..8 | NO | +//! | (0.4)..=(-0.2) | NO | +//! | ..(-3) | YES | +//! | 0.0003.. | YES | +//! | .. | YES | +//! | 400..=400 | YES | +//! //! ### Overlap //! //! Two `RangeBounds` are "overlapping" if there exists a point that is @@ -118,6 +144,11 @@ along with range_bounds_map. If not, see . //! When a `RangeBounds` "merges" other `RangeBounds` it absorbs them //! to become larger. //! +//! ### Further Reading +//! +//! See Wikipedia's article on Intervals: +//! +//! //! # Improvements/Caveats //! //! - Missing some functions common to BTreeMap and BTreeSet like: @@ -153,6 +184,7 @@ along with range_bounds_map. If not, see . //! - //! Very similar to this crate but can only use [`Range`]s and //! [`RangeInclusive`]s as keys in it's `map` and `set` structs (separately). +//! - //! - //! Cool library for fully-generic ranges (unlike std::ops ranges), along //! with a `Ranges` datastructure for storing them (Vec-based diff --git a/src/range_bounds_map.rs b/src/range_bounds_map.rs index 47b7ccb..922b098 100644 --- a/src/range_bounds_map.rs +++ b/src/range_bounds_map.rs @@ -327,16 +327,23 @@ where /// ``` #[trivial] pub fn is_empty(&self) -> bool { - self.len() == 0 + self.starts.is_empty() } /// Adds a new (`RangeBounds`, `Value`) pair to the map without /// modifying other entries. /// - /// If the new `RangeBounds` overlaps one or more `RangeBounds` + /// If the given `RangeBounds` overlaps one or more `RangeBounds` /// already in the map rather than just touching, then an /// [`OverlapError`] is returned and the map 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, RangeBoundsMap}; @@ -360,11 +367,8 @@ where return Err(OverlapError); } - let start = BoundOrd::start(range_bounds.start_bound()); - let end = BoundOrd::end(range_bounds.end_bound()); - - if start > end { - panic!("Invalid search range bounds!"); + if !is_valid_range_bounds(&range_bounds) { + panic!("Invalid range_bounds!"); } self.starts.insert( @@ -378,6 +382,13 @@ where /// Returns `true` if the given `RangeBounds` overlaps any of the /// `RangeBounds` in the map, 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::RangeBoundsMap; @@ -401,9 +412,16 @@ where } /// Returns an iterator over every (`RangeBounds`, `Value`) pair - /// in the map which overlap the given `range_bounds` in + /// in the map 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::RangeBoundsMap; @@ -431,7 +449,7 @@ where Q: RangeBounds, { if !is_valid_range_bounds(range_bounds) { - panic!("Invalid range bounds!"); + panic!("Invalid range_bounds!"); } let start = BoundOrd::start(range_bounds.start_bound().cloned()); @@ -614,9 +632,16 @@ where } /// Removes every (`RangeBounds`, `Value`) pair in the map which - /// overlaps the given `range_bounds` and returns them in + /// 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::RangeBoundsMap; @@ -681,6 +706,13 @@ where /// partially cut a `RangeBounds` then `V` must be cloned to be /// returned in the 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 std::ops::Bound; @@ -803,6 +835,13 @@ where /// iterator of `(Result, /// Value)`. /// + /// # 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::{RangeBoundsMap, TryFromBoundsError}; @@ -854,6 +893,13 @@ where /// `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; @@ -948,6 +994,13 @@ where /// Identical to [`RangeBoundsMap::gaps()`] except it returns an /// iterator of `Result`. /// + /// # 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; @@ -986,6 +1039,13 @@ where /// Returns `true` if the map 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::RangeBoundsMap; @@ -1025,7 +1085,7 @@ where /// If successful then a reference to the newly inserted /// `RangeBounds` is returned. /// - /// If the new `RangeBounds` overlaps one or more `RangeBounds` + /// If the given `RangeBounds` overlaps one or more `RangeBounds` /// already in the map rather than just touching, then an /// [`OverlapError`] is returned and the map is not updated. /// `RangeBounds` is returned. @@ -1034,6 +1094,13 @@ where /// [`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::{ @@ -1159,6 +1226,13 @@ where /// [`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::RangeBoundsMap; @@ -1257,6 +1331,13 @@ where /// [`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::RangeBoundsMap; @@ -1334,6 +1415,13 @@ where /// 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::RangeBoundsMap; @@ -1531,11 +1619,18 @@ where /// Similar to [`RangeBoundsMap::overlapping()`] except the /// `(Bound, Bound)`s returned in the iterator have been - /// trimmed/cut by the given `range_bounds`. + /// trimmed/cut by the given `RangeBounds`. /// /// This is sort of the analogue to the AND function between a /// `RangeBounds` AND a [`RangeBoundsMap`]. /// + /// # 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; @@ -1593,6 +1688,13 @@ where /// it returns an iterator of `(Result, Value)`. /// + /// # 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::{RangeBoundsMap, TryFromBoundsError}; diff --git a/src/range_bounds_set.rs b/src/range_bounds_set.rs index f57d309..3c59edd 100644 --- a/src/range_bounds_set.rs +++ b/src/range_bounds_set.rs @@ -171,16 +171,23 @@ where /// ``` #[trivial] pub fn is_empty(&self) -> bool { - self.len() == 0 + self.map.is_empty() } /// Adds a new `RangeBounds` to the set without modifying other /// `RangeBounds` in the set. /// - /// If the new `RangeBounds` overlaps one or more `RangeBounds` + /// If the given `RangeBounds` overlaps one or more `RangeBounds` /// already in the set rather than just touching, 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}; @@ -205,6 +212,13 @@ where /// 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; @@ -228,7 +242,14 @@ where } /// Returns an iterator over every `RangeBounds` in the set which - /// overlap the given `range_bounds` in ascending order. + /// 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 /// ``` @@ -316,7 +337,14 @@ where } /// Removes every `RangeBounds` in the set which overlaps the - /// given `range_bounds` and returns them in an iterator. + /// 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 /// ``` @@ -355,6 +383,13 @@ where /// 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; @@ -396,6 +431,13 @@ where /// Identical to [`RangeBoundsSet::cut()`] except it returns an /// iterator of `Result` /// + /// # 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, TryFromBoundsError}; @@ -438,6 +480,13 @@ where /// `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; @@ -472,6 +521,13 @@ where /// Identical to [`RangeBoundsSet::gaps()`] except it returns an /// iterator of `Result`. /// + /// # 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; @@ -503,6 +559,13 @@ where /// 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; @@ -534,7 +597,7 @@ where /// If successful then a reference to the newly inserted /// `RangeBounds` is returned. /// - /// If the new `RangeBounds` overlaps one or more `RangeBounds` + /// If the given `RangeBounds` overlaps one or more `RangeBounds` /// already in the set rather than just touching, then an /// [`OverlapError`] is returned and the set is not updated. /// @@ -542,6 +605,13 @@ where /// [`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::{ @@ -595,6 +665,13 @@ where /// [`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; @@ -646,6 +723,13 @@ where /// [`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; @@ -689,7 +773,7 @@ where } /// Adds a new `RangeBounds` to the set and overwrites any other - /// `RangeBounds` that overlap the new `RangeBounds`. + /// `RangeBounds` that overlap the given `RangeBounds`. /// /// This is equivalent to using [`RangeBoundsSet::cut()`] /// followed by [`RangeBoundsSet::insert_strict()`]. @@ -698,6 +782,13 @@ where /// 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; @@ -837,11 +928,18 @@ where /// Similar to [`RangeBoundsSet::overlapping()`] except the /// `(Bound, Bound)`s returned in the iterator have been - /// trimmed/cut by the given `range_bounds`. + /// trimmed/cut by the given `RangeBounds`. /// /// This is sort of the analogue to the AND function between a /// `RangeBounds` AND a [`RangeBoundsSet`]. /// + /// # 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; @@ -878,6 +976,13 @@ where /// it returns an iterator of `Result`. /// + /// # 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, TryFromBoundsError}; diff --git a/todo.md b/todo.md index 8274376..04ac732 100644 --- a/todo.md +++ b/todo.md @@ -20,8 +20,6 @@ - replace `RangeBounds` with `K` where applicatble in docs - replace rust types URL links with direct rust links -- add a # Panics section to every method that can panic, probably most - given invalid RangeBounds # features