1use typenum::{Cmp, Equal, Greater, Less};
2
3use std::marker::PhantomData;
4
5pub struct HNil;
6
7pub struct HCons<H, T>(PhantomData<(H, T)>);
8
9pub trait HList {}
10
11impl HList for HNil {}
12impl<H, T: HList> HList for HCons<H, T> {}
13
14#[macro_export]
15macro_rules! mk_hlist {
16 () => {
17 $crate::HNil
18 };
19 ($head:ty) => {
20 $crate::HCons<$head, $crate::HNil>
21 };
22 ($head:ty, $($tail:ty),+) => {
23 $crate::HCons<$head, $crate::mk_hlist!($($tail),+)>
24 };
25}
26
27pub trait SortedHList: HList {}
28
29impl SortedHList for HNil {}
30impl<H> SortedHList for HCons<H, HNil> {}
31
32pub trait LeOrEq {}
33impl LeOrEq for Equal {}
34impl LeOrEq for Less {}
35
36impl<H, HT, TT> SortedHList for HCons<H, HCons<HT, TT>>
37where
38 HCons<HT, TT>: SortedHList,
39 H: Cmp<HT>,
40 <H as Cmp<HT>>::Output: LeOrEq,
41{
42}
43
44pub trait NonEmptyHList: HList {}
45
46impl<H, T: HList> NonEmptyHList for HCons<H, T> {}
47
48pub trait Intersect<Other: SortedHList>: SortedHList {
49 type Output: SortedHList;
50}
51
52impl<H, T> Intersect<HNil> for HCons<H, T>
53where
54 HCons<H, T>: SortedHList,
55{
56 type Output = HNil;
57}
58
59impl<List: SortedHList> Intersect<List> for HNil {
60 type Output = HNil;
61}
62
63pub trait IntersectByOrder<Rhs: SortedHList, Ord>: SortedHList {
64 type Output: SortedHList;
65}
66
67impl<HA, TA, HB, TB> IntersectByOrder<HCons<HB, TB>, Less> for HCons<HA, TA>
68where
69 Self: SortedHList,
70 HCons<HB, TB>: SortedHList,
71 TA: Intersect<HCons<HB, TB>>,
72{
73 type Output = <TA as Intersect<HCons<HB, TB>>>::Output;
74}
75
76impl<HA, TA, HB, TB: SortedHList> IntersectByOrder<HCons<HB, TB>, Greater> for HCons<HA, TA>
77where
78 HCons<HA, TA>: SortedHList,
79 HCons<HB, TB>: SortedHList,
80 Self: Intersect<TB>,
81{
82 type Output = <Self as Intersect<TB>>::Output;
83}
84
85impl<HA, TA, HB, TB: SortedHList> IntersectByOrder<HCons<HB, TB>, Equal> for HCons<HA, TA>
86where
87 Self: SortedHList,
88 HCons<HB, TB>: SortedHList,
89 TA: Intersect<TB>,
90 HCons<HA, <TA as Intersect<TB>>::Output>: SortedHList,
91{
92 type Output = HCons<HA, <TA as Intersect<TB>>::Output>;
93}
94
95impl<HA, TA, HB, TB, Ordering> Intersect<HCons<HB, TB>> for HCons<HA, TA>
96where
97 HA: Cmp<HB, Output = Ordering>,
98 HCons<HA, TA>: IntersectByOrder<HCons<HB, TB>, Ordering>,
99 HCons<HB, TB>: SortedHList,
100{
101 type Output = <Self as IntersectByOrder<HCons<HB, TB>, Ordering>>::Output;
102}