#![cfg_attr(not(feature = "std"), no_std)]
use std::iter::FusedIterator;
#[cfg(feature = "unstable")]
use std::collections::BinaryHeap;
#[derive(Debug)]
pub struct MultiIterator<'a, T> {
data: &'a [T],
cursor: usize,
}
impl<'a, T> MultiIterator<'a, T> {
#[inline]
pub fn new(data: &'a [T]) -> Self {
Self { data, cursor: 0 }
}
#[inline]
pub fn peek_n(&self, n: usize) -> Option<&'a [T]> {
if n == 0 {
return None;
}
let start = self.cursor;
let end = start + n;
if end > self.data.len() {
None
} else {
Some(&self.data[start..end])
}
}
#[inline]
pub fn peek_remaining(&self) -> Option<&'a [T]> {
if self.len() == 0 {
None
} else {
self.peek_n(self.len())
}
}
#[inline]
pub fn next_n(&mut self, n: usize) -> Option<&'a [T]> {
let span = self.peek_n(n)?;
self.cursor += span.len();
Some(span)
}
#[inline]
pub fn next_n_if_each(&mut self, n: usize, func: impl Fn(&'a T) -> bool) -> Option<&'a [T]> {
let span = self.peek_n(n)?;
for elem in span {
if !func(elem) {
return None;
}
}
self.cursor += span.len();
Some(span)
}
#[inline]
pub fn next_n_if_slice(
&mut self,
n: usize,
func: impl FnOnce(&'a [T]) -> bool,
) -> Option<&'a [T]> {
let span = self.peek_n(n)?;
if func(span) {
self.cursor += span.len();
Some(span)
} else {
None
}
}
#[inline]
pub fn remaining(self) -> Option<&'a [T]> {
self.peek_remaining()
}
#[inline]
pub fn remaining_if_each(self, func: impl Fn(&'a T) -> bool) -> Option<&'a [T]> {
let span = self.peek_remaining()?;
for elem in span {
if !func(elem) {
return None;
}
}
Some(span)
}
#[inline]
pub fn remaining_if_slice(self, func: impl FnOnce(&'a [T]) -> bool) -> Option<&'a [T]> {
let span = self.peek_remaining()?;
if !func(span) {
None
} else {
Some(span)
}
}
}
impl<'a, T> Iterator for MultiIterator<'a, T> {
type Item = &'a T;
#[inline]
fn next(&mut self) -> Option<&'a T> {
let item = self.data.get(self.cursor);
self.cursor += 1;
item
}
#[inline]
fn count(self) -> usize {
self.len()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len(), None)
}
#[inline]
fn last(self) -> Option<&'a T> {
self.data.last()
}
}
impl<'a, T> ExactSizeIterator for MultiIterator<'a, T> {
#[inline]
fn len(&self) -> usize {
self.data.len() - self.cursor
}
}
impl<'a, T> FusedIterator for MultiIterator<'a, T> {}
pub trait IntoMultiIterator<'a> {
type Item;
fn multi_iter(&'a self) -> MultiIterator<'a, Self::Item>;
}
impl<'a, T> IntoMultiIterator<'a> for [T] {
type Item = T;
#[inline]
fn multi_iter(&'a self) -> MultiIterator<'a, Self::Item> {
MultiIterator::new(self)
}
}
#[cfg(feature = "std")]
impl<'a, T> IntoMultiIterator<'a> for Vec<T> {
type Item = T;
#[inline]
fn multi_iter(&'a self) -> MultiIterator<'a, Self::Item> {
MultiIterator::new(self.as_slice())
}
}
#[cfg(feature = "std")]
#[cfg(feature = "unstable")]
impl<'a, T> IntoMultiIterator<'a> for BinaryHeap<T> {
type Item = T;
#[inline]
fn multi_iter(&'a self) -> MultiIterator<'a, Self::Item> {
MultiIterator::new(self.as_slice())
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_peek_n() {
use super::IntoMultiIterator;
let a = [1, 2, 3];
let iter = a.multi_iter();
let items = iter.peek_n(0);
assert!(items.is_none());
let items = iter.peek_n(3).unwrap();
assert_eq!(items.len(), 3);
assert_eq!(items[0], 1);
assert_eq!(items[1], 2);
assert_eq!(items[2], 3);
assert_eq!(iter.len(), 3);
assert!(iter.peek_n(4).is_none());
}
#[test]
fn test_peek_remaining() {
use super::IntoMultiIterator;
let a = [1, 2, 3];
let iter = a.multi_iter();
let items = iter.peek_remaining().unwrap();
assert_eq!(items.len(), 3);
assert_eq!(items[0], 1);
assert_eq!(items[1], 2);
assert_eq!(items[2], 3);
assert_eq!(iter.len(), 3);
let b: [i32; 0] = [];
let iter = b.multi_iter().peek_remaining();
assert!(iter.is_none());
}
#[test]
fn test_next_n() {
use super::IntoMultiIterator;
let a = [1, 2, 3];
let mut iter = a.multi_iter();
let items = iter.next_n(0);
assert!(items.is_none());
let items = iter.next_n(4);
assert!(items.is_none());
assert_eq!(iter.len(), 3);
let items = iter.next_n(3).unwrap();
assert_eq!(items.len(), 3);
assert_eq!(items[0], 1);
assert_eq!(items[1], 2);
assert_eq!(items[2], 3);
assert_eq!(iter.len(), 0);
let b: [i32; 0] = [];
let iter = b.multi_iter().next_n(1);
assert!(iter.is_none());
}
#[test]
fn test_next_n_if_each() {
use super::IntoMultiIterator;
let a = [1, 2, 3];
let mut iter = a.multi_iter();
let items = iter.next_n_if_each(0, |_| true);
assert!(items.is_none());
let items = iter.next_n_if_slice(3, |x| x[0] == 1 && x[1] == 2 && x[2] == 4);
assert!(items.is_none());
assert_eq!(iter.len(), 3);
let items = iter.next_n_if_each(3, |x| *x >= 1).unwrap();
assert_eq!(items.len(), 3);
assert_eq!(items[0], 1);
assert_eq!(items[1], 2);
assert_eq!(items[2], 3);
assert_eq!(iter.len(), 0);
let items = iter.next_n_if_each(1, |x| *x >= 1);
assert!(items.is_none());
}
#[test]
fn test_next_n_if_slice() {
use super::IntoMultiIterator;
let a = [1, 2, 3];
let mut iter = a.multi_iter();
let items = iter.next_n_if_slice(0, |_| true);
assert!(items.is_none());
let items = iter.next_n_if_slice(3, |x| x[0] == 1 && x[1] == 2 && x[2] == 4);
assert!(items.is_none());
assert_eq!(iter.len(), 3);
let items = iter
.next_n_if_slice(3, |x| x[0] == 1 && x[1] == 2 && x[2] == 3)
.unwrap();
assert_eq!(items.len(), 3);
assert_eq!(items[0], 1);
assert_eq!(items[1], 2);
assert_eq!(items[2], 3);
assert_eq!(iter.len(), 0);
let items = iter.next_n_if_slice(1, |_| true);
assert!(items.is_none());
}
#[test]
fn test_remaining() {
use super::IntoMultiIterator;
let a = [1, 2, 3];
let iter = a.multi_iter();
let items = iter.remaining().unwrap();
assert_eq!(items.len(), 3);
assert_eq!(items[0], 1);
assert_eq!(items[1], 2);
assert_eq!(items[2], 3);
let b: [i32; 0] = [];
let iter = b.multi_iter().remaining();
assert!(iter.is_none());
}
#[test]
fn test_remaining_if_each() {
use super::IntoMultiIterator;
let a = [1, 2, 3];
let items = a.multi_iter().remaining_if_each(|x| *x >= 1).unwrap();
assert_eq!(items.len(), 3);
assert_eq!(items[0], 1);
assert_eq!(items[1], 2);
assert_eq!(items[2], 3);
let items = a.multi_iter().remaining_if_each(|x| *x > 1);
assert!(items.is_none());
let b: [i32; 0] = [];
let items = b.multi_iter().remaining_if_each(|_| true);
assert!(items.is_none());
}
#[test]
fn test_remaining_if_slice() {
use super::IntoMultiIterator;
let a = [1, 2, 3];
let items = a
.multi_iter()
.remaining_if_slice(|x| x[0] == 1 && x[1] == 2 && x[2] == 3)
.unwrap();
assert_eq!(items.len(), 3);
assert_eq!(items[0], 1);
assert_eq!(items[1], 2);
assert_eq!(items[2], 3);
assert!(a
.multi_iter()
.remaining_if_slice(|x| { x[0] == 1 && x[1] == 2 && x[2] == 4 })
.is_none());
let b: [i32; 0] = [];
assert!(b.multi_iter().remaining_if_slice(|_| true).is_none());
}
}