1 // SPDX-License-Identifier: GPL-2.0 2 3 use proc_macro::{Delimiter, Group, TokenStream 4 use std::collections::HashSet; 5 use std::fmt::Write; 6 7 pub(crate) fn vtable(_attr: TokenStream, ts: T 8 let mut tokens: Vec<_> = ts.into_iter().co 9 10 // Scan for the `trait` or `impl` keyword. 11 let is_trait = tokens 12 .iter() 13 .find_map(|token| match token { 14 TokenTree::Ident(ident) => match i 15 "trait" => Some(true), 16 "impl" => Some(false), 17 _ => None, 18 }, 19 _ => None, 20 }) 21 .expect("#[vtable] attribute should on 22 23 // Retrieve the main body. The main body s 24 let body = match tokens.pop() { 25 Some(TokenTree::Group(group)) if group 26 _ => panic!("cannot locate main body o 27 }; 28 29 let mut body_it = body.stream().into_iter( 30 let mut functions = Vec::new(); 31 let mut consts = HashSet::new(); 32 while let Some(token) = body_it.next() { 33 match token { 34 TokenTree::Ident(ident) if ident.t 35 let fn_name = match body_it.ne 36 Some(TokenTree::Ident(iden 37 // Possibly we've encounte 38 _ => continue, 39 }; 40 functions.push(fn_name); 41 } 42 TokenTree::Ident(ident) if ident.t 43 let const_name = match body_it 44 Some(TokenTree::Ident(iden 45 // Possibly we've encounte 46 _ => continue, 47 }; 48 consts.insert(const_name); 49 } 50 _ => (), 51 } 52 } 53 54 let mut const_items; 55 if is_trait { 56 const_items = " 57 /// A marker to prevent implem 58 /// attribute when implementin 59 const USE_VTABLE_ATTR: (); 60 " 61 .to_owned(); 62 63 for f in functions { 64 let gen_const_name = format!("HAS_ 65 // Skip if it's declared already - 66 if consts.contains(&gen_const_name 67 continue; 68 } 69 // We don't know on the implementa 70 // so we have to generate a const 71 write!( 72 const_items, 73 "/// Indicates if the `{f}` me 74 const {gen_const_name}: bool = 75 ) 76 .unwrap(); 77 consts.insert(gen_const_name); 78 } 79 } else { 80 const_items = "const USE_VTABLE_ATTR: 81 82 for f in functions { 83 let gen_const_name = format!("HAS_ 84 if consts.contains(&gen_const_name 85 continue; 86 } 87 write!(const_items, "const {gen_co 88 } 89 } 90 91 let new_body = vec![const_items.parse().un 92 .into_iter() 93 .collect(); 94 tokens.push(TokenTree::Group(Group::new(De 95 tokens.into_iter().collect() 96 }
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.