1use reify_reflect_core::{Reflect, RuntimeValue};
4use std::marker::PhantomData;
5
6pub struct HNil;
17
18pub struct HCons<H, T>(PhantomData<(H, T)>);
34
35pub trait HList {
47 fn len() -> usize;
49
50 fn is_empty() -> bool {
52 Self::len() == 0
53 }
54}
55
56impl HList for HNil {
57 fn len() -> usize {
58 0
59 }
60}
61
62impl<H, T: HList> HList for HCons<H, T> {
63 fn len() -> usize {
64 1 + T::len()
65 }
66}
67
68impl Reflect for HNil {
69 type Value = Vec<RuntimeValue>;
70
71 fn reflect() -> Self::Value {
72 vec![]
73 }
74}
75
76impl<H, T> Reflect for HCons<H, T>
77where
78 H: Reflect<Value = RuntimeValue>,
79 T: Reflect<Value = Vec<RuntimeValue>>,
80{
81 type Value = Vec<RuntimeValue>;
82
83 fn reflect() -> Self::Value {
84 let mut list = vec![H::reflect()];
85 list.extend(T::reflect());
86 list
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93 use crate::{S, Z};
94
95 #[test]
96 fn hnil_reflects_to_empty_list() {
97 assert_eq!(HNil::reflect(), Vec::<RuntimeValue>::new());
98 }
99
100 #[test]
101 fn single_element_list() {
102 type L = HCons<Z, HNil>;
103 assert_eq!(L::reflect(), vec![RuntimeValue::Nat(0)]);
104 }
105
106 #[test]
107 fn multi_element_list() {
108 type L = HCons<S<S<Z>>, HCons<S<Z>, HCons<Z, HNil>>>;
109 assert_eq!(
110 L::reflect(),
111 vec![
112 RuntimeValue::Nat(2),
113 RuntimeValue::Nat(1),
114 RuntimeValue::Nat(0),
115 ]
116 );
117 }
118
119 #[test]
120 fn hlist_len() {
121 assert_eq!(HNil::len(), 0);
122 assert_eq!(<HCons<Z, HNil>>::len(), 1);
123 assert_eq!(<HCons<Z, HCons<Z, HCons<Z, HNil>>>>::len(), 3);
124 }
125
126 #[test]
127 fn hlist_is_empty() {
128 assert!(HNil::is_empty());
129 assert!(!<HCons<Z, HNil>>::is_empty());
130 }
131
132 #[test]
133 fn round_trip_type_level_to_runtime() {
134 type List = HCons<S<S<S<Z>>>, HCons<S<Z>, HCons<Z, HNil>>>;
136 let reflected = List::reflect();
137 assert_eq!(reflected.len(), 3);
138 assert_eq!(reflected[0], RuntimeValue::Nat(3));
139 assert_eq!(reflected[1], RuntimeValue::Nat(1));
140 assert_eq!(reflected[2], RuntimeValue::Nat(0));
141 }
142}