1pub trait HList {
11 fn cons<X>(self, x: X) -> HCons<X, Self>
13 where
14 Self: Sized,
15 {
16 HCons(x, self)
17 }
18}
19
20#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
22pub struct HNil;
23
24impl HList for HNil {}
25
26#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
28pub struct HCons<H, T: HList>(pub H, pub T);
29
30impl<H, T: HList> HCons<H, T> {
31 pub fn head(&self) -> &H {
33 &self.0
34 }
35
36 pub fn tail(&self) -> &T {
38 &self.1
39 }
40}
41
42impl<H, T: HList> HList for HCons<H, T> {}
43
44pub trait FromHList<H>
46where
47 H: HList,
48{
49 fn from_hlist(hlist: H) -> Self;
50}
51
52pub trait ToHList<H>
54where
55 H: HList,
56{
57 fn to_hlist(&self) -> H;
58}
59
60pub trait IntoHList<H>
62where
63 H: HList,
64{
65 fn into_hlist(self) -> H;
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71 use pl_hlist_derive::HListSupport;
72
73 #[test]
74 fn head_should_work() {
75 let hlist = HCons(1u8, HNil);
76 assert_eq!(*hlist.head(), 1u8);
77 }
78
79 #[test]
80 fn tail_should_work() {
81 let hlist = HCons(1u8, HNil);
82 assert_eq!(*hlist.tail(), HNil);
83 }
84
85 #[test]
86 fn hlist_macros_should_work() {
87 {
88 let hlist1 = HNil;
89 let hlist2 = hlist!();
90 assert_eq!(hlist1, hlist2);
91 }
92
93 {
94 let hlist1 = HCons(1u8, HNil);
95 let hlist2 = hlist!(1u8);
96 assert_eq!(hlist1, hlist2);
97 }
98
99 {
100 let hlist1 = HCons(1u8, HCons(2i32, HCons("three", HNil)));
101 let hlist2 = hlist!(1u8, 2i32, "three");
102 assert_eq!(hlist1, hlist2);
103 }
104 }
105
106 #[derive(Debug, PartialEq, Eq, Clone, HListSupport)]
107 struct TestInnerStruct {
108 f1: u8,
109 f2: u8,
110 }
111
112 #[derive(Debug, PartialEq, Eq, Clone, HListSupport)]
113 struct TestStruct {
114 byte_field: u8,
115 inner_struct: TestInnerStruct,
116 }
117
118 #[test]
119 fn converting_struct_to_from_hlist_should_work() {
120 {
121 let s = TestInnerStruct::from_hlist(hlist!(1u8, 2u8));
122 assert_eq!(s.f1, 1u8);
123 assert_eq!(s.f2, 2u8);
124 let hlist0 = s.to_hlist();
125 assert_eq!(hlist0, hlist!(1u8, 2u8));
126 let hlist1 = s.into_hlist();
127 assert_eq!(hlist0, hlist1);
128 }
129
130 {
131 let s =
132 TestStruct::from_hlist(hlist!(7u8, TestInnerStruct::from_hlist(hlist!(1u8, 2u8))));
133 assert_eq!(s.byte_field, 7u8);
134 assert_eq!(s.inner_struct, TestInnerStruct { f1: 1, f2: 2 });
135 let hlist0 = s.to_hlist();
136 assert_eq!(hlist0, hlist!(7u8, TestInnerStruct { f1: 1, f2: 2 }));
137 let hlist1 = s.into_hlist();
138 assert_eq!(hlist0, hlist1);
139 }
140 }
141}