use proc_macro::TokenStream; use quote::quote; use syn::{ parse_macro_input, ItemFn, }; #[proc_macro_attribute] pub fn scanner(name: TokenStream, input: TokenStream) -> TokenStream { let name_str = parse_macro_input!(name as syn::LitStr).value(); let input = parse_macro_input!(input as ItemFn); let _fn_name = input.sig.ident.clone(); let body = &input.block; let result = quote! { #[no_mangle] pub extern "C" fn pscand_scanner() -> *mut std::os::raw::c_void { struct ScannerImpl; impl pscand_core::Scanner for ScannerImpl { fn name(&self) -> &'static str { #name_str } fn interval(&self) -> std::time::Duration { std::time::Duration::from_secs(1) } fn init(&mut self, _config: &toml::Value) -> pscand_core::Result<()> { Ok(()) } fn collect(&self) -> pscand_core::Result> { #body } fn cleanup(&mut self) -> pscand_core::Result<()> { Ok(()) } } let handle = unsafe { pscand_core::register_scanner(Box::new(ScannerImpl)) }; handle as *mut std::os::raw::c_void } }; result.into() } #[proc_macro] pub fn register_scanner(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as ItemFn); let fn_name = input.sig.ident.clone(); let result = quote! { #input #[no_mangle] pub extern "C" fn pscand_scanner() -> *mut std::os::raw::c_void { let handle = unsafe { pscand_core::register_scanner(Box::new(#fn_name())) }; handle as *mut std::os::raw::c_void } }; result.into() }