#![no_std]
use core::marker::PhantomData;
use typenum::{Cmp, Equal, Greater, Less};
pub struct HNil;
pub struct HCons<H, T>(PhantomData<(H, T)>);
pub trait HList {}
impl HList for HNil {}
impl<H, T: HList> HList for HCons<H, T> {}
#[macro_export]
macro_rules! mk_hlist {
() => { $crate::HNil };
($head:ty) => { $crate::HCons<$head, $crate::HNil> };
($head:ty, $($tail:ty),+) => {
$crate::HCons<$head, $crate::mk_hlist!($($tail),+)>
};
}
pub trait SortedHList: HList {}
impl SortedHList for HNil {}
impl<H> SortedHList for HCons<H, HNil> {}
impl<H, HT, TT> SortedHList for HCons<H, HCons<HT, TT>>
where
HCons<HT, TT>: SortedHList,
H: Cmp<HT>,
<H as Cmp<HT>>::Output: LeOrEq,
{
}
pub trait LeOrEq {}
impl LeOrEq for Equal {}
impl LeOrEq for Less {}
pub trait NonEmptyHList: HList {}
impl<H, T: HList> NonEmptyHList for HCons<H, T> {}
pub trait IntersectUnchecked<Other: HList>: HList {
type Output: HList;
}
impl<H, T: HList> IntersectUnchecked<HNil> for HCons<H, T> {
type Output = HNil;
}
impl<List: HList> IntersectUnchecked<List> for HNil {
type Output = HNil;
}
pub trait IntersectByOrder<Rhs: HList, Ord>: HList {
type Output: HList;
}
impl<HA, TA: HList, HB, TB: HList> IntersectByOrder<HCons<HB, TB>, Less> for HCons<HA, TA>
where
TA: IntersectUnchecked<HCons<HB, TB>>,
{
type Output = <TA as IntersectUnchecked<HCons<HB, TB>>>::Output;
}
impl<HA, TA: HList, HB, TB: HList> IntersectByOrder<HCons<HB, TB>, Greater> for HCons<HA, TA>
where
HCons<HA, TA>: IntersectUnchecked<TB>,
{
type Output = <HCons<HA, TA> as IntersectUnchecked<TB>>::Output;
}
impl<HA, TA: HList, HB, TB: HList> IntersectByOrder<HCons<HB, TB>, Equal> for HCons<HA, TA>
where
TA: IntersectUnchecked<TB>,
{
type Output = HCons<HA, <TA as IntersectUnchecked<TB>>::Output>;
}
impl<HA, TA: HList, HB, TB: HList, Ordering> IntersectUnchecked<HCons<HB, TB>> for HCons<HA, TA>
where
HA: Cmp<HB, Output = Ordering>,
HCons<HA, TA>: IntersectByOrder<HCons<HB, TB>, Ordering>,
{
type Output = <Self as IntersectByOrder<HCons<HB, TB>, Ordering>>::Output;
}
pub trait Intersect<Other: HList>: HList {
type Output: HList;
}
impl<LA, LB> Intersect<LB> for LA
where
LA: SortedHList + IntersectUnchecked<LB>,
LB: SortedHList,
{
type Output = <LA as IntersectUnchecked<LB>>::Output;
}