use core::marker::Destruct;
use array_trait::length::{self, Length, LengthValue};
use crate::{Bulk, BulkLength, DoubleEndedBulk, 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
}
}
const impl<I> Default for Rev<I>
where
I: [const] Bulk + DoubleEndedBulk + [const] Default
{
fn default() -> Self
{
I::default().rev()
}
}
const impl<I> IntoIterator for Rev<I>
where
I: DoubleEndedBulk + [const] IntoIterator<IntoIter: [const] Iterator>
{
type IntoIter = core::iter::Rev<I::IntoIter>;
type Item = I::Item;
fn into_iter(self) -> Self::IntoIter
{
self.into_inner().into_iter().rev()
}
}
const impl<I> Bulk for Rev<I>
where
I: [const] Bulk + [const] DoubleEndedBulk
{
type MaxLength = I::MaxLength;
type MinLength = I::MinLength;
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 = ()>
{
let Self { bulk } = self;
bulk.try_rev_for_each(f)
}
}
const impl<I> 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 = ()>
{
let Self { bulk } = self;
bulk.try_for_each(f)
}
}
const impl<I, N, L, R> SplitBulk<L> for Rev<I>
where
I: [const] SplitBulk<R, Left: [const] Bulk + DoubleEndedBulk, Right: [const] Bulk + DoubleEndedBulk> + [const] Bulk + [const] DoubleEndedBulk,
BulkLength<I>: Length<Value = N, Metadata = N::Metadata>,
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())
}
}
#[cfg(test)]
mod test
{
use crate::*;
#[test]
fn it_works()
{
let a = [1, 2, 3, 4, 5, 6];
let b = a.into_bulk().rev().map(|x| 7 - x).collect_array();
assert_eq!(a, b)
}
}