Path: blob/master/rust/pin-init/internal/src/pinned_drop.rs
29281 views
// SPDX-License-Identifier: Apache-2.0 OR MIT12#[cfg(not(kernel))]3use proc_macro2 as proc_macro;45use proc_macro::{TokenStream, TokenTree};67pub(crate) fn pinned_drop(_args: TokenStream, input: TokenStream) -> TokenStream {8let mut toks = input.into_iter().collect::<Vec<_>>();9assert!(!toks.is_empty());10// Ensure that we have an `impl` item.11assert!(matches!(&toks[0], TokenTree::Ident(i) if i.to_string() == "impl"));12// Ensure that we are implementing `PinnedDrop`.13let mut nesting: usize = 0;14let mut pinned_drop_idx = None;15for (i, tt) in toks.iter().enumerate() {16match tt {17TokenTree::Punct(p) if p.as_char() == '<' => {18nesting += 1;19}20TokenTree::Punct(p) if p.as_char() == '>' => {21nesting = nesting.checked_sub(1).unwrap();22continue;23}24_ => {}25}26if i >= 1 && nesting == 0 {27// Found the end of the generics, this should be `PinnedDrop`.28assert!(29matches!(tt, TokenTree::Ident(i) if i.to_string() == "PinnedDrop"),30"expected 'PinnedDrop', found: '{tt:?}'"31);32pinned_drop_idx = Some(i);33break;34}35}36let idx = pinned_drop_idx37.unwrap_or_else(|| panic!("Expected an `impl` block implementing `PinnedDrop`."));38// Fully qualify the `PinnedDrop`, as to avoid any tampering.39toks.splice(idx..idx, quote!(::pin_init::));40// Take the `{}` body and call the declarative macro.41if let Some(TokenTree::Group(last)) = toks.pop() {42let last = last.stream();43quote!(::pin_init::__pinned_drop! {44@impl_sig(#(#toks)*),45@impl_body(#last),46})47} else {48TokenStream::from_iter(toks)49}50}515253