use crate::errors::*;
use std::{fmt, iter::Iterator};
pub fn assert_iter_eq<T, U>(x: T, y: U)
where
T: IntoIterator,
U: IntoIterator,
T::Item: fmt::Debug+PartialEq<U::Item>,
U::Item: fmt::Debug,
{
let mut x = x.into_iter();
let mut y = y.into_iter();
loop {
match (x.next(), y.next()) {
(None, None) => return,
(a, b) => {
let equal = match (&a, &b) {
(&Some(ref a), &Some(ref b)) => a == b,
_ => false,
};
assert!(equal, "Iterators not equal {:?} != {:?}", a, b);
},
}
}
}
pub trait IteratorExt: Iterator {
fn consume(self) -> Self
where
Self: Sized;
fn drop(self, n: isize) -> Self
where
Self: Sized,
Self: DoubleEndedIterator;
fn first(self) -> Option<Self::Item>
where
Self: Sized;
fn first_result(self) -> FuResult<Self::Item>
where
Self: Sized;
fn last_result(self) -> FuResult<Self::Item>
where
Self: Sized;
fn single(self) -> FuResult<Self::Item>
where
Self: Sized;
fn slice(self, left: isize, right: isize) -> Self
where
Self: Sized,
Self: Clone,
Self: DoubleEndedIterator;
fn some(self) -> bool
where
Self: Sized;
}
impl<T: ?Sized> IteratorExt for T
where
T: Iterator,
{
#[allow(clippy::all)]
fn consume(mut self) -> Self
where
Self: Sized,
{
let mut iter = (&mut self).peekable();
while let Some(_) = iter.next() {}
self
}
fn drop(mut self, n: isize) -> Self
where
Self: Sized,
Self: DoubleEndedIterator,
{
if n > 0 {
self.nth(n as usize - 1);
}
if n < 0 {
(&mut self).rev().nth(n.abs() as usize - 1);
}
self
}
fn first(mut self) -> Option<Self::Item>
where
Self: Sized,
{
self.next()
}
fn first_result(mut self) -> FuResult<Self::Item>
where
Self: Sized,
{
match self.next() {
Some(first) => Ok(first),
None => Err(IterError::item_not_found().into()),
}
}
fn last_result(self) -> FuResult<Self::Item>
where
Self: Sized,
{
match self.last() {
Some(item) => Ok(item),
None => Err(IterError::item_not_found().into()),
}
}
fn single(mut self) -> FuResult<Self::Item>
where
Self: Sized,
{
match self.next() {
Some(item) => match self.next() {
Some(_) => Err(IterError::multiple_items_found().into()),
None => Ok(item),
},
None => Err(IterError::item_not_found().into()),
}
}
fn slice(mut self, left: isize, right: isize) -> Self
where
Self: Sized,
Self: Clone,
Self: DoubleEndedIterator,
{
let (mut l, mut r): (usize, usize) = (left as usize, 0);
let len = (self.clone()).count() as isize;
if left < 0 {
l = (len + left) as usize;
}
if l > 0 {
self.nth(l - 1);
}
if right > 0 && right < len {
r = (right - len + 1).abs() as usize;
} else if right < 0 && right.abs() <= len {
r = (right.abs() - 1).abs() as usize;
} else if right < 0 {
r = len as usize;
}
if r > 0 {
(&mut self).rev().nth(r - 1);
}
if left == 0 && right == 0 {
let i = len - 2;
if i > 0 {
(&mut self).rev().nth(i as usize);
}
}
self
}
fn some(mut self) -> bool
where
Self: Sized,
{
self.next().is_some()
}
}
#[cfg(test)]
mod tests {
use crate::prelude::*;
use std::path::Component;
#[test]
fn test_slice() {
assert_eq!(vec![0, 1, 2, 3].into_iter().slice(-1, -5).next(), None); assert_iter_eq(vec![0, 1, 2, 3], vec![0, 1, 2, 3].into_iter().slice(-4, -1)); assert_iter_eq(vec![0, 1, 2], vec![0, 1, 2, 3].into_iter().slice(-4, -2)); assert_iter_eq(vec![0, 1], vec![0, 1, 2, 3].into_iter().slice(-4, -3)); assert_iter_eq(vec![3], vec![0, 1, 2, 3].into_iter().slice(-1, -1)); assert_iter_eq(vec![2], vec![0, 1, 2, 3].into_iter().slice(-2, -2)); assert_iter_eq(vec![1], vec![0, 1, 2, 3].into_iter().slice(-3, -3)); assert_iter_eq(vec![0], vec![0, 1, 2, 3].into_iter().slice(-4, -4)); assert_iter_eq(vec![1, 2, 3], vec![0, 1, 2, 3].into_iter().slice(-3, -1)); assert_iter_eq(vec![1, 2], vec![0, 1, 2, 3].into_iter().slice(-3, -2)); assert_eq!(vec![0, 1, 2, 3].into_iter().slice(-1, -2).next(), None);
assert_iter_eq(vec![0, 1, 2, 3], vec![0, 1, 2, 3].into_iter().slice(0, 4)); assert_iter_eq(vec![0, 1, 2, 3], vec![0, 1, 2, 3].into_iter().slice(0, 3)); assert_iter_eq(vec![0, 1, 2], vec![0, 1, 2, 3].into_iter().slice(0, 2)); assert_iter_eq(vec![0, 1], vec![0, 1, 2, 3].into_iter().slice(0, 1)); assert_iter_eq(vec![3], vec![0, 1, 2, 3].into_iter().slice(3, 3)); assert_iter_eq(vec![2], vec![0, 1, 2, 3].into_iter().slice(2, 2)); assert_iter_eq(vec![1], vec![0, 1, 2, 3].into_iter().slice(1, 1)); assert_iter_eq(vec![0], vec![0, 1, 2, 3].into_iter().slice(0, 0)); assert_iter_eq(vec![1, 2, 3], vec![0, 1, 2, 3].into_iter().slice(1, 3)); assert_iter_eq(vec![1, 2], vec![0, 1, 2, 3].into_iter().slice(1, 2)); assert_eq!(vec![0, 1, 2, 3].into_iter().slice(3, 2).next(), None); assert_eq!(vec![0, 1, 2, 3].into_iter().slice(4, 3).next(), None);
assert_eq!(vec![0, 1, 2, 3].into_iter().slice(0, -5).next(), None); assert_iter_eq(vec![0, 1, 2, 3], vec![0, 1, 2, 3].into_iter().slice(0, -1)); assert_iter_eq(vec![0, 1, 2], vec![0, 1, 2, 3].into_iter().slice(0, -2)); assert_iter_eq(vec![0, 1], vec![0, 1, 2, 3].into_iter().slice(0, -3)); assert_iter_eq(vec![3], vec![0, 1, 2, 3].into_iter().slice(3, -1)); assert_iter_eq(vec![2], vec![0, 1, 2, 3].into_iter().slice(2, -2)); assert_iter_eq(vec![1], vec![0, 1, 2, 3].into_iter().slice(1, -3)); assert_iter_eq(vec![0], vec![0, 1, 2, 3].into_iter().slice(0, -4)); assert_iter_eq(vec![1, 2, 3], vec![0, 1, 2, 3].into_iter().slice(1, -1)); assert_iter_eq(vec![1, 2], vec![0, 1, 2, 3].into_iter().slice(1, -2)); assert_eq!(vec![0, 1, 2, 3].into_iter().slice(3, -2).next(), None); assert_eq!(vec![0, 1, 2, 3].into_iter().slice(4, -1).next(), None); }
#[test]
fn test_consume() {
assert_eq!(vec![0].into_iter().nth(0), Some(0));
assert_eq!(vec![0, 1, 2].into_iter().consume().nth(0), None);
}
#[test]
fn test_drop() {
assert_iter_eq(vec![2, 3], vec![1, 2, 3].into_iter().drop(1));
assert_iter_eq(PathBuf::from("bar").components(), PathBuf::from("foo/bar").components().drop(1));
assert_iter_eq(PathBuf::from("bar").components(), PathBuf::from("/foo/bar").components().drop(2));
assert_iter_eq(vec![1, 2], vec![1, 2, 3].into_iter().drop(-1));
assert_eq!(1, vec![1, 2, 3].into_iter().drop(-1).next().unwrap());
assert_iter_eq(PathBuf::from("foo").components(), PathBuf::from("foo/bar").components().drop(-1));
assert_iter_eq(PathBuf::from("/").components(), PathBuf::from("/foo/bar").components().drop(-2));
}
#[test]
fn test_eq() {
assert_iter_eq(vec![1, 2], vec![1, 2]);
assert!(std::panic::catch_unwind(|| assert_iter_eq(vec![1, 2], vec![1, 3])).is_err());
assert_iter_eq(PathBuf::from("foo/bar").components(), PathBuf::from("foo/bar").components());
assert!(std::panic::catch_unwind(|| assert_iter_eq(PathBuf::from("foo/bar").components(), PathBuf::from("bar").components())).is_err());
}
#[test]
fn test_first() {
assert_eq!(Component::Normal(OsStr::new("foo")), PathBuf::from("foo/bar").components().first().unwrap());
assert_ne!(Component::Normal(OsStr::new("bar")), PathBuf::from("foo/bar").components().first().unwrap());
}
#[test]
fn test_first_result() {
assert_eq!(Component::Normal(OsStr::new("foo")), PathBuf::from("foo/bar").components().first_result().unwrap());
assert_ne!(Component::Normal(OsStr::new("bar")), PathBuf::from("foo/bar").components().first_result().unwrap());
}
#[test]
fn test_last_result() {
assert_eq!(Component::Normal(OsStr::new("bar")), PathBuf::from("foo/bar").components().last_result().unwrap());
assert_ne!(Component::Normal(OsStr::new("foo")), PathBuf::from("foo/bar").components().last_result().unwrap());
}
#[test]
fn test_single() {
assert_eq!((0..10).filter(|&x| x == 2).single().unwrap(), 2);
assert_eq!((0..10).filter(|&x| x > 2).single().unwrap_err().downcast_ref::<IterError>(), Some(&IterError::multiple_items_found()));
assert_eq!((0..10).filter(|&x| x > 2 && x < 5).single().unwrap_err().downcast_ref::<IterError>(), Some(&IterError::multiple_items_found()));
}
#[test]
fn test_some() {
assert_eq!((0..10).filter(|&x| x == 2).some(), true);
assert_eq!((0..10).filter(|&x| x == 11).some(), false);
}
}