the finite pilgrimage has begun...
This commit is contained in:
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
Copyright 2022 James Forster
|
||||
|
||||
This file is part of range_bounds_map.
|
||||
|
||||
range_bounds_map is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
range_bounds_map is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with range_bounds_map. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::discrete_bounds::DiscreteBound;
|
||||
use crate::stepable::Stepable;
|
||||
|
||||
/// An newtype of [`Bound`] to implement [`Ord`] on types that
|
||||
/// implement [`Step`].
|
||||
///
|
||||
/// [`Step`]: std::iter::Step
|
||||
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
|
||||
pub enum DiscreteBoundOrd<T> {
|
||||
Included(T),
|
||||
StartUnbounded,
|
||||
EndUnbounded,
|
||||
}
|
||||
|
||||
impl<I> DiscreteBoundOrd<I> {
|
||||
pub(crate) fn start(discrete_bound: DiscreteBound<I>) -> Self {
|
||||
match discrete_bound {
|
||||
DiscreteBound::Included(point) => DiscreteBoundOrd::Included(point),
|
||||
DiscreteBound::Unbounded => DiscreteBoundOrd::StartUnbounded,
|
||||
}
|
||||
}
|
||||
pub(crate) fn end(discrete_bound: DiscreteBound<I>) -> Self {
|
||||
match discrete_bound {
|
||||
DiscreteBound::Included(point) => DiscreteBoundOrd::Included(point),
|
||||
DiscreteBound::Unbounded => DiscreteBoundOrd::EndUnbounded,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn up_if_finite(&self) -> DiscreteBoundOrd<I>
|
||||
where
|
||||
I: Stepable + Copy,
|
||||
{
|
||||
match self {
|
||||
DiscreteBoundOrd::Included(x) => DiscreteBoundOrd::Included(x.up().unwrap()),
|
||||
x => *x,
|
||||
}
|
||||
}
|
||||
pub fn down_if_finite(&self) -> DiscreteBoundOrd<I>
|
||||
where
|
||||
I: Stepable + Copy,
|
||||
{
|
||||
match self {
|
||||
DiscreteBoundOrd::Included(x) => DiscreteBoundOrd::Included(x.down().unwrap()),
|
||||
x => *x,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Ord for DiscreteBoundOrd<T>
|
||||
where
|
||||
T: Ord,
|
||||
{
|
||||
#[rustfmt::skip]
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
match (self, other) {
|
||||
(DiscreteBoundOrd::Included(start1), DiscreteBoundOrd::Included(start2)) => start1.cmp(start2),
|
||||
(DiscreteBoundOrd::Included(_), DiscreteBoundOrd::EndUnbounded) => Ordering::Less,
|
||||
(DiscreteBoundOrd::Included(_), DiscreteBoundOrd::StartUnbounded) => Ordering::Greater,
|
||||
|
||||
(DiscreteBoundOrd::StartUnbounded, DiscreteBoundOrd::Included(_)) => Ordering::Less,
|
||||
(DiscreteBoundOrd::StartUnbounded, DiscreteBoundOrd::StartUnbounded) => Ordering::Equal,
|
||||
(DiscreteBoundOrd::StartUnbounded, DiscreteBoundOrd::EndUnbounded) => Ordering::Less,
|
||||
|
||||
(DiscreteBoundOrd::EndUnbounded, DiscreteBoundOrd::Included(_)) => Ordering::Greater,
|
||||
(DiscreteBoundOrd::EndUnbounded, DiscreteBoundOrd::EndUnbounded) => Ordering::Equal,
|
||||
(DiscreteBoundOrd::EndUnbounded, DiscreteBoundOrd::StartUnbounded) => Ordering::Greater,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PartialOrd for DiscreteBoundOrd<T>
|
||||
where
|
||||
T: Ord,
|
||||
{
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PartialEq for DiscreteBoundOrd<T>
|
||||
where
|
||||
T: Ord,
|
||||
{
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.cmp(other).is_eq()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Eq for DiscreteBoundOrd<T> where T: Ord {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn mass_start_bound_partial_ord_test() {
|
||||
//Included
|
||||
assert!(DiscreteBoundOrd::Included(2) == DiscreteBoundOrd::Included(2));
|
||||
assert!(DiscreteBoundOrd::Included(2) <= DiscreteBoundOrd::Included(2));
|
||||
assert!(DiscreteBoundOrd::Included(2) >= DiscreteBoundOrd::Included(2));
|
||||
assert!(DiscreteBoundOrd::Included(0) < DiscreteBoundOrd::Included(2));
|
||||
assert!(DiscreteBoundOrd::Included(2) > DiscreteBoundOrd::Included(0));
|
||||
|
||||
assert!(DiscreteBoundOrd::Included(2) > DiscreteBoundOrd::StartUnbounded);
|
||||
|
||||
assert!(DiscreteBoundOrd::Included(2) < DiscreteBoundOrd::EndUnbounded);
|
||||
|
||||
//StartUnbounded
|
||||
assert!(DiscreteBoundOrd::StartUnbounded::<i8> == DiscreteBoundOrd::StartUnbounded);
|
||||
assert!(DiscreteBoundOrd::StartUnbounded::<i8> <= DiscreteBoundOrd::StartUnbounded);
|
||||
assert!(DiscreteBoundOrd::StartUnbounded::<i8> >= DiscreteBoundOrd::StartUnbounded);
|
||||
|
||||
assert!(DiscreteBoundOrd::StartUnbounded::<i8> < DiscreteBoundOrd::EndUnbounded);
|
||||
|
||||
//EndUnbounded
|
||||
assert!(DiscreteBoundOrd::EndUnbounded::<i8> == DiscreteBoundOrd::EndUnbounded);
|
||||
assert!(DiscreteBoundOrd::EndUnbounded::<i8> <= DiscreteBoundOrd::EndUnbounded);
|
||||
assert!(DiscreteBoundOrd::EndUnbounded::<i8> >= DiscreteBoundOrd::EndUnbounded);
|
||||
}
|
||||
}
|
||||
+5
-74
@@ -19,87 +19,18 @@ along with range_bounds_map. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use std::ops::{Bound, RangeBounds};
|
||||
|
||||
use crate::discrete_bound_ord::DiscreteBoundOrd;
|
||||
use crate::stepable::Stepable;
|
||||
use crate::try_from_discrete_bounds::TryFromDiscreteBounds;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct DiscreteBounds<I> {
|
||||
pub start: DiscreteBound<I>,
|
||||
pub end: DiscreteBound<I>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum DiscreteBound<I> {
|
||||
Included(I),
|
||||
Unbounded,
|
||||
}
|
||||
|
||||
impl<I> DiscreteBound<I>
|
||||
where
|
||||
I: Stepable + Copy,
|
||||
{
|
||||
pub fn start(bound: Bound<I>) -> Self {
|
||||
match bound {
|
||||
Bound::Included(x) => DiscreteBound::Included(x),
|
||||
Bound::Excluded(x) => DiscreteBound::Included(x.up().unwrap()),
|
||||
Bound::Unbounded => DiscreteBound::Unbounded,
|
||||
}
|
||||
}
|
||||
pub fn end(bound: Bound<I>) -> Self {
|
||||
match bound {
|
||||
Bound::Included(x) => DiscreteBound::Included(x),
|
||||
Bound::Excluded(x) => DiscreteBound::Included(x.down().unwrap()),
|
||||
Bound::Unbounded => DiscreteBound::Unbounded,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn up_if_finite(&self) -> DiscreteBound<I> {
|
||||
match self {
|
||||
DiscreteBound::Included(x) => DiscreteBound::Included(x.up().unwrap()),
|
||||
DiscreteBound::Unbounded => DiscreteBound::Unbounded,
|
||||
}
|
||||
}
|
||||
pub fn down_if_finite(&self) -> DiscreteBound<I> {
|
||||
match self {
|
||||
DiscreteBound::Included(x) => DiscreteBound::Included(x.down().unwrap()),
|
||||
DiscreteBound::Unbounded => DiscreteBound::Unbounded,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> From<DiscreteBoundOrd<I>> for DiscreteBound<I> {
|
||||
fn from(discrete_bound_ord: DiscreteBoundOrd<I>) -> Self {
|
||||
match discrete_bound_ord {
|
||||
DiscreteBoundOrd::Included(x) => DiscreteBound::Included(x),
|
||||
DiscreteBoundOrd::StartUnbounded => DiscreteBound::Unbounded,
|
||||
DiscreteBoundOrd::EndUnbounded => DiscreteBound::Unbounded,
|
||||
}
|
||||
}
|
||||
//both are always included
|
||||
pub start: I,
|
||||
pub end: I,
|
||||
}
|
||||
|
||||
impl<I> RangeBounds<I> for DiscreteBounds<I> {
|
||||
fn start_bound(&self) -> Bound<&I> {
|
||||
match self.start {
|
||||
DiscreteBound::Included(ref x) => Bound::Included(x),
|
||||
DiscreteBound::Unbounded => Bound::Unbounded,
|
||||
}
|
||||
Bound::Included(&self.start)
|
||||
}
|
||||
fn end_bound(&self) -> Bound<&I> {
|
||||
match self.end {
|
||||
DiscreteBound::Included(ref x) => Bound::Included(x),
|
||||
DiscreteBound::Unbounded => Bound::Unbounded,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> TryFromDiscreteBounds<I> for DiscreteBounds<I> {
|
||||
fn try_from_discrete_bounds(
|
||||
discrete_bounds: DiscreteBounds<I>,
|
||||
) -> Result<Self, crate::TryFromDiscreteBoundsError>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Ok(discrete_bounds)
|
||||
Bound::Included(&self.end)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-5
@@ -220,18 +220,14 @@ along with range_bounds_map. If not, see <https://www.gnu.org/licenses/>.
|
||||
pub mod test_ranges;
|
||||
pub(crate) mod utils;
|
||||
|
||||
pub(crate) mod discrete_bound_ord;
|
||||
pub mod discrete_bounds;
|
||||
|
||||
pub mod stepable;
|
||||
pub mod try_from_discrete_bounds;
|
||||
|
||||
pub mod range_bounds_map;
|
||||
pub mod range_bounds_set;
|
||||
|
||||
pub use crate::discrete_bounds::DiscreteBounds;
|
||||
pub use crate::range_bounds_map::{
|
||||
OverlapError, OverlapOrTryFromDiscreteBoundsError, RangeBoundsMap,
|
||||
};
|
||||
pub use crate::range_bounds_set::RangeBoundsSet;
|
||||
pub use crate::try_from_discrete_bounds::{TryFromDiscreteBounds, TryFromDiscreteBoundsError};
|
||||
pub use crate::discrete_bounds::DiscreteBounds;
|
||||
|
||||
+70
-170
@@ -30,11 +30,9 @@ use serde::de::{MapAccess, Visitor};
|
||||
use serde::ser::SerializeMap;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
use crate::discrete_bound_ord::DiscreteBoundOrd;
|
||||
use crate::discrete_bounds::{DiscreteBound, DiscreteBounds};
|
||||
use crate::stepable::Stepable;
|
||||
use crate::try_from_discrete_bounds::{TryFromDiscreteBounds, TryFromDiscreteBoundsError};
|
||||
use crate::utils::{cmp_discrete_bound_ord_with_range, cut_range, is_valid_range, overlaps};
|
||||
use crate::discrete_bounds::DiscreteBounds;
|
||||
use crate::stepable::Discrete;
|
||||
use crate::utils::{cmp_point_with_range, cut_range, is_valid_range, overlaps};
|
||||
|
||||
/// An ordered map of non-overlapping ranges based on [`BTreeMap`].
|
||||
///
|
||||
@@ -140,17 +138,9 @@ pub struct RangeBoundsMap<I, K, V> {
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub struct OverlapError;
|
||||
|
||||
/// An error type to represent either an [`OverlapError`] or a
|
||||
/// [`TryFromDiscreteBoundsError`].
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub enum OverlapOrTryFromDiscreteBoundsError {
|
||||
Overlap(OverlapError),
|
||||
TryFromDiscreteBounds(TryFromDiscreteBoundsError),
|
||||
}
|
||||
|
||||
impl<I, K, V> RangeBoundsMap<I, K, V>
|
||||
where
|
||||
I: Ord + Copy + Stepable,
|
||||
I: Ord + Copy + Discrete,
|
||||
K: DiscreteRange<I> + Copy,
|
||||
{
|
||||
/// Makes a new, empty `RangeBoundsMap`.
|
||||
@@ -370,8 +360,7 @@ where
|
||||
/// assert_eq!(map.get_at_point(1), Some(&true));
|
||||
/// ```
|
||||
pub fn get_at_point_mut(&mut self, point: I) -> Option<&mut V> {
|
||||
self.inner
|
||||
.get_mut(overlapping_comp(DiscreteBoundOrd::Included(point)))
|
||||
self.inner.get_mut(overlapping_comp(point))
|
||||
}
|
||||
|
||||
/// Returns `true` if the map contains a range that overlaps the
|
||||
@@ -430,26 +419,24 @@ where
|
||||
/// ```
|
||||
pub fn get_entry_at_point(&self, point: I) -> Result<(&K, &V), DiscreteBounds<I>> {
|
||||
self.inner
|
||||
.get_key_value(overlapping_comp(DiscreteBoundOrd::Included(point)))
|
||||
.ok_or_else(|| self.get_gap_at_raw(DiscreteBoundOrd::Included(point)))
|
||||
.get_key_value(overlapping_comp(point))
|
||||
.ok_or_else(|| self.get_gap_at_raw(point))
|
||||
}
|
||||
fn get_gap_at_raw(&self, discrete_bound_ord: DiscreteBoundOrd<I>) -> DiscreteBounds<I> {
|
||||
let lower = self.inner.upper_bound(
|
||||
overlapping_comp(discrete_bound_ord),
|
||||
SearchBoundCustom::Included,
|
||||
);
|
||||
let upper = self.inner.lower_bound(
|
||||
overlapping_comp(discrete_bound_ord),
|
||||
SearchBoundCustom::Included,
|
||||
);
|
||||
fn get_gap_at_raw(&self, point: I) -> DiscreteBounds<I> {
|
||||
let lower = self
|
||||
.inner
|
||||
.upper_bound(overlapping_comp(point), SearchBoundCustom::Included);
|
||||
let upper = self
|
||||
.inner
|
||||
.lower_bound(overlapping_comp(point), SearchBoundCustom::Included);
|
||||
|
||||
DiscreteBounds {
|
||||
start: lower.key().map_or(DiscreteBound::Unbounded, |lower| {
|
||||
DiscreteBound::from(lower.end()).up_if_finite()
|
||||
}),
|
||||
end: upper.key().map_or(DiscreteBound::Unbounded, |upper| {
|
||||
DiscreteBound::from(upper.start()).down_if_finite()
|
||||
}),
|
||||
start: lower
|
||||
.key()
|
||||
.map_or(I::MIN, |lower| lower.end().up().unwrap()),
|
||||
end: upper
|
||||
.key()
|
||||
.map_or(I::MAX, |upper| upper.start().down().unwrap()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -601,13 +588,10 @@ where
|
||||
/// );
|
||||
/// assert_eq!(base, after_cut);
|
||||
/// ```
|
||||
pub fn cut<'a, Q>(
|
||||
&'a mut self,
|
||||
range: Q,
|
||||
) -> Result<impl Iterator<Item = (DiscreteBounds<I>, V)> + '_, TryFromDiscreteBoundsError>
|
||||
pub fn cut<'a, Q>(&'a mut self, range: Q) -> impl Iterator<Item = (DiscreteBounds<I>, V)> + '_
|
||||
where
|
||||
Q: DiscreteRange<I> + Copy + 'a,
|
||||
K: TryFromDiscreteBounds<I>,
|
||||
K: From<DiscreteBounds<I>>,
|
||||
V: Clone,
|
||||
{
|
||||
invalid_range_panic(range);
|
||||
@@ -636,10 +620,10 @@ where
|
||||
&mut self,
|
||||
range: Q,
|
||||
single_overlapping_range: K,
|
||||
) -> Result<impl Iterator<Item = (DiscreteBounds<I>, V)>, TryFromDiscreteBoundsError>
|
||||
) -> impl Iterator<Item = (DiscreteBounds<I>, V)>
|
||||
where
|
||||
Q: DiscreteRange<I> + Copy,
|
||||
K: TryFromDiscreteBounds<I>,
|
||||
K: From<DiscreteBounds<I>>,
|
||||
V: Clone,
|
||||
{
|
||||
invalid_range_panic(range);
|
||||
@@ -670,10 +654,10 @@ where
|
||||
range: Q,
|
||||
left_overlapping: Option<K>,
|
||||
right_overlapping: Option<K>,
|
||||
) -> Result<impl Iterator<Item = (DiscreteBounds<I>, V)> + '_, TryFromDiscreteBoundsError>
|
||||
) -> impl Iterator<Item = (DiscreteBounds<I>, V)> + '_
|
||||
where
|
||||
Q: DiscreteRange<I> + Copy + 'a,
|
||||
K: TryFromDiscreteBounds<I>,
|
||||
K: From<DiscreteBounds<I>>,
|
||||
V: Clone,
|
||||
{
|
||||
invalid_range_panic(range);
|
||||
@@ -799,41 +783,24 @@ where
|
||||
(Some(mut start_gap), Some(mut end_gap)) => {
|
||||
if start_gap.start() == end_gap.start() {
|
||||
//it's the same gap
|
||||
if let DiscreteBoundOrd::Included(outer_range_start) = outer_range.start() {
|
||||
start_gap.start = DiscreteBound::Included(outer_range_start);
|
||||
}
|
||||
if let DiscreteBoundOrd::Included(outer_range_end) = outer_range.end() {
|
||||
start_gap.end = DiscreteBound::Included(outer_range_end);
|
||||
}
|
||||
start_gap.start = outer_range.start();
|
||||
start_gap.end = outer_range.end();
|
||||
|
||||
(Some(start_gap), None)
|
||||
} else {
|
||||
//it's different gaps
|
||||
//
|
||||
//trim the start gap to the outer range
|
||||
if let DiscreteBoundOrd::Included(outer_range_start) = outer_range.start() {
|
||||
start_gap.start = DiscreteBound::Included(outer_range_start);
|
||||
}
|
||||
//trim the end gap to the outer range
|
||||
if let DiscreteBoundOrd::Included(outer_range_end) = outer_range.end() {
|
||||
end_gap.end = DiscreteBound::Included(outer_range_end);
|
||||
}
|
||||
start_gap.start = outer_range.start();
|
||||
end_gap.end = outer_range.end();
|
||||
|
||||
(Some(start_gap), Some(end_gap))
|
||||
}
|
||||
}
|
||||
(Some(mut start_gap), None) => {
|
||||
//trim the start gap to the outer range
|
||||
if let DiscreteBoundOrd::Included(outer_range_start) = outer_range.start() {
|
||||
start_gap.start = DiscreteBound::Included(outer_range_start);
|
||||
}
|
||||
start_gap.start = outer_range.start();
|
||||
(Some(start_gap), None)
|
||||
}
|
||||
(None, Some(mut end_gap)) => {
|
||||
//trim the end gap to the outer range
|
||||
if let DiscreteBoundOrd::Included(outer_range_end) = outer_range.end() {
|
||||
end_gap.end = DiscreteBound::Included(outer_range_end);
|
||||
}
|
||||
end_gap.end = outer_range.end();
|
||||
(None, Some(end_gap))
|
||||
}
|
||||
(None, None) => (None, None),
|
||||
@@ -942,9 +909,9 @@ where
|
||||
get_end: G2,
|
||||
remove_start: R1,
|
||||
remove_end: R2,
|
||||
) -> Result<K, TryFromDiscreteBoundsError>
|
||||
) -> K
|
||||
where
|
||||
K: TryFromDiscreteBounds<I>,
|
||||
K: From<DiscreteBounds<I>>,
|
||||
G1: FnOnce(&Self, &V) -> Option<K>,
|
||||
G2: FnOnce(&Self, &V) -> Option<K>,
|
||||
R1: FnOnce(&mut Self, &V),
|
||||
@@ -1043,21 +1010,17 @@ where
|
||||
/// [(ie(1, 8), true), (ie(10, 16), false)]
|
||||
/// );
|
||||
/// ```
|
||||
pub fn insert_merge_touching(
|
||||
&mut self,
|
||||
range: K,
|
||||
value: V,
|
||||
) -> Result<K, OverlapOrTryFromDiscreteBoundsError>
|
||||
pub fn insert_merge_touching(&mut self, range: K, value: V) -> Result<K, OverlapError>
|
||||
where
|
||||
K: TryFromDiscreteBounds<I>,
|
||||
K: From<DiscreteBounds<I>>,
|
||||
{
|
||||
invalid_range_panic(range);
|
||||
|
||||
if self.overlaps(range) {
|
||||
return Err(OverlapOrTryFromDiscreteBoundsError::Overlap(OverlapError));
|
||||
return Err(OverlapError);
|
||||
}
|
||||
|
||||
self.insert_merge_with_comps(
|
||||
Ok(self.insert_merge_with_comps(
|
||||
range,
|
||||
value,
|
||||
|selfy, _| {
|
||||
@@ -1080,8 +1043,7 @@ where
|
||||
|selfy, _| {
|
||||
selfy.inner.remove(touching_end_comp(range.end()));
|
||||
},
|
||||
)
|
||||
.map_err(OverlapOrTryFromDiscreteBoundsError::TryFromDiscreteBounds)
|
||||
))
|
||||
}
|
||||
|
||||
/// Adds a new entry to the map and merges into other ranges in
|
||||
@@ -1146,15 +1108,15 @@ where
|
||||
&mut self,
|
||||
range: K,
|
||||
value: V,
|
||||
) -> Result<K, OverlapOrTryFromDiscreteBoundsError>
|
||||
) -> Result<K, OverlapError>
|
||||
where
|
||||
K: TryFromDiscreteBounds<I>,
|
||||
K: From<DiscreteBounds<I>>,
|
||||
V: Eq,
|
||||
{
|
||||
invalid_range_panic(range);
|
||||
|
||||
if self.overlaps(range) {
|
||||
return Err(OverlapOrTryFromDiscreteBoundsError::Overlap(OverlapError));
|
||||
return Err(OverlapError);
|
||||
}
|
||||
|
||||
let get_start = |selfy: &Self, value: &V| {
|
||||
@@ -1174,7 +1136,7 @@ where
|
||||
.copied()
|
||||
};
|
||||
|
||||
self.insert_merge_with_comps(
|
||||
Ok(self.insert_merge_with_comps(
|
||||
range,
|
||||
value,
|
||||
get_start,
|
||||
@@ -1189,8 +1151,7 @@ where
|
||||
selfy.inner.remove(touching_end_comp(range.end()));
|
||||
}
|
||||
},
|
||||
)
|
||||
.map_err(OverlapOrTryFromDiscreteBoundsError::TryFromDiscreteBounds)
|
||||
))
|
||||
}
|
||||
|
||||
/// Adds a new entry to the map and merges into other ranges in
|
||||
@@ -1248,13 +1209,9 @@ where
|
||||
/// [(ie(1, 4), false), (ie(4, 8), false), (ie(10, 16), false)]
|
||||
/// );
|
||||
/// ```
|
||||
pub fn insert_merge_overlapping(
|
||||
&mut self,
|
||||
range: K,
|
||||
value: V,
|
||||
) -> Result<K, TryFromDiscreteBoundsError>
|
||||
pub fn insert_merge_overlapping(&mut self, range: K, value: V) -> K
|
||||
where
|
||||
K: TryFromDiscreteBounds<I>,
|
||||
K: From<DiscreteBounds<I>>,
|
||||
{
|
||||
invalid_range_panic(range);
|
||||
|
||||
@@ -1335,13 +1292,9 @@ where
|
||||
/// [(ie(1, 8), false), (ie(10, 16), false)]
|
||||
/// );
|
||||
/// ```
|
||||
pub fn insert_merge_touching_or_overlapping(
|
||||
&mut self,
|
||||
range: K,
|
||||
value: V,
|
||||
) -> Result<K, TryFromDiscreteBoundsError>
|
||||
pub fn insert_merge_touching_or_overlapping(&mut self, range: K, value: V) -> K
|
||||
where
|
||||
K: TryFromDiscreteBounds<I>,
|
||||
K: From<DiscreteBounds<I>>,
|
||||
{
|
||||
invalid_range_panic(range);
|
||||
|
||||
@@ -1412,17 +1365,15 @@ where
|
||||
/// [(ie(2, 4), false), (ie(4, 6), true), (ie(6, 8), false)]
|
||||
/// );
|
||||
/// ```
|
||||
pub fn insert_overwrite(&mut self, range: K, value: V) -> Result<(), TryFromDiscreteBoundsError>
|
||||
pub fn insert_overwrite(&mut self, range: K, value: V)
|
||||
where
|
||||
K: TryFromDiscreteBounds<I>,
|
||||
K: From<DiscreteBounds<I>>,
|
||||
V: Clone,
|
||||
{
|
||||
invalid_range_panic(range);
|
||||
|
||||
let _ = self.cut(range)?;
|
||||
self.insert_unchecked(range, value);
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// Returns the first entry in the map, if any.
|
||||
@@ -1520,88 +1471,38 @@ where
|
||||
fn double_comp<K, I>() -> impl FnMut(&K, &K) -> Ordering
|
||||
where
|
||||
K: DiscreteRange<I>,
|
||||
I: Ord + Stepable,
|
||||
I: Ord + Discrete,
|
||||
{
|
||||
|inner_range: &K, new_range: &K| new_range.start().cmp(&inner_range.start())
|
||||
}
|
||||
fn overlapping_comp<I, K>(bound: DiscreteBoundOrd<I>) -> impl FnMut(&K) -> Ordering
|
||||
fn overlapping_comp<I, K>(point: I) -> impl FnMut(&K) -> Ordering
|
||||
where
|
||||
I: Ord + Copy,
|
||||
K: DiscreteRange<I> + Copy,
|
||||
{
|
||||
move |inner_range: &K| cmp_discrete_bound_ord_with_range(bound, *inner_range)
|
||||
move |inner_range: &K| cmp_point_with_range(point, *inner_range)
|
||||
}
|
||||
fn touching_start_comp<I, K>(start: DiscreteBoundOrd<I>) -> impl FnMut(&K) -> Ordering
|
||||
fn touching_start_comp<I, K>(start: I) -> impl FnMut(&K) -> Ordering
|
||||
where
|
||||
I: Ord + Copy + Stepable,
|
||||
I: Ord + Copy + Discrete,
|
||||
K: DiscreteRange<I>,
|
||||
{
|
||||
move |inner_range: &K| match (inner_range.end(), start) {
|
||||
//we only allow Ordering::Equal here since if they are equal
|
||||
//then the ranges would be touching
|
||||
(DiscreteBoundOrd::Included(end), DiscreteBoundOrd::Included(start))
|
||||
if end.up().unwrap() == start =>
|
||||
{
|
||||
Ordering::Equal
|
||||
}
|
||||
|
||||
(end, start) => {
|
||||
let normal_result = start.cmp(&end);
|
||||
|
||||
//we overide any Equals to a non-Equal since we
|
||||
//don't want non-touching matches
|
||||
match normal_result {
|
||||
Ordering::Equal => Ordering::Greater,
|
||||
x => x,
|
||||
}
|
||||
}
|
||||
}
|
||||
move |inner_range: &K| start.cmp(&inner_range.end().up().unwrap())
|
||||
}
|
||||
fn touching_end_comp<I, K>(end: DiscreteBoundOrd<I>) -> impl FnMut(&K) -> Ordering
|
||||
fn touching_end_comp<I, K>(end: I) -> impl FnMut(&K) -> Ordering
|
||||
where
|
||||
I: Ord + Copy + Stepable,
|
||||
I: Ord + Copy + Discrete,
|
||||
K: DiscreteRange<I>,
|
||||
{
|
||||
move |inner_range: &K| match (end, inner_range.start()) {
|
||||
//we only allow Ordering::Equal here since if they are equal
|
||||
//then the ranges would be touching
|
||||
(DiscreteBoundOrd::Included(end), DiscreteBoundOrd::Included(start))
|
||||
if end.up().unwrap() == start =>
|
||||
{
|
||||
Ordering::Equal
|
||||
}
|
||||
|
||||
(end, _start) => {
|
||||
let normal_result = end.cmp(&inner_range.start());
|
||||
|
||||
//we overide any Equals to a non-Equal since we
|
||||
//don't want non-touching matches
|
||||
match normal_result {
|
||||
Ordering::Equal => Ordering::Less,
|
||||
x => x,
|
||||
}
|
||||
}
|
||||
}
|
||||
move |inner_range: &K| end.cmp(&inner_range.start().down().unwrap())
|
||||
}
|
||||
|
||||
/// A simple helper trait to make my implemtation nicer, if you
|
||||
/// already implement RangeBounds and Copy on your type then this will
|
||||
/// also be implemted.
|
||||
pub trait DiscreteRange<I> {
|
||||
fn start(&self) -> DiscreteBoundOrd<I>;
|
||||
fn end(&self) -> DiscreteBoundOrd<I>;
|
||||
}
|
||||
impl<K, I> DiscreteRange<I> for K
|
||||
where
|
||||
I: Copy + Stepable,
|
||||
K: RangeBounds<I> + Copy,
|
||||
{
|
||||
fn start(&self) -> DiscreteBoundOrd<I> {
|
||||
DiscreteBoundOrd::start(DiscreteBound::start(self.start_bound().cloned()))
|
||||
}
|
||||
fn end(&self) -> DiscreteBoundOrd<I> {
|
||||
DiscreteBoundOrd::end(DiscreteBound::end(self.end_bound().cloned()))
|
||||
}
|
||||
fn start(&self) -> I;
|
||||
fn end(&self) -> I;
|
||||
}
|
||||
|
||||
// Trait Impls ==========================
|
||||
@@ -1646,7 +1547,7 @@ impl<I, K, V> Default for RangeBoundsMap<I, K, V> {
|
||||
|
||||
impl<I, K, V> Serialize for RangeBoundsMap<I, K, V>
|
||||
where
|
||||
I: Ord + Copy + Stepable,
|
||||
I: Ord + Copy + Discrete,
|
||||
K: DiscreteRange<I> + Copy + Serialize,
|
||||
V: Serialize,
|
||||
{
|
||||
@@ -1664,7 +1565,7 @@ where
|
||||
|
||||
impl<'de, I, K, V> Deserialize<'de> for RangeBoundsMap<I, K, V>
|
||||
where
|
||||
I: Ord + Copy + Stepable,
|
||||
I: Ord + Copy + Discrete,
|
||||
K: DiscreteRange<I> + Copy + Deserialize<'de>,
|
||||
V: Deserialize<'de>,
|
||||
{
|
||||
@@ -1688,7 +1589,7 @@ struct RangeBoundsMapVisitor<I, K, V> {
|
||||
|
||||
impl<'de, I, K, V> Visitor<'de> for RangeBoundsMapVisitor<I, K, V>
|
||||
where
|
||||
I: Ord + Copy + Stepable,
|
||||
I: Ord + Copy + Discrete,
|
||||
K: DiscreteRange<I> + Copy + Deserialize<'de>,
|
||||
V: Deserialize<'de>,
|
||||
{
|
||||
@@ -1717,7 +1618,6 @@ mod tests {
|
||||
|
||||
use super::*;
|
||||
use crate::test_ranges::{ee, ei, ie, ii, iu, ue, ui, uu};
|
||||
use crate::try_from_discrete_bounds::TryFromDiscreteBounds;
|
||||
use crate::utils::{config, Config, CutResult};
|
||||
|
||||
//only every other number to allow mathematical_overlapping_definition
|
||||
@@ -1926,13 +1826,13 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
fn assert_cut<const N: usize, const Y: usize, Q, I, K, V>(
|
||||
fn assert_cut<const N: usize, const Y: usize>(
|
||||
mut before: RangeBoundsMap<I, K, V>,
|
||||
to_cut: Q,
|
||||
result: Result<[(DiscreteBounds<I>, V); Y], TryFromDiscreteBoundsError>,
|
||||
after: Option<[(K, V); N]>,
|
||||
) where
|
||||
I: Ord + Debug + Copy + Stepable,
|
||||
I: Ord + Debug + Copy + Discrete,
|
||||
K: DiscreteRange<I> + TryFromDiscreteBounds<I> + PartialEq + Debug + Copy,
|
||||
Q: DiscreteRange<I> + Copy,
|
||||
V: PartialEq + Debug + Clone,
|
||||
@@ -2031,7 +1931,7 @@ mod tests {
|
||||
result: Result<K, OverlapOrTryFromDiscreteBoundsError>,
|
||||
after: Option<[(K, V); N]>,
|
||||
) where
|
||||
I: Ord + Debug + Copy + Stepable,
|
||||
I: Ord + Debug + Copy + Discrete,
|
||||
K: DiscreteRange<I> + TryFromDiscreteBounds<I> + PartialEq + Debug + Copy,
|
||||
V: PartialEq + Debug + Clone,
|
||||
{
|
||||
@@ -2096,7 +1996,7 @@ mod tests {
|
||||
result: Result<K, OverlapOrTryFromDiscreteBoundsError>,
|
||||
after: Option<[(K, V); N]>,
|
||||
) where
|
||||
I: Ord + Debug + Copy + Stepable,
|
||||
I: Ord + Debug + Copy + Discrete,
|
||||
K: DiscreteRange<I> + TryFromDiscreteBounds<I> + PartialEq + Debug + Copy,
|
||||
V: Eq + Debug + Clone,
|
||||
{
|
||||
@@ -2162,7 +2062,7 @@ mod tests {
|
||||
result: Result<K, TryFromDiscreteBoundsError>,
|
||||
after: Option<[(K, V); N]>,
|
||||
) where
|
||||
I: Ord + Debug + Copy + Stepable,
|
||||
I: Ord + Debug + Copy + Discrete,
|
||||
K: DiscreteRange<I> + TryFromDiscreteBounds<I> + PartialEq + Debug + Copy,
|
||||
V: PartialEq + Debug + Clone,
|
||||
{
|
||||
@@ -2248,7 +2148,7 @@ mod tests {
|
||||
result: Result<K, TryFromDiscreteBoundsError>,
|
||||
after: Option<[(K, V); N]>,
|
||||
) where
|
||||
I: Ord + Debug + Copy + Stepable,
|
||||
I: Ord + Debug + Copy + Discrete,
|
||||
K: DiscreteRange<I> + TryFromDiscreteBounds<I> + PartialEq + Debug + Copy,
|
||||
V: PartialEq + Debug + Clone,
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
use crate::discrete_bounds::DiscreteBounds;
|
||||
use crate::range_bounds_map::{DiscreteRange, IntoIter as RangeBoundsMapIntoIter};
|
||||
use crate::stepable::Stepable;
|
||||
use crate::stepable::Discrete;
|
||||
use crate::try_from_discrete_bounds::TryFromDiscreteBounds;
|
||||
use crate::{
|
||||
OverlapError, OverlapOrTryFromDiscreteBoundsError, RangeBoundsMap, TryFromDiscreteBoundsError,
|
||||
@@ -33,7 +33,7 @@ pub struct RangeBoundsSet<I, K> {
|
||||
|
||||
impl<I, K> RangeBoundsSet<I, K>
|
||||
where
|
||||
I: Ord + Copy + Stepable,
|
||||
I: Ord + Copy + Discrete,
|
||||
K: DiscreteRange<I> + Copy,
|
||||
{
|
||||
/// See [`RangeBoundsMap::new()`] for more details.
|
||||
@@ -217,7 +217,7 @@ where
|
||||
|
||||
impl<I, K> Serialize for RangeBoundsSet<I, K>
|
||||
where
|
||||
I: Ord + Copy + Stepable,
|
||||
I: Ord + Copy + Discrete,
|
||||
K: DiscreteRange<I> + Copy + Serialize,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
@@ -234,7 +234,7 @@ where
|
||||
|
||||
impl<'de, I, K> Deserialize<'de> for RangeBoundsSet<I, K>
|
||||
where
|
||||
I: Ord + Copy + Stepable,
|
||||
I: Ord + Copy + Discrete,
|
||||
K: DiscreteRange<I> + Copy + Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
@@ -255,7 +255,7 @@ struct RangeBoundsSetVisitor<I, K> {
|
||||
|
||||
impl<'de, I, K> Visitor<'de> for RangeBoundsSetVisitor<I, K>
|
||||
where
|
||||
I: Ord + Copy + Stepable,
|
||||
I: Ord + Copy + Discrete,
|
||||
K: DiscreteRange<I> + Copy + Deserialize<'de>,
|
||||
{
|
||||
type Value = RangeBoundsSet<I, K>;
|
||||
|
||||
+5
-2
@@ -19,7 +19,10 @@ along with range_bounds_map. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use std::iter::Step;
|
||||
|
||||
pub trait Stepable {
|
||||
pub trait Discrete {
|
||||
const MIN: Self;
|
||||
const MAX: Self;
|
||||
|
||||
fn up(self) -> Option<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
@@ -28,7 +31,7 @@ pub trait Stepable {
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
impl<T> Stepable for T
|
||||
impl<T> Discrete for T
|
||||
where
|
||||
T: Sized + Step,
|
||||
{
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
use std::ops::{Bound, RangeBounds};
|
||||
|
||||
use crate::discrete_bounds::{DiscreteBound, DiscreteBounds};
|
||||
use crate::stepable::Stepable;
|
||||
use crate::stepable::Discrete;
|
||||
use crate::{TryFromDiscreteBounds, TryFromDiscreteBoundsError};
|
||||
|
||||
pub fn uu() -> DiscreteBounds<i8> {
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
use crate::discrete_bounds::DiscreteBounds;
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub struct TryFromDiscreteBoundsError;
|
||||
|
||||
pub trait TryFromDiscreteBounds<I> {
|
||||
fn try_from_discrete_bounds(
|
||||
discrete_bounds: DiscreteBounds<I>,
|
||||
) -> Result<Self, TryFromDiscreteBoundsError>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
+10
-11
@@ -19,22 +19,21 @@ along with range_bounds_map. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use crate::discrete_bound_ord::DiscreteBoundOrd;
|
||||
use crate::discrete_bounds::DiscreteBounds;
|
||||
use crate::range_bounds_map::DiscreteRange;
|
||||
use crate::stepable::Stepable;
|
||||
use crate::stepable::Discrete;
|
||||
|
||||
pub(crate) fn cmp_discrete_bound_ord_with_range<A, B>(
|
||||
discrete_bound_ord: DiscreteBoundOrd<B>,
|
||||
range: A,
|
||||
pub(crate) fn cmp_point_with_range<I, K>(
|
||||
point: I,
|
||||
range: K,
|
||||
) -> Ordering
|
||||
where
|
||||
A: DiscreteRange<B>,
|
||||
B: Ord,
|
||||
I: Ord,
|
||||
K: DiscreteRange<I>,
|
||||
{
|
||||
if discrete_bound_ord < range.start() {
|
||||
if point < range.start() {
|
||||
Ordering::Less
|
||||
} else if discrete_bound_ord > range.end() {
|
||||
} else if point > range.end() {
|
||||
Ordering::Greater
|
||||
} else {
|
||||
Ordering::Equal
|
||||
@@ -121,7 +120,7 @@ where
|
||||
A: DiscreteRange<I>,
|
||||
I: Ord,
|
||||
{
|
||||
cmp_discrete_bound_ord_with_range(discrete_bound_ord, range).is_eq()
|
||||
cmp_point_with_range(discrete_bound_ord, range).is_eq()
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -134,7 +133,7 @@ pub(crate) fn cut_range<I, B, C>(base: B, cut: C) -> CutResult<I>
|
||||
where
|
||||
B: DiscreteRange<I> + Copy,
|
||||
C: DiscreteRange<I> + Copy,
|
||||
I: Ord + Copy + Stepable,
|
||||
I: Ord + Copy + Discrete,
|
||||
{
|
||||
let mut result = CutResult {
|
||||
before_cut: None,
|
||||
|
||||
Reference in New Issue
Block a user