use either::Either;
use crate::primitive_types::{JoinFlatTypes, MaybeFlatType, SimpleType};
pub trait Sealed {}
pub trait LayoutElement: Sealed + Sized {
const ALIGNMENT: u32;
const IS_EMPTY: bool;
type Flat: MaybeFlatType;
fn flatten(self) -> Self::Flat;
}
impl Sealed for () {}
impl<T> Sealed for T where T: SimpleType {}
impl LayoutElement for () {
const ALIGNMENT: u32 = 1;
const IS_EMPTY: bool = true;
type Flat = ();
fn flatten(self) -> Self::Flat {}
}
impl<T> LayoutElement for T
where
T: SimpleType,
{
const ALIGNMENT: u32 = <T as SimpleType>::ALIGNMENT;
const IS_EMPTY: bool = false;
type Flat = <T as SimpleType>::Flat;
fn flatten(self) -> Self::Flat {
<T as SimpleType>::flatten(self)
}
}
impl<L, R> Sealed for Either<L, R>
where
L: LayoutElement,
R: LayoutElement,
{
}
impl<L, R> LayoutElement for Either<L, R>
where
L: LayoutElement,
R: LayoutElement,
Either<L::Flat, R::Flat>: JoinFlatTypes,
{
const ALIGNMENT: u32 = if L::ALIGNMENT > R::ALIGNMENT {
L::ALIGNMENT
} else {
R::ALIGNMENT
};
const IS_EMPTY: bool = L::IS_EMPTY && R::IS_EMPTY;
type Flat = <Either<L::Flat, R::Flat> as JoinFlatTypes>::Flat;
fn flatten(self) -> Self::Flat {
match self {
Either::Left(left) => Either::Left(left.flatten()).join(),
Either::Right(right) => Either::Right(right.flatten()).join(),
}
}
}