warp/
generic.rs

1#[derive(Debug)]
2pub struct Product<H, T: HList>(pub(crate) H, pub(crate) T);
3
4pub type One<T> = (T,);
5
6#[inline]
7pub(crate) fn one<T>(val: T) -> One<T> {
8    (val,)
9}
10
11#[derive(Debug)]
12pub enum Either<T, U> {
13    A(T),
14    B(U),
15}
16
17// Converts Product (and ()) into tuples.
18pub trait HList: Sized {
19    type Tuple: Tuple<HList = Self>;
20
21    fn flatten(self) -> Self::Tuple;
22}
23
24// Typeclass that tuples can be converted into a Product (or unit ()).
25pub trait Tuple: Sized {
26    type HList: HList<Tuple = Self>;
27
28    fn hlist(self) -> Self::HList;
29
30    #[inline]
31    fn combine<T>(self, other: T) -> CombinedTuples<Self, T>
32    where
33        Self: Sized,
34        T: Tuple,
35        Self::HList: Combine<T::HList>,
36    {
37        self.hlist().combine(other.hlist()).flatten()
38    }
39}
40
41pub type CombinedTuples<T, U> =
42    <<<T as Tuple>::HList as Combine<<U as Tuple>::HList>>::Output as HList>::Tuple;
43
44// Combines Product together.
45pub trait Combine<T: HList> {
46    type Output: HList;
47
48    fn combine(self, other: T) -> Self::Output;
49}
50
51pub trait Func<Args> {
52    type Output;
53
54    fn call(&self, args: Args) -> Self::Output;
55}
56
57// ===== impl Combine =====
58
59impl<T: HList> Combine<T> for () {
60    type Output = T;
61    #[inline]
62    fn combine(self, other: T) -> Self::Output {
63        other
64    }
65}
66
67impl<H, T: HList, U: HList> Combine<U> for Product<H, T>
68where
69    T: Combine<U>,
70    Product<H, <T as Combine<U>>::Output>: HList,
71{
72    type Output = Product<H, <T as Combine<U>>::Output>;
73
74    #[inline]
75    fn combine(self, other: U) -> Self::Output {
76        Product(self.0, self.1.combine(other))
77    }
78}
79
80impl HList for () {
81    type Tuple = ();
82    #[inline]
83    fn flatten(self) -> Self::Tuple {}
84}
85
86impl Tuple for () {
87    type HList = ();
88
89    #[inline]
90    fn hlist(self) -> Self::HList {}
91}
92
93impl<F, R> Func<()> for F
94where
95    F: Fn() -> R,
96{
97    type Output = R;
98
99    #[inline]
100    fn call(&self, _args: ()) -> Self::Output {
101        (*self)()
102    }
103}
104
105impl<F, R> Func<crate::Rejection> for F
106where
107    F: Fn(crate::Rejection) -> R,
108{
109    type Output = R;
110
111    #[inline]
112    fn call(&self, arg: crate::Rejection) -> Self::Output {
113        (*self)(arg)
114    }
115}
116
117macro_rules! product {
118    ($H:expr) => { Product($H, ()) };
119    ($H:expr, $($T:expr),*) => { Product($H, product!($($T),*)) };
120}
121
122macro_rules! Product {
123    ($H:ty) => { Product<$H, ()> };
124    ($H:ty, $($T:ty),*) => { Product<$H, Product!($($T),*)> };
125}
126
127macro_rules! product_pat {
128    ($H:pat) => { Product($H, ()) };
129    ($H:pat, $($T:pat),*) => { Product($H, product_pat!($($T),*)) };
130}
131
132macro_rules! generics {
133    ($type:ident) => {
134        impl<$type> HList for Product!($type) {
135            type Tuple = ($type,);
136
137            #[inline]
138            fn flatten(self) -> Self::Tuple {
139                (self.0,)
140            }
141        }
142
143        impl<$type> Tuple for ($type,) {
144            type HList = Product!($type);
145            #[inline]
146            fn hlist(self) -> Self::HList {
147                product!(self.0)
148            }
149        }
150
151        impl<F, R, $type> Func<Product!($type)> for F
152        where
153            F: Fn($type) -> R,
154        {
155            type Output = R;
156
157            #[inline]
158            fn call(&self, args: Product!($type)) -> Self::Output {
159                (*self)(args.0)
160            }
161
162        }
163
164        impl<F, R, $type> Func<($type,)> for F
165        where
166            F: Fn($type) -> R,
167        {
168            type Output = R;
169
170            #[inline]
171            fn call(&self, args: ($type,)) -> Self::Output {
172                (*self)(args.0)
173            }
174        }
175
176    };
177
178    ($type1:ident, $( $type:ident ),*) => {
179        generics!($( $type ),*);
180
181        impl<$type1, $( $type ),*> HList for Product!($type1, $($type),*) {
182            type Tuple = ($type1, $( $type ),*);
183
184            #[inline]
185            fn flatten(self) -> Self::Tuple {
186                #[allow(non_snake_case)]
187                let product_pat!($type1, $( $type ),*) = self;
188                ($type1, $( $type ),*)
189            }
190        }
191
192        impl<$type1, $( $type ),*> Tuple for ($type1, $($type),*) {
193            type HList = Product!($type1, $( $type ),*);
194
195            #[inline]
196            fn hlist(self) -> Self::HList {
197                #[allow(non_snake_case)]
198                let ($type1, $( $type ),*) = self;
199                product!($type1, $( $type ),*)
200            }
201        }
202
203        impl<F, R, $type1, $( $type ),*> Func<Product!($type1, $($type),*)> for F
204        where
205            F: Fn($type1, $( $type ),*) -> R,
206        {
207            type Output = R;
208
209            #[inline]
210            fn call(&self, args: Product!($type1, $($type),*)) -> Self::Output {
211                #[allow(non_snake_case)]
212                let product_pat!($type1, $( $type ),*) = args;
213                (*self)($type1, $( $type ),*)
214            }
215        }
216
217        impl<F, R, $type1, $( $type ),*> Func<($type1, $($type),*)> for F
218        where
219            F: Fn($type1, $( $type ),*) -> R,
220        {
221            type Output = R;
222
223            #[inline]
224            fn call(&self, args: ($type1, $($type),*)) -> Self::Output {
225                #[allow(non_snake_case)]
226                let ($type1, $( $type ),*) = args;
227                (*self)($type1, $( $type ),*)
228            }
229        }
230    };
231}
232
233generics! {
234    T1,
235    T2,
236    T3,
237    T4,
238    T5,
239    T6,
240    T7,
241    T8,
242    T9,
243    T10,
244    T11,
245    T12,
246    T13,
247    T14,
248    T15,
249    T16
250}