use crate::span::{BoundSpan, UnboundSpan};
pub(crate) trait SpanIterator: Iterator<Item = UnboundSpan> {
fn i(&self) -> usize;
fn exhaustive(&self) -> bool;
fn incr(&mut self);
fn is_finished(&self) -> bool;
fn reset(&mut self);
fn get(&self) -> Option<<Self as Iterator>::Item>;
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct UnboundSpanIterator {
span: UnboundSpan,
i: usize,
iter_span: bool,
}
impl UnboundSpanIterator {
pub(crate) fn new(span: UnboundSpan, iter_span: bool) -> Self {
Self {
span,
i: 0,
iter_span,
}
}
}
impl SpanIterator for UnboundSpanIterator {
fn i(&self) -> usize {
self.i
}
fn exhaustive(&self) -> bool {
false
}
fn incr(&mut self) {
self.i += 1;
}
fn is_finished(&self) -> bool {
self.i() >= self.len()
}
fn reset(&mut self) {
self.i = 0;
}
fn get(&self) -> Option<<Self as Iterator>::Item> {
match self.iter_span {
true => {
if self.i == 0 {
Some(self.span)
} else {
None
}
}
false => self.span.get_index(self.i).map(|i| i.into()),
}
}
}
impl ExactSizeIterator for UnboundSpanIterator {
fn len(&self) -> usize {
if self.iter_span {
1
} else {
self.span.len()
}
}
}
impl Iterator for UnboundSpanIterator {
type Item = UnboundSpan;
fn next(&mut self) -> Option<Self::Item> {
let item = self.get();
self.incr();
item
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct BoundSpanIterator {
bound_span: BoundSpan,
i: usize,
iter_seq: bool,
iter_span: bool,
}
impl BoundSpanIterator {
pub(crate) fn new(span: BoundSpan, iter_seq: bool, iter_span: bool) -> Self {
Self {
bound_span: span,
i: 0,
iter_seq,
iter_span,
}
}
}
impl SpanIterator for BoundSpanIterator {
fn i(&self) -> usize {
self.i
}
fn exhaustive(&self) -> bool {
self.iter_span && self.bound_span.exhaustive()
}
fn incr(&mut self) {
self.i += 1;
}
fn is_finished(&self) -> bool {
self.i() >= self.len()
}
fn reset(&mut self) {
self.i = 0;
}
fn get(&self) -> Option<<Self as Iterator>::Item> {
match (self.iter_seq, self.iter_span) {
(true, true) => {
if self.bound_span.is_wrapping() {
match self.i {
0 => self.bound_span.get_span(1),
1 => self.bound_span.get_span(0),
_ => None,
}
} else {
self.bound_span.get_span(0)
}
}
(true, false) => self.bound_span.get_index_ordered(self.i).map(|i| i.into()),
(false, true) => self.bound_span.get_span(self.i),
(false, false) => self.bound_span.get_index(self.i).map(|i| i.into()),
}
}
}
impl ExactSizeIterator for BoundSpanIterator {
fn len(&self) -> usize {
if self.iter_span {
match self.bound_span.is_wrapping() {
true => 2,
false => 1,
}
} else {
self.bound_span.len()
}
}
}
impl Iterator for BoundSpanIterator {
type Item = UnboundSpan;
fn next(&mut self) -> Option<Self::Item> {
let item = self.get();
self.incr();
item
}
}
#[cfg(test)]
mod tests {
#[cfg(test)]
mod unbound {
use crate::span::UnboundSpan;
use crate::span_iter::UnboundSpanIterator;
#[test]
fn len() {
let idx_iter = UnboundSpanIterator::new(UnboundSpan::new(1, 3), false);
let span_iter = UnboundSpanIterator::new(UnboundSpan::new(1, 3), true);
assert_eq!(idx_iter.len(), 3);
assert_eq!(span_iter.len(), 1);
}
#[test]
fn iter() {
let iter = UnboundSpanIterator::new(UnboundSpan::new(1, 3), false);
#[rustfmt::skip]
assert_eq!(iter.collect::<Vec<_>>(), [
(1, 1).into(), (2, 2).into(), (3, 3).into()
]);
}
#[test]
fn iter_span() {
let iter = UnboundSpanIterator::new(UnboundSpan::new(1, 3), true);
assert_eq!(iter.collect::<Vec<_>>(), [(1, 3).into()]);
}
}
#[cfg(test)]
mod bound {
use crate::span::BoundSpan;
use crate::span_iter::BoundSpanIterator;
#[test]
fn len() {
let idx_iter = BoundSpanIterator::new(BoundSpan::new(4, 5, 6), false, false);
let span_iter = BoundSpanIterator::new(BoundSpan::new(4, 5, 6), false, true);
assert_eq!(idx_iter.len(), 5);
assert_eq!(span_iter.len(), 2);
}
#[test]
fn iter() {
let iter = BoundSpanIterator::new(BoundSpan::new(4, 5, 6), false, false);
#[rustfmt::skip]
assert_eq!(iter.collect::<Vec<_>>(), [
(4, 4).into(), (5, 5).into(), (0, 0).into(), (1, 1).into(), (2, 2).into()
]);
}
#[test]
fn iter_seq() {
let iter = BoundSpanIterator::new(BoundSpan::new(4, 5, 6), true, false);
#[rustfmt::skip]
assert_eq!(iter.collect::<Vec<_>>(), [
(0, 0).into(), (1, 1).into(), (2, 2).into(), (4, 4).into(), (5, 5).into()
]);
}
#[test]
fn iter_span() {
let iter = BoundSpanIterator::new(BoundSpan::new(4, 5, 6), false, true);
assert_eq!(iter.collect::<Vec<_>>(), [(4, 5).into(), (0, 2).into()]);
}
#[test]
fn iter_seq_span() {
let iter = BoundSpanIterator::new(BoundSpan::new(4, 5, 6), true, true);
assert_eq!(iter.collect::<Vec<_>>(), [(0, 2).into(), (4, 5).into()]);
}
}
}