use std::{
iter::{FusedIterator, Peekable},
};
pub struct SkipFirst {
first: bool,
}
impl SkipFirst {
pub fn new() -> Self {
Self {
first: true,
}
}
pub fn skip_first<R>(&mut self, f: impl FnOnce() -> R) -> Option<R> {
if self.first {
self.first = false;
None
} else {
Some(f())
}
}
}
pub struct WithStatus<I: Iterator> {
iter: Peekable<I>,
first: bool,
}
impl<I: Iterator> WithStatus<I> {
fn new(iter: I) -> Self {
Self {
iter: iter.peekable(),
first: true,
}
}
}
impl<I: Iterator> Iterator for WithStatus<I> {
type Item = (I::Item, Status);
fn next(&mut self) -> Option<Self::Item> {
let item = self.iter.next();
let status = Status {
first: self.first,
last: self.iter.peek().is_none(),
};
if self.first {
self.first = false;
}
item.map(|elem| (elem, status))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<I: FusedIterator> FusedIterator for WithStatus<I> {}
impl<I: ExactSizeIterator> ExactSizeIterator for WithStatus<I> {
fn len(&self) -> usize {
self.iter.len()
}
}
pub trait IterStatusExt: Iterator + Sized {
fn with_status(self) -> WithStatus<Self>;
}
impl<I: Iterator> IterStatusExt for I {
fn with_status(self) -> WithStatus<Self> {
WithStatus::new(self)
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Status {
first: bool,
last: bool,
}
impl Status {
pub fn is_first(&self) -> bool {
self.first
}
pub fn is_first_only(&self) -> bool {
self.first && !self.last
}
pub fn is_last(&self) -> bool {
self.last
}
pub fn is_last_only(&self) -> bool {
self.last && !self.first
}
pub fn is_in_between(&self) -> bool {
!self.first && !self.last
}
}