use std::cmp::Ordering;
use std::iter::{FusedIterator, Peekable};
use std::ops::{Add, Sub};
use crate::intervals::meta::BoundInclusivity;
use crate::intervals::ops::{BoundEq, BoundOrd, BoundOrdering, BoundOverlapDisambiguationRuleSet};
use crate::intervals::relative::RelBound;
use crate::iter::intervals::layered_bounds::rel_state_change::LayeredBoundsStateChangeAtRelBound;
use crate::iter::intervals::layered_bounds::state::LayeredBoundsState;
#[derive(Debug, Clone, Hash)]
pub struct LayeredRelBounds<I1, I2> {
first_layer: I1,
second_layer: I2,
state: LayeredBoundsState,
queued_result: Option<LayeredBoundsStateChangeAtRelBound>,
exhausted: bool,
}
impl<I1, I2> LayeredRelBounds<I1, I2> {
#[must_use]
pub fn state(&self) -> LayeredBoundsState {
self.state
}
}
impl<I1, I2> LayeredRelBounds<I1, I2>
where
I1: Iterator<Item = RelBound>,
I2: Iterator<Item = RelBound>,
{
#[must_use]
pub fn new(first_layer_iter: I1, second_layer_iter: I2) -> LayeredRelBounds<Peekable<I1>, Peekable<I2>> {
LayeredRelBounds {
first_layer: first_layer_iter.peekable(),
second_layer: second_layer_iter.peekable(),
state: LayeredBoundsState::default(),
queued_result: None,
exhausted: false,
}
}
}
impl<I1, I2> Iterator for LayeredRelBounds<Peekable<I1>, Peekable<I2>>
where
I1: Iterator<Item = RelBound>,
I2: Iterator<Item = RelBound>,
{
type Item = LayeredBoundsStateChangeAtRelBound;
fn next(&mut self) -> Option<Self::Item> {
if self.exhausted {
return None;
}
if let Some(queued_result) = self.queued_result.take() {
return Some(queued_result);
}
let old_state = self.state();
let first_layer_peek = self.first_layer.peek();
let second_layer_peek = self.second_layer.peek();
match (first_layer_peek, second_layer_peek) {
(None, None) => {
self.exhausted = true;
self.state = LayeredBoundsState::NoLayers;
self.first_layer.next();
self.second_layer.next();
None
},
(Some(RelBound::Start(_)), None) => Some(layered_rel_bounds_change_start_first_layer(
old_state,
&mut self.first_layer,
&mut self.state,
)),
(Some(RelBound::End(_)), None) => Some(layered_rel_bounds_change_end_first_layer(
old_state,
&mut self.first_layer,
&mut self.state,
)),
(None, Some(RelBound::Start(_))) => Some(layered_rel_bounds_change_start_second_layer(
old_state,
&mut self.second_layer,
&mut self.state,
)),
(None, Some(RelBound::End(_))) => Some(layered_rel_bounds_change_end_second_layer(
old_state,
&mut self.second_layer,
&mut self.state,
)),
(Some(RelBound::Start(first_layer_peeked_start)), Some(RelBound::Start(second_layer_peeked_start))) => {
Some(layered_rel_bounds_change_start_start(
old_state,
first_layer_peeked_start.cmp(second_layer_peeked_start),
&mut self.first_layer,
&mut self.second_layer,
&mut self.state,
))
},
(Some(RelBound::Start(first_layer_peeked_start)), Some(RelBound::End(second_layer_peeked_end))) => {
Some(layered_rel_bounds_change_start_end(
old_state,
first_layer_peeked_start.bound_cmp(second_layer_peeked_end),
&mut self.first_layer,
&mut self.second_layer,
&mut self.state,
&mut self.queued_result,
))
},
(Some(RelBound::End(first_layer_peeked_end)), Some(RelBound::Start(second_layer_peeked_start))) => {
Some(layered_rel_bounds_change_end_start(
old_state,
first_layer_peeked_end.bound_cmp(second_layer_peeked_start),
&mut self.first_layer,
&mut self.second_layer,
&mut self.state,
&mut self.queued_result,
))
},
(Some(RelBound::End(first_layer_peeked_end)), Some(RelBound::End(second_layer_peeked_end))) => {
Some(layered_rel_bounds_change_end_end(
old_state,
first_layer_peeked_end.cmp(second_layer_peeked_end),
&mut self.first_layer,
&mut self.second_layer,
&mut self.state,
))
},
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let first_layer_size_hint = self.first_layer.size_hint();
let second_layer_size_hint = self.second_layer.size_hint();
(
first_layer_size_hint.0.max(second_layer_size_hint.0),
first_layer_size_hint.1.and_then(|first_layer_upper_bound| {
second_layer_size_hint
.1
.and_then(|second_layer_upper_bound| first_layer_upper_bound.checked_add(second_layer_upper_bound))
}),
)
}
}
impl<I1, I2> FusedIterator for LayeredRelBounds<Peekable<I1>, Peekable<I2>>
where
I1: Iterator<Item = RelBound>,
I2: Iterator<Item = RelBound>,
{
}
#[must_use]
pub fn layered_rel_bounds_change_start_first_layer(
old_state: LayeredBoundsState,
first_layer: &mut Peekable<impl Iterator<Item = RelBound>>,
state_mut: &mut LayeredBoundsState,
) -> LayeredBoundsStateChangeAtRelBound {
type Change = LayeredBoundsStateChangeAtRelBound;
let first_layer_start = first_layer
.next()
.expect("Peeked `Some`, got `None` after calling `next()`")
.start()
.expect("Matched for `RelBound::Start(_)`, destructured to something else");
*state_mut = (*state_mut).add(LayeredBoundsState::FirstLayer);
Change::new(
old_state,
*state_mut,
first_layer_start.opposite(),
Some(first_layer_start),
)
}
#[must_use]
pub fn layered_rel_bounds_change_end_first_layer(
old_state: LayeredBoundsState,
first_layer: &mut Peekable<impl Iterator<Item = RelBound>>,
state_mut: &mut LayeredBoundsState,
) -> LayeredBoundsStateChangeAtRelBound {
type Change = LayeredBoundsStateChangeAtRelBound;
let first_layer_end = first_layer
.next()
.expect("Peeked `Some`, got `None` after calling `next()`")
.end()
.expect("Matched for `RelBound::End(_)`, destructured to something else");
*state_mut = (*state_mut).sub(LayeredBoundsState::FirstLayer);
Change::new(old_state, *state_mut, Some(first_layer_end), first_layer_end.opposite())
}
#[must_use]
pub fn layered_rel_bounds_change_start_second_layer(
old_state: LayeredBoundsState,
second_layer: &mut Peekable<impl Iterator<Item = RelBound>>,
state_mut: &mut LayeredBoundsState,
) -> LayeredBoundsStateChangeAtRelBound {
type Change = LayeredBoundsStateChangeAtRelBound;
let second_layer_start = second_layer
.next()
.expect("Peeked `Some`, got `None` after calling `next()`")
.start()
.expect("Matched for `RelBound::Start(_)`, destructured to something else");
*state_mut = (*state_mut).add(LayeredBoundsState::SecondLayer);
Change::new(
old_state,
*state_mut,
second_layer_start.opposite(),
Some(second_layer_start),
)
}
#[must_use]
pub fn layered_rel_bounds_change_end_second_layer(
old_state: LayeredBoundsState,
second_layer: &mut Peekable<impl Iterator<Item = RelBound>>,
state_mut: &mut LayeredBoundsState,
) -> LayeredBoundsStateChangeAtRelBound {
type Change = LayeredBoundsStateChangeAtRelBound;
let second_layer_end = second_layer
.next()
.expect("Peeked `Some`, got `None` after calling `next()`")
.end()
.expect("Matched for `RelBound::End(_)`, destructured to something else");
*state_mut = (*state_mut).sub(LayeredBoundsState::SecondLayer);
Change::new(
old_state,
*state_mut,
Some(second_layer_end),
second_layer_end.opposite(),
)
}
#[must_use]
pub fn layered_rel_bounds_change_start_start(
old_state: LayeredBoundsState,
start_start_cmp: Ordering,
first_layer: &mut Peekable<impl Iterator<Item = RelBound>>,
second_layer: &mut Peekable<impl Iterator<Item = RelBound>>,
state_mut: &mut LayeredBoundsState,
) -> LayeredBoundsStateChangeAtRelBound {
type Change = LayeredBoundsStateChangeAtRelBound;
match start_start_cmp {
Ordering::Less => {
let first_layer_start = first_layer
.next()
.expect("Peeked `Some`, got `None` after calling `next()`")
.start()
.expect("Matched for `RelBound::Start(_)`, destructured to something else");
*state_mut = (*state_mut).add(LayeredBoundsState::FirstLayer);
Change::new(
old_state,
*state_mut,
first_layer_start.opposite(),
Some(first_layer_start),
)
},
Ordering::Equal => {
let first_layer_start = first_layer
.next()
.expect("Peeked `Some`, got `None` after calling `next()`")
.start()
.expect("Matched for `RelBound::Start(_)`, destructured to something else");
second_layer.next();
*state_mut = (*state_mut).add(LayeredBoundsState::BothLayers);
Change::new(
old_state,
*state_mut,
first_layer_start.opposite(),
Some(first_layer_start),
)
},
Ordering::Greater => {
let second_layer_start = second_layer
.next()
.expect("Peeked `Some`, got `None` after calling `next()`")
.start()
.expect("Matched for `RelBound::Start(_)`, destructured to something else");
*state_mut = (*state_mut).add(LayeredBoundsState::SecondLayer);
Change::new(
old_state,
*state_mut,
second_layer_start.opposite(),
Some(second_layer_start),
)
},
}
}
#[must_use]
pub fn layered_rel_bounds_change_start_end(
old_state: LayeredBoundsState,
start_end_cmp: BoundOrdering,
first_layer: &mut Peekable<impl Iterator<Item = RelBound>>,
second_layer: &mut Peekable<impl Iterator<Item = RelBound>>,
state_mut: &mut LayeredBoundsState,
queued_result_mut: &mut Option<LayeredBoundsStateChangeAtRelBound>,
) -> LayeredBoundsStateChangeAtRelBound {
type Change = LayeredBoundsStateChangeAtRelBound;
match start_end_cmp.disambiguate(BoundOverlapDisambiguationRuleSet::Lenient) {
Ordering::Less => {
let first_layer_start = first_layer
.next()
.expect("Peeked `Some`, got `None` after calling `next()`")
.start()
.expect("Matched for `RelBound::Start(_)`, destructured to something else");
*state_mut = (*state_mut).add(LayeredBoundsState::FirstLayer);
Change::new(
old_state,
*state_mut,
first_layer_start.opposite(),
Some(first_layer_start),
)
},
Ordering::Equal => {
let finite_first_layer_start = first_layer
.next()
.expect("Peeked `Some`, got `None` after calling `next()`")
.start()
.expect("Matched for `RelBound::Start(_)`, destructured to something else")
.finite()
.expect("An RelStartBound and an RelEndBound can only be equal if they are finite");
let finite_second_layer_end = second_layer
.next()
.expect("Peeked `Some`, got `None` after calling `next()`")
.end()
.expect("Matched for `RelBound::End(_)`, destructured to something else")
.finite()
.expect("An RelStartBound and an RelEndBound can only be equal if they are finite");
if finite_first_layer_start.bound_eq(&finite_second_layer_end, BoundOverlapDisambiguationRuleSet::Strict) {
let mut end_of_second_layer = finite_second_layer_end; end_of_second_layer
.pos_mut()
.set_inclusivity(BoundInclusivity::Exclusive);
let change_to_return = Change::new(
old_state,
LayeredBoundsState::BothLayers,
Some(end_of_second_layer.to_end_bound()),
Some(finite_first_layer_start.to_start_bound()),
);
let mut start_of_first_layer = finite_first_layer_start; start_of_first_layer
.pos_mut()
.set_inclusivity(BoundInclusivity::Inclusive);
*state_mut = LayeredBoundsState::FirstLayer;
*queued_result_mut = Some(Change::new(
LayeredBoundsState::BothLayers,
*state_mut,
Some(finite_first_layer_start.pos().to_end_bound()),
Some(start_of_first_layer.to_start_bound()),
));
change_to_return
} else {
*state_mut = (*state_mut)
.add(LayeredBoundsState::FirstLayer)
.sub(LayeredBoundsState::SecondLayer);
Change::new(
old_state,
*state_mut,
Some(finite_second_layer_end.to_end_bound()),
Some(finite_first_layer_start.to_start_bound()),
)
}
},
Ordering::Greater => {
let second_layer_end = second_layer
.next()
.expect("Peeked `Some`, got `None` after calling `next()`")
.end()
.expect("Matched for `RelBound::End(_)`, destructured to something else");
*state_mut = (*state_mut).sub(LayeredBoundsState::SecondLayer);
Change::new(
old_state,
*state_mut,
Some(second_layer_end),
second_layer_end.opposite(),
)
},
}
}
#[must_use]
pub fn layered_rel_bounds_change_end_start(
old_state: LayeredBoundsState,
end_start_cmp: BoundOrdering,
first_layer: &mut Peekable<impl Iterator<Item = RelBound>>,
second_layer: &mut Peekable<impl Iterator<Item = RelBound>>,
state_mut: &mut LayeredBoundsState,
queued_result_mut: &mut Option<LayeredBoundsStateChangeAtRelBound>,
) -> LayeredBoundsStateChangeAtRelBound {
type Change = LayeredBoundsStateChangeAtRelBound;
match end_start_cmp.disambiguate(BoundOverlapDisambiguationRuleSet::Lenient) {
Ordering::Less => {
let first_layer_end = first_layer
.next()
.expect("Peeked `Some`, got `None` after calling `next()`")
.end()
.expect("Matched for `RelBound::End(_)`, destructured to something else");
*state_mut = (*state_mut).sub(LayeredBoundsState::FirstLayer);
Change::new(old_state, *state_mut, Some(first_layer_end), first_layer_end.opposite())
},
Ordering::Equal => {
let finite_first_layer_end = first_layer
.next()
.expect("Peeked `Some`, got `None` after calling `next()`")
.end()
.expect("Matched for `RelBound::End(_)`, destructured to something else")
.finite()
.expect("An RelStartBound and an RelEndBound can only be equal if they are finite");
let finite_second_layer_start = second_layer
.next()
.expect("Peeked `Some`, got `None` after calling `next()`")
.start()
.expect("Matched for `RelBound::Start(_)`, destructured to something else")
.finite()
.expect("An RelStartBound and an RelEndBound can only be equal if they are finite");
if finite_first_layer_end.bound_eq(&finite_second_layer_start, BoundOverlapDisambiguationRuleSet::Strict) {
let mut end_of_first_layer = finite_first_layer_end; end_of_first_layer
.pos_mut()
.set_inclusivity(BoundInclusivity::Exclusive);
let change_to_return = Change::new(
old_state,
LayeredBoundsState::BothLayers,
Some(end_of_first_layer.to_end_bound()),
Some(finite_second_layer_start.to_start_bound()),
);
let mut start_of_second_layer = finite_second_layer_start; start_of_second_layer
.pos_mut()
.set_inclusivity(BoundInclusivity::Exclusive);
*state_mut = LayeredBoundsState::SecondLayer;
*queued_result_mut = Some(Change::new(
LayeredBoundsState::BothLayers,
*state_mut,
Some(finite_second_layer_start.pos().to_end_bound()),
Some(start_of_second_layer.to_start_bound()),
));
change_to_return
} else {
*state_mut = (*state_mut)
.sub(LayeredBoundsState::FirstLayer)
.add(LayeredBoundsState::SecondLayer);
Change::new(
old_state,
*state_mut,
Some(finite_first_layer_end.to_end_bound()),
Some(finite_second_layer_start.to_start_bound()),
)
}
},
Ordering::Greater => {
let second_layer_start = second_layer
.next()
.expect("Peeked `Some`, got `None` after calling `next()`")
.start()
.expect("Matched for `RelBound::Start(_)`, destructured to something else");
*state_mut = (*state_mut).add(LayeredBoundsState::SecondLayer);
Change::new(
old_state,
*state_mut,
second_layer_start.opposite(),
Some(second_layer_start),
)
},
}
}
#[must_use]
pub fn layered_rel_bounds_change_end_end(
old_state: LayeredBoundsState,
end_end_cmp: Ordering,
first_layer: &mut Peekable<impl Iterator<Item = RelBound>>,
second_layer: &mut Peekable<impl Iterator<Item = RelBound>>,
state_mut: &mut LayeredBoundsState,
) -> LayeredBoundsStateChangeAtRelBound {
type Change = LayeredBoundsStateChangeAtRelBound;
match end_end_cmp {
Ordering::Less => {
let first_layer_end = first_layer
.next()
.expect("Peeked `Some`, got `None` after calling `next()`")
.end()
.expect("Matched for `RelBound::End(_)`, destructured to something else");
*state_mut = (*state_mut).sub(LayeredBoundsState::FirstLayer);
Change::new(old_state, *state_mut, Some(first_layer_end), first_layer_end.opposite())
},
Ordering::Equal => {
let first_layer_end = first_layer
.next()
.expect("Peeked `Some`, got `None` after calling `next()`")
.end()
.expect("Matched for `RelBound::End(_)`, destructured to something else");
second_layer.next();
*state_mut = (*state_mut).sub(LayeredBoundsState::BothLayers);
Change::new(old_state, *state_mut, Some(first_layer_end), first_layer_end.opposite())
},
Ordering::Greater => {
let second_layer_end = second_layer
.next()
.expect("Peeked `Some`, got `None` after calling `next()`")
.end()
.expect("Matched for `RelBound::End(_)`, destructured to something else");
*state_mut = (*state_mut).sub(LayeredBoundsState::SecondLayer);
Change::new(
old_state,
*state_mut,
Some(second_layer_end),
second_layer_end.opposite(),
)
},
}
}