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]]
|
||||
name = "discrete_range_map"
|
||||
version = "0.4.2"
|
||||
version = "0.4.3"
|
||||
dependencies = [
|
||||
"btree_monstrousity",
|
||||
"either",
|
||||
|
||||
+99
-69
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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(_, _))
|
||||
|
||||
Reference in New Issue
Block a user