typsy 0.1.0

Heterogenous containers
Documentation
use std::vec::Vec;

use super::{Named, Unnamed};
use crate::hlist::*;

pub trait DeepTransformFrom<T, I> {
    fn deep_transform_from(value: T) -> Self;
}

pub trait DeepTransform<T, I> {
    fn deep_transform(self) -> T;
}

impl<T: DeepTransformFrom<U, I>, U, I> DeepTransform<T, I> for U {
    fn deep_transform(self) -> T { T::deep_transform_from(self) }
}

macro_rules! primitive {
    ($($primitive:ty),* $(,)?) => {
        $(
            impl DeepTransformFrom<$primitive, ()> for $primitive {
                fn deep_transform_from(prim: $primitive) -> Self { prim }
            }
        )*
    };
}

primitive! { (), u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize, f32, f64, bool, char }

impl<T, U: DeepTransformFrom<T, I>, I> DeepTransformFrom<Vec<T>, I> for Vec<U> {
    fn deep_transform_from(value: Vec<T>) -> Self { value.into_iter().map(U::deep_transform_from).collect() }
}

impl DeepTransformFrom<Nil, ()> for Nil {
    fn deep_transform_from(Nil: Self) -> Self { Self }
}

impl<T, R> DeepTransformFrom<Cons<T, R>, ()> for Nil {
    fn deep_transform_from(_: Cons<T, R>) -> Self { Self }
}

impl<T, Rt, L, I, Ti, Ri, Name> DeepTransformFrom<L, (I, Ti, Ri)> for Cons<Named<T, Name>, Rt>
where
    L: super::RemoveField<Name, I>,
    L::Value: DeepTransform<T, Ti>,
    L::Remainder: DeepTransform<Rt, Ri>,
{
    fn deep_transform_from(list: L) -> Self {
        let (value, rest) = list.remove_field();
        Self {
            value: Named::new(value.deep_transform()),
            rest: rest.deep_transform(),
        }
    }
}

impl<T, Rt, L: DeepTransform<Rt, Ri>, I, Ri> DeepTransformFrom<Cons<Unnamed<T>, L>, (I, Ri)> for Cons<Unnamed<T>, Rt> {
    fn deep_transform_from(list: Cons<Unnamed<T>, L>) -> Self {
        Self {
            value: list.value,
            rest: list.rest.deep_transform(),
        }
    }
}

impl<T, U: DeepTransform<T, I>, I, N> DeepTransformFrom<Named<U, N>, I> for Named<T, N> {
    fn deep_transform_from(value: Named<U, N>) -> Self {
        let value = value.0;
        let value = value.deep_transform();
        Self::new(value)
    }
}