1use std::{convert::Infallible, error::Error};
4
5use crate::cons::{AsRefTuple, Cons, Nil};
6
7pub trait Constructor<In, Out> {
15 fn construct(self, input: In) -> Out;
17}
18
19pub trait ListValidator<List, Out, Err> {
25 fn validate(self, values: &List) -> Result<Out, Err>;
27}
28
29impl<Out, F> Constructor<(), Out> for F
30where
31 F: FnMut() -> Out,
32{
33 fn construct(mut self, _: ()) -> Out {
34 self()
35 }
36}
37
38impl<A, Out, F> Constructor<(A,), Out> for F
39where
40 F: FnMut(A) -> Out,
41{
42 fn construct(mut self, (a,): (A,)) -> Out {
43 self(a)
44 }
45}
46
47macro_rules! impl_constructor {
48 ($($elem:ident),+) => {
49 impl< $( $elem ),+ , Out, Func> Constructor<($( $elem ),+), Out> for Func
50 where
51 Func: FnMut( $( $elem ),+ ) -> Out,
52 {
53 #[allow(non_snake_case)]
54 fn construct(mut self, ( $( $elem ),+ ): ( $( $elem ),+ )) -> Out {
55 self( $( $elem ),+ )
56 }
57 }
58 };
59}
60
61impl_constructor!(A, B);
62impl_constructor!(A, B, C);
63impl_constructor!(A, B, C, D);
64impl_constructor!(A, B, C, D, E);
65impl_constructor!(A, B, C, D, E, F);
66impl_constructor!(A, B, C, D, E, F, G);
67impl_constructor!(A, B, C, D, E, F, G, H);
68impl_constructor!(A, B, C, D, E, F, G, H, I);
69impl_constructor!(A, B, C, D, E, F, G, H, I, J);
70impl_constructor!(A, B, C, D, E, F, G, H, I, J, K);
71impl_constructor!(A, B, C, D, E, F, G, H, I, J, K, L);
72
73impl<Out, Func> ListValidator<Nil, Out, Infallible> for Func
74where
75 Func: FnMut() -> Result<Out, Infallible>,
76{
77 fn validate(mut self, _: &Nil) -> Result<Out, Infallible> {
78 self()
79 }
80}
81
82impl<A, Out, Err, Func> ListValidator<Cons<A, Nil>, Out, Err> for Func
83where
84 Func: for<'a> FnMut(&'a A) -> Result<Out, Err>,
85 Err: Error + Send + Sync + 'static,
86{
87 fn validate(mut self, values: &Cons<A, Nil>) -> Result<Out, Err> {
88 let (a,) = values.as_unwraped_tuple();
89 self(a)
90 }
91}
92
93macro_rules! list_type {
94 ($head:ident, $($tail:ident),*) => {
95 Cons< $head, list_type!( $( $tail ),* ) >
96 };
97 ($head:ident) => {
98 Cons< $head, Nil >
99 };
100 () => {
101 Nil
102 };
103}
104
105macro_rules! impl_validator {
106 ($($elem:ident),+) => {
107 impl<$( $elem ),+ , Out, Err, Func> ListValidator<list_type!( $( $elem ),+ ), Out, Err> for Func
108 where
109 Func: for<'a> FnMut( $( &'a $elem ),+ ) -> Result<Out, Err>,
110 Err: Error + Send + Sync + 'static,
111 {
112 #[allow(non_snake_case)]
113 fn validate(mut self, values: & list_type!( $( $elem ),+ )) -> Result<Out, Err> {
114 let ( $( $elem ),+ ) = $crate::cons::AsRefTuple::as_unwraped_tuple(values);
115 self( $( $elem ),+ )
116 }
117 }
118 };
119}
120
121impl_validator!(A, B);
122impl_validator!(A, B, C);
123impl_validator!(A, B, C, D);
124impl_validator!(A, B, C, D, E);
125impl_validator!(A, B, C, D, E, F);
126impl_validator!(A, B, C, D, E, F, G);
127impl_validator!(A, B, C, D, E, F, G, H);
128impl_validator!(A, B, C, D, E, F, G, H, I);
129impl_validator!(A, B, C, D, E, F, G, H, I, J);
130impl_validator!(A, B, C, D, E, F, G, H, I, J, K);
131impl_validator!(A, B, C, D, E, F, G, H, I, J, K, L);