use core::marker::Destruct;
use array_trait::length::LengthValue;
use crate::{Bulk, DoubleEndedBulk, OnceWith, RepeatN, RepeatNWith, SplitBulk, StaticBulk, util::{TakeOne, YieldOnce}};
pub const fn once<T>(value: T) -> Once<T>
{
Once(value)
}
#[must_use = "bulks are lazy and do nothing unless consumed"]
#[derive(Clone, Debug)]
pub struct Once<T>(T);
impl<T> IntoIterator for Once<T>
{
type Item = T;
type IntoIter = core::iter::Once<T>;
fn into_iter(self) -> Self::IntoIter
{
core::iter::once(self.0)
}
}
impl<T> const Bulk for Once<T>
{
type MinLength = [(); 1];
type MaxLength = [(); 1];
fn len(&self) -> usize
{
1
}
fn is_empty(&self) -> bool
{
false
}
fn first(self) -> Option<Self::Item>
where
Self::Item: ~const Destruct,
Self: Sized
{
Some(self.0)
}
fn last(self) -> Option<Self::Item>
where
Self::Item: ~const Destruct,
Self: Sized
{
Some(self.0)
}
fn for_each<FF>(self, mut f: FF)
where
Self: Sized,
FF: ~const FnMut(Self::Item) + ~const Destruct
{
f(self.0)
}
fn try_for_each<FF, R>(self, mut f: FF) -> R
where
Self: Sized,
Self::Item: ~const Destruct,
FF: ~const FnMut(Self::Item) -> R + ~const Destruct,
R: ~const core::ops::Try<Output = (), Residual: ~const Destruct>
{
f(self.0)
}
}
impl<T> const DoubleEndedBulk for Once<T>
{
fn rev_for_each<FF>(self, f: FF)
where
Self: Sized,
FF: ~const FnMut(Self::Item) + ~const Destruct
{
self.for_each(f);
}
fn try_rev_for_each<FF, R>(self, f: FF) -> R
where
Self: Sized,
Self::Item: ~const Destruct,
FF: ~const FnMut(Self::Item) -> R + ~const Destruct,
R: ~const core::ops::Try<Output = (), Residual: ~const Destruct>
{
self.try_for_each(f)
}
}
impl<T, L> const SplitBulk<L> for Once<T>
where
L: LengthValue,
OnceWith<YieldOnce<T>>: ~const SplitBulk<L, Item = T, Left: ~const Bulk, Right: ~const Bulk>
{
type Left = <OnceWith<YieldOnce<T>> as SplitBulk<L>>::Left;
type Right = <OnceWith<YieldOnce<T>> as SplitBulk<L>>::Right;
fn split_at(bulk: Self, n: L) -> (Self::Left, Self::Right)
where
Self: Sized
{
OnceWith::from(bulk).split_at(n)
}
}
pub const trait OnceBulk: ~const DoubleEndedBulk + StaticBulk<Array<<Self as IntoIterator>::Item> = [<Self as IntoIterator>::Item; 1]>
{
}
impl<T> const OnceBulk for T
where
T: ~const DoubleEndedBulk + StaticBulk<Array<<Self as IntoIterator>::Item> = [<Self as IntoIterator>::Item; 1]>
{
}
impl<A> const From<Once<A>> for OnceWith<YieldOnce<A>>
{
fn from(value: Once<A>) -> Self
{
crate::once_with(YieldOnce::new(value.0))
}
}
impl<A> const From<Once<A>> for RepeatN<A, [(); 1]>
where
A: Clone
{
fn from(value: Once<A>) -> Self
{
crate::repeat_n(value.0, [(); 1])
}
}
impl<A> const From<Once<A>> for RepeatNWith<TakeOne<YieldOnce<A>>, [(); 1]>
{
fn from(value: Once<A>) -> Self
{
crate::repeat_n_with(TakeOne::new(YieldOnce::new(value.0)), [(); 1])
}
}
#[cfg(test)]
mod test
{
use crate::Bulk;
#[test]
fn it_works()
{
let a = const {
crate::once(1).collect::<[_; _], _>()
};
assert_eq!(a, [1])
}
}