state_validation_derive/
lib.rs

1use darling::FromDeriveInput;
2use proc_macro::TokenStream;
3use proc_macro2::Span;
4use syn::{Expr, Ident, Type, parse_macro_input};
5
6#[derive(darling::FromDeriveInput)]
7#[darling(attributes(state_filter_input))]
8struct StateFilterInputData {
9    remainder_type: Option<Type>,
10    remainder: Option<Expr>,
11}
12
13#[proc_macro_derive(StateFilterInput, attributes(state_filter_input))]
14pub fn state_filter_input(input: TokenStream) -> TokenStream {
15    let ast = parse_macro_input!(input as syn::DeriveInput);
16    let name = &ast.ident;
17    let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
18    let data = StateFilterInputData::from_derive_input(&ast).unwrap();
19    let remainder_code = if let Some(remainder_type) = data.remainder_type {
20        let remainder_expr = data.remainder.expect("expected `remainder` expression");
21        quote::quote! {
22            impl #impl_generics state_validation::StateFilterInputConversion<Self> for #name #ty_generics #where_clause {
23                type Remainder = #remainder_type;
24                fn split_take(self) -> (Self, Self::Remainder) {
25                    (self, #remainder_expr)
26                }
27            }
28        }
29    } else {
30        quote::quote! {
31            impl #impl_generics state_validation::StateFilterInputConversion<Self> for #name #ty_generics #where_clause {
32                type Remainder = ();
33                fn split_take(self) -> (Self, Self::Remainder) {
34                    (self, ())
35                }
36            }
37        }
38    };
39    let mut generics_1 = ast.generics.clone();
40    generics_1
41        .params
42        .push(syn::GenericParam::Type(syn::TypeParam {
43            attrs: Vec::new(),
44            ident: Ident::new("T", Span::call_site()),
45            colon_token: None,
46            bounds: syn::punctuated::Punctuated::new(),
47            eq_token: None,
48            default: None,
49        }));
50    let (_impl_generics_1, _ty_generics_1, _where_clause_1) = generics_1.split_for_impl();
51    let mut generics_2 = ast.generics.clone();
52    generics_2
53        .params
54        .push(syn::GenericParam::Type(syn::TypeParam {
55            attrs: Vec::new(),
56            ident: Ident::new("T0", Span::call_site()),
57            colon_token: None,
58            bounds: syn::punctuated::Punctuated::new(),
59            eq_token: None,
60            default: None,
61        }));
62    generics_2
63        .params
64        .push(syn::GenericParam::Type(syn::TypeParam {
65            attrs: Vec::new(),
66            ident: Ident::new("T1", Span::call_site()),
67            colon_token: None,
68            bounds: syn::punctuated::Punctuated::new(),
69            eq_token: None,
70            default: None,
71        }));
72    let (_impl_generics_2, _ty_generics_2, _where_clause_2) = generics_2.split_for_impl();
73    quote::quote! {
74        impl #impl_generics state_validation::StateFilterInput for #name #ty_generics #where_clause {}
75        #remainder_code
76        /*impl #impl_generics_1 card_game::validation::StateFilterInputConversion<#name #ty_generics> for (#name #ty_generics, T) #where_clause {
77            type Remainder = (T,);
78            fn combine(input: #name #ty_generics, remainder: Self::Remainder) -> Self {
79                (input, remainder.0)
80            }
81            fn split_take(self) -> (#name #ty_generics, Self::Remainder) {
82                (self.0, (self.1,))
83            }
84        }
85        impl #impl_generics_2 card_game::validation::StateFilterInputConversion<#name #ty_generics> for (#name #ty_generics, T0, T1) #where_clause {
86            type Remainder = (T0, T1);
87            fn combine(input: #name #ty_generics, remainder: Self::Remainder) -> Self {
88                (input, remainder.0, remainder.1)
89            }
90            fn split_take(self) -> (#name #ty_generics, Self::Remainder) {
91                (self.0, (self.1, self.2))
92            }
93        }
94        impl #impl_generics_2 card_game::validation::StateFilterInputConversion<(#name #ty_generics, T0)> for (#name #ty_generics, T0, T1) #where_clause {
95            type Remainder = (T1,);
96            fn combine(input: (#name #ty_generics, T0), remainder: Self::Remainder) -> Self {
97                (input.0, input.1, remainder.0)
98            }
99            fn split_take(self) -> ((#name #ty_generics, T0), Self::Remainder) {
100                ((self.0, self.1), (self.2,))
101            }
102        }*/
103        /*impl #impl_generics_1 card_game::validation::StateFilterInputConversion<T> for (#name #ty_generics, T) #where_clause {
104            type Remainder = (#name #ty_generics,);
105            fn combine(input: T, remainder: Self::Remainder) -> Self {
106                (remainder.0, input)
107            }
108            fn split_take(self) -> (T, Self::Remainder) {
109                (self.0, (self.1,))
110            }
111        }*/
112        /*impl #impl_generics_2 card_game::validation::StateFilterInputConversion<(#name #ty_generics, T0)> for (#name #ty_generics, T0, T1) #where_clause {
113            type Remainder = (T1,);
114            fn combine(input: (#name #ty_generics, T0), remainder: Self::Remainder) -> Self {
115                (input.0, input.1, remainder.0)
116            }
117            fn split_take(self) -> ((#name #ty_generics, T0), Self::Remainder) {
118                ((self.0, self.1), (self.2,))
119            }
120        }*/
121        /*impl #impl_generics_2 card_game::validation::StateFilterInputConversion<(T0, T1)> for (T0, #name #ty_generics, T1) #where_clause {
122            type Remainder = (#name #ty_generics,);
123            fn combine(input: (T0, T1), remainder: Self::Remainder) -> Self {
124                (input.0, remainder.0, input.1)
125            }
126            fn split_take(self) -> ((T0, T1), Self::Remainder) {
127                ((self.0, self.2), (self.1,))
128            }
129        }
130        impl #impl_generics_2 card_game::validation::StateFilterInputConversion<(T0, T1)> for (#name #ty_generics, T0, T1) #where_clause {
131            type Remainder = (#name #ty_generics,);
132            fn combine(input: (T0, T1), remainder: Self::Remainder) -> Self {
133                (remainder.0, input.0, input.1)
134            }
135            fn split_take(self) -> ((T0, T1), Self::Remainder) {
136                ((self.1, self.2), (self.0,))
137            }
138        }*/
139    }
140    .into()
141}