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