structural/type_level/
list.rs

1/*!
2Contains type-level lists,and related items
3*/
4
5use std_::{
6    fmt::{self, Debug},
7    marker::PhantomData,
8};
9
10use crate::type_level::collection_traits::{
11    Append, AppendOut, Flatten, PushBack, PushBackOut, ToTList, ToTListOut,
12};
13
14#[cfg(test)]
15mod tests;
16
17////////////////////////////////////////////////////////////////////////////////
18
19/// A type-level non-empty list.
20pub struct TList<Curr, Rem>(PhantomData<fn() -> (Curr, Rem)>);
21
22/// A type-level empty list.
23#[derive(Debug, Copy, Clone)]
24pub struct TNil;
25
26////////////////////////////////////////////////////////////////////////////////
27
28impl<Curr, Rem> core_extensions::ConstDefault for TList<Curr, Rem> {
29    const DEFAULT: Self = TList(PhantomData);
30}
31
32impl<Curr, Rem> Debug for TList<Curr, Rem> {
33    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34        f.debug_struct("TList").finish()
35    }
36}
37
38impl<Curr, Rem> Copy for TList<Curr, Rem> {}
39
40impl<Curr, Rem> Clone for TList<Curr, Rem> {
41    fn clone(&self) -> Self {
42        TList::NEW
43    }
44}
45
46impl<Curr, Rem> TList<Curr, Rem> {
47    /// Constructs this list.
48    pub const NEW: Self = TList(PhantomData);
49}
50
51/////////////////////////////////////////////////////////////////////////////////
52
53impl<T, Rem> ToTList for TList<T, Rem> {
54    type Output = Self;
55}
56
57impl ToTList for TNil {
58    type Output = Self;
59}
60
61/////////////////////////////////////////////////////////////////////////////////
62
63impl core_extensions::ConstDefault for TNil {
64    const DEFAULT: Self = TNil;
65}
66
67impl TNil {
68    /// Constructs this empty list.
69    pub const NEW: Self = TNil;
70}
71
72////////////////////////////////////////////////////////////////////////////////
73
74impl<Current, Rem, Elem> PushBack<Elem> for TList<Current, Rem>
75where
76    Rem: PushBack<Elem>,
77{
78    type Output = TList<Current, PushBackOut<Rem, Elem>>;
79}
80
81impl<Elem> PushBack<Elem> for TNil {
82    type Output = TList<Elem, TNil>;
83}
84
85////////////////////////////////////////////////////////////////////////////////
86
87impl<T, Rem, T2, Rem2> Append<TList<T2, Rem2>> for TList<T, Rem>
88where
89    Rem: Append<TList<T2, Rem2>>,
90{
91    type Output = TList<T, AppendOut<Rem, TList<T2, Rem2>>>;
92}
93
94impl<T, Rem> Append<TNil> for TList<T, Rem> {
95    type Output = TList<T, Rem>;
96}
97
98impl<T, Rem> Append<TList<T, Rem>> for TNil {
99    type Output = TList<T, Rem>;
100}
101
102impl Append<TNil> for TNil {
103    type Output = TNil;
104}
105
106////////////////////////////////////////////////////////////////////////////////
107
108impl Flatten for TNil {
109    type Output = TNil;
110}
111impl<Curr, Rem, Out> Flatten for TList<Curr, Rem>
112where
113    (): FlattenOutImpl<Rem, Curr, Output = Out>,
114{
115    type Output = Out;
116}
117
118#[doc(hidden)]
119pub trait FlattenOutImpl<Outer, Inner> {
120    type Output;
121}
122
123impl<List> FlattenOutImpl<TNil, List> for ()
124where
125    List: ToTList,
126{
127    type Output = ToTListOut<List>;
128}
129
130impl<Curr, Rem, Out> FlattenOutImpl<TList<Curr, Rem>, TNil> for ()
131where
132    Curr: ToTList,
133    (): FlattenOutImpl<Rem, ToTListOut<Curr>, Output = Out>,
134{
135    type Output = Out;
136}
137
138impl<CurrI, RemI, CurrO, RemO, Out> FlattenOutImpl<TList<CurrO, RemO>, TList<CurrI, RemI>> for ()
139where
140    RemI: ToTList,
141    (): FlattenOutImpl<TList<CurrO, RemO>, ToTListOut<RemI>, Output = Out>,
142{
143    type Output = TList<CurrI, Out>;
144}