use std::{iter::from_fn, ops::Range};
#[derive(Debug)]
pub enum AxisRange {
Sequentual(Range<usize>),
Split(Range<usize>, Range<usize>),
}
impl AxisRange {
pub(crate) fn new_sequentual(low: usize, high: usize) -> Self {
debug_assert!(low < high);
AxisRange::Sequentual(low..high)
}
pub(crate) fn new_split(low: (usize, usize), high: (usize, usize)) -> Self {
debug_assert!(low.0 < low.1 && low.1 < high.0 && high.0 < high.1);
AxisRange::Split(low.0..low.1, high.0..high.1)
}
pub(crate) fn decr_bound(&self) -> usize {
match self {
AxisRange::Sequentual(range) | AxisRange::Split(_, range) => range.start,
}
}
pub(crate) fn incr_bound(&self) -> usize {
match self {
AxisRange::Sequentual(range) | AxisRange::Split(range, _) => range.end,
}
}
pub fn iter<'a>(&'a self) -> impl Iterator<Item = usize> + 'a {
let range_iter = |i: &mut usize, range: &Range<usize>| {
if *i >= range.end {
None
} else {
if *i < range.start {
*i = range.start;
};
*i += 1;
Some(*i - 1)
}
};
let mut i = 0;
from_fn(move || match &self {
AxisRange::Sequentual(range) => range_iter(&mut i, &range),
AxisRange::Split(range0, range1) => {
range_iter(&mut i, &range0).or_else(|| range_iter(&mut i, &range1))
}
})
}
}
#[test]
fn test_iter() {
let sequentual = AxisRange::new_sequentual(0, 10);
let split = AxisRange::new_split((0, 10), (30, 40));
assert_eq!(
sequentual.iter().collect::<Vec<_>>(),
(0..10).collect::<Vec<_>>()
);
assert_eq!(
split.iter().collect::<Vec<_>>(),
(0..10)
.into_iter()
.chain((30..40).into_iter())
.collect::<Vec<_>>()
);
}