use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, punctuated::Punctuated, ItemFn, Meta, Token};
#[proc_macro_attribute]
pub fn rmlx_kernel(attr: TokenStream, item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as ItemFn);
let attrs = parse_macro_input!(attr with Punctuated::<Meta, Token![,]>::parse_terminated);
let fn_name = &input.sig.ident;
if input.sig.inputs.len() != 1 {
return syn::Error::new_spanned(
&input.sig,
"rmlx_kernel: expected exactly one parameter (registry: &KernelRegistry)",
)
.to_compile_error()
.into();
}
let mut kernel_name: Option<String> = None;
for meta in &attrs {
if let Meta::NameValue(nv) = meta {
if nv.path.is_ident("name") {
if let syn::Expr::Lit(syn::ExprLit {
lit: syn::Lit::Str(s),
..
}) = &nv.value
{
kernel_name = Some(s.value());
}
}
}
}
let kernel_name_str = kernel_name.unwrap_or_else(|| fn_name.to_string());
let metadata_fn_name = syn::Ident::new(&format!("{fn_name}_kernel_metadata"), fn_name.span());
let output = quote! {
#input
#[doc(hidden)]
pub fn #metadata_fn_name() -> &'static str {
#kernel_name_str
}
};
output.into()
}