use core::{
iter::FusedIterator,
ops::{self, RangeInclusive},
};
use crate::{BitAndMerge, BitOrMerge, BitSubMerge, BitXOrTee, Integer, SortedDisjoint};
#[derive(Clone, Debug)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct NotIter<T, I>
where
T: Integer,
I: SortedDisjoint<T>,
{
iter: I,
start_not: T,
next_time_return_none: bool,
}
impl<T, I> NotIter<T, I>
where
T: Integer,
I: SortedDisjoint<T>,
{
pub fn new<J>(iter: J) -> Self
where
J: IntoIterator<Item = RangeInclusive<T>, IntoIter = I>,
{
NotIter {
iter: iter.into_iter(),
start_not: T::min_value(),
next_time_return_none: false,
}
}
}
impl<T, I> FusedIterator for NotIter<T, I>
where
T: Integer,
I: SortedDisjoint<T> + FusedIterator,
{
}
impl<T, I> Iterator for NotIter<T, I>
where
T: Integer,
I: SortedDisjoint<T>,
{
type Item = RangeInclusive<T>;
fn next(&mut self) -> Option<RangeInclusive<T>> {
debug_assert!(T::min_value() <= T::safe_max_value()); if self.next_time_return_none {
return None;
}
let next_item = self.iter.next();
if let Some(range) = next_item {
let (start, end) = range.into_inner();
debug_assert!(start <= end && end <= T::safe_max_value());
if self.start_not < start {
let result = Some(self.start_not..=start - T::one());
if end < T::safe_max_value() {
self.start_not = end + T::one();
} else {
self.next_time_return_none = true;
}
result
} else if end < T::safe_max_value() {
self.start_not = end + T::one();
self.next() } else {
self.next_time_return_none = true;
None
}
} else {
self.next_time_return_none = true;
Some(self.start_not..=T::safe_max_value())
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (low, high) = self.iter.size_hint();
let low = if low > 0 { low - 1 } else { 0 };
let high = high.map(|high| {
if high < usize::MAX {
high + 1
} else {
usize::MAX
}
});
(low, high)
}
}
impl<T: Integer, I> ops::Not for NotIter<T, I>
where
I: SortedDisjoint<T>,
{
type Output = NotIter<T, Self>;
fn not(self) -> Self::Output {
self.complement()
}
}
impl<T: Integer, R, L> ops::BitOr<R> for NotIter<T, L>
where
L: SortedDisjoint<T>,
R: SortedDisjoint<T>,
{
type Output = BitOrMerge<T, Self, R>;
fn bitor(self, other: R) -> Self::Output {
SortedDisjoint::union(self, other)
}
}
impl<T: Integer, R, L> ops::Sub<R> for NotIter<T, L>
where
L: SortedDisjoint<T>,
R: SortedDisjoint<T>,
{
type Output = BitSubMerge<T, Self, R>;
fn sub(self, other: R) -> Self::Output {
SortedDisjoint::difference(self, other)
}
}
impl<T: Integer, R, L> ops::BitXor<R> for NotIter<T, L>
where
L: SortedDisjoint<T>,
R: SortedDisjoint<T>,
{
type Output = BitXOrTee<T, Self, R>;
#[allow(clippy::suspicious_arithmetic_impl)]
fn bitxor(self, other: R) -> Self::Output {
SortedDisjoint::symmetric_difference(self, other)
}
}
impl<T: Integer, R, L> ops::BitAnd<R> for NotIter<T, L>
where
L: SortedDisjoint<T>,
R: SortedDisjoint<T>,
{
type Output = BitAndMerge<T, Self, R>;
fn bitand(self, other: R) -> Self::Output {
SortedDisjoint::intersection(self, other)
}
}