Merge pull request #56 from ripytide/better_intervals
Improved `InclusiveInterval` struct
This commit is contained in:
@@ -27,7 +27,7 @@ for some methods so if in doubt check a methods trait bounds.
|
||||
## Example using an Inclusive-Exclusive range
|
||||
|
||||
```rust
|
||||
use discrete_range_map::test_ranges::ie;
|
||||
use discrete_range_map::inclusive_interval::ie;
|
||||
use discrete_range_map::DiscreteRangeMap;
|
||||
|
||||
let mut map = DiscreteRangeMap::new();
|
||||
@@ -45,7 +45,7 @@ assert_eq!(map.contains_point(5), true);
|
||||
```rust
|
||||
use std::ops::{Bound, RangeBounds};
|
||||
|
||||
use discrete_range_map::test_ranges::ie;
|
||||
use discrete_range_map::inclusive_interval::ie;
|
||||
use discrete_range_map::{
|
||||
DiscreteFinite, DiscreteRangeMap, InclusiveInterval,
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
|
||||
+40
-75
@@ -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/>.
|
||||
*/
|
||||
|
||||
//! The module containing [`DiscreteRangeMap`] and related types.
|
||||
//! A module containing [`DiscreteRangeMap`] and related types.
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use core::cmp::Ordering;
|
||||
use core::fmt::{self, Debug};
|
||||
use core::iter::once;
|
||||
use core::marker::PhantomData;
|
||||
use core::ops::{Bound, RangeBounds};
|
||||
|
||||
use btree_monstrousity::btree_map::{
|
||||
IntoIter as BTreeMapIntoIter, SearchBoundCustom,
|
||||
@@ -36,8 +35,8 @@ use serde::de::{SeqAccess, Visitor};
|
||||
use serde::ser::SerializeSeq;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
use crate::utils::{cmp_point_with_range, cut_range, is_valid_range, overlaps};
|
||||
use crate::DiscreteFinite;
|
||||
use crate::utils::{cmp_point_with_range, cut_range, overlaps};
|
||||
use crate::{DiscreteFinite, InclusiveInterval};
|
||||
|
||||
/// An ordered map of non-overlapping ranges based on [`BTreeMap`].
|
||||
///
|
||||
@@ -54,7 +53,7 @@ use crate::DiscreteFinite;
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use discrete_range_map::test_ranges::ie;
|
||||
/// use discrete_range_map::inclusive_interval::ie;
|
||||
/// use discrete_range_map::DiscreteRangeMap;
|
||||
///
|
||||
/// // Make a map of ranges to booleans
|
||||
@@ -93,40 +92,6 @@ pub struct OverlapError<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
|
||||
/// which implement this traits' super-traits so you shouln't need to implement this yourself.
|
||||
pub trait PointType: Ord + Copy + DiscreteFinite {}
|
||||
@@ -161,7 +126,7 @@ where
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use discrete_range_map::test_ranges::{ie, ii};
|
||||
/// use discrete_range_map::inclusive_interval::{ie, ii};
|
||||
/// use discrete_range_map::DiscreteRangeMap;
|
||||
///
|
||||
/// let mut map = DiscreteRangeMap::new();
|
||||
@@ -194,7 +159,7 @@ where
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use discrete_range_map::test_ranges::ie;
|
||||
/// use discrete_range_map::inclusive_interval::ie;
|
||||
/// use discrete_range_map::DiscreteRangeMap;
|
||||
///
|
||||
/// let map = DiscreteRangeMap::from_slice_strict([
|
||||
@@ -241,7 +206,7 @@ where
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use discrete_range_map::test_ranges::ie;
|
||||
/// use discrete_range_map::inclusive_interval::ie;
|
||||
/// use discrete_range_map::DiscreteRangeMap;
|
||||
///
|
||||
/// let mut map = DiscreteRangeMap::from_slice_strict([
|
||||
@@ -283,7 +248,7 @@ where
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use discrete_range_map::test_ranges::ie;
|
||||
/// use discrete_range_map::inclusive_interval::ie;
|
||||
/// use discrete_range_map::DiscreteRangeMap;
|
||||
///
|
||||
/// let map = DiscreteRangeMap::from_slice_strict([
|
||||
@@ -306,7 +271,7 @@ where
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use discrete_range_map::test_ranges::ie;
|
||||
/// use discrete_range_map::inclusive_interval::ie;
|
||||
/// use discrete_range_map::DiscreteRangeMap;
|
||||
/// let mut map =
|
||||
/// DiscreteRangeMap::from_slice_strict([(ie(1, 4), false)])
|
||||
@@ -327,7 +292,7 @@ where
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use discrete_range_map::test_ranges::ie;
|
||||
/// use discrete_range_map::inclusive_interval::ie;
|
||||
/// use discrete_range_map::DiscreteRangeMap;
|
||||
///
|
||||
/// let map = DiscreteRangeMap::from_slice_strict([
|
||||
@@ -353,7 +318,7 @@ where
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use discrete_range_map::test_ranges::{ie, iu};
|
||||
/// use discrete_range_map::inclusive_interval::{ie, iu};
|
||||
/// use discrete_range_map::DiscreteRangeMap;
|
||||
///
|
||||
/// let map = DiscreteRangeMap::from_slice_strict([
|
||||
@@ -402,7 +367,7 @@ where
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use discrete_range_map::test_ranges::ie;
|
||||
/// use discrete_range_map::inclusive_interval::ie;
|
||||
/// use discrete_range_map::DiscreteRangeMap;
|
||||
///
|
||||
/// let mut map = DiscreteRangeMap::from_slice_strict([
|
||||
@@ -466,7 +431,7 @@ where
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use discrete_range_map::test_ranges::{ie, ii};
|
||||
/// use discrete_range_map::inclusive_interval::{ie, ii};
|
||||
/// use discrete_range_map::DiscreteRangeMap;
|
||||
///
|
||||
/// let mut base = DiscreteRangeMap::from_slice_strict([
|
||||
@@ -633,7 +598,7 @@ where
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use discrete_range_map::test_ranges::{ie, iu};
|
||||
/// use discrete_range_map::inclusive_interval::{ie, iu};
|
||||
/// use discrete_range_map::DiscreteRangeMap;
|
||||
///
|
||||
/// let map = DiscreteRangeMap::from_slice_strict([
|
||||
@@ -706,7 +671,7 @@ where
|
||||
end: second.0.down().unwrap(),
|
||||
})
|
||||
})
|
||||
.filter(|range| is_valid_range(*range));
|
||||
.filter(|range| range.is_valid());
|
||||
|
||||
//possibly add the trimmed start and end gaps
|
||||
return trimmed_start_gap
|
||||
@@ -727,7 +692,7 @@ where
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use discrete_range_map::test_ranges::ie;
|
||||
/// use discrete_range_map::inclusive_interval::ie;
|
||||
/// use discrete_range_map::DiscreteRangeMap;
|
||||
///
|
||||
/// let map = DiscreteRangeMap::from_slice_strict([
|
||||
@@ -765,7 +730,7 @@ where
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use discrete_range_map::test_ranges::ie;
|
||||
/// use discrete_range_map::inclusive_interval::ie;
|
||||
/// use discrete_range_map::{DiscreteRangeMap, OverlapError};
|
||||
///
|
||||
/// let mut map = DiscreteRangeMap::new();
|
||||
@@ -865,7 +830,7 @@ where
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use discrete_range_map::test_ranges::ie;
|
||||
/// use discrete_range_map::inclusive_interval::ie;
|
||||
/// use discrete_range_map::{DiscreteRangeMap, OverlapError};
|
||||
///
|
||||
/// let mut map = DiscreteRangeMap::from_slice_strict([
|
||||
@@ -953,7 +918,7 @@ where
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use discrete_range_map::test_ranges::ie;
|
||||
/// use discrete_range_map::inclusive_interval::ie;
|
||||
/// use discrete_range_map::{DiscreteRangeMap, OverlapError};
|
||||
///
|
||||
/// let mut map = DiscreteRangeMap::from_slice_strict([
|
||||
@@ -1054,7 +1019,7 @@ where
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use discrete_range_map::test_ranges::ie;
|
||||
/// use discrete_range_map::inclusive_interval::ie;
|
||||
/// use discrete_range_map::{DiscreteRangeMap, OverlapError};
|
||||
///
|
||||
/// let mut map = DiscreteRangeMap::from_slice_strict([
|
||||
@@ -1127,7 +1092,7 @@ where
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use discrete_range_map::test_ranges::ie;
|
||||
/// use discrete_range_map::inclusive_interval::ie;
|
||||
/// use discrete_range_map::{DiscreteRangeMap, OverlapError};
|
||||
///
|
||||
/// let mut map = DiscreteRangeMap::from_slice_strict([
|
||||
@@ -1215,7 +1180,7 @@ where
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use discrete_range_map::test_ranges::ie;
|
||||
/// use discrete_range_map::inclusive_interval::ie;
|
||||
/// use discrete_range_map::DiscreteRangeMap;
|
||||
///
|
||||
/// let mut map =
|
||||
@@ -1254,7 +1219,7 @@ where
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use discrete_range_map::test_ranges::ie;
|
||||
/// use discrete_range_map::inclusive_interval::ie;
|
||||
/// use discrete_range_map::DiscreteRangeMap;
|
||||
///
|
||||
/// let map = DiscreteRangeMap::from_slice_strict([
|
||||
@@ -1288,7 +1253,7 @@ where
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use discrete_range_map::test_ranges::ie;
|
||||
/// use discrete_range_map::inclusive_interval::ie;
|
||||
/// use discrete_range_map::DiscreteRangeMap;
|
||||
///
|
||||
/// let slice =
|
||||
@@ -1296,7 +1261,7 @@ where
|
||||
///
|
||||
/// let map: DiscreteRangeMap<_, _, _> =
|
||||
/// DiscreteRangeMap::from_iter_strict(
|
||||
/// slice.into_iter().filter(|(range, _)| range.start > 2),
|
||||
/// slice.into_iter().filter(|(range, _)| range.start() > 2),
|
||||
/// )
|
||||
/// .unwrap();
|
||||
/// ```
|
||||
@@ -1332,7 +1297,7 @@ impl<I, K, V> DiscreteRangeMap<I, K, V> {
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use discrete_range_map::test_ranges::ie;
|
||||
/// use discrete_range_map::inclusive_interval::ie;
|
||||
/// use discrete_range_map::DiscreteRangeMap;
|
||||
///
|
||||
/// let mut map = DiscreteRangeMap::new();
|
||||
@@ -1350,7 +1315,7 @@ impl<I, K, V> DiscreteRangeMap<I, K, V> {
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use discrete_range_map::test_ranges::ie;
|
||||
/// use discrete_range_map::inclusive_interval::ie;
|
||||
/// use discrete_range_map::DiscreteRangeMap;
|
||||
///
|
||||
/// let mut map = DiscreteRangeMap::new();
|
||||
@@ -1368,7 +1333,7 @@ impl<I, K, V> DiscreteRangeMap<I, K, V> {
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use discrete_range_map::test_ranges::ie;
|
||||
/// use discrete_range_map::inclusive_interval::ie;
|
||||
/// use discrete_range_map::DiscreteRangeMap;
|
||||
///
|
||||
/// let map = DiscreteRangeMap::from_slice_strict([
|
||||
@@ -1394,7 +1359,7 @@ impl<I, K, V> DiscreteRangeMap<I, K, V> {
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use discrete_range_map::test_ranges::ie;
|
||||
/// use discrete_range_map::inclusive_interval::ie;
|
||||
/// use discrete_range_map::DiscreteRangeMap;
|
||||
///
|
||||
/// let mut map = DiscreteRangeMap::from_slice_strict([
|
||||
@@ -1422,7 +1387,7 @@ impl<I, K, V> DiscreteRangeMap<I, K, V> {
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use discrete_range_map::test_ranges::ie;
|
||||
/// use discrete_range_map::inclusive_interval::ie;
|
||||
/// use discrete_range_map::DiscreteRangeMap;
|
||||
///
|
||||
/// let map = DiscreteRangeMap::from_slice_strict([
|
||||
@@ -1443,7 +1408,7 @@ impl<I, K, V> DiscreteRangeMap<I, K, V> {
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// 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([
|
||||
/// (ie(1, 4), false),
|
||||
@@ -1463,12 +1428,12 @@ impl<I, K, V> DiscreteRangeMap<I, K, V> {
|
||||
|
||||
// Helper Functions ==========================
|
||||
|
||||
fn invalid_range_panic<Q, I>(range: Q)
|
||||
pub(crate) fn invalid_range_panic<Q, I>(range: Q)
|
||||
where
|
||||
I: PointType,
|
||||
Q: RangeType<I>,
|
||||
{
|
||||
if !is_valid_range(range) {
|
||||
if !range.is_valid() {
|
||||
panic!(
|
||||
"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 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};
|
||||
|
||||
//only every other number to allow mathematical_overlapping_definition
|
||||
@@ -2339,24 +2304,24 @@ mod tests {
|
||||
fn cut_range_bounds_should_return_valid_ranges() {
|
||||
let result: CutResult<i8> = cut_range(ie(3, 8), ie(5, 8));
|
||||
if let Some(x) = result.before_cut {
|
||||
assert!(is_valid_range(x));
|
||||
assert!(x.is_valid());
|
||||
}
|
||||
if let Some(x) = result.inside_cut {
|
||||
assert!(is_valid_range(x));
|
||||
assert!(x.is_valid());
|
||||
}
|
||||
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));
|
||||
if let Some(x) = result.before_cut {
|
||||
assert!(is_valid_range(x));
|
||||
assert!(x.is_valid());
|
||||
}
|
||||
if let Some(x) = result.inside_cut {
|
||||
assert!(is_valid_range(x));
|
||||
assert!(x.is_valid());
|
||||
}
|
||||
if let Some(x) = result.after_cut {
|
||||
assert!(is_valid_range(x));
|
||||
assert!(x.is_valid());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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/>.
|
||||
*/
|
||||
|
||||
//! The module containing [`DiscreteRangeSet`] and related types. Since
|
||||
//! [`DiscreteRangeSet`] is just a wrapper around [`DiscreteRangeMap`], most of
|
||||
//! the methods' docs will point towards the equivalent method's docs on
|
||||
//! [`DiscreteRangeMap`] to prevent inconsistency.
|
||||
//! A module containing [`DiscreteRangeSet`] and related types.
|
||||
//!
|
||||
//! Since [`DiscreteRangeSet`] is just a wrapper around
|
||||
//! [`DiscreteRangeMap`], most of the methods' docs will point towards the
|
||||
//! equivalent method's docs on [`DiscreteRangeMap`] to prevent
|
||||
//! inconsistency.
|
||||
|
||||
use core::fmt;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
@@ -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
@@ -35,7 +35,7 @@ along with discrete_range_map. If not, see <https://www.gnu.org/licenses/>.
|
||||
//! ## Example using an Inclusive-Exclusive range
|
||||
//!
|
||||
//! ```rust
|
||||
//! use discrete_range_map::test_ranges::ie;
|
||||
//! use discrete_range_map::inclusive_interval::ie;
|
||||
//! use discrete_range_map::DiscreteRangeMap;
|
||||
//!
|
||||
//! let mut map = DiscreteRangeMap::new();
|
||||
@@ -53,7 +53,7 @@ along with discrete_range_map. If not, see <https://www.gnu.org/licenses/>.
|
||||
//! ```rust
|
||||
//! use std::ops::{Bound, RangeBounds};
|
||||
//!
|
||||
//! use discrete_range_map::test_ranges::ie;
|
||||
//! use discrete_range_map::inclusive_interval::ie;
|
||||
//! use discrete_range_map::{
|
||||
//! DiscreteFinite, DiscreteRangeMap, InclusiveInterval,
|
||||
//! 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>>
|
||||
//! impl From<InclusiveInterval<i8>> for Reservation {
|
||||
//! fn from(value: InclusiveInterval<i8>) -> Self {
|
||||
//! if value.end == i8::MAX {
|
||||
//! Reservation::Infinite(value.start)
|
||||
//! if value.end() == i8::MAX {
|
||||
//! Reservation::Infinite(value.start())
|
||||
//! } else {
|
||||
//! Reservation::Finite(
|
||||
//! value.start,
|
||||
//! value.end.up().unwrap(),
|
||||
//! value.start(),
|
||||
//! 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
|
||||
//! 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
|
||||
//!
|
||||
//! 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
|
||||
//! // returned by `get_entry_at_point()`, for example:
|
||||
//!
|
||||
//! use discrete_range_map::inclusive_interval::uu;
|
||||
//! use discrete_range_map::{DiscreteRangeMap, InclusiveInterval};
|
||||
//!
|
||||
//! 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));
|
||||
//!
|
||||
//! assert_eq!(
|
||||
//! gap,
|
||||
//! Err(InclusiveInterval {
|
||||
//! start: WithInfinity::Finite(0),
|
||||
//! end: WithInfinity::Infinity,
|
||||
//! })
|
||||
//! );
|
||||
//! assert_eq!(gap, Err(uu()));
|
||||
//! ```
|
||||
//!
|
||||
//! ### Invalid Ranges
|
||||
@@ -276,7 +275,8 @@ along with discrete_range_map. If not, see <https://www.gnu.org/licenses/>.
|
||||
//! ### Overlap
|
||||
//!
|
||||
//! 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
|
||||
//!
|
||||
@@ -384,11 +384,11 @@ pub(crate) mod utils;
|
||||
pub mod discrete_finite;
|
||||
pub mod discrete_range_map;
|
||||
pub mod discrete_range_set;
|
||||
pub mod test_ranges;
|
||||
pub mod inclusive_interval;
|
||||
|
||||
pub use crate::discrete_finite::DiscreteFinite;
|
||||
pub use crate::discrete_range_map::{
|
||||
DiscreteRangeMap, InclusiveInterval, InclusiveRange, OverlapError,
|
||||
PointType, RangeType,
|
||||
DiscreteRangeMap, InclusiveRange, OverlapError, PointType, RangeType,
|
||||
};
|
||||
pub use crate::discrete_range_set::DiscreteRangeSet;
|
||||
pub use crate::inclusive_interval::InclusiveInterval;
|
||||
|
||||
@@ -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
@@ -19,7 +19,7 @@ along with discrete_range_map. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
where
|
||||
@@ -190,20 +190,12 @@ where
|
||||
|
||||
//only return valid ranges
|
||||
return CutResult {
|
||||
before_cut: result.before_cut.filter(|x| is_valid_range(*x)),
|
||||
inside_cut: result.inside_cut.filter(|x| is_valid_range(*x)),
|
||||
after_cut: result.after_cut.filter(|x| is_valid_range(*x)),
|
||||
before_cut: result.before_cut.filter(|x| x.is_valid()),
|
||||
inside_cut: result.inside_cut.filter(|x| x.is_valid()),
|
||||
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
|
||||
where
|
||||
I: PointType,
|
||||
|
||||
Reference in New Issue
Block a user