omgosh cut is so pretty! everything compiles with a beautiful cut function written

This commit is contained in:
ripytide
2023-04-03 17:59:46 +01:00
parent ac0532b882
commit 14e9734791
3 changed files with 122 additions and 55 deletions
+4 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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),
}
}
}