bulks 0.11.3

Amazing bulks! They are like iterators, but in bulk, and therefore support collection into arrays.
Documentation
use crate::Bulk;
use crate::DoubleEndedBulk;
use crate::IntoBulk;

use array_trait::length;
use array_trait::length::LengthValue;
pub(crate) use private::IntoContained as IntoContained;
#[allow(unused)]
pub(crate) use private::IntoContainedIter as IntoContainedIter;

pub struct Contained<I>
where
    I: Iterator
{
    iter: I
}

const impl<I> Iterator for Contained<I>
where
    I: ~const Iterator
{
    type Item = I::Item;

    fn next(&mut self) -> Option<Self::Item>
    {
        self.iter.next()
    }
}
impl<I> ExactSizeIterator for Contained<I>
where
    I: Iterator
{
    fn len(&self) -> usize
    {
        Bulk::len(self)
    }
    fn is_empty(&self) -> bool
    {
        Bulk::is_empty(self)
    }
}
const impl<I> DoubleEndedIterator for Contained<I>
where
    I: ~const DoubleEndedIterator
{
    fn next_back(&mut self) -> Option<Self::Item>
    {
        self.iter.next_back()
    }
}

impl<I> Contained<I>
where
    I: Iterator
{
    /// # Safety
    /// 
    /// This creates a bulk that is possibly only invalid.
    /// 
    /// Always wrap this bulk in another bulk so that its length is limited.
    pub(crate) const unsafe fn new(iter: I) -> Self
    {
        Self {
            iter
        }
    }
}

impl<I> Bulk for Contained<I>
where
    I: Iterator
{
    default type MinLength = <I as private::InfiniteSpec>::Length;
    default type MaxLength = <I as private::InfiniteSpec>::Length;

    #[inline]
    default fn len(&self) -> usize
    {
        self.iter.size_hint().1.unwrap_or(usize::MAX)
    }

    #[inline]
    default fn is_empty(&self) -> bool
    {
        Bulk::len(self) == 0
    }

    fn first(mut self) -> Option<Self::Item>
    where
        Self: Sized
    {
        self.iter.next()
    }
    fn last(self) -> Option<Self::Item>
    where
        Self: Sized
    {
        self.iter.last()
    }
    fn nth<L>(mut self, n: L) -> Option<Self::Item>
    where
        Self: Sized,
        L: LengthValue
    {
        self.iter.nth(length::value::len(n))
    }
    
    #[inline]
    default fn for_each<F>(self, _f: F)
    where
        Self: Sized,
        F: FnMut(Self::Item)
    {
        panic!("Possibly infinite iterator.")
    }
    
    #[inline]
    default fn try_for_each<F, R>(self, _f: F) -> R
    where
        Self: Sized,
        F: FnMut(Self::Item) -> R,
        R: core::ops::Try<Output = ()>
    {
        panic!("Possibly infinite iterator.")
    }
}
impl<I> Bulk for Contained<I>
where
    I: ExactSizeIterator
{
    type MinLength = <I as private::InfiniteSpec>::Length;
    type MaxLength = <I as private::InfiniteSpec>::Length;

    #[inline]
    fn len(&self) -> usize
    {
        self.iter.len()
    }

    #[inline]
    fn is_empty(&self) -> bool
    {
        self.iter.is_empty()
    }
    
    #[inline]
    fn for_each<F>(self, f: F)
    where
        Self: Sized,
        F: FnMut(Self::Item)
    {
        self.iter.for_each(f);
    }
    
    #[inline]
    fn try_for_each<F, R>(mut self, f: F) -> R
    where
        Self: Sized,
        F: FnMut(Self::Item) -> R,
        R: core::ops::Try<Output = ()>
    {
        self.iter.try_for_each(f)
    }
}
impl<I> DoubleEndedBulk for Contained<I>
where
    I: DoubleEndedIterator
{
    #[inline]
    default fn rev_for_each<F>(self, _f: F)
    where
        Self: Sized,
        F: FnMut(Self::Item)
    {
        panic!("Possibly infinite iterator.")
    }
    
    #[inline]
    default fn try_rev_for_each<F, R>(self, _f: F) -> R
    where
        Self: Sized,
        F: FnMut(Self::Item) -> R,
        R: core::ops::Try<Output = ()>
    {
        panic!("Possibly infinite iterator.")
    }
}
impl<I> DoubleEndedBulk for Contained<I>
where
    I: DoubleEndedIterator + ExactSizeIterator
{
    #[inline]
    fn rev_for_each<F>(self, f: F)
    where
        Self: Sized,
        F: FnMut(Self::Item)
    {
        self.iter.rev().for_each(f);
    }
    
    #[inline]
    fn try_rev_for_each<F, R>(self, f: F) -> R
    where
        Self: Sized,
        F: FnMut(Self::Item) -> R,
        R: core::ops::Try<Output = ()>
    {
        self.iter.rev().try_for_each(f)
    }
}

