pub trait Tuple: Sized {
type HList: HList<Tuple = Self>;
fn hlist(self) -> Self::HList;
}
impl Tuple for () {
type HList = HNil;
#[inline(always)]
fn hlist(self) -> Self::HList {
HNil
}
}
pub trait HList: Sized {
type Tuple: Tuple<HList = Self>;
fn tuple(self) -> Self::Tuple;
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct HNil;
impl HList for HNil {
type Tuple = ();
#[inline(always)]
fn tuple(self) -> Self::Tuple {
()
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct HCons<H, T: HList> {
pub head: H,
pub tail: T,
}
macro_rules! hcons {
($H:expr) => {
HCons {
head: $H,
tail: HNil,
}
};
($H:expr, $($T:expr),*) => {
HCons {
head: $H,
tail: hcons!($($T),*),
}
};
}
macro_rules! HCons {
($H:ty) => { HCons<$H, HNil> };
($H:ty, $($T:ty),*) => { HCons<$H, HCons!($($T),*)> };
}
macro_rules! hcons_pat {
($H:pat) => {
HCons {
head: $H,
tail: HNil,
}
};
($H:pat, $($T:pat),*) => {
HCons {
head: $H,
tail: hcons_pat!($($T),*),
}
};
}
macro_rules! generics {
($T:ident) => {
impl<$T> HList for HCons!($T) {
type Tuple = ($T,);
#[inline(always)]
fn tuple(self) -> Self::Tuple {
(self.head,)
}
}
impl<$T> Tuple for ($T,) {
type HList = HCons!($T);
#[inline(always)]
fn hlist(self) -> Self::HList {
hcons!(self.0)
}
}
};
($H:ident, $($T:ident),*) => {
generics!($($T),*);
impl<$H, $($T),*> HList for HCons!($H, $($T),*) {
type Tuple = ($H, $($T),*);
#[inline(always)]
fn tuple(self) -> Self::Tuple {
#[allow(non_snake_case)]
let hcons_pat!($H, $($T),*) = self;
($H, $($T),*)
}
}
impl<$H, $($T),*> Tuple for ($H, $($T),*) {
type HList = HCons!($H, $($T),*);
#[inline(always)]
fn hlist(self) -> Self::HList {
#[allow(non_snake_case)]
let ($H, $($T),*) = self;
hcons!($H, $($T),*)
}
}
};
($H:ident, $($T:ident,)*) => {
generics!($H, $($T),*);
};
}
generics! {
T15, T14, T13, T12, T11, T10, T9, T8, T7, T6, T5, T4, T3, T2, T1, T0,
}