Merge pull request #56 from ripytide/better_intervals

Improved `InclusiveInterval` struct
This commit is contained in:
ripytide
2023-12-27 15:07:54 +00:00
committed by GitHub
7 changed files with 481 additions and 195 deletions
+8 -3
View File
@@ -27,7 +27,7 @@ for some methods so if in doubt check a methods trait bounds.
## Example using an Inclusive-Exclusive range ## Example using an Inclusive-Exclusive range
```rust ```rust
use discrete_range_map::test_ranges::ie; use discrete_range_map::inclusive_interval::ie;
use discrete_range_map::DiscreteRangeMap; use discrete_range_map::DiscreteRangeMap;
let mut map = DiscreteRangeMap::new(); let mut map = DiscreteRangeMap::new();
@@ -45,7 +45,7 @@ assert_eq!(map.contains_point(5), true);
```rust ```rust
use std::ops::{Bound, RangeBounds}; use std::ops::{Bound, RangeBounds};
use discrete_range_map::test_ranges::ie; use discrete_range_map::inclusive_interval::ie;
use discrete_range_map::{ use discrete_range_map::{
DiscreteFinite, DiscreteRangeMap, InclusiveInterval, DiscreteFinite, DiscreteRangeMap, InclusiveInterval,
InclusiveRange, InclusiveRange,
@@ -127,6 +127,10 @@ differ depending on whether the underlying type is `Discrete` or
`Discrete` but `5.0..=6.0` does **not** touch `7.0..=8.0` since the `Discrete` but `5.0..=6.0` does **not** touch `7.0..=8.0` since the
value `6.5` exists. value `6.5` exists.
Importantly, this also makes Inclusive/Exclusive ended ranges really
easy to work with as they can be losslessly converted between one
another. For example, `3..6` is equivalent to `3..=5`.
### Finite-ness ### Finite-ness
At the moment this crate is also designed to work only with [`Finite`] At the moment this crate is also designed to work only with [`Finite`]
@@ -268,7 +272,8 @@ Here are a few examples of ranges and whether they are valid:
### Overlap ### Overlap
Two ranges are "overlapping" if there exists a point that is contained Two ranges are "overlapping" if there exists a point that is contained
within both ranges. within both ranges. For example, `2..4` and `2..6` overlap but `2..4`
and `4..8` do not.
### Touching ### Touching
+40 -75
View File
@@ -17,14 +17,13 @@ You should have received a copy of the GNU Affero General Public License
along with discrete_range_map. If not, see <https://www.gnu.org/licenses/>. along with discrete_range_map. If not, see <https://www.gnu.org/licenses/>.
*/ */
//! The module containing [`DiscreteRangeMap`] and related types. //! A module containing [`DiscreteRangeMap`] and related types.
use alloc::vec::Vec; use alloc::vec::Vec;
use core::cmp::Ordering; use core::cmp::Ordering;
use core::fmt::{self, Debug}; use core::fmt::{self, Debug};
use core::iter::once; use core::iter::once;
use core::marker::PhantomData; use core::marker::PhantomData;
use core::ops::{Bound, RangeBounds};
use btree_monstrousity::btree_map::{ use btree_monstrousity::btree_map::{
IntoIter as BTreeMapIntoIter, SearchBoundCustom, IntoIter as BTreeMapIntoIter, SearchBoundCustom,
@@ -36,8 +35,8 @@ use serde::de::{SeqAccess, Visitor};
use serde::ser::SerializeSeq; use serde::ser::SerializeSeq;
use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::utils::{cmp_point_with_range, cut_range, is_valid_range, overlaps}; use crate::utils::{cmp_point_with_range, cut_range, overlaps};
use crate::DiscreteFinite; use crate::{DiscreteFinite, InclusiveInterval};
/// An ordered map of non-overlapping ranges based on [`BTreeMap`]. /// An ordered map of non-overlapping ranges based on [`BTreeMap`].
/// ///
@@ -54,7 +53,7 @@ use crate::DiscreteFinite;
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// use discrete_range_map::test_ranges::ie; /// use discrete_range_map::inclusive_interval::ie;
/// use discrete_range_map::DiscreteRangeMap; /// use discrete_range_map::DiscreteRangeMap;
/// ///
/// // Make a map of ranges to booleans /// // Make a map of ranges to booleans
@@ -93,40 +92,6 @@ pub struct OverlapError<V> {
pub value: V, pub value: V,
} }
/// A compatibility type used in [`RangeType`] for allowing the library to
/// create the custom K type used in the map when necessary.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct InclusiveInterval<I> {
/// The start of the interval, inclusive.
pub start: I,
/// The end of the interval, inclusive.
pub end: I,
}
impl<I> RangeBounds<I> for InclusiveInterval<I>
where
I: PointType,
{
fn start_bound(&self) -> Bound<&I> {
Bound::Included(&self.start)
}
fn end_bound(&self) -> Bound<&I> {
Bound::Included(&self.end)
}
}
impl<I> InclusiveRange<I> for InclusiveInterval<I>
where
I: PointType,
{
fn start(&self) -> I {
self.start
}
fn end(&self) -> I {
self.end
}
}
/// The marker trait for valid point types, a blanket implementation is provided for all types /// The marker trait for valid point types, a blanket implementation is provided for all types
/// which implement this traits' super-traits so you shouln't need to implement this yourself. /// which implement this traits' super-traits so you shouln't need to implement this yourself.
pub trait PointType: Ord + Copy + DiscreteFinite {} pub trait PointType: Ord + Copy + DiscreteFinite {}
@@ -161,7 +126,7 @@ where
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// use discrete_range_map::test_ranges::{ie, ii}; /// use discrete_range_map::inclusive_interval::{ie, ii};
/// use discrete_range_map::DiscreteRangeMap; /// use discrete_range_map::DiscreteRangeMap;
/// ///
/// let mut map = DiscreteRangeMap::new(); /// let mut map = DiscreteRangeMap::new();
@@ -194,7 +159,7 @@ where
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// use discrete_range_map::test_ranges::ie; /// use discrete_range_map::inclusive_interval::ie;
/// use discrete_range_map::DiscreteRangeMap; /// use discrete_range_map::DiscreteRangeMap;
/// ///
/// let map = DiscreteRangeMap::from_slice_strict([ /// let map = DiscreteRangeMap::from_slice_strict([
@@ -241,7 +206,7 @@ where
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// use discrete_range_map::test_ranges::ie; /// use discrete_range_map::inclusive_interval::ie;
/// use discrete_range_map::DiscreteRangeMap; /// use discrete_range_map::DiscreteRangeMap;
/// ///
/// let mut map = DiscreteRangeMap::from_slice_strict([ /// let mut map = DiscreteRangeMap::from_slice_strict([
@@ -283,7 +248,7 @@ where
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// use discrete_range_map::test_ranges::ie; /// use discrete_range_map::inclusive_interval::ie;
/// use discrete_range_map::DiscreteRangeMap; /// use discrete_range_map::DiscreteRangeMap;
/// ///
/// let map = DiscreteRangeMap::from_slice_strict([ /// let map = DiscreteRangeMap::from_slice_strict([
@@ -306,7 +271,7 @@ where
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// use discrete_range_map::test_ranges::ie; /// use discrete_range_map::inclusive_interval::ie;
/// use discrete_range_map::DiscreteRangeMap; /// use discrete_range_map::DiscreteRangeMap;
/// let mut map = /// let mut map =
/// DiscreteRangeMap::from_slice_strict([(ie(1, 4), false)]) /// DiscreteRangeMap::from_slice_strict([(ie(1, 4), false)])
@@ -327,7 +292,7 @@ where
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// use discrete_range_map::test_ranges::ie; /// use discrete_range_map::inclusive_interval::ie;
/// use discrete_range_map::DiscreteRangeMap; /// use discrete_range_map::DiscreteRangeMap;
/// ///
/// let map = DiscreteRangeMap::from_slice_strict([ /// let map = DiscreteRangeMap::from_slice_strict([
@@ -353,7 +318,7 @@ where
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// use discrete_range_map::test_ranges::{ie, iu}; /// use discrete_range_map::inclusive_interval::{ie, iu};
/// use discrete_range_map::DiscreteRangeMap; /// use discrete_range_map::DiscreteRangeMap;
/// ///
/// let map = DiscreteRangeMap::from_slice_strict([ /// let map = DiscreteRangeMap::from_slice_strict([
@@ -402,7 +367,7 @@ where
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// use discrete_range_map::test_ranges::ie; /// use discrete_range_map::inclusive_interval::ie;
/// use discrete_range_map::DiscreteRangeMap; /// use discrete_range_map::DiscreteRangeMap;
/// ///
/// let mut map = DiscreteRangeMap::from_slice_strict([ /// let mut map = DiscreteRangeMap::from_slice_strict([
@@ -466,7 +431,7 @@ where
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// use discrete_range_map::test_ranges::{ie, ii}; /// use discrete_range_map::inclusive_interval::{ie, ii};
/// use discrete_range_map::DiscreteRangeMap; /// use discrete_range_map::DiscreteRangeMap;
/// ///
/// let mut base = DiscreteRangeMap::from_slice_strict([ /// let mut base = DiscreteRangeMap::from_slice_strict([
@@ -633,7 +598,7 @@ where
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// use discrete_range_map::test_ranges::{ie, iu}; /// use discrete_range_map::inclusive_interval::{ie, iu};
/// use discrete_range_map::DiscreteRangeMap; /// use discrete_range_map::DiscreteRangeMap;
/// ///
/// let map = DiscreteRangeMap::from_slice_strict([ /// let map = DiscreteRangeMap::from_slice_strict([
@@ -706,7 +671,7 @@ where
end: second.0.down().unwrap(), end: second.0.down().unwrap(),
}) })
}) })
.filter(|range| is_valid_range(*range)); .filter(|range| range.is_valid());
//possibly add the trimmed start and end gaps //possibly add the trimmed start and end gaps
return trimmed_start_gap return trimmed_start_gap
@@ -727,7 +692,7 @@ where
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// use discrete_range_map::test_ranges::ie; /// use discrete_range_map::inclusive_interval::ie;
/// use discrete_range_map::DiscreteRangeMap; /// use discrete_range_map::DiscreteRangeMap;
/// ///
/// let map = DiscreteRangeMap::from_slice_strict([ /// let map = DiscreteRangeMap::from_slice_strict([
@@ -765,7 +730,7 @@ where
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// use discrete_range_map::test_ranges::ie; /// use discrete_range_map::inclusive_interval::ie;
/// use discrete_range_map::{DiscreteRangeMap, OverlapError}; /// use discrete_range_map::{DiscreteRangeMap, OverlapError};
/// ///
/// let mut map = DiscreteRangeMap::new(); /// let mut map = DiscreteRangeMap::new();
@@ -865,7 +830,7 @@ where
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// use discrete_range_map::test_ranges::ie; /// use discrete_range_map::inclusive_interval::ie;
/// use discrete_range_map::{DiscreteRangeMap, OverlapError}; /// use discrete_range_map::{DiscreteRangeMap, OverlapError};
/// ///
/// let mut map = DiscreteRangeMap::from_slice_strict([ /// let mut map = DiscreteRangeMap::from_slice_strict([
@@ -953,7 +918,7 @@ where
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// use discrete_range_map::test_ranges::ie; /// use discrete_range_map::inclusive_interval::ie;
/// use discrete_range_map::{DiscreteRangeMap, OverlapError}; /// use discrete_range_map::{DiscreteRangeMap, OverlapError};
/// ///
/// let mut map = DiscreteRangeMap::from_slice_strict([ /// let mut map = DiscreteRangeMap::from_slice_strict([
@@ -1054,7 +1019,7 @@ where
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// use discrete_range_map::test_ranges::ie; /// use discrete_range_map::inclusive_interval::ie;
/// use discrete_range_map::{DiscreteRangeMap, OverlapError}; /// use discrete_range_map::{DiscreteRangeMap, OverlapError};
/// ///
/// let mut map = DiscreteRangeMap::from_slice_strict([ /// let mut map = DiscreteRangeMap::from_slice_strict([
@@ -1127,7 +1092,7 @@ where
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// use discrete_range_map::test_ranges::ie; /// use discrete_range_map::inclusive_interval::ie;
/// use discrete_range_map::{DiscreteRangeMap, OverlapError}; /// use discrete_range_map::{DiscreteRangeMap, OverlapError};
/// ///
/// let mut map = DiscreteRangeMap::from_slice_strict([ /// let mut map = DiscreteRangeMap::from_slice_strict([
@@ -1215,7 +1180,7 @@ where
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// use discrete_range_map::test_ranges::ie; /// use discrete_range_map::inclusive_interval::ie;
/// use discrete_range_map::DiscreteRangeMap; /// use discrete_range_map::DiscreteRangeMap;
/// ///
/// let mut map = /// let mut map =
@@ -1254,7 +1219,7 @@ where
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// use discrete_range_map::test_ranges::ie; /// use discrete_range_map::inclusive_interval::ie;
/// use discrete_range_map::DiscreteRangeMap; /// use discrete_range_map::DiscreteRangeMap;
/// ///
/// let map = DiscreteRangeMap::from_slice_strict([ /// let map = DiscreteRangeMap::from_slice_strict([
@@ -1288,7 +1253,7 @@ where
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// use discrete_range_map::test_ranges::ie; /// use discrete_range_map::inclusive_interval::ie;
/// use discrete_range_map::DiscreteRangeMap; /// use discrete_range_map::DiscreteRangeMap;
/// ///
/// let slice = /// let slice =
@@ -1296,7 +1261,7 @@ where
/// ///
/// let map: DiscreteRangeMap<_, _, _> = /// let map: DiscreteRangeMap<_, _, _> =
/// DiscreteRangeMap::from_iter_strict( /// DiscreteRangeMap::from_iter_strict(
/// slice.into_iter().filter(|(range, _)| range.start > 2), /// slice.into_iter().filter(|(range, _)| range.start() > 2),
/// ) /// )
/// .unwrap(); /// .unwrap();
/// ``` /// ```
@@ -1332,7 +1297,7 @@ impl<I, K, V> DiscreteRangeMap<I, K, V> {
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// use discrete_range_map::test_ranges::ie; /// use discrete_range_map::inclusive_interval::ie;
/// use discrete_range_map::DiscreteRangeMap; /// use discrete_range_map::DiscreteRangeMap;
/// ///
/// let mut map = DiscreteRangeMap::new(); /// let mut map = DiscreteRangeMap::new();
@@ -1350,7 +1315,7 @@ impl<I, K, V> DiscreteRangeMap<I, K, V> {
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// use discrete_range_map::test_ranges::ie; /// use discrete_range_map::inclusive_interval::ie;
/// use discrete_range_map::DiscreteRangeMap; /// use discrete_range_map::DiscreteRangeMap;
/// ///
/// let mut map = DiscreteRangeMap::new(); /// let mut map = DiscreteRangeMap::new();
@@ -1368,7 +1333,7 @@ impl<I, K, V> DiscreteRangeMap<I, K, V> {
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// use discrete_range_map::test_ranges::ie; /// use discrete_range_map::inclusive_interval::ie;
/// use discrete_range_map::DiscreteRangeMap; /// use discrete_range_map::DiscreteRangeMap;
/// ///
/// let map = DiscreteRangeMap::from_slice_strict([ /// let map = DiscreteRangeMap::from_slice_strict([
@@ -1394,7 +1359,7 @@ impl<I, K, V> DiscreteRangeMap<I, K, V> {
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// use discrete_range_map::test_ranges::ie; /// use discrete_range_map::inclusive_interval::ie;
/// use discrete_range_map::DiscreteRangeMap; /// use discrete_range_map::DiscreteRangeMap;
/// ///
/// let mut map = DiscreteRangeMap::from_slice_strict([ /// let mut map = DiscreteRangeMap::from_slice_strict([
@@ -1422,7 +1387,7 @@ impl<I, K, V> DiscreteRangeMap<I, K, V> {
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// use discrete_range_map::test_ranges::ie; /// use discrete_range_map::inclusive_interval::ie;
/// use discrete_range_map::DiscreteRangeMap; /// use discrete_range_map::DiscreteRangeMap;
/// ///
/// let map = DiscreteRangeMap::from_slice_strict([ /// let map = DiscreteRangeMap::from_slice_strict([
@@ -1443,7 +1408,7 @@ impl<I, K, V> DiscreteRangeMap<I, K, V> {
/// # Examples /// # Examples
/// ``` /// ```
/// use discrete_range_map::DiscreteRangeMap; /// use discrete_range_map::DiscreteRangeMap;
/// use discrete_range_map::test_ranges::ie; /// use discrete_range_map::inclusive_interval::ie;
/// ///
/// let map = DiscreteRangeMap::from_slice_strict([ /// let map = DiscreteRangeMap::from_slice_strict([
/// (ie(1, 4), false), /// (ie(1, 4), false),
@@ -1463,12 +1428,12 @@ impl<I, K, V> DiscreteRangeMap<I, K, V> {
// Helper Functions ========================== // Helper Functions ==========================
fn invalid_range_panic<Q, I>(range: Q) pub(crate) fn invalid_range_panic<Q, I>(range: Q)
where where
I: PointType, I: PointType,
Q: RangeType<I>, Q: RangeType<I>,
{ {
if !is_valid_range(range) { if !range.is_valid() {
panic!( panic!(
"invalid range given to function see here for more details: https://docs.rs/discrete_range_map/latest/discrete_range_map/#invalid-ranges" "invalid range given to function see here for more details: https://docs.rs/discrete_range_map/latest/discrete_range_map/#invalid-ranges"
); );
@@ -1713,7 +1678,7 @@ mod tests {
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use super::*; use super::*;
use crate::test_ranges::{ee, ei, ie, ii, iu, ue, ui, uu}; use crate::inclusive_interval::{ee, ei, ie, ii, iu, ue, ui, uu};
use crate::utils::{config, contains_point, Config, CutResult}; use crate::utils::{config, contains_point, Config, CutResult};
//only every other number to allow mathematical_overlapping_definition //only every other number to allow mathematical_overlapping_definition
@@ -2339,24 +2304,24 @@ mod tests {
fn cut_range_bounds_should_return_valid_ranges() { fn cut_range_bounds_should_return_valid_ranges() {
let result: CutResult<i8> = cut_range(ie(3, 8), ie(5, 8)); let result: CutResult<i8> = cut_range(ie(3, 8), ie(5, 8));
if let Some(x) = result.before_cut { if let Some(x) = result.before_cut {
assert!(is_valid_range(x)); assert!(x.is_valid());
} }
if let Some(x) = result.inside_cut { if let Some(x) = result.inside_cut {
assert!(is_valid_range(x)); assert!(x.is_valid());
} }
if let Some(x) = result.after_cut { if let Some(x) = result.after_cut {
assert!(is_valid_range(x)); assert!(x.is_valid());
} }
let result = cut_range(ie(3, 8), ie(3, 5)); let result = cut_range(ie(3, 8), ie(3, 5));
if let Some(x) = result.before_cut { if let Some(x) = result.before_cut {
assert!(is_valid_range(x)); assert!(x.is_valid());
} }
if let Some(x) = result.inside_cut { if let Some(x) = result.inside_cut {
assert!(is_valid_range(x)); assert!(x.is_valid());
} }
if let Some(x) = result.after_cut { if let Some(x) = result.after_cut {
assert!(is_valid_range(x)); assert!(x.is_valid());
} }
} }
+6 -4
View File
@@ -17,10 +17,12 @@ You should have received a copy of the GNU Affero General Public License
along with discrete_range_map. If not, see <https://www.gnu.org/licenses/>. along with discrete_range_map. If not, see <https://www.gnu.org/licenses/>.
*/ */
//! The module containing [`DiscreteRangeSet`] and related types. Since //! A module containing [`DiscreteRangeSet`] and related types.
//! [`DiscreteRangeSet`] is just a wrapper around [`DiscreteRangeMap`], most of //!
//! the methods' docs will point towards the equivalent method's docs on //! Since [`DiscreteRangeSet`] is just a wrapper around
//! [`DiscreteRangeMap`] to prevent inconsistency. //! [`DiscreteRangeMap`], most of the methods' docs will point towards the
//! equivalent method's docs on [`DiscreteRangeMap`] to prevent
//! inconsistency.
use core::fmt; use core::fmt;
use core::marker::PhantomData; use core::marker::PhantomData;
+406
View File
@@ -0,0 +1,406 @@
/*
Copyright 2022,2023 James Forster
This file is part of discrete_range_map.
discrete_range_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.
discrete_range_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 discrete_range_map. If not, see <https://www.gnu.org/licenses/>.
*/
//! A module containing [`InclusiveInterval`] and its constructors.
//!
//! The constructors are not associated functions as then you must write
//! `InclusiveInterval` before it every time you want create an interval
//! which is a bit annoying as you can't import associated function in rust
//! yet. If you would still like the associated versions I would be happy to
//! add them as well, just open a PR/Issue.
use core::ops::{Bound, Range, RangeBounds, RangeInclusive};
use serde::{Deserialize, Serialize};
use crate::discrete_range_map::invalid_range_panic;
use crate::{InclusiveRange, PointType};
/// An inclusive interval, only valid intervals can be constructed.
///
/// This interval struct is used throughout this crate for the examples and
/// tests but can also be used by library users if they don't wish to create
/// their own interval types.
///
/// To create an `InclusiveInterval` use one of the various contrutor
/// functions which will all panic if you try to create an invalid range.
/// See [`Invalid
/// Ranges`](https://docs.rs/discrete_range_map/latest/discrete_range_map/index.html#invalid-ranges)
/// for more details.
///
/// ```
/// use discrete_range_map::inclusive_interval::{ee, ii};
///
/// let inclusive_interval = ii(4, 4);
/// let exclusive_interval = ee(3, 5);
///
/// assert_eq!(inclusive_interval, exclusive_interval);
/// ```
///
/// ```should_panic
/// use discrete_range_map::inclusive_interval::ee;
///
/// let invalid_interval = ee(4, 4);
/// ```
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct InclusiveInterval<I> {
/// The start of the interval, inclusive.
pub(crate) start: I,
/// The end of the interval, inclusive.
pub(crate) end: I,
}
impl<I> InclusiveInterval<I>
where
I: PointType,
{
/// The start of the range, inclusive.
///
/// ```
/// use discrete_range_map::inclusive_interval::ii;
///
/// assert_eq!(ii(2, 4).start(), 2);
/// ```
pub fn start(&self) -> I {
self.start
}
/// The end of the range, inclusive.
///
/// ```
/// use discrete_range_map::inclusive_interval::ii;
///
/// assert_eq!(ii(2, 4).end(), 4);
/// ```
pub fn end(&self) -> I {
self.end
}
}
impl<I> RangeBounds<I> for InclusiveInterval<I>
where
I: PointType,
{
fn start_bound(&self) -> Bound<&I> {
Bound::Included(&self.start)
}
fn end_bound(&self) -> Bound<&I> {
Bound::Included(&self.end)
}
}
impl<I> InclusiveRange<I> for InclusiveInterval<I>
where
I: PointType,
{
fn start(&self) -> I {
self.start
}
fn end(&self) -> I {
self.end
}
}
impl<I> From<InclusiveInterval<I>> for RangeInclusive<I> {
fn from(value: InclusiveInterval<I>) -> Self {
value.start..=value.end
}
}
impl<I> From<RangeInclusive<I>> for InclusiveInterval<I>
where
I: PointType,
{
fn from(value: RangeInclusive<I>) -> Self {
ii(*value.start(), *value.end())
}
}
impl<I> From<InclusiveInterval<I>> for Range<I>
where
I: PointType,
{
fn from(value: InclusiveInterval<I>) -> Self {
value.start..value.end.up().unwrap()
}
}
impl<I> From<Range<I>> for InclusiveInterval<I>
where
I: PointType,
{
fn from(value: Range<I>) -> Self {
ie(value.start, value.end)
}
}
/// Create an new Unbounded-Unbounded interval.
///
/// # Panics
///
/// Panics if the range is an invalid range. See [`Invalid
/// Ranges`](https://docs.rs/discrete_range_map/latest/discrete_range_map/index.html#invalid-ranges)
/// for more details.
///
/// ```
/// use discrete_range_map::inclusive_interval::uu;
/// use discrete_range_map::InclusiveInterval;
///
/// let interval1: InclusiveInterval<u8> = uu();
/// let interval2: InclusiveInterval<u8> = uu();
///
/// assert_eq!(interval1, interval2)
/// ```
pub fn uu<I>() -> InclusiveInterval<I>
where
I: PointType,
{
let interval = InclusiveInterval {
start: I::MIN,
end: I::MAX,
};
invalid_range_panic(interval);
interval
}
/// Create an new Unbounded-Included interval.
///
/// # Panics
///
/// Panics if the range is an invalid range. See [`Invalid
/// Ranges`](https://docs.rs/discrete_range_map/latest/discrete_range_map/index.html#invalid-ranges)
/// for more details.
///
/// ```
/// use discrete_range_map::inclusive_interval::ui;
///
/// let interval1 = ui(1);
/// let interval2 = ui(4);
///
/// assert_ne!(interval1, interval2)
/// ```
pub fn ui<I>(x: I) -> InclusiveInterval<I>
where
I: PointType,
{
let interval = InclusiveInterval {
start: I::MIN,
end: x,
};
invalid_range_panic(interval);
interval
}
/// Create an new Unbounded-Excluded interval.
///
/// # Panics
///
/// Panics if the range is an invalid range. See [`Invalid
/// Ranges`](https://docs.rs/discrete_range_map/latest/discrete_range_map/index.html#invalid-ranges)
/// for more details.
///
/// ```
/// use discrete_range_map::inclusive_interval::ue;
///
/// let interval1 = ue(1);
/// let interval2 = ue(4);
///
/// assert_ne!(interval1, interval2)
/// ```
pub fn ue<I>(x: I) -> InclusiveInterval<I>
where
I: PointType,
{
let interval = InclusiveInterval {
start: I::MIN,
end: x.down().unwrap(),
};
invalid_range_panic(interval);
interval
}
/// Create an new Included-Unbounded interval.
///
/// # Panics
///
/// Panics if the range is an invalid range. See [`Invalid
/// Ranges`](https://docs.rs/discrete_range_map/latest/discrete_range_map/index.html#invalid-ranges)
/// for more details.
///
/// ```
/// use discrete_range_map::inclusive_interval::iu;
///
/// let interval1 = iu(1);
/// let interval2 = iu(4);
///
/// assert_ne!(interval1, interval2)
/// ```
pub fn iu<I>(x: I) -> InclusiveInterval<I>
where
I: PointType,
{
let interval = InclusiveInterval {
start: x,
end: I::MAX,
};
invalid_range_panic(interval);
interval
}
/// Create an new Excluded-Unbounded interval.
///
/// # Panics
///
/// Panics if the range is an invalid range. See [`Invalid
/// Ranges`](https://docs.rs/discrete_range_map/latest/discrete_range_map/index.html#invalid-ranges)
/// for more details.
///
/// ```
/// use discrete_range_map::inclusive_interval::eu;
///
/// let interval1 = eu(1);
/// let interval2 = eu(4);
///
/// assert_ne!(interval1, interval2)
/// ```
pub fn eu<I>(x: I) -> InclusiveInterval<I>
where
I: PointType,
{
let interval = InclusiveInterval {
start: x.up().unwrap(),
end: I::MAX,
};
invalid_range_panic(interval);
interval
}
/// Create an new Included-Included interval.
///
/// # Panics
///
/// Panics if the range is an invalid range. See [`Invalid
/// Ranges`](https://docs.rs/discrete_range_map/latest/discrete_range_map/index.html#invalid-ranges)
/// for more details.
///
/// ```
/// use discrete_range_map::inclusive_interval::ii;
///
/// let interval1 = ii(0, 4);
/// let interval2 = ii(2, 6);
///
/// assert_ne!(interval1, interval2)
/// ```
pub fn ii<I>(x1: I, x2: I) -> InclusiveInterval<I>
where
I: PointType,
{
let interval = InclusiveInterval { start: x1, end: x2 };
invalid_range_panic(interval);
interval
}
/// Create an new Included-Excluded interval.
///
/// # Panics
///
/// Panics if the range is an invalid range. See [`Invalid
/// Ranges`](https://docs.rs/discrete_range_map/latest/discrete_range_map/index.html#invalid-ranges)
/// for more details.
///
/// ```
/// use discrete_range_map::inclusive_interval::ie;
///
/// let interval1 = ie(0, 4);
/// let interval2 = ie(2, 6);
///
/// assert_ne!(interval1, interval2)
/// ```
pub fn ie<I>(x1: I, x2: I) -> InclusiveInterval<I>
where
I: PointType,
{
let interval = InclusiveInterval {
start: x1,
end: x2.down().unwrap(),
};
invalid_range_panic(interval);
interval
}
/// Create an new Excluded-Included interval.
///
/// # Panics
///
/// Panics if the range is an invalid range. See [`Invalid
/// Ranges`](https://docs.rs/discrete_range_map/latest/discrete_range_map/index.html#invalid-ranges)
/// for more details.
///
/// ```
/// use discrete_range_map::inclusive_interval::ei;
///
/// let interval1 = ei(0, 4);
/// let interval2 = ei(2, 6);
///
/// assert_ne!(interval1, interval2)
/// ```
pub fn ei<I>(x1: I, x2: I) -> InclusiveInterval<I>
where
I: PointType,
{
let interval = InclusiveInterval {
start: x1.up().unwrap(),
end: x2,
};
invalid_range_panic(interval);
interval
}
/// Create an new Excluded-Excluded interval.
///
/// # Panics
///
/// Panics if the range is an invalid range. See [`Invalid
/// Ranges`](https://docs.rs/discrete_range_map/latest/discrete_range_map/index.html#invalid-ranges)
/// for more details.
///
/// ```
/// use discrete_range_map::inclusive_interval::ee;
///
/// let interval1 = ee(0, 4);
/// let interval2 = ee(2, 6);
///
/// assert_ne!(interval1, interval2)
/// ```
pub fn ee<I>(x1: I, x2: I) -> InclusiveInterval<I>
where
I: PointType,
{
let interval = InclusiveInterval {
start: x1.up().unwrap(),
end: x2.down().unwrap(),
};
invalid_range_panic(interval);
interval
}
+17 -17
View File
@@ -35,7 +35,7 @@ along with discrete_range_map. If not, see <https://www.gnu.org/licenses/>.
//! ## Example using an Inclusive-Exclusive range //! ## Example using an Inclusive-Exclusive range
//! //!
//! ```rust //! ```rust
//! use discrete_range_map::test_ranges::ie; //! use discrete_range_map::inclusive_interval::ie;
//! use discrete_range_map::DiscreteRangeMap; //! use discrete_range_map::DiscreteRangeMap;
//! //!
//! let mut map = DiscreteRangeMap::new(); //! let mut map = DiscreteRangeMap::new();
@@ -53,7 +53,7 @@ along with discrete_range_map. If not, see <https://www.gnu.org/licenses/>.
//! ```rust //! ```rust
//! use std::ops::{Bound, RangeBounds}; //! use std::ops::{Bound, RangeBounds};
//! //!
//! use discrete_range_map::test_ranges::ie; //! use discrete_range_map::inclusive_interval::ie;
//! use discrete_range_map::{ //! use discrete_range_map::{
//! DiscreteFinite, DiscreteRangeMap, InclusiveInterval, //! DiscreteFinite, DiscreteRangeMap, InclusiveInterval,
//! InclusiveRange, //! InclusiveRange,
@@ -86,12 +86,12 @@ along with discrete_range_map. If not, see <https://www.gnu.org/licenses/>.
//! // Second, we need to implement From<InclusiveInterval<i8>> //! // Second, we need to implement From<InclusiveInterval<i8>>
//! impl From<InclusiveInterval<i8>> for Reservation { //! impl From<InclusiveInterval<i8>> for Reservation {
//! fn from(value: InclusiveInterval<i8>) -> Self { //! fn from(value: InclusiveInterval<i8>) -> Self {
//! if value.end == i8::MAX { //! if value.end() == i8::MAX {
//! Reservation::Infinite(value.start) //! Reservation::Infinite(value.start())
//! } else { //! } else {
//! Reservation::Finite( //! Reservation::Finite(
//! value.start, //! value.start(),
//! value.end.up().unwrap(), //! value.end().up().unwrap(),
//! ) //! )
//! } //! }
//! } //! }
@@ -135,6 +135,10 @@ along with discrete_range_map. If not, see <https://www.gnu.org/licenses/>.
//! `Discrete` but `5.0..=6.0` does **not** touch `7.0..=8.0` since the //! `Discrete` but `5.0..=6.0` does **not** touch `7.0..=8.0` since the
//! value `6.5` exists. //! value `6.5` exists.
//! //!
//! Importantly, this also makes Inclusive/Exclusive ended ranges really
//! easy to work with as they can be losslessly converted between one
//! another. For example, `3..6` is equivalent to `3..=5`.
//!
//! ### Finite-ness //! ### Finite-ness
//! //!
//! At the moment this crate is also designed to work only with [`Finite`] //! At the moment this crate is also designed to work only with [`Finite`]
@@ -231,6 +235,7 @@ along with discrete_range_map. If not, see <https://www.gnu.org/licenses/>.
//! // Infinity is encountered such as when it might be //! // Infinity is encountered such as when it might be
//! // returned by `get_entry_at_point()`, for example: //! // returned by `get_entry_at_point()`, for example:
//! //!
//! use discrete_range_map::inclusive_interval::uu;
//! use discrete_range_map::{DiscreteRangeMap, InclusiveInterval}; //! use discrete_range_map::{DiscreteRangeMap, InclusiveInterval};
//! //!
//! let map: DiscreteRangeMap< //! let map: DiscreteRangeMap<
@@ -241,13 +246,7 @@ along with discrete_range_map. If not, see <https://www.gnu.org/licenses/>.
//! //!
//! let mut gap = map.get_entry_at_point(WithInfinity::Finite(4)); //! let mut gap = map.get_entry_at_point(WithInfinity::Finite(4));
//! //!
//! assert_eq!( //! assert_eq!(gap, Err(uu()));
//! gap,
//! Err(InclusiveInterval {
//! start: WithInfinity::Finite(0),
//! end: WithInfinity::Infinity,
//! })
//! );
//! ``` //! ```
//! //!
//! ### Invalid Ranges //! ### Invalid Ranges
@@ -276,7 +275,8 @@ along with discrete_range_map. If not, see <https://www.gnu.org/licenses/>.
//! ### Overlap //! ### Overlap
//! //!
//! Two ranges are "overlapping" if there exists a point that is contained //! Two ranges are "overlapping" if there exists a point that is contained
//! within both ranges. //! within both ranges. For example, `2..4` and `2..6` overlap but `2..4`
//! and `4..8` do not.
//! //!
//! ### Touching //! ### Touching
//! //!
@@ -384,11 +384,11 @@ pub(crate) mod utils;
pub mod discrete_finite; pub mod discrete_finite;
pub mod discrete_range_map; pub mod discrete_range_map;
pub mod discrete_range_set; pub mod discrete_range_set;
pub mod test_ranges; pub mod inclusive_interval;
pub use crate::discrete_finite::DiscreteFinite; pub use crate::discrete_finite::DiscreteFinite;
pub use crate::discrete_range_map::{ pub use crate::discrete_range_map::{
DiscreteRangeMap, InclusiveInterval, InclusiveRange, OverlapError, DiscreteRangeMap, InclusiveRange, OverlapError, PointType, RangeType,
PointType, RangeType,
}; };
pub use crate::discrete_range_set::DiscreteRangeSet; pub use crate::discrete_range_set::DiscreteRangeSet;
pub use crate::inclusive_interval::InclusiveInterval;
-84
View File
@@ -1,84 +0,0 @@
/*
Copyright 2022,2023 James Forster
This file is part of discrete_range_map.
discrete_range_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.
discrete_range_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 discrete_range_map. If not, see <https://www.gnu.org/licenses/>.
*/
//! A collection of helper functions for making [`InclusiveInterval`]s from `i8`'s used for testing
//! and example purposes.
use crate::{DiscreteFinite, InclusiveInterval};
/// An unbounded-unbounded interval
pub fn uu() -> InclusiveInterval<i8> {
InclusiveInterval {
start: i8::MIN,
end: i8::MAX,
}
}
/// An unbounded-included interval
pub fn ui(x: i8) -> InclusiveInterval<i8> {
InclusiveInterval {
start: i8::MIN,
end: x,
}
}
/// An unbounded-excluded interval
pub fn ue(x: i8) -> InclusiveInterval<i8> {
InclusiveInterval {
start: i8::MIN,
end: x.down().unwrap(),
}
}
/// An included-unbounded interval
pub fn iu(x: i8) -> InclusiveInterval<i8> {
InclusiveInterval {
start: x,
end: i8::MAX,
}
}
/// An excluded-unbounded interval
pub fn eu(x: i8) -> InclusiveInterval<i8> {
InclusiveInterval {
start: x.up().unwrap(),
end: i8::MAX,
}
}
/// An included-included interval
pub fn ii(x1: i8, x2: i8) -> InclusiveInterval<i8> {
InclusiveInterval { start: x1, end: x2 }
}
/// An included-excluded interval
pub fn ie(x1: i8, x2: i8) -> InclusiveInterval<i8> {
InclusiveInterval {
start: x1,
end: x2.down().unwrap(),
}
}
/// An excluded-included interval
pub fn ei(x1: i8, x2: i8) -> InclusiveInterval<i8> {
InclusiveInterval {
start: x1.up().unwrap(),
end: x2,
}
}
/// An excluded-excluded interval
pub fn ee(x1: i8, x2: i8) -> InclusiveInterval<i8> {
InclusiveInterval {
start: x1.up().unwrap(),
end: x2.down().unwrap(),
}
}
+4 -12
View File
@@ -19,7 +19,7 @@ along with discrete_range_map. If not, see <https://www.gnu.org/licenses/>.
use core::cmp::Ordering; use core::cmp::Ordering;
use crate::{InclusiveInterval, PointType, RangeType}; use crate::{InclusiveInterval, PointType, RangeType, InclusiveRange};
pub(crate) fn cmp_point_with_range<I, K>(point: I, range: K) -> Ordering pub(crate) fn cmp_point_with_range<I, K>(point: I, range: K) -> Ordering
where where
@@ -190,20 +190,12 @@ where
//only return valid ranges //only return valid ranges
return CutResult { return CutResult {
before_cut: result.before_cut.filter(|x| is_valid_range(*x)), before_cut: result.before_cut.filter(|x| x.is_valid()),
inside_cut: result.inside_cut.filter(|x| is_valid_range(*x)), inside_cut: result.inside_cut.filter(|x| x.is_valid()),
after_cut: result.after_cut.filter(|x| is_valid_range(*x)), after_cut: result.after_cut.filter(|x| x.is_valid()),
}; };
} }
pub(crate) fn is_valid_range<I, K>(range: K) -> bool
where
I: PointType,
K: RangeType<I>,
{
range.start() <= range.end()
}
pub(crate) fn overlaps<I, A, B>(a: A, b: B) -> bool pub(crate) fn overlaps<I, A, B>(a: A, b: B) -> bool
where where
I: PointType, I: PointType,