pub trait HList {
fn cons<X>(self, x: X) -> HCons<X, Self>
where
Self: Sized,
{
HCons(x, self)
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct HNil;
impl HList for HNil {}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct HCons<H, T: HList>(pub H, pub T);
impl<H, T: HList> HCons<H, T> {
pub fn head(&self) -> &H {
&self.0
}
pub fn tail(&self) -> &T {
&self.1
}
}
impl<H, T: HList> HList for HCons<H, T> {}
pub trait FromHList<H>
where
H: HList,
{
fn from_hlist(hlist: H) -> Self;
}
pub trait ToHList<H>
where
H: HList,
{
fn to_hlist(&self) -> H;
}
pub trait IntoHList<H>
where
H: HList,
{
fn into_hlist(self) -> H;
}
#[cfg(test)]
mod tests {
use super::*;
use pl_hlist_derive::HListSupport;
#[test]
fn head_should_work() {
let hlist = HCons(1u8, HNil);
assert_eq!(*hlist.head(), 1u8);
}
#[test]
fn tail_should_work() {
let hlist = HCons(1u8, HNil);
assert_eq!(*hlist.tail(), HNil);
}
#[test]
fn hlist_macros_should_work() {
{
let hlist1 = HNil;
let hlist2 = hlist!();
assert_eq!(hlist1, hlist2);
}
{
let hlist1 = HCons(1u8, HNil);
let hlist2 = hlist!(1u8);
assert_eq!(hlist1, hlist2);
}
{
let hlist1 = HCons(1u8, HCons(2i32, HCons("three", HNil)));
let hlist2 = hlist!(1u8, 2i32, "three");
assert_eq!(hlist1, hlist2);
}
}
#[derive(Debug, PartialEq, Eq, Clone, HListSupport)]
struct TestInnerStruct {
f1: u8,
f2: u8,
}
#[derive(Debug, PartialEq, Eq, Clone, HListSupport)]
struct TestStruct {
byte_field: u8,
inner_struct: TestInnerStruct,
}
#[test]
fn converting_struct_to_from_hlist_should_work() {
{
let s = TestInnerStruct::from_hlist(hlist!(1u8, 2u8));
assert_eq!(s.f1, 1u8);
assert_eq!(s.f2, 2u8);
let hlist0 = s.to_hlist();
assert_eq!(hlist0, hlist!(1u8, 2u8));
let hlist1 = s.into_hlist();
assert_eq!(hlist0, hlist1);
}
{
let s =
TestStruct::from_hlist(hlist!(7u8, TestInnerStruct::from_hlist(hlist!(1u8, 2u8))));
assert_eq!(s.byte_field, 7u8);
assert_eq!(s.inner_struct, TestInnerStruct { f1: 1, f2: 2 });
let hlist0 = s.to_hlist();
assert_eq!(hlist0, hlist!(7u8, TestInnerStruct { f1: 1, f2: 2 }));
let hlist1 = s.into_hlist();
assert_eq!(hlist0, hlist1);
}
}
}