commonlibsse_ng_proc_macro_common/
fn_args_parser.rs1use proc_macro2::TokenStream;
2use syn::{FnArg, punctuated::Punctuated, token::Comma};
3
4pub struct FnArgs {
5 pub call_args: proc_macro2::TokenStream,
6 pub type_args: proc_macro2::TokenStream,
7 pub self_type: Option<proc_macro2::TokenStream>,
8 pub cast_self: Option<proc_macro2::TokenStream>,
9}
10
11pub fn create_fn_args(
13 fn_inputs: &Punctuated<FnArg, Comma>,
14 variadic: &Option<syn::Variadic>,
15) -> FnArgs {
16 let mut call_args = vec![];
17 let mut type_args = vec![];
18 let mut self_type = None;
19 let mut cast_self = None;
20
21 for arg in fn_inputs {
22 match arg {
23 syn::FnArg::Typed(pat_type) => {
24 let pat = &pat_type.pat;
25 if let syn::Pat::Ident(ident) = &**pat {
26 if ident.ident == "self" {
27 let syn::PatIdent { by_ref, mutability, .. } = ident;
28 let (self_type_, cast_self_) =
29 create_self_and_cast(by_ref.is_some(), mutability.is_some());
30 self_type = Some(self_type_);
31 cast_self = Some(cast_self_);
32 continue;
33 }
34 }
35
36 let ident = &pat_type.pat;
37 let ty = &pat_type.ty;
38 call_args.push(quote::quote! { #ident });
39 type_args.push(quote::quote! { #ty });
40 }
41 syn::FnArg::Receiver(receiver) => {
42 let reference = receiver.reference.as_ref().map(|(and, _lifetime)| and);
43 let mutability = &receiver.mutability;
44
45 let (self_type_, cast_self_) =
46 create_self_and_cast(reference.is_some(), mutability.is_some());
47 self_type = Some(self_type_);
48 cast_self = Some(cast_self_);
49 }
50 }
51 }
52
53 if variadic.is_some() {
54 call_args.push(quote::quote! { ... });
55 }
56
57 FnArgs {
58 call_args: quote::quote! { #(#call_args),* },
59 type_args: quote::quote! { #(#type_args),* },
60 self_type,
61 cast_self,
62 }
63}
64
65fn create_self_and_cast(by_ref: bool, mutability: bool) -> (TokenStream, TokenStream) {
66 match (by_ref, mutability) {
67 (true, true) => (quote::quote! { *mut (), }, quote::quote! { (self as *mut Self).cast(), }),
68 (true, false) => {
69 (quote::quote! { *const (), }, quote::quote! { (self as *const Self).cast(), })
70 }
71 (false, _) => (
72 quote::quote! { *mut (), },
73 quote::quote! { Box::into_raw(Box::new(self) as *mut ()), }, ),
75 }
76}