omgosh cut is so pretty! everything compiles with a beautiful cut function written
This commit is contained in:
+4
-4
@@ -130,13 +130,13 @@ where
|
||||
|
||||
#[derive(Debug)]
|
||||
struct CutResult<I> {
|
||||
before_cut: Option<(Bound<I>, Bound<I>)>,
|
||||
inside_cut: Option<(Bound<I>, Bound<I>)>,
|
||||
after_cut: Option<(Bound<I>, Bound<I>)>,
|
||||
pub before_cut: Option<(Bound<I>, Bound<I>)>,
|
||||
pub inside_cut: Option<(Bound<I>, Bound<I>)>,
|
||||
pub after_cut: Option<(Bound<I>, Bound<I>)>,
|
||||
}
|
||||
|
||||
#[tested]
|
||||
fn cut_range_bounds<'a, I, B, C>(
|
||||
pub(crate) fn cut_range_bounds<'a, I, B, C>(
|
||||
base_range_bounds: &'a B,
|
||||
cut_range_bounds: &'a C,
|
||||
) -> CutResult<&'a I>
|
||||
|
||||
+95
-15
@@ -33,8 +33,8 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
use crate::bound_ord::BoundOrd;
|
||||
use crate::helpers::{
|
||||
cmp_range_bounds_with_bound_ord, contains_bound_ord, is_valid_range_bounds,
|
||||
overlaps,
|
||||
cmp_range_bounds_with_bound_ord, contains_bound_ord, cut_range_bounds,
|
||||
is_valid_range_bounds, overlaps,
|
||||
};
|
||||
use crate::TryFromBounds;
|
||||
|
||||
@@ -666,19 +666,99 @@ where
|
||||
/// assert_eq!(base, after_cut);
|
||||
/// assert!(base.cut(&(60..=80)).is_err());
|
||||
/// ```
|
||||
//#[tested]
|
||||
//pub fn cut<Q>(
|
||||
//&mut self,
|
||||
//range_bounds: Q,
|
||||
//) -> Result<
|
||||
//impl DoubleEndedIterator<Item = ((Bound<&I>, Bound<&I>), V)>,
|
||||
//TryFromBoundsError,
|
||||
//>
|
||||
//where
|
||||
//Q: RangeBounds<I> + Clone,
|
||||
//{
|
||||
//todo!()
|
||||
//}
|
||||
#[tested]
|
||||
pub fn cut<'a, Q>(
|
||||
&'a mut self,
|
||||
range_bounds: Q,
|
||||
) -> Result<impl Iterator<Item = (K, V)> + '_, TryFromBoundsError>
|
||||
where
|
||||
Q: 'a + RangeBounds<I>,
|
||||
I: Clone,
|
||||
K: TryFromBounds<I>,
|
||||
V: Clone,
|
||||
{
|
||||
// This is so clean and mathematically pleasing omg i'm in love with it
|
||||
match range_bounds.start_bound() {
|
||||
Bound::Included(point) => self.bisect_at_point(point, false)?,
|
||||
Bound::Excluded(point) => self.bisect_at_point(point, true)?,
|
||||
Bound::Unbounded => {}
|
||||
}
|
||||
match range_bounds.end_bound() {
|
||||
Bound::Included(point) => self.bisect_at_point(point, true)?,
|
||||
Bound::Excluded(point) => self.bisect_at_point(point, false)?,
|
||||
Bound::Unbounded => {}
|
||||
}
|
||||
|
||||
return Ok(self.remove_overlapping(range_bounds));
|
||||
}
|
||||
//does nothing if it hits a degenerate interval or if it would
|
||||
//leave invalid range_bounds within the structure
|
||||
fn bisect_at_point(
|
||||
&mut self,
|
||||
point: &I,
|
||||
inclusive_on_left: bool,
|
||||
) -> Result<(), TryFromBoundsError>
|
||||
where
|
||||
I: Clone,
|
||||
K: TryFromBounds<I>,
|
||||
V: Clone,
|
||||
{
|
||||
if let Some((start_bound, end_bound)) =
|
||||
self.get_entry_at_point(point).map(|range_bounds| {
|
||||
(
|
||||
range_bounds.0.start_bound().cloned(),
|
||||
range_bounds.0.end_bound().cloned(),
|
||||
)
|
||||
}) {
|
||||
//don't bother doing anything in these situations
|
||||
match (&start_bound, &end_bound) {
|
||||
(Bound::Included(start_point), _) if start_point == point => {
|
||||
if !inclusive_on_left {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
(_, Bound::Included(end_point)) if end_point == point => {
|
||||
if inclusive_on_left {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
(Bound::Included(start_point), Bound::Included(end_point))
|
||||
if start_point == end_point =>
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let before_section = K::try_from_bounds(
|
||||
start_bound,
|
||||
if inclusive_on_left {
|
||||
Bound::Included(point.clone())
|
||||
} else {
|
||||
Bound::Excluded(point.clone())
|
||||
},
|
||||
)?;
|
||||
let after_section = K::try_from_bounds(
|
||||
if !inclusive_on_left {
|
||||
Bound::Included(point.clone())
|
||||
} else {
|
||||
Bound::Excluded(point.clone())
|
||||
},
|
||||
end_bound,
|
||||
)?;
|
||||
|
||||
let value = self
|
||||
.inner
|
||||
.remove(comp_start(Bound::Included(point)))
|
||||
.unwrap();
|
||||
|
||||
self.inner
|
||||
.insert(before_section, value.clone(), double_comp());
|
||||
self.inner.insert(after_section, value, double_comp());
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
/// Identical to [`RangeBoundsMap::cut()`] except it returns an
|
||||
/// iterator of `(Result<RangeBounds, TryFromBoundsError>,
|
||||
|
||||
+23
-36
@@ -24,6 +24,8 @@ use std::ops::{
|
||||
|
||||
use labels::{not_a_fn, trivial};
|
||||
|
||||
use crate::TryFromBoundsError;
|
||||
|
||||
/// A "newtype" trait to copy [`TryFrom`].
|
||||
///
|
||||
/// I am forced to use this "newtype" instead of [`TryFrom`] because
|
||||
@@ -41,24 +43,9 @@ pub trait TryFromBounds<I> {
|
||||
fn try_from_bounds(
|
||||
start_bound: Bound<I>,
|
||||
end_bound: Bound<I>,
|
||||
) -> Option<Self>
|
||||
) -> Result<Self, TryFromBoundsError>
|
||||
where
|
||||
Self: Sized;
|
||||
// optimisation: make this non-implemented so the trait impls can
|
||||
// define them more efficiently
|
||||
#[not_a_fn]
|
||||
fn is_valid<Q>(range_bounds: &Q) -> bool
|
||||
where
|
||||
Q: RangeBounds<I>,
|
||||
Self: Sized,
|
||||
I: Clone,
|
||||
{
|
||||
Self::try_from_bounds(
|
||||
range_bounds.start_bound().cloned(),
|
||||
range_bounds.end_bound().cloned(),
|
||||
)
|
||||
.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> TryFromBounds<I> for (Bound<I>, Bound<I>) {
|
||||
@@ -66,8 +53,8 @@ impl<I> TryFromBounds<I> for (Bound<I>, Bound<I>) {
|
||||
fn try_from_bounds(
|
||||
start_bound: Bound<I>,
|
||||
end_bound: Bound<I>,
|
||||
) -> Option<Self> {
|
||||
Some((start_bound, end_bound))
|
||||
) -> Result<Self, TryFromBoundsError> {
|
||||
Ok((start_bound, end_bound))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,10 +63,10 @@ impl<I> TryFromBounds<I> for Range<I> {
|
||||
fn try_from_bounds(
|
||||
start_bound: Bound<I>,
|
||||
end_bound: Bound<I>,
|
||||
) -> Option<Self> {
|
||||
) -> Result<Self, TryFromBoundsError> {
|
||||
match (start_bound, end_bound) {
|
||||
(Bound::Included(start), Bound::Excluded(end)) => Some(start..end),
|
||||
_ => None,
|
||||
(Bound::Included(start), Bound::Excluded(end)) => Ok(start..end),
|
||||
_ => Err(TryFromBoundsError),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,10 +76,10 @@ impl<I> TryFromBounds<I> for RangeInclusive<I> {
|
||||
fn try_from_bounds(
|
||||
start_bound: Bound<I>,
|
||||
end_bound: Bound<I>,
|
||||
) -> Option<Self> {
|
||||
) -> Result<Self, TryFromBoundsError> {
|
||||
match (start_bound, end_bound) {
|
||||
(Bound::Included(start), Bound::Included(end)) => Some(start..=end),
|
||||
_ => None,
|
||||
(Bound::Included(start), Bound::Included(end)) => Ok(start..=end),
|
||||
_ => Err(TryFromBoundsError),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -102,10 +89,10 @@ impl<I> TryFromBounds<I> for RangeFrom<I> {
|
||||
fn try_from_bounds(
|
||||
start_bound: Bound<I>,
|
||||
end_bound: Bound<I>,
|
||||
) -> Option<Self> {
|
||||
) -> Result<Self, TryFromBoundsError> {
|
||||
match (start_bound, end_bound) {
|
||||
(Bound::Included(start), Bound::Unbounded) => Some(start..),
|
||||
_ => None,
|
||||
(Bound::Included(start), Bound::Unbounded) => Ok(start..),
|
||||
_ => Err(TryFromBoundsError),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,10 +102,10 @@ impl<I> TryFromBounds<I> for RangeTo<I> {
|
||||
fn try_from_bounds(
|
||||
start_bound: Bound<I>,
|
||||
end_bound: Bound<I>,
|
||||
) -> Option<Self> {
|
||||
) -> Result<Self, TryFromBoundsError> {
|
||||
match (start_bound, end_bound) {
|
||||
(Bound::Unbounded, Bound::Excluded(end)) => Some(..end),
|
||||
_ => None,
|
||||
(Bound::Unbounded, Bound::Excluded(end)) => Ok(..end),
|
||||
_ => Err(TryFromBoundsError),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -128,10 +115,10 @@ impl<I> TryFromBounds<I> for RangeToInclusive<I> {
|
||||
fn try_from_bounds(
|
||||
start_bound: Bound<I>,
|
||||
end_bound: Bound<I>,
|
||||
) -> Option<Self> {
|
||||
) -> Result<Self, TryFromBoundsError> {
|
||||
match (start_bound, end_bound) {
|
||||
(Bound::Unbounded, Bound::Included(end)) => Some(..=end),
|
||||
_ => None,
|
||||
(Bound::Unbounded, Bound::Included(end)) => Ok(..=end),
|
||||
_ => Err(TryFromBoundsError),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -141,10 +128,10 @@ impl<I> TryFromBounds<I> for RangeFull {
|
||||
fn try_from_bounds(
|
||||
start_bound: Bound<I>,
|
||||
end_bound: Bound<I>,
|
||||
) -> Option<Self> {
|
||||
) -> Result<Self, TryFromBoundsError> {
|
||||
match (start_bound, end_bound) {
|
||||
(Bound::Unbounded, Bound::Unbounded) => Some(..),
|
||||
_ => None,
|
||||
(Bound::Unbounded, Bound::Unbounded) => Ok(..),
|
||||
_ => Err(TryFromBoundsError),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user