tuplez 0.14.16

Tuples represented in recursive form
Documentation
use crate::{ToArray, Tuple, TupleLike, Unit};
use std::mem::MaybeUninit;

trait FillSlice<T>: TupleLike {
    fn fill_slice(self, arr: &mut [MaybeUninit<T>], index: usize);
}

impl<T> FillSlice<T> for Unit {
    fn fill_slice(self, _: &mut [MaybeUninit<T>], _: usize) {}
}

impl<First, Other> FillSlice<First> for Tuple<First, Other>
where
    Other: FillSlice<First>,
{
    fn fill_slice(self, arr: &mut [MaybeUninit<First>], index: usize) {
        let Tuple(first, other) = self;
        arr[index].write(first);
        other.fill_slice(arr, index + 1);
    }
}

impl<T> ToArray<T> for Unit {
    type Array = [T; 0];
    type Iter<'a> = std::array::IntoIter<&'a T, 0> where Self: 'a, T: 'a;
    type IterMut<'a> = std::array::IntoIter<&'a mut T, 0> where Self: 'a, T: 'a;

    fn to_array(self) -> Self::Array {
        Default::default()
    }

    fn iter<'a>(&'a self) -> Self::Iter<'a>
    where
        Self: 'a,
        T: 'a,
    {
        self.as_ref().to_array().into_iter()
    }

    fn iter_mut<'a>(&'a mut self) -> Self::IterMut<'a>
    where
        Self: 'a,
        T: 'a,
    {
        self.as_mut().to_array().into_iter()
    }
}

impl<First, Other> ToArray<First> for Tuple<First, Other>
where
    Self: FillSlice<First>,
    [First; Self::LEN]:,
{
    type Array = [First; Self::LEN];

    type Iter<'a> = <<<Tuple<First, Other> as TupleLike>::AsRefOutput<'a> as
        ToArray<&'a First>>::Array as IntoIterator>::IntoIter
    where
        Self::AsRefOutput<'a>: ToArray<&'a First>,
        Self: 'a,
        First: 'a;

    type IterMut<'a> = <<<Tuple<First, Other> as TupleLike>::AsMutOutput<'a> as
        ToArray<&'a mut First>>::Array as IntoIterator>::IntoIter
    where
        Self::AsMutOutput<'a>: ToArray<&'a mut First>,
        Self: 'a,
        First: 'a;

    fn to_array(self) -> Self::Array {
        let mut arr: [MaybeUninit<First>; Self::LEN] = MaybeUninit::uninit_array();
        self.fill_slice(&mut arr, 0);
        unsafe { MaybeUninit::array_assume_init(arr) }
    }

    fn iter<'a>(&'a self) -> Self::Iter<'a>
    where
        Self::AsRefOutput<'a>: ToArray<&'a First>,
        Self: 'a,
        First: 'a,
    {
        self.as_ref().to_array().into_iter()
    }

    fn iter_mut<'a>(&'a mut self) -> Self::IterMut<'a>
    where
        Self::AsMutOutput<'a>: ToArray<&'a mut First>,
        Self: 'a,
        First: 'a,
    {
        self.as_mut().to_array().into_iter()
    }
}

trait FromSlice<T>: TupleLike {
    fn from_slice(arr: &mut [MaybeUninit<T>], index: usize) -> Self;
}

impl<T> FromSlice<T> for Unit {
    fn from_slice(_: &mut [MaybeUninit<T>], _: usize) -> Self {
        Unit
    }
}

impl<First, Other> FromSlice<First> for Tuple<First, Other>
where
    Other: FromSlice<First>,
{
    fn from_slice(arr: &mut [MaybeUninit<First>], index: usize) -> Self {
        let v = std::mem::replace(&mut arr[index], MaybeUninit::uninit());
        Tuple(
            unsafe { v.assume_init() },
            Other::from_slice(arr, index + 1),
        )
    }
}

impl<T> From<[T; 0]> for Unit {
    fn from(_: [T; 0]) -> Self {
        Unit
    }
}

impl<First, Other> From<[First; Self::LEN]> for Tuple<First, Other>
where
    Self: FromSlice<First>,
{
    fn from(value: [First; Self::LEN]) -> Self {
        let mut arr = MaybeUninit::new(value).transpose();
        Self::from_slice(&mut arr, 0)
    }
}