use core::{fmt, marker::Destruct};
use array_trait::length::LengthValue;
use crate::{Bulk, DoubleEndedBulk, SplitBulk};
#[must_use = "bulks are lazy and do nothing unless consumed"]
#[derive(Clone)]
pub struct Map<I, F>
where
I: Bulk,
F: FnMut<(I::Item,)>
{
bulk: I,
f: F
}
impl<I, F> Map<I, F>
where
I: Bulk,
F: FnMut<(I::Item,)>
{
pub(crate) const fn new(bulk: I, f: F) -> Self
{
Self { bulk, f }
}
}
impl<I, F> fmt::Debug for Map<I, F>
where
I: Bulk + fmt::Debug,
F: FnMut<(I::Item,)>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
let Self { bulk, f: _ } = self;
f.debug_struct("Map").field("bulk", bulk).finish()
}
}
const impl<I, F> IntoIterator for Map<I, F>
where
I: Bulk + [const] IntoIterator<IntoIter: [const] Iterator>,
F: FnMut<(I::Item,)>
{
type IntoIter = core::iter::Map<I::IntoIter, F>;
type Item = F::Output;
fn into_iter(self) -> Self::IntoIter
{
let Self { bulk, f } = self;
bulk.into_iter().map(f)
}
}
const impl<I, F> Bulk for Map<I, F>
where
I: [const] Bulk<Item: [const] Destruct>,
F: [const] FnMut<(I::Item,)> + [const] Destruct
{
type MaxLength = I::MaxLength;
type MinLength = I::MinLength;
fn len(&self) -> usize
{
let Self { bulk, f: _ } = self;
bulk.len()
}
fn is_empty(&self) -> bool
{
let Self { bulk, f: _ } = self;
bulk.is_empty()
}
fn first(self) -> Option<Self::Item>
where
Self::Item: [const] Destruct,
Self: Sized
{
let Self { bulk, mut f } = self;
bulk.first().map(&mut f)
}
fn for_each<FF>(self, f: FF)
where
Self: Sized,
FF: [const] FnMut(Self::Item) + [const] Destruct
{
let Self { bulk, f: map } = self;
bulk.for_each(Closure { map, f })
}
fn try_for_each<FF, R>(self, f: FF) -> R
where
Self: Sized,
FF: [const] FnMut(Self::Item) -> R + [const] Destruct,
R: [const] core::ops::Try<Output = ()>
{
let Self { bulk, f: map } = self;
bulk.try_for_each(Closure { map, f })
}
}
const impl<I, F> DoubleEndedBulk for Map<I, F>
where
I: [const] DoubleEndedBulk<Item: [const] Destruct>,
F: [const] FnMut<(I::Item,)> + [const] Destruct
{
fn rev_for_each<FF>(self, f: FF)
where
Self: Sized,
FF: [const] FnMut(Self::Item) + [const] Destruct
{
let Self { bulk, f: map } = self;
bulk.rev_for_each(Closure { map, f })
}
fn try_rev_for_each<FF, R>(self, f: FF) -> R
where
Self: Sized,
FF: [const] FnMut(Self::Item) -> R + [const] Destruct,
R: [const] core::ops::Try<Output = ()>
{
let Self { bulk, f: map } = self;
bulk.try_rev_for_each(Closure { map, f })
}
}
const impl<I, F, L> SplitBulk<L> for Map<I, F>
where
I: [const] SplitBulk<L, Item: [const] Destruct, Left: [const] Bulk, Right: [const] Bulk>,
F: [const] FnMut<(I::Item,)> + [const] Clone + [const] Destruct,
L: LengthValue
{
type Left = Map<I::Left, F>;
type Right = Map<I::Right, F>;
fn split_at(Self { bulk, f }: Self, n: L) -> (Self::Left, Self::Right)
where
Self: Sized
{
let (left, right) = bulk.split_at(n);
(left.map(f.clone()), right.map(f))
}
}
struct Closure<M, F>
{
map: M,
f: F
}
const impl<M, F, T, U, R> FnOnce<(T,)> for Closure<M, F>
where
M: [const] FnOnce(T) -> U,
F: [const] FnOnce(U) -> R
{
type Output = R;
extern "rust-call" fn call_once(self, (x,): (T,)) -> Self::Output
{
let Self { map, f } = self;
f(map(x))
}
}
const impl<M, F, T, U, R> FnMut<(T,)> for Closure<M, F>
where
M: [const] FnMut(T) -> U,
F: [const] FnMut(U) -> R
{
extern "rust-call" fn call_mut(&mut self, (x,): (T,)) -> Self::Output
{
let Self { map, f } = self;
f(map(x))
}
}