use core::{
cmp::Ordering,
iter::{self, Product, Sum},
};
use non_zero_size::Size;
use crate::{
adapter::NonEmptyAdapter, chain::Chain, cloned::Cloned, copied::Copied, cycle::Cycle,
enumerate::Enumerate, flat_map::FlatMap, flatten::Flatten, fuse::Fuse, inspect::Inspect,
map::Map, peeked::Peeked, rev::Rev, step_by::StepBy, take::Take, zip::Zip,
};
pub unsafe trait NonEmptyIterator: IntoIterator + Sized {
#[must_use]
fn consume(self) -> (Self::Item, Self::IntoIter) {
let mut iterator = self.into_iter();
let item = unsafe { iterator.next().unwrap_unchecked() };
(item, iterator)
}
#[must_use]
fn count(self) -> Size {
let count = self.into_iter().count();
unsafe { Size::new_unchecked(count) }
}
fn enumerate(self) -> Enumerate<Self> {
Enumerate::new(self)
}
fn peeked(self) -> Peeked<Self::IntoIter> {
let (item, rest) = self.consume();
Peeked::new(item, rest)
}
fn chain<I: IntoIterator<Item = Self::Item>>(self, other: I) -> Chain<Self, I::IntoIter> {
Chain::new(self, other.into_iter())
}
fn cloned<'a, T>(self) -> Cloned<Self>
where
Self: NonEmptyIterator<Item = &'a T>,
T: Clone + 'a,
{
Cloned::new(self)
}
fn copied<'a, T>(self) -> Copied<Self>
where
Self: NonEmptyIterator<Item = &'a T>,
T: Copy + 'a,
{
Copied::new(self)
}
fn zip<I: IntoNonEmptyIterator>(self, other: I) -> Zip<Self, I::IntoNonEmptyIter> {
Zip::new(self, other.into_non_empty_iter())
}
#[must_use]
fn sum<S: Sum<Self::Item>>(self) -> S {
self.into_iter().sum()
}
#[must_use]
fn product<P: Product<Self::Item>>(self) -> P {
self.into_iter().product()
}
fn all<P: FnMut(Self::Item) -> bool>(self, predicate: P) -> bool {
self.into_iter().all(predicate)
}
fn any<P: FnMut(Self::Item) -> bool>(self, predicate: P) -> bool {
self.into_iter().any(predicate)
}
fn none<P: FnMut(Self::Item) -> bool>(self, predicate: P) -> bool {
!self.any(predicate)
}
#[must_use]
fn reduce<F>(self, function: F) -> Self::Item
where
F: FnMut(Self::Item, Self::Item) -> Self::Item,
{
let output = self.into_iter().reduce(function);
unsafe { output.unwrap_unchecked() }
}
fn unzip<T, U, C: Default + Extend<T>, D: Default + Extend<U>>(self) -> (C, D)
where
Self: NonEmptyIterator<Item = (T, U)>,
{
self.into_iter().unzip()
}
fn collect<C: FromIterator<Self::Item>>(self) -> C {
self.into_iter().collect()
}
fn collect_non_empty<C: FromNonEmptyIterator<Self::Item>>(self) -> C {
C::from_non_empty_iter(self)
}
fn flat_map<J: IntoNonEmptyIterator, F: FnMut(Self::Item) -> J>(
self,
function: F,
) -> FlatMap<Self, J, F> {
FlatMap::new(self, function)
}
fn flatten(self) -> Flatten<Self>
where
Self::Item: IntoNonEmptyIterator,
{
Flatten::new(self)
}
fn filter<P: FnMut(&Self::Item) -> bool>(
self,
predicate: P,
) -> iter::Filter<Self::IntoIter, P> {
self.into_iter().filter(predicate)
}
fn find<P: FnMut(&Self::Item) -> bool>(self, predicate: P) -> Option<Self::Item> {
self.into_iter().find(predicate)
}
fn filter_map<T, F: FnMut(Self::Item) -> Option<T>>(
self,
function: F,
) -> iter::FilterMap<Self::IntoIter, F> {
self.into_iter().filter_map(function)
}
#[must_use]
fn fold<A, F: FnMut(A, Self::Item) -> A>(self, initial: A, function: F) -> A {
self.into_iter().fold(initial, function)
}
fn map<U, F: FnMut(Self::Item) -> U>(self, function: F) -> Map<Self, F> {
Map::new(self, function)
}
#[must_use]
fn max(self) -> Self::Item
where
Self::Item: Ord,
{
let max = self.into_iter().max();
unsafe { max.unwrap_unchecked() }
}
#[must_use]
fn max_by<F: FnMut(&Self::Item, &Self::Item) -> Ordering>(self, function: F) -> Self::Item {
let max = self.into_iter().max_by(function);
unsafe { max.unwrap_unchecked() }
}
#[must_use]
fn max_by_key<K: Ord, F: FnMut(&Self::Item) -> K>(self, function: F) -> Self::Item {
let max = self.into_iter().max_by_key(function);
unsafe { max.unwrap_unchecked() }
}
#[must_use]
fn min(self) -> Self::Item
where
Self::Item: Ord,
{
let min = self.into_iter().min();
unsafe { min.unwrap_unchecked() }
}
#[must_use]
fn min_by<F: FnMut(&Self::Item, &Self::Item) -> Ordering>(self, function: F) -> Self::Item {
let min = self.into_iter().min_by(function);
unsafe { min.unwrap_unchecked() }
}
#[must_use]
fn min_by_key<K: Ord, F: FnMut(&Self::Item) -> K>(self, function: F) -> Self::Item {
let min = self.into_iter().min_by_key(function);
unsafe { min.unwrap_unchecked() }
}
fn nth(self, n: Size) -> Option<Self::Item> {
self.into_iter().nth(n.get())
}
fn skip(self, count: Size) -> iter::Skip<Self::IntoIter> {
self.into_iter().skip(count.get())
}
fn take(self, count: Size) -> Take<Self> {
Take::new(self, count)
}
#[must_use]
fn last(self) -> Self::Item {
let last = self.into_iter().last();
unsafe { last.unwrap_unchecked() }
}
fn step_by(self, step: Size) -> StepBy<Self> {
StepBy::new(self, step)
}
fn for_each<F: FnMut(Self::Item)>(self, function: F) {
self.into_iter().for_each(function);
}
fn exhaust(self) {
self.for_each(drop);
}
fn skip_while<P: FnMut(&Self::Item) -> bool>(
self,
predicate: P,
) -> iter::SkipWhile<Self::IntoIter, P> {
self.into_iter().skip_while(predicate)
}
fn take_while<P: FnMut(&Self::Item) -> bool>(
self,
predicate: P,
) -> iter::TakeWhile<Self::IntoIter, P> {
self.into_iter().take_while(predicate)
}
fn map_while<T, P: FnMut(Self::Item) -> Option<T>>(
self,
predicate: P,
) -> iter::MapWhile<Self::IntoIter, P> {
self.into_iter().map_while(predicate)
}
fn scan<S, T, F: FnMut(&mut S, Self::Item) -> Option<T>>(
self,
initial: S,
function: F,
) -> iter::Scan<Self::IntoIter, S, F> {
self.into_iter().scan(initial, function)
}
fn inspect<F: FnMut(&Self::Item)>(self, function: F) -> Inspect<Self, F> {
Inspect::new(self, function)
}
fn partition<C: Default + Extend<Self::Item>, F: FnMut(&Self::Item) -> bool>(
self,
function: F,
) -> (C, C) {
self.into_iter().partition(function)
}
fn position<P: FnMut(Self::Item) -> bool>(self, predicate: P) -> Option<usize> {
self.into_iter().position(predicate)
}
fn cmp<I: IntoIterator<Item = Self::Item>>(self, other: I) -> Ordering
where
Self::Item: Ord,
{
self.into_iter().cmp(other)
}
fn partial_cmp<I: IntoIterator>(self, other: I) -> Option<Ordering>
where
Self::Item: PartialOrd<I::Item>,
{
self.into_iter().partial_cmp(other)
}
fn eq<I: IntoIterator>(self, other: I) -> bool
where
Self::Item: PartialEq<I::Item>,
{
self.into_iter().eq(other)
}
fn ne<I: IntoIterator>(self, other: I) -> bool
where
Self::Item: PartialEq<I::Item>,
{
self.into_iter().ne(other)
}
fn lt<I: IntoIterator>(self, other: I) -> bool
where
Self::Item: PartialOrd<I::Item>,
{
self.into_iter().lt(other)
}
fn le<I: IntoIterator>(self, other: I) -> bool
where
Self::Item: PartialOrd<I::Item>,
{
self.into_iter().le(other)
}
fn gt<I: IntoIterator>(self, other: I) -> bool
where
Self::Item: PartialOrd<I::Item>,
{
self.into_iter().gt(other)
}
fn ge<I: IntoIterator>(self, other: I) -> bool
where
Self::Item: PartialOrd<I::Item>,
{
self.into_iter().ge(other)
}
#[allow(clippy::wrong_self_convention)]
fn is_sorted(self) -> bool
where
Self::Item: PartialOrd,
{
self.into_iter().is_sorted()
}
#[allow(clippy::wrong_self_convention)]
fn is_sorted_by<F: FnMut(&Self::Item, &Self::Item) -> bool>(self, function: F) -> bool {
self.into_iter().is_sorted_by(function)
}
#[allow(clippy::wrong_self_convention)]
fn is_sorted_by_key<K: PartialOrd, F: FnMut(Self::Item) -> K>(self, function: F) -> bool {
self.into_iter().is_sorted_by_key(function)
}
fn collect_into<C: Extend<Self::Item>>(self, collection: &mut C) -> &mut C {
collection.extend(self);
collection
}
fn find_map<T, F: FnMut(Self::Item) -> Option<T>>(self, function: F) -> Option<T> {
self.into_iter().find_map(function)
}
fn fuse(self) -> Fuse<Self> {
Fuse::new(self)
}
fn rev(self) -> Rev<Self>
where
Self::IntoIter: DoubleEndedIterator,
{
Rev::new(self)
}
fn cycle(self) -> Cycle<Self>
where
Self::IntoIter: Clone,
{
Cycle::new(self)
}
}
pub trait FromNonEmptyIterator<T>: Sized {
fn from_non_empty_iter<I: IntoNonEmptyIterator<Item = T>>(iterable: I) -> Self;
}
pub trait IntoNonEmptyIterator: IntoIterator {
type IntoNonEmptyIter: NonEmptyIterator<Item = Self::Item>;
fn into_non_empty_iter(self) -> Self::IntoNonEmptyIter;
}
impl<I: NonEmptyIterator> IntoNonEmptyIterator for I {
type IntoNonEmptyIter = Self;
fn into_non_empty_iter(self) -> Self::IntoNonEmptyIter {
self
}
}
mod sealed {
pub trait Sealed {}
}
pub trait TryIntoNonEmptyIterator: sealed::Sealed {
type Item;
type IntoNonEmptyIter: NonEmptyIterator<Item = Self::Item>;
fn try_into_non_empty_iter(self) -> Option<Self::IntoNonEmptyIter>;
}
impl<I: IntoIterator> sealed::Sealed for I {}
impl<I: IntoIterator> TryIntoNonEmptyIterator for I {
type Item = I::Item;
type IntoNonEmptyIter = NonEmptyAdapter<iter::Peekable<I::IntoIter>>;
fn try_into_non_empty_iter(self) -> Option<Self::IntoNonEmptyIter> {
let mut peekable = self.into_iter().peekable();
peekable.peek()?;
Some(unsafe { NonEmptyAdapter::new(peekable) })
}
}