From 7ce68cd11516bd7cf037ecea99a92aee7c31b2c3 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Sat, 28 Mar 2026 00:47:46 +0800 Subject: Add initial Mingling framework codebase --- mingling_macros/src/dispatcher.rs | 72 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 mingling_macros/src/dispatcher.rs (limited to 'mingling_macros/src/dispatcher.rs') diff --git a/mingling_macros/src/dispatcher.rs b/mingling_macros/src/dispatcher.rs new file mode 100644 index 0000000..a411081 --- /dev/null +++ b/mingling_macros/src/dispatcher.rs @@ -0,0 +1,72 @@ +//! Dispatcher Derive Macro Implementation +//! +//! This module provides the `Dispatcher` derive macro for automatically +//! implementing the `mingling::Dispatcher` trait for structs. + +use just_fmt::dot_case; +use proc_macro::TokenStream; +use quote::quote; +use syn::{Attribute, DeriveInput, Ident, Lit, Meta, MetaNameValue, parse_macro_input}; + +/// Parses the `#[dispatcher("path")]` attribute if present +fn parse_dispatcher_attribute(attrs: &[Attribute]) -> Option { + for attr in attrs { + if attr.path().is_ident("dispatcher") { + match attr.parse_args::() { + Ok(Meta::NameValue(MetaNameValue { + value: + syn::Expr::Lit(syn::ExprLit { + lit: Lit::Str(lit_str), + .. + }), + .. + })) => { + return Some(lit_str.value()); + } + Ok(_) => { + // If it's not a string literal, we'll use a default + return None; + } + Err(_) => { + // If parsing fails, we'll use a default + return None; + } + } + } + } + None +} + +/// Generates the command node path from the struct name or attribute +fn generate_command_path(struct_name: &Ident, attr_path: Option) -> String { + if let Some(path) = attr_path { + path + } else { + // Convert struct name to dot_case for default path using the dot_case! macro + dot_case!(struct_name.to_string()) + } +} + +/// Implementation of the `Dispatcher` derive macro +pub fn dispatcher_derive(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as DeriveInput); + + let struct_name = &input.ident; + + // Parse the dispatcher attribute if present + let attr_path = parse_dispatcher_attribute(&input.attrs); + + // Generate the command path + let command_path = generate_command_path(struct_name, attr_path); + + // Generate the implementation + let expanded = quote! { + impl ::mingling::Dispatcher for #struct_name { + fn node(&self) -> ::mingling::Node { + ::mingling::macros::node!(#command_path) + } + } + }; + + expanded.into() +} -- cgit