mod private
{
    use array_trait::{length::Length, same::Same};

    use crate::{Contained, IntoBulk, util::InfiniteIterator};

    pub trait InfiniteSpec
    {
        type Length: Length<Elem = ()> + ?Sized;
    }
    impl<I> InfiniteSpec for I
    {
        default type Length = [()];
    }
    impl<I> InfiniteSpec for I
    where
        I: InfiniteIterator
    {
        type Length = [(); usize::MAX];
    }

    /// # Safety
    /// 
    /// This creates an iterator that is possibly only invalid.
    /// 
    /// Always wrap this bulk in another bulk so that its length is limited.
    #[allow(unused)]
    pub unsafe trait IntoContainedIter: IntoIterator
    {
        type IntoContainedIter: ExactSizeIterator<Item = Self::Item>;

        /// # Safety
        /// 
        /// This creates a bulk that is possibly only invalid.
        /// 
        /// Always wrap this bulk in another bulk so that its length is limited.
        unsafe fn into_contained_iter(self) -> Self::IntoContainedIter;
    }
    unsafe impl<T> IntoContainedIter for T
    where
        T: IntoIterator
    {
        default type IntoContainedIter = Contained<T::IntoIter>;

        default unsafe fn into_contained_iter(self) -> Self::IntoContainedIter
        {
            unsafe {
                Contained::new(self.into_iter()).same().ok().unwrap()
            }
        }
    }
    unsafe impl<T> IntoContainedIter for T
    where
        T: IntoIterator<IntoIter: ExactSizeIterator>
    {
        type IntoContainedIter = T::IntoIter;

        unsafe fn into_contained_iter(self) -> Self::IntoContainedIter
        {
            self.into_iter()
        }
    }

    /// # Safety
    /// 
    /// This creates a bulk that is possibly only invalid.
    /// 
    /// Always wrap this bulk in another bulk so that its length is limited.
    pub const unsafe trait IntoContained: IntoIterator
    {
        type IntoContained: ~const IntoBulk<Item = Self::Item, IntoIter: ExactSizeIterator<Item = Self::Item>>;

        /// # Safety
        /// 
        /// This creates a bulk that is possibly only invalid.
        /// 
        /// Always wrap this bulk in another bulk so that its length is limited.
        unsafe fn into_contained(self) -> Self::IntoContained;
    }
    unsafe impl<T> IntoContained for T
    where
        T: IntoIterator
    {
        default type IntoContained = Contained<T::IntoIter>;

        default unsafe fn into_contained(self) -> Self::IntoContained
        {
            unsafe {
                Contained::new(self.into_iter()).same().ok().unwrap()
            }
        }
    }
    const unsafe impl<T> IntoContained for T
    where
        T: ~const IntoBulk
    {
        type IntoContained = T;

        unsafe fn into_contained(self) -> Self::IntoContained
        {
            self
        }
    }

    pub trait EitherIntoBulk<B>: IntoIterator
    where
        B: IntoIterator
    {
        type EitherIntoBulk: IntoIterator;
    }
    impl<T, B> EitherIntoBulk<B> for T
    where
        T: IntoIterator,
        B: IntoIterator
    {
        default type EitherIntoBulk = T;
    }
    impl<T, B> EitherIntoBulk<B> for T
    where
        T: IntoIterator,
        B: IntoBulk
    {
        type EitherIntoBulk = B;
    }
}

#[rustc_on_unimplemented(
    message = "value of type `{Self}` cannot be zipped with `{B}` in bulk",
    label = "neither `{Self}` nor `{B}` can be converted into bulks",
)]
pub trait EitherIntoBulk<B>: private::EitherIntoBulk<B, EitherIntoBulk: IntoBulk>
where
    B: IntoIterator
{
    
}
impl<T, B> EitherIntoBulk<B> for T
where
    T: private::EitherIntoBulk<B, EitherIntoBulk: IntoBulk>,
    B: IntoIterator
{
    
}

#[rustc_on_unimplemented(
    message = "value of type `{Self}` cannot be zipped with `{B}` in bulk",
    label = "value of type `{Self}` cannot be zipped with `{B}` in bulk",
)]
pub const trait IntoContainedBy<B>: ~const IntoContained + EitherIntoBulk<B> + Sized
where
    B: IntoIterator
{

}
const impl<T, B> IntoContainedBy<B> for T
where
    T: ~const IntoContained + EitherIntoBulk<B>,
    B: IntoIterator
{

}