Path: blob/master/rust/pin-init/internal/src/zeroable.rs
29281 views
// SPDX-License-Identifier: GPL-2.012#[cfg(not(kernel))]3use proc_macro2 as proc_macro;45use crate::helpers::{parse_generics, Generics};6use proc_macro::{TokenStream, TokenTree};78pub(crate) fn parse_zeroable_derive_input(9input: TokenStream,10) -> (11Vec<TokenTree>,12Vec<TokenTree>,13Vec<TokenTree>,14Option<TokenTree>,15) {16let (17Generics {18impl_generics,19decl_generics: _,20ty_generics,21},22mut rest,23) = parse_generics(input);24// This should be the body of the struct `{...}`.25let last = rest.pop();26// Now we insert `Zeroable` as a bound for every generic parameter in `impl_generics`.27let mut new_impl_generics = Vec::with_capacity(impl_generics.len());28// Are we inside of a generic where we want to add `Zeroable`?29let mut in_generic = !impl_generics.is_empty();30// Have we already inserted `Zeroable`?31let mut inserted = false;32// Level of `<>` nestings.33let mut nested = 0;34for tt in impl_generics {35match &tt {36// If we find a `,`, then we have finished a generic/constant/lifetime parameter.37TokenTree::Punct(p) if nested == 0 && p.as_char() == ',' => {38if in_generic && !inserted {39new_impl_generics.extend(quote! { : ::pin_init::Zeroable });40}41in_generic = true;42inserted = false;43new_impl_generics.push(tt);44}45// If we find `'`, then we are entering a lifetime.46TokenTree::Punct(p) if nested == 0 && p.as_char() == '\'' => {47in_generic = false;48new_impl_generics.push(tt);49}50TokenTree::Punct(p) if nested == 0 && p.as_char() == ':' => {51new_impl_generics.push(tt);52if in_generic {53new_impl_generics.extend(quote! { ::pin_init::Zeroable + });54inserted = true;55}56}57TokenTree::Punct(p) if p.as_char() == '<' => {58nested += 1;59new_impl_generics.push(tt);60}61TokenTree::Punct(p) if p.as_char() == '>' => {62assert!(nested > 0);63nested -= 1;64new_impl_generics.push(tt);65}66_ => new_impl_generics.push(tt),67}68}69assert_eq!(nested, 0);70if in_generic && !inserted {71new_impl_generics.extend(quote! { : ::pin_init::Zeroable });72}73(rest, new_impl_generics, ty_generics, last)74}7576pub(crate) fn derive(input: TokenStream) -> TokenStream {77let (rest, new_impl_generics, ty_generics, last) = parse_zeroable_derive_input(input);78quote! {79::pin_init::__derive_zeroable!(80parse_input:81@sig(#(#rest)*),82@impl_generics(#(#new_impl_generics)*),83@ty_generics(#(#ty_generics)*),84@body(#last),85);86}87}8889pub(crate) fn maybe_derive(input: TokenStream) -> TokenStream {90let (rest, new_impl_generics, ty_generics, last) = parse_zeroable_derive_input(input);91quote! {92::pin_init::__maybe_derive_zeroable!(93parse_input:94@sig(#(#rest)*),95@impl_generics(#(#new_impl_generics)*),96@ty_generics(#(#ty_generics)*),97@body(#last),98);99}100}101102103