use core::cmp::Ordering::*;
use crate::{map::Key, set::iterators::Iter, Segment, SegmentMap, SegmentSet};
impl<T> SegmentSet<T> {
pub fn iter_intersection<'a>(&'a self, other: &'a Self) -> Intersection<'a, T> {
Intersection {
iter_a: self.iter(),
prev_a: None,
iter_b: other.iter(),
prev_b: None,
}
}
pub fn intersection<'a>(&'a self, other: &'a Self) -> SegmentSet<&'a T>
where
T: Ord,
{
SegmentSet {
map: SegmentMap {
map: self
.iter_intersection(other)
.map(|r| (Key(r), ()))
.collect(),
store: alloc::vec::Vec::new(),
},
}
}
}
impl<'a, T: Ord + Clone> core::ops::BitAnd<&'a SegmentSet<T>> for &'a SegmentSet<T> {
type Output = SegmentSet<&'a T>;
fn bitand(self, rhs: &'a SegmentSet<T>) -> SegmentSet<&'a T> {
self.intersection(rhs)
}
}
impl<'a, T: Ord + Clone> core::ops::BitAnd<SegmentSet<T>> for SegmentSet<T> {
type Output = SegmentSet<T>;
fn bitand(self, rhs: SegmentSet<T>) -> SegmentSet<T> {
self.intersection(&rhs).cloned()
}
}
pub struct Intersection<'a, T> {
iter_a: Iter<'a, T>,
prev_a: Option<Segment<&'a T>>,
iter_b: Iter<'a, T>,
prev_b: Option<Segment<&'a T>>,
}
impl<'a, T: Ord> Iterator for Intersection<'a, T> {
type Item = Segment<&'a T>;
fn next(&mut self) -> Option<Self::Item> {
let mut next_a = self
.prev_a
.take()
.or_else(|| self.iter_a.next().map(|x| x.as_ref()))?;
let mut next_b = self
.prev_b
.take()
.or_else(|| self.iter_b.next().map(|x| x.as_ref()))?;
loop {
if next_a.end.cmp_start(&next_b.start).is_gt() {
next_a = self.iter_a.next()?.as_ref();
continue;
}
if next_a.start.cmp_end(&next_b.end).is_gt() {
next_b = self.iter_b.next()?.as_ref();
continue;
}
match (next_a.start.cmp(&next_b.start), next_a.end.cmp(&next_b.end)) {
(Less, Less) => {
next_a.start =
core::mem::replace(&mut next_b.start, next_a.borrow_bound_after().unwrap());
self.prev_b.insert(next_b);
return Some(next_a);
}
(Less, Equal) => return Some(next_b),
(Less, Greater) => {
next_a.start = next_b.borrow_bound_after().unwrap();
self.prev_a.insert(next_a);
return Some(next_b);
}
(Equal, Less) => {
next_b.start = next_a.borrow_bound_after().unwrap();
self.prev_b.insert(next_b);
return Some(next_a);
}
(Equal, Equal) => return Some(next_a),
(Equal, Greater) => {
next_a.start = next_b.borrow_bound_after().unwrap();
self.prev_a.insert(next_a);
return Some(next_b);
}
(Greater, Less) => {
next_b.start = next_a.borrow_bound_after().unwrap();
self.prev_b.insert(next_b);
return Some(next_a);
}
(Greater, Equal) => return Some(next_a),
(Greater, Greater) => {
next_b.start =
core::mem::replace(&mut next_a.start, next_b.borrow_bound_after().unwrap());
self.prev_a.insert(next_a);
return Some(next_b);
}
}
}
}
}