use core::{marker::Destruct, ptr::Pointee};
use array_trait::length::{self, Length, LengthValue};
use crate::{Bulk, DoubleEndedBulk, RandomAccessBulk, InplaceBulk, InplaceBulkSpec, RandomAccessBulkSpec, SplitBulk};
#[derive(Clone, Debug)]
#[must_use = "bulks are lazy and do nothing unless consumed"]
pub struct Rev<I>
where
I: DoubleEndedBulk
{
bulk: I,
}
impl<I> Rev<I>
where
I: DoubleEndedBulk
{
pub(crate) const fn new(bulk: I) -> Self
{
Self {
bulk
}
}
pub const fn into_inner(self) -> I
{
let Self { bulk } = self;
bulk
}
}
impl<I> const Default for Rev<I>
where
I: ~const Bulk + DoubleEndedBulk + ~const Default
{
fn default() -> Self
{
I::default().rev()
}
}
impl<I> IntoIterator for Rev<I>
where
I: DoubleEndedBulk
{
type IntoIter = core::iter::Rev<I::IntoIter>;
type Item = I::Item;
fn into_iter(self) -> Self::IntoIter
{
self.into_inner().into_iter().rev()
}
}
impl<I> const Bulk for Rev<I>
where
I: ~const Bulk + ~const DoubleEndedBulk
{
type MinLength = I::MinLength;
type MaxLength = I::MaxLength;
fn len(&self) -> usize
{
let Self { bulk } = self;
bulk.len()
}
fn is_empty(&self) -> bool
{
let Self { bulk } = self;
bulk.is_empty()
}
fn for_each<F>(self, f: F)
where
Self: Sized,
F: ~const FnMut(Self::Item) + ~const Destruct
{
let Self { bulk } = self;
bulk.rev_for_each(f);
}
fn try_for_each<F, R>(self, f: F) -> R
where
Self: Sized,
Self::Item: ~const Destruct,
F: ~const FnMut(Self::Item) -> R + ~const Destruct,
R: ~const core::ops::Try<Output = (), Residual: ~const Destruct>
{
let Self { bulk } = self;
bulk.try_rev_for_each(f)
}
}
impl<I> const DoubleEndedBulk for Rev<I>
where
I: ~const Bulk + ~const DoubleEndedBulk
{
fn rev_for_each<F>(self, f: F)
where
Self: Sized,
F: ~const FnMut(Self::Item) + ~const Destruct
{
let Self { bulk } = self;
bulk.for_each(f);
}
fn try_rev_for_each<F, R>(self, f: F) -> R
where
Self: Sized,
Self::Item: ~const Destruct,
F: ~const FnMut(Self::Item) -> R + ~const Destruct,
R: ~const core::ops::Try<Output = (), Residual: ~const Destruct>
{
let Self { bulk } = self;
bulk.try_for_each(f)
}
}
impl<I, N, L, R> const SplitBulk<L> for Rev<I>
where
I: ~const SplitBulk<R, Left: ~const Bulk + DoubleEndedBulk, Right: ~const Bulk + DoubleEndedBulk> + ~const Bulk<Length: Length<Value = N> + Pointee<Metadata = N::Metadata>> + ~const DoubleEndedBulk,
N: LengthValue<SaturatingSub<L> = R>,
L: LengthValue,
R: LengthValue
{
type Left = Rev<I::Right>;
type Right = Rev<I::Left>;
fn split_at(Self { bulk }: Self, m: L) -> (Self::Left, Self::Right)
where
Self: Sized
{
let n = bulk.length();
let (left, right) = bulk.split_at(length::value::saturating_sub(n, m));
(
right.rev(),
left.rev()
)
}
}
impl<I> const RandomAccessBulk for Rev<I>
where
I: for<'a, 'b> ~const RandomAccessBulk<ItemPointee: 'b,
EachRef<'a>: ~const RandomAccessBulk<EachRef<'b> = I::EachRef<'b>> + 'b + ~const DoubleEndedBulk
> + ~const DoubleEndedBulk
{
type ItemPointee = I::ItemPointee;
type EachRef<'a> = Rev<I::EachRef<'a>>
where
Self::ItemPointee: 'a,
Self: 'a;
fn each_ref<'a>(Self { bulk }: &'a Self) -> Self::EachRef<'a>
where
Self::ItemPointee: 'a,
Self: 'a
{
bulk.each_ref().rev()
}
}
impl<I> const InplaceBulk for Rev<I>
where
I: for<'a, 'b> ~const InplaceBulk<ItemPointee: 'b,
EachRef<'a>: ~const RandomAccessBulk<EachRef<'b> = I::EachRef<'b>> + 'b + ~const DoubleEndedBulk,
EachMut<'a>: ~const InplaceBulk<EachRef<'b> = I::EachRef<'b>, EachMut<'b> = I::EachMut<'b>> + 'b + ~const DoubleEndedBulk
> + ~const DoubleEndedBulk
{
type EachMut<'a> = Rev<I::EachMut<'a>>
where
Self::ItemPointee: 'a,
Self: 'a;
fn each_mut<'a>(Self { bulk }: &'a mut Self) -> Self::EachMut<'a>
where
Self::ItemPointee: 'a,
Self: 'a
{
bulk.each_mut().rev()
}
}
impl<I> const RandomAccessBulkSpec for Rev<I>
where
I: for<'a, 'b> ~const RandomAccessBulk<ItemPointee: 'b,
EachRef<'a>: ~const RandomAccessBulk<EachRef<'b> = I::EachRef<'b>> + 'b + ~const DoubleEndedBulk
> + ~const DoubleEndedBulk
{
fn _get<'a, L>(Self { bulk }: &'a Self, i: L) -> Option<&'a <Self as RandomAccessBulk>::ItemPointee>
where
L: LengthValue,
Self: 'a
{
if let Some(ip1) = length::value::checked_add(i, [(); 1]) && let Some(j) = length::value::checked_sub(bulk.length(), ip1)
{
bulk.get(j)
}
else
{
None
}
}
}
impl<I> const InplaceBulkSpec for Rev<I>
where
I: for<'a, 'b> ~const InplaceBulk<ItemPointee: 'b,
EachRef<'a>: ~const RandomAccessBulk<EachRef<'b> = I::EachRef<'b>> + 'b + ~const DoubleEndedBulk,
EachMut<'a>: ~const InplaceBulk<EachRef<'b> = I::EachRef<'b>, EachMut<'b> = I::EachMut<'b>> + 'b + ~const DoubleEndedBulk
> + ~const DoubleEndedBulk
{
fn _get_mut<'a, L>(bulk: &'a mut Self, i: L) -> Option<&'a mut <Self as RandomAccessBulk>::ItemPointee>
where
L: LengthValue,
Self: 'a
{
if let Some(ip1) = length::value::checked_add(i, [(); 1]) && let Some(j) = length::value::checked_sub(bulk.length(), ip1)
{
bulk.get_mut(j)
}
else
{
None
}
}
}
#[cfg(test)]
mod test
{
use crate::*;
#[test]
fn it_works()
{
let a = [1, 2, 3, 4, 5, 6];
let mut b = a.into_bulk();
b.each_mut()
.for_each(|x| *x = 7 - *x);
let b = b.collect_array();
println!("b = {b:?}");
}
}