use core::cmp::Ordering;
use crate::WellBehavedCollection;
pub trait NonEmptyIntoIter: IntoIterator + Sized {
fn into_first_and_remaining(self) -> (Self::Item, Self::IntoIter);
fn map<U, F>(self, f: F) -> Map<Self, F> where F: FnMut(Self::Item) -> U {
Map {
iter: self,
f,
}
}
fn reduce<F>(self, f: F) -> Self::Item where F: FnMut(Self::Item, Self::Item) -> Self::Item {
let (accum, iter) = self.into_first_and_remaining();
iter.fold(accum, f)
}
fn min(self) -> Self::Item where Self::Item: Ord {
self.reduce(Ord::min)
}
fn min_by<F>(self, mut f: F) -> Self::Item where F: FnMut(&Self::Item, &Self::Item) -> Ordering {
self.reduce(move |a, b| if f(&a, &b).is_le() { a } else { b })
}
fn min_by_key<K, F>(self, mut f: F) -> Self::Item where F: FnMut(&Self::Item) -> Ordering {
self.reduce(move |a, b| if f(&a) <= f(&b) { a } else { b })
}
fn max(self) -> Self::Item where Self::Item: Ord {
self.reduce(Ord::max)
}
fn max_by<F>(self, mut f: F) -> Self::Item where F: FnMut(&Self::Item, &Self::Item) -> Ordering {
self.reduce(move |a, b| if f(&a, &b).is_ge() { a } else { b })
}
fn max_by_key<K, F>(self, mut f: F) -> Self::Item where F: FnMut(&Self::Item) -> Ordering {
self.reduce(move |a, b| if f(&a) >= f(&b) { a } else { b })
}
fn collect<T>(self) -> T where T: FromNonEmptyIterator<Self::Item> {
T::from_non_empty_iter(self)
}
}
pub trait FromNonEmptyIterator<Item> {
fn from_non_empty_iter<I: NonEmptyIntoIter<Item = Item>>(iter: I) -> Self;
}
pub(crate) fn from_iter_spec<S: NonEmptyIntoIter, D: crate::traits::FromInner>(src: S) -> D where D::Inner: FromIterator<S::Item> {
let collection = if crate::is_well_behaved::<S>() {
src.into_iter().collect()
} else {
let (first, iter) = src.into_first_and_remaining();
core::iter::once(first).chain(iter).collect()
};
unsafe { D::from_inner(collection) }
}
pub struct Map<Iter, F> {
iter: Iter,
f: F,
}
impl<Iter: NonEmptyIntoIter, U, F: FnMut(Iter::Item) -> U> IntoIterator for Map<Iter, F> {
type IntoIter = core::iter::Map<Iter::IntoIter, F>;
type Item = U;
fn into_iter(self) -> Self::IntoIter {
self.iter.into_iter().map(self.f)
}
}
impl<Iter: NonEmptyIntoIter, U, F: FnMut(Iter::Item) -> U> NonEmptyIntoIter for Map<Iter, F> {
fn into_first_and_remaining(mut self) -> (Self::Item, Self::IntoIter) {
let (first, remaining) = self.iter.into_first_and_remaining();
let first = (self.f)(first);
let iter = remaining.map(self.f);
(first, iter)
}
}
unsafe impl<Iter: WellBehavedCollection, F> WellBehavedCollection for Map<Iter, F> {}
pub(crate) unsafe fn into_first_and_remaining<T: IntoIterator>(iter: T) -> (T::Item, T::IntoIter) {
let mut iter = iter.into_iter();
let first = crate::unwrap_opt::<T, _>(iter.next());
(first, iter)
}
pub trait DoubleEndedNonEmptyIntoIter: NonEmptyIntoIter where Self::IntoIter: DoubleEndedIterator {
fn into_last_and_remaining(self) -> (Self::Item, Self::IntoIter);
fn rev(self) -> Rev<Self> {
Rev(self)
}
}
pub struct Rev<T>(T);
impl<T: IntoIterator> IntoIterator for Rev<T> where T::IntoIter: DoubleEndedIterator {
type Item = T::Item;
type IntoIter = core::iter::Rev<T::IntoIter>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter().rev()
}
}
impl<T: DoubleEndedNonEmptyIntoIter> NonEmptyIntoIter for Rev<T> where T::IntoIter: DoubleEndedIterator {
fn into_first_and_remaining(self) -> (Self::Item, Self::IntoIter) {
let (first, remaining) = self.0.into_last_and_remaining();
(first, remaining.rev())
}
}
impl<T: DoubleEndedNonEmptyIntoIter> DoubleEndedNonEmptyIntoIter for Rev<T> where T::IntoIter: DoubleEndedIterator {
fn into_last_and_remaining(self) -> (Self::Item, Self::IntoIter) {
let (first, remaining) = self.0.into_first_and_remaining();
(first, remaining.rev())
}
}
pub struct Once<T>(T);
impl<T> IntoIterator for Once<T> {
type Item = T;
type IntoIter = core::iter::Once<T>;
fn into_iter(self) -> Self::IntoIter {
core::iter::once(self.0)
}
}
impl<T> NonEmptyIntoIter for Once<T> {
fn into_first_and_remaining(self) -> (Self::Item, Self::IntoIter) {
let mut iter = self.into_iter();
let first = iter.next().unwrap();
(first, iter)
}
}