added return iterator to cut

This commit is contained in:
ripytide
2022-12-11 16:32:27 +00:00
parent 1ff034be6a
commit c879168c59
2 changed files with 160 additions and 108 deletions
+153 -107
View File
@@ -680,65 +680,88 @@ where
/// assert_eq!(base, after_cut);
/// assert_eq!(base.cut(&(60..=80)), Err(TryFromBoundsError));
/// ```
//#[untested]
//pub fn cut<Q>(&mut self, range_bounds: &Q) -> Result<(), TryFromBoundsError>
//where
//Q: RangeBounds<I>,
//K: TryFromBounds<I>,
//V: Clone,
//{
//let mut to_insert = Vec::new();
#[tested]
pub fn cut<Q>(&mut self, range_bounds: &Q) -> Result<impl DoubleEndedIterator<Item = ((Bound<I>, Bound<I>), V)>, TryFromBoundsError>
where
Q: RangeBounds<I>,
K: TryFromBounds<I>,
V: Clone,
{
let mut to_insert = Vec::new();
let mut partial_first = None;
let mut partial_last = None;
//{
//let mut overlapping = self.overlapping(range_bounds);
{
// only the first and last range_bounds in overlapping stand a
// change of remaining after the cut so we don't need to
// collect the iterator and can just look at the first and
// last elements since range is a double ended iterator ;p
let mut overlapping = self.overlapping(range_bounds);
//let first_last = (overlapping.next(), overlapping.next_back());
if let Some(first) = overlapping.next() {
let cut_result = cut_range_bounds(first.0, range_bounds);
//match first_last {
//(Some(first), Some(last)) => {
//match cut_range_bounds(first.0, range_bounds) {
//CutResult::Nothing => {}
//CutResult::Single(left_section) => {
//to_insert.push((left_section, first.1.clone()));
//}
//CutResult::Double(_, _) => unreachable!(),
//}
//match cut_range_bounds(last.0, range_bounds) {
//CutResult::Nothing => {}
//CutResult::Single(right_section) => {
//to_insert.push((right_section, last.1.clone()));
//}
//CutResult::Double(_, _) => unreachable!(),
//}
//(Some(first), None) => {
//match cut_range_bounds(first.0, range_bounds) {
//CutResult::Nothing => {}
//CutResult::Single(section) => {
//to_insert.push((section, first.1.clone()));
//}
//CutResult::Double(left_section, right_section) => {
//to_insert.push((left_section, first.1.clone()));
//to_insert.push((right_section, first.1.clone()));
//}
//(None, None) => {}
//(None, Some(_)) => unreachable!(),
//}
if let Some(before) = cut_result.before_cut {
to_insert.push((cloned_bounds(before), first.1.clone()));
}
if let Some(after) = cut_result.after_cut {
to_insert.push((cloned_bounds(after), first.1.clone()));
}
//// Make sure that the inserts will work before we try to do
//// them, so if one fails the map remains unchanged
//if to_insert.iter().all(|(x, _)| K::is_valid(x)) {
//let removed = self.remove_overlapping(range_bounds);
//for ((start, end), value) in to_insert.into_iter() {
//self.insert_platonic(
//K::try_from_bounds(start, end).unwrap(),
//value.clone(),
//)
//.unwrap();
//}
//return Ok(());
//} else {
//return Err(TryFromBoundsError);
//}
partial_first = cut_result.inside_cut.map(cloned_bounds);
}
if let Some(last) = overlapping.next_back() {
let cut_result = cut_range_bounds(last.0, range_bounds);
if cut_result.before_cut.is_some() {
unreachable!()
}
if let Some(after) = cut_result.after_cut {
to_insert.push((cloned_bounds(after), last.1.clone()));
}
partial_last = cut_result.inside_cut.map(cloned_bounds);
}
}
// Make sure that the inserts will work before we try to do
// them, so if one fails the map remains unchanged
if to_insert.iter().all(|(x, _)| K::is_valid(x)) {
let mut removed = self.remove_overlapping(range_bounds);
for ((start, end), value) in to_insert.into_iter() {
self.insert_platonic(
K::try_from_bounds(start, end).unwrap(),
value,
)
.unwrap();
}
let mut removed_first =
removed.next().map(|(key, value)| (expand_cloned(&key), value));
let mut removed_last = removed
.next_back()
.map(|(key, value)| (expand_cloned(&key), value));
//remove the full rangebounds and replace with their partial cuts
//if they exist
if let Some(partial_first) = partial_first {
removed_first = removed_first.map(|(_, v)| (partial_first, v));
}
if let Some(partial_last) = partial_last {
removed_last = removed_last.map(|(_, v)| (partial_last, v));
}
// I'm in love again with this lol
let result = removed_first
.into_iter()
.chain(removed.map(|(key, value)| (expand_cloned(&key), value)))
.chain(removed_last.into_iter());
return Ok(result);
} else {
return Err(TryFromBoundsError);
}
}
/// Returns an iterator of `(Bound<&I>, Bound<&I>)` over all the
/// maximally-sized gaps in the map that are also within the given
@@ -1205,21 +1228,21 @@ where
/// [(&(2..4), &false), (&(4..6), &true), (&(6..8), &false)]
/// );
/// ```
//#[trivial]
//pub fn overwrite(
//&mut self,
//range_bounds: K,
//value: V,
//) -> Result<(), TryFromBoundsError>
//where
//V: Clone,
//K: TryFromBounds<I>,
//{
//self.cut(&range_bounds)?;
//self.insert_platonic(range_bounds, value).unwrap();
#[trivial]
pub fn overwrite(
&mut self,
range_bounds: K,
value: V,
) -> Result<(), TryFromBoundsError>
where
V: Clone,
K: TryFromBounds<I>,
{
self.cut(&range_bounds)?;
self.insert_platonic(range_bounds, value).unwrap();
//return Ok(());
//}
return Ok(());
}
/// Returns the first (`RangeBounds`, `Value`) pair in the map, if
/// any.
@@ -1400,24 +1423,10 @@ where
}
#[derive(Debug)]
enum CutResult<I> {
Nothing((Bound<I>, Bound<I>)),
Everything((Bound<I>, Bound<I>)),
Single(SingleCutResult<I>),
Double(DoubleCutResult<I>),
}
#[derive(Debug)]
struct SingleCutResult<I> {
inside_cut: (Bound<I>, Bound<I>),
outside_cut: (Bound<I>, Bound<I>),
}
#[derive(Debug)]
struct DoubleCutResult<I> {
inside_cut: (Bound<I>, Bound<I>),
before_cut: (Bound<I>, Bound<I>),
after_cut: (Bound<I>, Bound<I>),
struct CutResult<I> {
before_cut: Option<(Bound<I>, Bound<I>)>,
inside_cut: Option<(Bound<I>, Bound<I>)>,
after_cut: Option<(Bound<I>, Bound<I>)>,
}
#[untested]
@@ -1437,29 +1446,39 @@ where
let cut_all @ (cut_start, cut_end) =
(cut_range_bounds.start_bound(), cut_range_bounds.end_bound());
match config(base_range_bounds, cut_range_bounds) {
Config::LeftFirstNonOverlapping(_, _) => CutResult::Nothing(base_all),
Config::LeftFirstPartialOverlap(_, _) => {
CutResult::Single(SingleCutResult {
inside_cut: (cut_start, base_end),
outside_cut: (base_start, flip_bound(cut_start)),
})
}
Config::LeftContainsRight(a, b) => CutResult::Double(DoubleCutResult {
inside_cut: cut_all,
before_cut: (base_start, flip_bound(cut_start)),
after_cut: (flip_bound(cut_end), base_end),
}),
let mut result = CutResult {
before_cut: None,
inside_cut: None,
after_cut: None,
};
Config::RightFirstNonOverlapping(_, _) => CutResult::Nothing(base_all),
Config::RightFirstPartialOverlap(_, _) => {
CutResult::Single(SingleCutResult {
inside_cut: (base_start, cut_end),
outside_cut: (flip_bound(cut_end), base_end),
})
match config(base_range_bounds, cut_range_bounds) {
Config::LeftFirstNonOverlapping(_, _) => {
result.before_cut = Some(base_all);
}
Config::LeftFirstPartialOverlap(_, _) => {
result.inside_cut = Some((cut_start, base_end));
result.after_cut = Some((base_start, flip_bound(cut_start)));
}
Config::LeftContainsRight(a, b) => {
result.before_cut = Some((base_start, flip_bound(cut_start)));
result.inside_cut = Some(cut_all);
result.after_cut = Some((flip_bound(cut_end), base_end));
}
Config::RightFirstNonOverlapping(_, _) => {
result.after_cut = Some(base_all);
}
Config::RightFirstPartialOverlap(_, _) => {
result.before_cut = Some((flip_bound(cut_end), base_end));
result.inside_cut = Some((base_start, cut_end));
}
Config::RightContainsLeft(_, _) => {
result.inside_cut = Some(base_all);
}
Config::RightContainsLeft(_, _) => CutResult::Everything(base_all),
}
return result;
}
#[trivial]
@@ -1510,6 +1529,33 @@ where
}
}
#[trivial]
fn expand<I, K>(range_bounds: &K) -> (Bound<&I>, Bound<&I>)
where
K: RangeBounds<I>,
{
(range_bounds.start_bound(), range_bounds.end_bound())
}
#[trivial]
fn expand_cloned<I, K>(range_bounds: &K) -> (Bound<I>, Bound<I>)
where
K: RangeBounds<I>,
I: Clone
{
cloned_bounds((range_bounds.start_bound(), range_bounds.end_bound()))
}
#[trivial]
fn cloned_bounds<I>(
(start, end): (Bound<&I>, Bound<&I>),
) -> (Bound<I>, Bound<I>)
where
I: Clone,
{
(start.cloned(), end.cloned())
}
#[trivial]
fn flip_bound<I>(bound: Bound<&I>) -> Bound<&I> {
match bound {
+7 -1
View File
@@ -6,6 +6,8 @@
- make a range_bounds configuration: NonOverlapping, A contained in B,
A partial overlap B, with A before B. And use it to simplify all the
logic based RangeBounds functions
- make an expand function to go RangeBounds -> (Bound, Bound) rather
than doing it manually everywhere
# features
@@ -15,6 +17,10 @@
just add unwraps everywhere to simplify signatures on known-"Safe"
symmetric types such as Range
- make gaps() DoubleEndedIterator
- make all iterators cutsom types as is standardised in libraries for
some reason
- add coalesce if same-value otherwise overwrite) function to make
finally make range_bounds_map a superset of rangemap
@@ -34,7 +40,7 @@
- copy map to set again
- copy readme to lib.rs docs again
- take a look around idiomatic rust for a bit first
- run is_labelled again
- run is_labelled again and check they are accurate
- review method parameter names for all public functions
- update lines of code figures on docs
- add issues to github for all the caveats