made IncludedInterval helper methods apart of the trait to make them more flexible and fixed doctests

This commit is contained in:
ripytide
2023-06-18 09:02:55 +01:00
parent bae726a324
commit eb7f93fa61
7 changed files with 210 additions and 172 deletions
Generated
+1 -1
View File
@@ -36,7 +36,7 @@ checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
[[package]]
name = "discrete_range_map"
version = "0.4.2"
version = "0.4.3"
dependencies = [
"btree_monstrousity",
"either",
+99 -69
View File
@@ -21,6 +21,7 @@ use std::cmp::Ordering;
use std::fmt::{self, Debug};
use std::iter::once;
use std::marker::PhantomData;
use std::ops::RangeBounds;
use btree_monstrousity::btree_map::{
IntoIter as BTreeMapIntoIter, SearchBoundCustom,
@@ -33,7 +34,7 @@ use serde::ser::SerializeSeq;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::discrete_finite::DiscreteFinite;
use crate::interval::Interval;
use crate::interval::InclusiveInterval;
use crate::utils::{cmp_point_with_range, cut_range, is_valid_range, overlaps};
/// An ordered map of non-overlapping ranges based on [`BTreeMap`].
@@ -90,7 +91,7 @@ pub struct OverlapError;
impl<I, K, V> DiscreteRangeMap<I, K, V>
where
I: Ord + Copy + DiscreteFinite,
K: FiniteRange<I> + Copy + From<Interval<I>>,
K: InclusiveRange<I> + Copy + From<InclusiveInterval<I>>,
{
/// Returns `true` if the given range overlaps any of the
/// other ranges in the map, and `false` if not.
@@ -118,7 +119,7 @@ where
/// ```
pub fn overlaps<Q>(&self, range: Q) -> bool
where
Q: FiniteRange<I> + Copy,
Q: InclusiveRange<I> + Copy,
{
invalid_range_panic(range);
@@ -158,7 +159,7 @@ where
range: Q,
) -> impl DoubleEndedIterator<Item = (&K, &V)>
where
Q: FiniteRange<I> + Copy,
Q: InclusiveRange<I> + Copy,
{
invalid_range_panic(range);
@@ -206,7 +207,7 @@ where
range: Q,
) -> impl DoubleEndedIterator<Item = (&K, &mut V)>
where
Q: FiniteRange<I> + Copy,
Q: InclusiveRange<I> + Copy,
{
invalid_range_panic(range);
@@ -315,7 +316,7 @@ where
.get_key_value(overlapping_comp(point))
.ok_or_else(|| K::from(self.get_gap_at_raw(point)))
}
fn get_gap_at_raw(&self, point: I) -> Interval<I> {
fn get_gap_at_raw(&self, point: I) -> InclusiveInterval<I> {
let lower = self
.inner
.upper_bound(overlapping_comp(point), SearchBoundCustom::Included);
@@ -323,7 +324,7 @@ where
.inner
.lower_bound(overlapping_comp(point), SearchBoundCustom::Included);
Interval {
InclusiveInterval {
start: lower
.key()
.map_or(I::MIN, |lower| lower.end().up().unwrap()),
@@ -371,7 +372,7 @@ where
range: Q,
) -> impl Iterator<Item = (K, V)> + '_
where
Q: FiniteRange<I> + Copy + 'a,
Q: InclusiveRange<I> + Copy + 'a,
{
invalid_range_panic(range);
@@ -435,7 +436,7 @@ where
range: Q,
) -> impl Iterator<Item = (K, V)> + '_
where
Q: FiniteRange<I> + Copy + 'a,
Q: InclusiveRange<I> + Copy + 'a,
V: Clone,
{
invalid_range_panic(range);
@@ -466,7 +467,7 @@ where
single_overlapping_range: K,
) -> impl Iterator<Item = (K, V)>
where
Q: FiniteRange<I> + Copy,
Q: InclusiveRange<I> + Copy,
V: Clone,
{
invalid_range_panic(range);
@@ -494,7 +495,7 @@ where
right_overlapping: Option<K>,
) -> impl Iterator<Item = (K, V)> + '_
where
Q: FiniteRange<I> + Copy + 'a,
Q: InclusiveRange<I> + Copy + 'a,
V: Clone,
{
invalid_range_panic(range);
@@ -547,7 +548,7 @@ where
.into_iter()
.chain(self.remove_overlapping(range).map(|(key, value)| {
(
K::from(Interval {
K::from(InclusiveInterval {
start: key.start(),
end: key.end(),
}),
@@ -587,7 +588,7 @@ where
/// ```
pub fn gaps<'a, Q>(&'a self, outer_range: Q) -> impl Iterator<Item = K> + '_
where
Q: FiniteRange<I> + Copy + 'a,
Q: InclusiveRange<I> + Copy + 'a,
{
invalid_range_panic(outer_range);
@@ -636,7 +637,7 @@ where
let inner_gaps = overlapping
.tuple_windows()
.map(|(first, second)| {
K::from(Interval {
K::from(InclusiveInterval {
start: first.1.up().unwrap(),
end: second.0.down().unwrap(),
})
@@ -678,7 +679,7 @@ where
/// ```
pub fn contains_range<Q>(&self, range: Q) -> bool
where
Q: FiniteRange<I> + Copy,
Q: InclusiveRange<I> + Copy,
{
invalid_range_panic(range);
@@ -749,15 +750,17 @@ where
let matching_end = get_end(self, &value);
let returning = match (matching_start, matching_end) {
(Some(matching_start), Some(matching_end)) => K::from(Interval {
start: matching_start.start(),
end: matching_end.end(),
}),
(Some(matching_start), None) => K::from(Interval {
(Some(matching_start), Some(matching_end)) => {
K::from(InclusiveInterval {
start: matching_start.start(),
end: matching_end.end(),
})
}
(Some(matching_start), None) => K::from(InclusiveInterval {
start: matching_start.start(),
end: range.end(),
}),
(None, Some(matching_end)) => K::from(Interval {
(None, Some(matching_end)) => K::from(InclusiveInterval {
start: range.start(),
end: matching_end.end(),
}),
@@ -1210,9 +1213,9 @@ impl<I, K, V> DiscreteRangeMap<I, K, V> {
///
/// # Examples
/// ```
/// use discrete_range_map::{DiscreteRangeMap, Interval};
/// use discrete_range_map::{DiscreteRangeMap, InclusiveInterval};
///
/// let map: DiscreteRangeMap<i8, Interval<i8>, bool> =
/// let map: DiscreteRangeMap<i8, InclusiveInterval<i8>, bool> =
/// DiscreteRangeMap::new();
/// ```
pub fn new() -> Self {
@@ -1359,7 +1362,7 @@ impl<I, K, V> DiscreteRangeMap<I, K, V> {
fn invalid_range_panic<Q, I>(range: Q)
where
Q: FiniteRange<I>,
Q: InclusiveRange<I>,
I: Ord,
{
if !is_valid_range(range) {
@@ -1371,7 +1374,7 @@ where
fn double_comp<K, I>() -> impl FnMut(&K, &K) -> Ordering
where
K: FiniteRange<I>,
K: InclusiveRange<I>,
I: Ord + DiscreteFinite,
{
|inner_range: &K, new_range: &K| new_range.start().cmp(&inner_range.start())
@@ -1379,14 +1382,14 @@ where
fn overlapping_comp<I, K>(point: I) -> impl FnMut(&K) -> Ordering
where
I: Ord + Copy,
K: FiniteRange<I> + Copy,
K: InclusiveRange<I> + Copy,
{
move |inner_range: &K| cmp_point_with_range(point, *inner_range)
}
fn touching_start_comp<I, K>(start: I) -> impl FnMut(&K) -> Ordering
where
I: Ord + Copy + DiscreteFinite,
K: FiniteRange<I>,
K: InclusiveRange<I>,
{
move |inner_range: &K| match inner_range.end().up() {
Some(touching_position) => start.cmp(&touching_position),
@@ -1396,7 +1399,7 @@ where
fn touching_end_comp<I, K>(end: I) -> impl FnMut(&K) -> Ordering
where
I: Ord + Copy + DiscreteFinite,
K: FiniteRange<I>,
K: InclusiveRange<I>,
{
move |inner_range: &K| match inner_range.start().down() {
Some(touching_position) => end.cmp(&touching_position),
@@ -1404,10 +1407,37 @@ where
}
}
/// A range that has Finite **Inclusive** end-points.
pub trait FiniteRange<I> {
/// A range that has **Inclusive** end-points.
pub trait InclusiveRange<I>: RangeBounds<I> {
fn start(&self) -> I;
fn end(&self) -> I;
///requires that self comes before other and they don't overlap
fn touches_ordered(&self, other: &Self) -> bool
where
I: DiscreteFinite + Ord,
{
self.end() == other.start().down().unwrap()
}
///requires that self comes before other
fn overlaps_ordered(&self, other: &Self) -> bool
where
I: DiscreteFinite + Ord,
{
self.contains(&other.start()) || self.contains(&other.end())
}
///requires that self comes before other
fn merge_ordered(&self, other: &Self) -> Self
where
Self: From<InclusiveInterval<I>>,
{
Self::from(InclusiveInterval {
start: self.start(),
end: other.end(),
})
}
}
// Trait Impls ==========================
@@ -1470,7 +1500,7 @@ where
impl<'de, I, K, V> Deserialize<'de> for DiscreteRangeMap<I, K, V>
where
I: Ord + Copy + DiscreteFinite,
K: FiniteRange<I> + Copy + From<Interval<I>> + Deserialize<'de>,
K: InclusiveRange<I> + Copy + From<InclusiveInterval<I>> + Deserialize<'de>,
V: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
@@ -1494,7 +1524,7 @@ struct DiscreteRangeMapVisitor<I, K, V> {
impl<'de, I, K, V> Visitor<'de> for DiscreteRangeMapVisitor<I, K, V>
where
I: Ord + Copy + DiscreteFinite,
K: FiniteRange<I> + Copy + From<Interval<I>> + Deserialize<'de>,
K: InclusiveRange<I> + Copy + From<InclusiveInterval<I>> + Deserialize<'de>,
V: Deserialize<'de>,
{
type Value = DiscreteRangeMap<I, K, V>;
@@ -1531,7 +1561,7 @@ mod tests {
pub(crate) const NUMBERS_DOMAIN: &'static [i8] =
&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
fn basic() -> DiscreteRangeMap<i8, Interval<i8>, bool> {
fn basic() -> DiscreteRangeMap<i8, InclusiveInterval<i8>, bool> {
DiscreteRangeMap::from_slice_strict([
(ui(4), false),
(ee(5, 7), true),
@@ -1540,7 +1570,7 @@ mod tests {
])
.unwrap()
}
fn basic_slice() -> [(Interval<i8>, bool); 4] {
fn basic_slice() -> [(InclusiveInterval<i8>, bool); 4] {
[
(ui(4), false),
(ee(5, 7), true),
@@ -1583,10 +1613,10 @@ mod tests {
);
}
fn assert_insert_strict<const N: usize>(
mut before: DiscreteRangeMap<i8, Interval<i8>, bool>,
to_insert: (Interval<i8>, bool),
mut before: DiscreteRangeMap<i8, InclusiveInterval<i8>, bool>,
to_insert: (InclusiveInterval<i8>, bool),
result: Result<(), OverlapError>,
after: [(Interval<i8>, bool); N],
after: [(InclusiveInterval<i8>, bool); N],
) {
assert_eq!(before.insert_strict(to_insert.0, to_insert.1), result);
assert_eq!(before, DiscreteRangeMap::from_slice_strict(after).unwrap())
@@ -1598,7 +1628,7 @@ mod tests {
for overlap_range in all_valid_test_bounds() {
//you can't overlap nothing
assert!(
DiscreteRangeMap::<i8, Interval<i8>, ()>::new()
DiscreteRangeMap::<i8, InclusiveInterval<i8>, ()>::new()
.overlapping(overlap_range)
.next()
.is_none()
@@ -1702,10 +1732,10 @@ mod tests {
);
}
fn assert_remove_overlapping<const N: usize, const Y: usize>(
mut before: DiscreteRangeMap<i8, Interval<i8>, bool>,
to_remove: Interval<i8>,
result: [(Interval<i8>, bool); N],
after: [(Interval<i8>, bool); Y],
mut before: DiscreteRangeMap<i8, InclusiveInterval<i8>, bool>,
to_remove: InclusiveInterval<i8>,
result: [(InclusiveInterval<i8>, bool); N],
after: [(InclusiveInterval<i8>, bool); Y],
) {
assert_eq!(
before.remove_overlapping(to_remove).collect::<Vec<_>>(),
@@ -1752,10 +1782,10 @@ mod tests {
);
}
fn assert_cut<const N: usize, const Y: usize>(
mut before: DiscreteRangeMap<i8, Interval<i8>, bool>,
to_cut: Interval<i8>,
result: [(Interval<i8>, bool); Y],
after: [(Interval<i8>, bool); N],
mut before: DiscreteRangeMap<i8, InclusiveInterval<i8>, bool>,
to_cut: InclusiveInterval<i8>,
result: [(InclusiveInterval<i8>, bool); Y],
after: [(InclusiveInterval<i8>, bool); N],
) {
assert_eq!(before.cut(to_cut).collect::<Vec<_>>(), result);
assert_eq!(before, DiscreteRangeMap::from_slice_strict(after).unwrap());
@@ -1791,9 +1821,9 @@ mod tests {
);
}
fn assert_gaps<const N: usize>(
map: DiscreteRangeMap<i8, Interval<i8>, bool>,
outer_range: Interval<i8>,
result: [Interval<i8>; N],
map: DiscreteRangeMap<i8, InclusiveInterval<i8>, bool>,
outer_range: InclusiveInterval<i8>,
result: [InclusiveInterval<i8>; N],
) {
assert_eq!(map.gaps(outer_range).collect::<Vec<_>>(), result);
}
@@ -1841,10 +1871,10 @@ mod tests {
);
}
fn assert_insert_merge_touching<const N: usize>(
mut before: DiscreteRangeMap<i8, Interval<i8>, bool>,
to_insert: (Interval<i8>, bool),
result: Result<Interval<i8>, OverlapError>,
after: [(Interval<i8>, bool); N],
mut before: DiscreteRangeMap<i8, InclusiveInterval<i8>, bool>,
to_insert: (InclusiveInterval<i8>, bool),
result: Result<InclusiveInterval<i8>, OverlapError>,
after: [(InclusiveInterval<i8>, bool); N],
) {
assert_eq!(
before.insert_merge_touching(to_insert.0, to_insert.1),
@@ -1897,10 +1927,10 @@ mod tests {
);
}
fn assert_insert_merge_touching_if_values_equal<const N: usize>(
mut before: DiscreteRangeMap<i8, Interval<i8>, bool>,
to_insert: (Interval<i8>, bool),
result: Result<Interval<i8>, OverlapError>,
after: [(Interval<i8>, bool); N],
mut before: DiscreteRangeMap<i8, InclusiveInterval<i8>, bool>,
to_insert: (InclusiveInterval<i8>, bool),
result: Result<InclusiveInterval<i8>, OverlapError>,
after: [(InclusiveInterval<i8>, bool); N],
) {
assert_eq!(
before.insert_merge_touching_if_values_equal(
@@ -1961,10 +1991,10 @@ mod tests {
);
}
fn assert_insert_merge_overlapping<const N: usize>(
mut before: DiscreteRangeMap<i8, Interval<i8>, bool>,
to_insert: (Interval<i8>, bool),
result: Interval<i8>,
after: [(Interval<i8>, bool); N],
mut before: DiscreteRangeMap<i8, InclusiveInterval<i8>, bool>,
to_insert: (InclusiveInterval<i8>, bool),
result: InclusiveInterval<i8>,
after: [(InclusiveInterval<i8>, bool); N],
) {
assert_eq!(
before.insert_merge_overlapping(to_insert.0, to_insert.1),
@@ -2037,10 +2067,10 @@ mod tests {
);
}
fn assert_insert_merge_touching_or_overlapping<const N: usize>(
mut before: DiscreteRangeMap<i8, Interval<i8>, bool>,
to_insert: (Interval<i8>, bool),
result: Interval<i8>,
after: [(Interval<i8>, bool); N],
mut before: DiscreteRangeMap<i8, InclusiveInterval<i8>, bool>,
to_insert: (InclusiveInterval<i8>, bool),
result: InclusiveInterval<i8>,
after: [(InclusiveInterval<i8>, bool); N],
) {
assert_eq!(
before
@@ -2138,7 +2168,7 @@ mod tests {
}
}
}
fn con(x: Option<Interval<i8>>, point: &i8) -> bool {
fn con(x: Option<InclusiveInterval<i8>>, point: &i8) -> bool {
match x {
Some(y) => contains_point(y, *point),
None => false,
@@ -2172,7 +2202,7 @@ mod tests {
// Test Helper Functions
//======================
fn all_non_overlapping_test_bound_entries()
-> Vec<(Interval<i8>, Interval<i8>)> {
-> Vec<(InclusiveInterval<i8>, InclusiveInterval<i8>)> {
let mut output = Vec::new();
for test_bounds1 in all_valid_test_bounds() {
for test_bounds2 in all_valid_test_bounds() {
@@ -2185,12 +2215,12 @@ mod tests {
return output;
}
fn all_valid_test_bounds() -> Vec<Interval<i8>> {
fn all_valid_test_bounds() -> Vec<InclusiveInterval<i8>> {
let mut output = Vec::new();
for i in NUMBERS {
for j in NUMBERS {
if i <= j {
output.push(Interval { start: *i, end: *j });
output.push(InclusiveInterval { start: *i, end: *j });
}
}
}
+11 -11
View File
@@ -7,9 +7,9 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::discrete_finite::DiscreteFinite;
use crate::discrete_range_map::{
FiniteRange, IntoIter as DiscreteRangeMapIntoIter,
InclusiveRange, IntoIter as DiscreteRangeMapIntoIter,
};
use crate::interval::Interval;
use crate::interval::InclusiveInterval;
use crate::{DiscreteRangeMap, OverlapError};
/// An ordered set of non-overlapping ranges based on [`DiscreteRangeMap`].
@@ -31,12 +31,12 @@ pub struct DiscreteRangeSet<I, K> {
impl<I, K> DiscreteRangeSet<I, K>
where
I: Ord + Copy + DiscreteFinite,
K: FiniteRange<I> + Copy + From<Interval<I>>,
K: InclusiveRange<I> + Copy + From<InclusiveInterval<I>>,
{
/// See [`DiscreteRangeMap::overlaps()`] for more details.
pub fn overlaps<Q>(&self, range: Q) -> bool
where
Q: FiniteRange<I> + Copy,
Q: InclusiveRange<I> + Copy,
{
self.inner.overlaps(range)
}
@@ -46,7 +46,7 @@ where
range: Q,
) -> impl DoubleEndedIterator<Item = &K>
where
Q: FiniteRange<I> + Copy,
Q: InclusiveRange<I> + Copy,
{
self.inner.overlapping(range).map(first)
}
@@ -64,28 +64,28 @@ where
range: Q,
) -> impl Iterator<Item = K> + '_
where
Q: FiniteRange<I> + Copy + 'a,
Q: InclusiveRange<I> + Copy + 'a,
{
self.inner.remove_overlapping(range).map(first)
}
/// See [`DiscreteRangeMap::cut()`] for more details.
pub fn cut<'a, Q>(&'a mut self, range: Q) -> impl Iterator<Item = K> + '_
where
Q: FiniteRange<I> + Copy + 'a,
Q: InclusiveRange<I> + Copy + 'a,
{
self.inner.cut(range).map(first)
}
/// See [`DiscreteRangeMap::gaps()`] for more details.
pub fn gaps<'a, Q>(&'a self, range: Q) -> impl Iterator<Item = K> + '_
where
Q: FiniteRange<I> + Copy + 'a,
Q: InclusiveRange<I> + Copy + 'a,
{
self.inner.gaps(range)
}
/// See [`DiscreteRangeMap::contains_range()`] for more details.
pub fn contains_range<Q>(&self, range: Q) -> bool
where
Q: FiniteRange<I> + Copy,
Q: InclusiveRange<I> + Copy,
{
self.inner.contains_range(range)
}
@@ -218,7 +218,7 @@ where
impl<'de, I, K> Deserialize<'de> for DiscreteRangeSet<I, K>
where
I: Ord + Copy + DiscreteFinite,
K: FiniteRange<I> + Copy + From<Interval<I>> + Deserialize<'de>,
K: InclusiveRange<I> + Copy + From<InclusiveInterval<I>> + Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
@@ -239,7 +239,7 @@ struct DiscreteRangeSetVisitor<I, K> {
impl<'de, I, K> Visitor<'de> for DiscreteRangeSetVisitor<I, K>
where
I: Ord + Copy + DiscreteFinite,
K: FiniteRange<I> + Copy + From<Interval<I>> + Deserialize<'de>,
K: InclusiveRange<I> + Copy + From<InclusiveInterval<I>> + Deserialize<'de>,
{
type Value = DiscreteRangeSet<I, K>;
+16 -25
View File
@@ -17,44 +17,35 @@ 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/>.
*/
use crate::discrete_range_map::FiniteRange;
use std::ops::{Bound, RangeBounds};
use serde::{Deserialize, Serialize};
use crate::discrete_range_map::InclusiveRange;
use crate::DiscreteFinite;
///both ends are always included
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Interval<I> {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct InclusiveInterval<I> {
pub start: I,
pub end: I,
}
impl<I> Interval<I>
impl<I> InclusiveInterval<I> where I: Ord + DiscreteFinite + Copy {}
impl<I> RangeBounds<I> for InclusiveInterval<I>
where
I: Ord + DiscreteFinite + Copy,
I: Copy,
{
pub fn contains(&self, point: I) -> bool {
point >= self.start && point <= self.end
fn start_bound(&self) -> Bound<&I> {
Bound::Included(&self.start)
}
///requires that self comes before other and they don't overlap
pub fn touches_ordered(&self, other: &Self) -> bool {
self.end == other.start.down().unwrap()
}
///requires that self comes before other
pub fn overlaps_ordered(&self, other: &Self) -> bool {
self.contains(other.start) || self.contains(other.end)
}
///requires that self comes before other
pub fn merge_ordered(self, other: &Self) -> Self {
Interval {
start: self.start,
end: other.end,
}
fn end_bound(&self) -> Bound<&I> {
Bound::Included(&self.end)
}
}
impl<I> FiniteRange<I> for Interval<I>
impl<I> InclusiveRange<I> for InclusiveInterval<I>
where
I: Copy,
{
+35 -18
View File
@@ -46,21 +46,40 @@ along with discrete_range_map. If not, see <https://www.gnu.org/licenses/>.
//! ## Example using a custom range type
//!
//! ```rust
//! use std::ops::{Bound, RangeBounds};
//! use discrete_range_map::test_ranges::ie;
//! use discrete_range_map::{
//! DiscreteFinite, DiscreteRangeMap, FiniteRange, Interval,
//! DiscreteFinite, DiscreteRangeMap, InclusiveInterval,
//! InclusiveRange,
//! };
//!
//! #[derive(Debug, Copy, Clone)]
//! enum Reservation {
//! // Start, End (Inclusive-Exclusive)
//! // Start, End (Inclusive-Inclusive)
//! Finite(i8, i8),
//! // Start (Inclusive-Forever)
//! // Start (Inclusive-Infinity)
//! Infinite(i8),
//! }
//!
//! // First, we need to implement FiniteRange
//! impl FiniteRange<i8> for Reservation {
//! // First, we need to implement RangeBounds since its a super-trait
//! // of InclusiveRange
//! impl RangeBounds<i8> for Reservation {
//! fn start_bound(&self) -> Bound<&i8> {
//! match self {
//! Reservation::Finite(start, _) => Bound::Included(start),
//! Reservation::Infinite(start) => Bound::Included(start),
//! }
//! }
//! fn end_bound(&self) -> Bound<&i8> {
//! match self {
//! Reservation::Finite(_, end) => Bound::Included(end),
//! Reservation::Infinite(_) => Bound::Included(&i8::MAX),
//! }
//! }
//! }
//!
//! // First, we need to implement InclusiveRange
//! impl InclusiveRange<i8> for Reservation {
//! fn start(&self) -> i8 {
//! match self {
//! Reservation::Finite(start, _) => *start,
@@ -69,23 +88,21 @@ along with discrete_range_map. If not, see <https://www.gnu.org/licenses/>.
//! }
//! fn end(&self) -> i8 {
//! match self {
//! //the end is exclusive so we take off 1 with checking
//! //for compile time error overflow detection
//! Reservation::Finite(_, end) => end.down().unwrap(),
//! Reservation::Finite(_, end) => *end,
//! Reservation::Infinite(_) => i8::MAX,
//! }
//! }
//! }
//!
//! // Second, we need to implement From<Interval<i8>>
//! impl From<Interval<i8>> for Reservation {
//! fn from(bounds: Interval<i8>) -> Self {
//! if bounds.end == i8::MAX {
//! Reservation::Infinite(bounds.start)
//! // 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)
//! } else {
//! Reservation::Finite(
//! bounds.start,
//! bounds.end.up().unwrap(),
//! value.start,
//! value.end.up().unwrap(),
//! )
//! }
//! }
@@ -94,7 +111,7 @@ along with discrete_range_map. If not, see <https://www.gnu.org/licenses/>.
//! // Next we can create a custom typed DiscreteRangeMap
//! let reservation_map = DiscreteRangeMap::from_slice_strict([
//! (Reservation::Finite(10, 20), "Ferris".to_string()),
//! (Reservation::Infinite(20), "Corro".to_string()),
//! (Reservation::Infinite(21), "Corro".to_string()),
//! ])
//! .unwrap();
//!
@@ -277,7 +294,7 @@ pub mod discrete_range_set;
pub use crate::discrete_finite::DiscreteFinite;
pub use crate::discrete_range_map::{
DiscreteRangeMap, FiniteRange, OverlapError,
DiscreteRangeMap, InclusiveRange, OverlapError,
};
pub use crate::discrete_range_set::DiscreteRangeSet;
pub use crate::interval::Interval;
pub use crate::interval::InclusiveInterval;
+17 -17
View File
@@ -1,26 +1,26 @@
use crate::discrete_finite::DiscreteFinite;
use crate::interval::Interval;
use crate::interval::InclusiveInterval;
pub fn uu() -> Interval<i8> {
Interval {
pub fn uu() -> InclusiveInterval<i8> {
InclusiveInterval {
start: i8::MIN,
end: i8::MAX,
}
}
pub fn ui(x: i8) -> Interval<i8> {
Interval {
pub fn ui(x: i8) -> InclusiveInterval<i8> {
InclusiveInterval {
start: i8::MIN,
end: x,
}
}
pub fn ue(x: i8) -> Interval<i8> {
Interval {
pub fn ue(x: i8) -> InclusiveInterval<i8> {
InclusiveInterval {
start: i8::MIN,
end: x.down().unwrap(),
}
}
pub fn iu(x: i8) -> Interval<i8> {
Interval {
pub fn iu(x: i8) -> InclusiveInterval<i8> {
InclusiveInterval {
start: x,
end: i8::MAX,
}
@@ -28,23 +28,23 @@ pub fn iu(x: i8) -> Interval<i8> {
//fn eu(x: i8) -> TestBounds {
//(Bound::Excluded(x), Bound::Unbounded)
//}
pub fn ii(x1: i8, x2: i8) -> Interval<i8> {
Interval { start: x1, end: x2 }
pub fn ii(x1: i8, x2: i8) -> InclusiveInterval<i8> {
InclusiveInterval { start: x1, end: x2 }
}
pub fn ie(x1: i8, x2: i8) -> Interval<i8> {
Interval {
pub fn ie(x1: i8, x2: i8) -> InclusiveInterval<i8> {
InclusiveInterval {
start: x1,
end: x2.down().unwrap(),
}
}
pub fn ei(x1: i8, x2: i8) -> Interval<i8> {
Interval {
pub fn ei(x1: i8, x2: i8) -> InclusiveInterval<i8> {
InclusiveInterval {
start: x1.up().unwrap(),
end: x2,
}
}
pub fn ee(x1: i8, x2: i8) -> Interval<i8> {
Interval {
pub fn ee(x1: i8, x2: i8) -> InclusiveInterval<i8> {
InclusiveInterval {
start: x1.up().unwrap(),
end: x2.down().unwrap(),
}
+31 -31
View File
@@ -20,13 +20,13 @@ along with discrete_range_map. If not, see <https://www.gnu.org/licenses/>.
use std::cmp::Ordering;
use crate::discrete_finite::DiscreteFinite;
use crate::discrete_range_map::FiniteRange;
use crate::interval::Interval;
use crate::discrete_range_map::InclusiveRange;
use crate::interval::InclusiveInterval;
pub(crate) fn cmp_point_with_range<I, K>(point: I, range: K) -> Ordering
where
I: Ord,
K: FiniteRange<I>,
K: InclusiveRange<I>,
{
if point < range.start() {
Ordering::Less
@@ -49,8 +49,8 @@ pub(crate) enum Config {
}
pub(crate) fn config<I, A, B>(a: A, b: B) -> Config
where
A: FiniteRange<I> + Copy,
B: FiniteRange<I> + Copy,
A: InclusiveRange<I> + Copy,
B: InclusiveRange<I> + Copy,
I: Ord,
{
if a.start() < b.start() {
@@ -71,21 +71,21 @@ where
}
enum SortedConfig<I> {
NonOverlapping(Interval<I>, Interval<I>),
PartialOverlap(Interval<I>, Interval<I>),
Swallowed(Interval<I>, Interval<I>),
NonOverlapping(InclusiveInterval<I>, InclusiveInterval<I>),
PartialOverlap(InclusiveInterval<I>, InclusiveInterval<I>),
Swallowed(InclusiveInterval<I>, InclusiveInterval<I>),
}
fn sorted_config<I, A, B>(a: A, b: B) -> SortedConfig<I>
where
A: FiniteRange<I> + Copy,
B: FiniteRange<I> + Copy,
A: InclusiveRange<I> + Copy,
B: InclusiveRange<I> + Copy,
I: Ord,
{
let ae = Interval {
let ae = InclusiveInterval {
start: a.start(),
end: a.end(),
};
let be = Interval {
let be = InclusiveInterval {
start: b.start(),
end: b.end(),
};
@@ -106,7 +106,7 @@ where
pub(crate) fn contains_point<I, A>(range: A, point: I) -> bool
where
A: FiniteRange<I>,
A: InclusiveRange<I>,
I: Ord,
{
cmp_point_with_range(point, range).is_eq()
@@ -114,14 +114,14 @@ where
#[derive(Debug)]
pub(crate) struct CutResult<I> {
pub(crate) before_cut: Option<Interval<I>>,
pub(crate) inside_cut: Option<Interval<I>>,
pub(crate) after_cut: Option<Interval<I>>,
pub(crate) before_cut: Option<InclusiveInterval<I>>,
pub(crate) inside_cut: Option<InclusiveInterval<I>>,
pub(crate) after_cut: Option<InclusiveInterval<I>>,
}
pub(crate) fn cut_range<I, B, C>(base: B, cut: C) -> CutResult<I>
where
B: FiniteRange<I> + Copy,
C: FiniteRange<I> + Copy,
B: InclusiveRange<I> + Copy,
C: InclusiveRange<I> + Copy,
I: Ord + Copy + DiscreteFinite,
{
let mut result = CutResult {
@@ -132,34 +132,34 @@ where
match config(base, cut) {
Config::LeftFirstNonOverlapping => {
result.before_cut = Some(Interval {
result.before_cut = Some(InclusiveInterval {
start: base.start(),
end: base.end(),
});
}
Config::LeftFirstPartialOverlap => {
result.before_cut = Some(Interval {
result.before_cut = Some(InclusiveInterval {
start: base.start(),
end: cut.start().down().unwrap(),
});
result.inside_cut = Some(Interval {
result.inside_cut = Some(InclusiveInterval {
start: cut.start(),
end: base.end(),
});
}
Config::LeftContainsRight => {
result.before_cut = Some(Interval {
result.before_cut = Some(InclusiveInterval {
start: base.start(),
end: cut.start().down().unwrap(),
});
result.inside_cut = Some(Interval {
result.inside_cut = Some(InclusiveInterval {
start: cut.start(),
end: cut.end(),
});
//if cut is already max then we don't need to have an
//after_cut
if let Some(upped_end) = cut.end().up() {
result.after_cut = Some(Interval {
result.after_cut = Some(InclusiveInterval {
start: upped_end,
end: base.end(),
});
@@ -167,23 +167,23 @@ where
}
Config::RightFirstNonOverlapping => {
result.after_cut = Some(Interval {
result.after_cut = Some(InclusiveInterval {
start: base.start(),
end: base.end(),
});
}
Config::RightFirstPartialOverlap => {
result.after_cut = Some(Interval {
result.after_cut = Some(InclusiveInterval {
start: cut.end().up().unwrap(),
end: base.end(),
});
result.inside_cut = Some(Interval {
result.inside_cut = Some(InclusiveInterval {
start: base.start(),
end: cut.end(),
});
}
Config::RightContainsLeft => {
result.inside_cut = Some(Interval {
result.inside_cut = Some(InclusiveInterval {
start: base.start(),
end: base.end(),
});
@@ -201,15 +201,15 @@ where
pub(crate) fn is_valid_range<I, K>(range: K) -> bool
where
I: Ord,
K: FiniteRange<I>,
K: InclusiveRange<I>,
{
range.start() <= range.end()
}
pub(crate) fn overlaps<I, A, B>(a: A, b: B) -> bool
where
A: FiniteRange<I> + Copy,
B: FiniteRange<I> + Copy,
A: InclusiveRange<I> + Copy,
B: InclusiveRange<I> + Copy,
I: Ord,
{
!matches!(sorted_config(a, b), SortedConfig::NonOverlapping(_, _))