use crate::map::ValueCarrier;
use crate::merge_map::KMergeMap;
use crate::sorted_disjoint_map::{Priority, PrioritySortedStartsMap};
use crate::{AssumeSortedStarts, MergeMap, SortedDisjointMap, UnionKMergeMap, UnionMergeMap};
use alloc::{collections::BinaryHeap, vec};
use core::cmp::min;
use core::iter::FusedIterator;
use core::ops::RangeInclusive;
use itertools::Itertools;
use crate::Integer;
use crate::unsorted_priority_map::AssumePrioritySortedStartsMap;
use crate::unsorted_priority_map::UnsortedPriorityMap;
type SortedStartsInVecMap<T, VC> = AssumePrioritySortedStartsMap<vec::IntoIter<Priority<T, VC>>>;
#[allow(clippy::redundant_pub_crate)]
pub(crate) type SortedStartsInVec<T> = AssumeSortedStarts<T, vec::IntoIter<RangeInclusive<T>>>;
#[derive(Clone, Debug)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct UnionIterMap<T, VC, SS> {
iter: SS,
next_item: Option<Priority<T, VC>>,
workspace: BinaryHeap<Priority<T, VC>>,
gather: Option<(RangeInclusive<T>, VC)>,
ready_to_go: Option<(RangeInclusive<T>, VC)>,
}
impl<T, VC, I> Iterator for UnionIterMap<T, VC, I>
where
T: Integer,
VC: ValueCarrier,
I: PrioritySortedStartsMap<T, VC>,
{
type Item = (RangeInclusive<T>, VC);
fn next(&mut self) -> Option<(RangeInclusive<T>, VC)> {
loop {
if let Some(value) = self.ready_to_go.take() {
return Some(value);
}
if let Some(next_item) = self.next_item.take() {
let (next_start, next_end) = next_item.start_and_end();
let Some(best) = self.workspace.peek() else {
self.workspace.push(next_item);
self.next_item = self.iter.next();
continue; };
if next_start == best.start() {
if &next_item > best || next_end > best.end() {
self.workspace.push(next_item);
}
self.next_item = self.iter.next();
continue; }
self.next_item = Some(next_item);
}
let Some(best) = self.workspace.peek() else {
debug_assert!(self.next_item.is_none());
debug_assert!(self.ready_to_go.is_none());
return self.gather.take();
};
let next_end = self.next_item.as_ref().map_or_else(
|| best.end(),
|next_item| min(next_item.start().sub_one(), best.end()),
);
if let Some((mut gather_range, gather_value)) = self.gather.take() {
if gather_value.value_eq(best.value())
&& (*gather_range.end()).add_one() == best.start()
{
gather_range = *gather_range.start()..=next_end;
self.gather = Some((gather_range, gather_value));
} else {
self.ready_to_go = Some((gather_range, gather_value));
self.gather = Some((best.start()..=next_end, best.value().clone()));
}
} else {
self.gather = Some((best.start()..=next_end, best.value().clone()));
}
let mut new_workspace = BinaryHeap::new();
while let Some(item) = self.workspace.pop() {
let mut item = item;
if item.end() <= next_end {
continue; }
item.set_range(next_end.add_one()..=item.end());
let Some(new_best) = new_workspace.peek() else {
new_workspace.push(item);
continue; };
if &item < new_best && item.end() <= new_best.end() {
continue; }
new_workspace.push(item);
}
self.workspace = new_workspace;
} }
}
impl<T, VC, I> UnionIterMap<T, VC, I>
where
T: Integer,
VC: ValueCarrier,
I: PrioritySortedStartsMap<T, VC>,
{
#[inline]
pub(crate) fn new(mut iter: I) -> Self {
let item = iter.next();
Self {
iter,
next_item: item,
workspace: BinaryHeap::new(),
gather: None,
ready_to_go: None,
}
}
}
impl<T, VC, L, R> UnionMergeMap<T, VC, L, R>
where
T: Integer,
VC: ValueCarrier,
L: SortedDisjointMap<T, VC>,
R: SortedDisjointMap<T, VC>,
{
#[inline]
pub(crate) fn new2(left: L, right: R) -> Self {
let iter = MergeMap::new(left, right);
Self::new(iter)
}
}
impl<T, VC, J> UnionKMergeMap<T, VC, J>
where
T: Integer,
VC: ValueCarrier,
J: SortedDisjointMap<T, VC>,
{
#[inline]
pub(crate) fn new_k<K>(k: K) -> Self
where
K: IntoIterator<Item = J>,
{
let iter = KMergeMap::new(k);
Self::new(iter)
}
}
impl<T, VC> FromIterator<(RangeInclusive<T>, VC)>
for UnionIterMap<T, VC, SortedStartsInVecMap<T, VC>>
where
T: Integer,
VC: ValueCarrier,
{
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = (RangeInclusive<T>, VC)>,
{
let iter = iter.into_iter();
let iter = UnsortedPriorityMap::new(iter);
let iter = iter.sorted_by(|a, b| a.start().cmp(&b.start()));
let iter = AssumePrioritySortedStartsMap::new(iter);
Self::new(iter)
}
}
impl<T, VC, I> FusedIterator for UnionIterMap<T, VC, I>
where
T: Integer,
VC: ValueCarrier,
I: PrioritySortedStartsMap<T, VC> + FusedIterator,
{
}