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