bulks 0.6.11

Amazing bulks! They are like iterators, but in bulk, and therefore support collection into arrays.
Documentation
use core::{marker::Destruct, ptr::Thin};

use array_trait::length::LengthValue;

use crate::{Bulk, IntoBulk, StaticBulk};

pub const trait RandomAccessBulk: ~const Bulk // DoubleEndedBulk
{
    type ItemPointee: Sized + Thin;
    type EachRef<'a>: ~const RandomAccessBulk<ItemPointee = Self::ItemPointee, Item = &'a Self::ItemPointee, EachRef<'a> = Self::EachRef<'a>> + 'a + ~const Destruct
    where
        Self::ItemPointee: 'a,
        Self: 'a;

    fn each_ref<'a>(bulk: &'a Self) -> Self::EachRef<'a>
    where
        Self::ItemPointee: 'a,
        Self: 'a;
}

pub const trait InplaceBulk: ~const RandomAccessBulk
{
    type EachMut<'a>: ~const InplaceBulk<ItemPointee = Self::ItemPointee, Item = &'a mut Self::ItemPointee, EachRef<'a> = Self::EachRef<'a>, EachMut<'a> = Self::EachMut<'a>> + 'a + ~const Destruct
    where
        Self::ItemPointee: 'a,
        Self: 'a;

    fn each_mut<'a>(bulk: &'a mut Self) -> Self::EachMut<'a>
    where
        Self::ItemPointee: 'a,
        Self: 'a;
}

pub(crate) const trait RandomAccessBulkSpec: Bulk
{
    fn _get<'a, L>(bulk: &'a Self, i: L) -> Option<&'a <Self as RandomAccessBulk>::ItemPointee>
    where
        L: LengthValue,
        Self: ~const RandomAccessBulk + 'a;

    fn _get_many<'a, NN, const N: usize>(bulk: &'a Self, i: NN) -> [Option<&'a <Self as RandomAccessBulk>::ItemPointee>; N]
    where
        Self: ~const RandomAccessBulk + 'a,
        NN: ~const IntoBulk<Item = usize, IntoBulk: ~const Bulk + StaticBulk<Array<()> = [(); N]>>;
}
impl<I> const RandomAccessBulkSpec for I
where
    I: Bulk + ?Sized
{
    default fn _get<'a, L>(bulk: &'a Self, i: L) -> Option<&'a <Self as RandomAccessBulk>::ItemPointee>
    where
        L: LengthValue,
        Self: ~const RandomAccessBulk + 'a
    {
        bulk.each_ref().nth(i)
    }

    default fn _get_many<'a, NN, const N: usize>(bulk: &'a Self, i: NN) -> [Option<&'a <Self as RandomAccessBulk>::ItemPointee>; N]
    where
        Self: ~const RandomAccessBulk + 'a,
        NN: ~const IntoBulk<Item = usize, IntoBulk: ~const Bulk + StaticBulk<Array<()> = [(); N]>>
    {
        bulk.each_ref().many(i)
    }
}

pub(crate) const trait InplaceBulkSpec: Bulk
{
    fn _get_mut<'a, L>(bulk: &'a mut Self, i: L) -> Option<&'a mut <Self as RandomAccessBulk>::ItemPointee>
    where
        L: LengthValue,
        Self: ~const InplaceBulk + 'a;

    fn _get_many_mut<'a, NN, const N: usize>(bulk: &'a mut Self, i: NN) -> [Option<&'a mut <Self as RandomAccessBulk>::ItemPointee>; N]
    where
        Self: ~const InplaceBulk + 'a,
        NN: ~const IntoBulk<Item = usize, IntoBulk: ~const Bulk + StaticBulk<Array<()> = [(); N]>>;
}
impl<I> const InplaceBulkSpec for I
where
    I: Bulk + ?Sized
{
    default fn _get_mut<'a, L>(bulk: &'a mut Self, i: L) -> Option<&'a mut <Self as RandomAccessBulk>::ItemPointee>
    where
        L: LengthValue,
        Self: ~const InplaceBulk + 'a
    {
        bulk.each_mut().nth(i)
    }

    default fn _get_many_mut<'a, NN, const N: usize>(bulk: &'a mut Self, i: NN) -> [Option<&'a mut <Self as RandomAccessBulk>::ItemPointee>; N]
    where
        Self: ~const InplaceBulk + 'a,
        NN: ~const IntoBulk<Item = usize, IntoBulk: ~const Bulk + StaticBulk<Array<()> = [(); N]>>
    {
        bulk.each_mut().many(i)
    }
}

#[cfg(test)]
mod test
{
    use crate::*;

    #[test]
    fn test_swap()
    {
        fn swaps<B>(bulk: &mut B)
        where
            B: InplaceBulk
        {
            bulk.swap_inplace(0, 3);
            bulk.swap_inplace(1, 2);
        }

        let a = [1, 2, 3, 4];
        let mut bulk = a.into_bulk();
        swaps(&mut bulk);
        let b = bulk.collect_nearest();
        println!("{b:?}")
    }

    #[test]
    fn test_many()
    {
        let a = [1, 2, 3, 4];
        let mut bulk = a.into_bulk();
        let [x1, x2, x3] = bulk.get_many_mut([1, 0, 3]).map(Option::unwrap);

        std::mem::swap(x1, x2);
        std::mem::swap(x2, x3);

        let b = bulk.collect_nearest();

        println!("{b:?}");
    }
}