use core::cmp::Ordering;
use core::iter::{FusedIterator, Peekable};
use core::ops::{Range, RangeInclusive};
trait RangeOrder {
fn order_start(&self, other: &Self) -> Ordering;
fn order_end(&self, other: &Self) -> Ordering;
}
impl<T: Ord> RangeOrder for Range<T> {
fn order_start(&self, other: &Self) -> Ordering {
self.start.cmp(&other.start)
}
fn order_end(&self, other: &Self) -> Ordering {
self.end.cmp(&other.end)
}
}
impl<T: Ord> RangeOrder for RangeInclusive<T> {
fn order_start(&self, other: &Self) -> Ordering {
self.start().cmp(other.start())
}
fn order_end(&self, other: &Self) -> Ordering {
self.end().cmp(other.end())
}
}
trait RangeMerge: Sized {
fn merge(&mut self, next: &Self) -> bool;
}
impl<T: Ord + Clone> RangeMerge for Range<T> {
fn merge(&mut self, other: &Self) -> bool {
if !self.contains(&other.start) {
return false;
}
if other.end > self.end {
self.end = other.end.clone();
}
true
}
}
impl<T: Ord + Clone> RangeMerge for RangeInclusive<T> {
fn merge(&mut self, other: &Self) -> bool {
if !self.contains(other.start()) {
return false;
}
if other.end() > self.end() {
*self = RangeInclusive::new(self.start().clone(), other.end().clone());
}
true
}
}
trait RangeIntersect: Sized {
fn intersect(&self, next: &Self) -> Option<Self>;
}
impl<T: Ord + Clone> RangeIntersect for Range<T> {
fn intersect(&self, other: &Self) -> Option<Self> {
let start = (&self.start).max(&other.start);
let end = (&self.end).min(&other.end);
if start >= end {
return None;
}
Some(start.clone()..end.clone())
}
}
impl<T: Ord + Clone> RangeIntersect for RangeInclusive<T> {
fn intersect(&self, other: &Self) -> Option<Self> {
let start = self.start().max(other.start());
let end = self.end().min(other.end());
if start > end {
return None;
}
Some(start.clone()..=end.clone())
}
}
#[test]
fn test_intersect() {
assert_eq!((0..5).intersect(&(0..3)), Some(0..3));
assert_eq!((0..3).intersect(&(0..5)), Some(0..3));
assert_eq!((0..3).intersect(&(3..3)), None);
}
pub struct Union<'a, T, L, R = L>
where
T: 'a,
L: Iterator<Item = &'a T>,
R: Iterator<Item = &'a T>,
{
left: Peekable<L>,
right: Peekable<R>,
}
impl<'a, T, L, R> Union<'a, T, L, R>
where
T: 'a,
L: Iterator<Item = &'a T>,
R: Iterator<Item = &'a T>,
{
pub fn new(left: L, right: R) -> Self {
Self {
left: left.peekable(),
right: right.peekable(),
}
}
}
impl<'a, R, I> Iterator for Union<'a, R, I>
where
R: RangeOrder + RangeMerge + Clone,
I: Iterator<Item = &'a R>,
{
type Item = R;
fn next(&mut self) -> Option<Self::Item> {
let mut range = match (self.left.peek(), self.right.peek()) {
(Some(_), None) => self.left.next().unwrap(),
(None, Some(_)) => self.right.next().unwrap(),
(Some(left), Some(right)) => {
if left.order_start(right).is_lt() {
self.left.next().unwrap()
} else {
self.right.next().unwrap()
}
}
(None, None) => return None,
}
.clone();
let mut join = |iter: &mut Peekable<I>| {
if let Some(next) = iter.peek() {
if range.merge(next) {
iter.next().unwrap();
return true;
}
}
false
};
loop {
if !(join(&mut self.left) || join(&mut self.right)) {
break;
}
}
Some(range)
}
}
impl<'a, R, I> FusedIterator for Union<'a, R, I>
where
R: RangeOrder + RangeMerge + Clone,
I: Iterator<Item = &'a R>,
{
}
pub struct Intersection<'a, T, L, R = L>
where
T: 'a,
L: Iterator<Item = &'a T>,
R: Iterator<Item = &'a T>,
{
left: Peekable<L>,
right: Peekable<R>,
}
impl<'a, T, L, R> Intersection<'a, T, L, R>
where
T: 'a,
L: Iterator<Item = &'a T>,
R: Iterator<Item = &'a T>,
{
pub fn new(left: L, right: R) -> Self {
Self {
left: left.peekable(),
right: right.peekable(),
}
}
}
impl<'a, R, I> Iterator for Intersection<'a, R, I>
where
R: RangeOrder + RangeIntersect + Clone,
I: Iterator<Item = &'a R>,
{
type Item = R;
fn next(&mut self) -> Option<Self::Item> {
loop {
let (Some(left), Some(right)) = (self.left.peek(), self.right.peek()) else {
return None;
};
let intersection = left.intersect(right);
if left.order_end(right).is_lt() {
self.left.next();
} else {
self.right.next();
}
if let Some(intersection) = intersection {
return Some(intersection);
}
}
}
}