summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-04-05 22:33:19 +0800
committer魏曹先生 <1992414357@qq.com>2026-04-05 22:33:19 +0800
commitbdbaad9eff0eb3425dd0af8d3f479c7d8dcfd632 (patch)
treec645834ff10ca06a2f146a3486b49aeb250de771
parentd21d963a0f152d58a5997195b145cac4b8ccd018 (diff)
Add Groupped derive macro for automatic trait implementation
-rw-r--r--mingling/src/lib.rs3
-rw-r--r--mingling_macros/src/groupped.rs71
-rw-r--r--mingling_macros/src/lib.rs12
3 files changed, 86 insertions, 0 deletions
diff --git a/mingling/src/lib.rs b/mingling/src/lib.rs
index dcb9dd0..eb1d970 100644
--- a/mingling/src/lib.rs
+++ b/mingling/src/lib.rs
@@ -87,6 +87,9 @@ pub mod macros {
pub use mingling_macros::renderer;
}
+/// derive macro Groupped
+pub use mingling_macros::Groupped;
+
pub mod docs {
pub mod basic {
//! # Basic Usage
diff --git a/mingling_macros/src/groupped.rs b/mingling_macros/src/groupped.rs
new file mode 100644
index 0000000..187ea46
--- /dev/null
+++ b/mingling_macros/src/groupped.rs
@@ -0,0 +1,71 @@
+//! Groupped Derive Macro Implementation
+//!
+//! This module provides the `#[derive(Groupped)]` macro for automatically
+//! implementing the `Groupped` trait on structs and enums.
+
+use proc_macro::TokenStream;
+use proc_macro2::Span;
+use quote::quote;
+use syn::{Attribute, DeriveInput, Ident, parse_macro_input};
+
+/// Parses the `#[group(...)]` attribute to extract the group type
+fn parse_group_attribute(attrs: &[Attribute]) -> Option<Ident> {
+ for attr in attrs {
+ if attr.path().is_ident("group") {
+ if let Ok(meta) = attr.parse_args::<syn::Meta>() {
+ if let syn::Meta::Path(path) = meta {
+ if let Some(segment) = path.segments.last() {
+ return Some(segment.ident.clone());
+ }
+ }
+ }
+ }
+ }
+ None
+}
+
+pub fn derive_groupped(input: TokenStream) -> TokenStream {
+ // Parse the input struct/enum
+ let input = parse_macro_input!(input as DeriveInput);
+ let struct_name = input.ident;
+
+ // Parse attributes to find #[group(...)]
+ let group_ident = parse_group_attribute(&input.attrs)
+ .unwrap_or_else(|| Ident::new("DefaultProgram", Span::call_site()));
+
+ // Generate the Groupped trait implementation
+ let expanded = quote! {
+ impl ::mingling::Groupped<#group_ident> for #struct_name {
+ fn member_id() -> #group_ident {
+ #group_ident::#struct_name
+ }
+ }
+ };
+
+ expanded.into()
+}
+
+#[cfg(feature = "general_renderer")]
+pub fn derive_groupped_serialize(input: TokenStream) -> TokenStream {
+ // Parse the input struct/enum
+ let input_parsed = parse_macro_input!(input as DeriveInput);
+ let struct_name = input_parsed.ident.clone();
+
+ // Parse attributes to find #[group(...)]
+ let group_ident = parse_group_attribute(&input_parsed.attrs)
+ .unwrap_or_else(|| Ident::new("DefaultProgram", Span::call_site()));
+
+ // Generate both Serialize and Groupped implementations
+ let expanded = quote! {
+ #[derive(serde::Serialize)]
+ #input_parsed
+
+ impl ::mingling::Groupped<#group_ident> for #struct_name {
+ fn member_id() -> #group_ident {
+ #group_ident::#struct_name
+ }
+ }
+ };
+
+ expanded.into()
+}
diff --git a/mingling_macros/src/lib.rs b/mingling_macros/src/lib.rs
index 9513875..4341669 100644
--- a/mingling_macros/src/lib.rs
+++ b/mingling_macros/src/lib.rs
@@ -10,6 +10,7 @@ use syn::parse_macro_input;
mod chain;
mod dispatcher_chain;
+mod groupped;
mod node;
mod pack;
mod program_setup;
@@ -74,6 +75,17 @@ pub fn program_setup(attr: TokenStream, item: TokenStream) -> TokenStream {
program_setup::setup_attr(attr, item)
}
+#[proc_macro_derive(Groupped, attributes(group))]
+pub fn derive_groupped(input: TokenStream) -> TokenStream {
+ groupped::derive_groupped(input)
+}
+
+#[cfg(feature = "general_renderer")]
+#[proc_macro_derive(GrouppedSerialize, attributes(group))]
+pub fn derive_groupped_serialize(input: TokenStream) -> TokenStream {
+ groupped::derive_groupped_serialize(input)
+}
+
#[proc_macro]
pub fn gen_program(input: TokenStream) -> TokenStream {
let name = if input.is_empty() {