1 // SPDX-License-Identifier: Apache-2.0 OR MIT
3 use proc_macro::{Punct, Spacing, TokenStream, TokenTree};
5 pub(crate) fn pin_data(args: TokenStream, input: TokenStream) -> TokenStream {
6 // This proc-macro only does some pre-parsing and then delegates the actual parsing to
7 // `kernel::__pin_data!`.
9 // In here we only collect the generics, since parsing them in declarative macros is very
10 // elaborate. We also do not need to analyse their structure, we only need to collect them.
12 // `impl_generics`, the declared generics with their bounds.
13 let mut impl_generics = vec![];
14 // Only the names of the generics, without any bounds.
15 let mut ty_generics = vec![];
16 // Tokens not related to the generics e.g. the `impl` token.
17 let mut rest = vec![];
18 // The current level of `<`.
20 let mut toks = input.into_iter();
21 // If we are at the beginning of a generic parameter.
22 let mut at_start = true;
25 TokenTree::Punct(p) if p.as_char() == '<' => {
27 impl_generics.push(tt);
31 TokenTree::Punct(p) if p.as_char() == '>' => {
37 impl_generics.push(tt);
47 TokenTree::Ident(i) if i.to_string() == "const" => {}
48 TokenTree::Ident(_) if at_start => {
49 ty_generics.push(tt.clone());
50 ty_generics.push(TokenTree::Punct(Punct::new(',', Spacing::Alone)));
53 TokenTree::Punct(p) if p.as_char() == ',' => at_start = true,
54 TokenTree::Punct(p) if p.as_char() == '\'' && at_start => {
55 ty_generics.push(tt.clone());
61 impl_generics.push(tt);
62 } else if nesting == 0 {
69 // This should be the body of the struct `{...}`.
70 let last = rest.pop();
71 quote!(::kernel::__pin_data! {
75 @impl_generics(#(#impl_generics)*),
76 @ty_generics(#(#ty_generics)*),