use either::Either;
use frunk::{HCons, HNil};
use crate::primitive_types::{FlatType, JoinFlatTypes};
pub trait JoinFlatLayouts<Target> {
fn into_joined(self) -> Target;
fn from_joined(joined: Target) -> Self;
}
impl JoinFlatLayouts<HNil> for HNil {
fn into_joined(self) -> HNil {
HNil
}
fn from_joined(_joined: HNil) -> Self {
HNil
}
}
impl<TargetHead, TargetTail> JoinFlatLayouts<HCons<TargetHead, TargetTail>> for HNil
where
TargetHead: Default,
HNil: JoinFlatLayouts<TargetTail>,
{
fn into_joined(self) -> HCons<TargetHead, TargetTail> {
HCons {
head: TargetHead::default(),
tail: HNil.into_joined(),
}
}
fn from_joined(_joined: HCons<TargetHead, TargetTail>) -> Self {
HNil
}
}
impl<SourceHead, SourceTail, TargetHead, TargetTail> JoinFlatLayouts<HCons<TargetHead, TargetTail>>
for HCons<SourceHead, SourceTail>
where
SourceHead: FlatType,
TargetHead: FlatType,
Either<SourceHead, TargetHead>: JoinFlatTypes<Flat = TargetHead>,
SourceTail: JoinFlatLayouts<TargetTail>,
{
fn into_joined(self) -> HCons<TargetHead, TargetTail> {
HCons {
head: Either::Left(self.head).join(),
tail: self.tail.into_joined(),
}
}
fn from_joined(joined: HCons<TargetHead, TargetTail>) -> Self {
HCons {
head: joined.head.split_into(),
tail: SourceTail::from_joined(joined.tail),
}
}
}