scroll.server/crates/logic-derive/src/lib.rs
WiseDev d25a6de423 move all crates into crates/, glob members
pure move, no code touched. readme and protocol.md paths fixed up.
2026-08-23 08:15:45 +03:00

46 lines
1.7 KiB
Rust

use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput, Error, Expr, LitStr, Result};
#[proc_macro_derive(Command, attributes(command))]
pub fn derive_command(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
expand(&input)
.unwrap_or_else(Error::into_compile_error)
.into()
}
fn expand(input: &DeriveInput) -> Result<proc_macro2::TokenStream> {
let attr = input
.attrs
.iter()
.find(|attr| attr.path().is_ident("command"))
.ok_or_else(|| {
Error::new_spanned(&input.ident, "missing #[command(id = ...)] attribute")
})?;
let mut id: Option<proc_macro2::TokenStream> = None;
let mut name: Option<String> = None;
attr.parse_nested_meta(|meta| {
if meta.path.is_ident("id") {
let value: Expr = meta.value()?.parse()?;
id = Some(quote!(#value));
return Ok(());
}
if meta.path.is_ident("name") {
let value: LitStr = meta.value()?.parse()?;
name = Some(value.value());
return Ok(());
}
Err(meta.error("unsupported #[command(...)] key"))
})?;
let id = id.ok_or_else(|| Error::new_spanned(attr, "#[command(...)] requires `id`"))?;
let ident = &input.ident;
let name = name.unwrap_or_else(|| ident.to_string());
Ok(quote! {
impl ::logic::commands::CommandMeta for #ident {
const COMMAND_TYPE: i32 = #id;
const NAME: &'static str = #name;
}
::titan::inventory::submit! {
::logic::commands::CommandRegistryEntry::of::<#ident>()
}
})
}