hooks_macro_core/
detected.rs

1use proc_macro2::{Span, TokenStream};
2use quote::{quote_spanned, ToTokens};
3
4pub struct DetectedHooksTokens {
5    pub fn_arg_data_pat: TokenStream,
6    pub fn_stmts_extract_data: Option<TokenStream>,
7}
8
9pub struct DetectedHook {
10    pub ident: syn::Ident,
11}
12
13pub fn detected_hooks_to_tokens(
14    mut used_hooks: Vec<DetectedHook>,
15    hooks_core_path: impl ToTokens,
16    span: Span,
17) -> DetectedHooksTokens {
18    match used_hooks.len() {
19        0 => DetectedHooksTokens {
20            fn_arg_data_pat: quote_spanned! {span=>
21                _: ::core::pin::Pin<&mut #hooks_core_path::HookTuple::<()>>
22            },
23            fn_stmts_extract_data: None,
24        },
25        1 => {
26            let DetectedHook { ident } = used_hooks.pop().unwrap();
27            DetectedHooksTokens {
28                fn_arg_data_pat: quote_spanned! {span=>
29                    #ident: ::core::pin::Pin<&mut _>
30                },
31                fn_stmts_extract_data: None,
32            }
33        }
34        _ => {
35            let ident_hooks_data = syn::Ident::new("__hooks_hook_data", span);
36
37            let used_id = used_hooks.iter().map(|h| &h.ident);
38
39            let impl_extract_hooks_data = quote_spanned! {span=>
40                // SAFETY: pin projection
41                #hooks_core_path::__impl_pin_project_hook_tuple!(#ident_hooks_data, #(#used_id,)*);
42            };
43
44            DetectedHooksTokens {
45                fn_arg_data_pat: quote_spanned! {span=>
46                    #ident_hooks_data: ::core::pin::Pin<&mut _>
47                },
48                fn_stmts_extract_data: Some(impl_extract_hooks_data),
49            }
50        }
51    }
52}