1use proc_macro::{TokenStream, TokenTree};
4
5pub(crate) fn pinned_drop(_args: TokenStream, input: TokenStream) -> TokenStream {
6 let mut toks = input.into_iter().collect::<Vec<_>>();
7 assert!(!toks.is_empty());
8 assert!(matches!(&toks[0], TokenTree::Ident(i) if i.to_string() == "impl"));
10 let mut nesting: usize = 0;
12 let mut pinned_drop_idx = None;
13 for (i, tt) in toks.iter().enumerate() {
14 match tt {
15 TokenTree::Punct(p) if p.as_char() == '<' => {
16 nesting += 1;
17 }
18 TokenTree::Punct(p) if p.as_char() == '>' => {
19 nesting = nesting.checked_sub(1).unwrap();
20 continue;
21 }
22 _ => {}
23 }
24 if i >= 1 && nesting == 0 {
25 assert!(
27 matches!(tt, TokenTree::Ident(i) if i.to_string() == "PinnedDrop"),
28 "expected 'PinnedDrop', found: '{tt:?}'"
29 );
30 pinned_drop_idx = Some(i);
31 break;
32 }
33 }
34 let idx = pinned_drop_idx
35 .unwrap_or_else(|| panic!("Expected an `impl` block implementing `PinnedDrop`."));
36 toks.splice(idx..idx, quote!(::kernel::init::));
38 if let Some(TokenTree::Group(last)) = toks.pop() {
40 let last = last.stream();
41 quote!(::kernel::__pinned_drop! {
42 @impl_sig(#(#toks)*),
43 @impl_body(#last),
44 })
45 } else {
46 TokenStream::from_iter(toks)
47 }
48}