aboutsummaryrefslogtreecommitdiff
path: root/mingling_macros/src/func/program_final_gen.rs
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-08-04 13:26:48 +0800
committer魏曹先生 <1992414357@qq.com>2026-08-04 13:26:48 +0800
commit4588e17f7ddacd8391a5c881a209735e08d48797 (patch)
tree2b513f4d4f8a18ebd3a34cff7c0fb8abf5787321 /mingling_macros/src/func/program_final_gen.rs
parentf7862affd74ac3b129f9e9791a4cd4e1c7e3e6d1 (diff)
feat: add entry metadata system with compile-time typed values
Add `Metadata<B>` trait and `#[metadata(Entry)]` attribute macro to attach arbitrary, compile-time-typed metadata to entries. Implement `ProgramCollect::get_metadata<T>()` for runtime retrieval, backed by a global registry populated by `register_metadata!`. Extend `pathf` with `MetadataPattern` to resolve metadata types across modules at build time. Add two examples demonstrating metadata usage with and without pathf integration.
Diffstat (limited to 'mingling_macros/src/func/program_final_gen.rs')
-rw-r--r--mingling_macros/src/func/program_final_gen.rs35
1 files changed, 35 insertions, 0 deletions
diff --git a/mingling_macros/src/func/program_final_gen.rs b/mingling_macros/src/func/program_final_gen.rs
index e8545f4..429e60c 100644
--- a/mingling_macros/src/func/program_final_gen.rs
+++ b/mingling_macros/src/func/program_final_gen.rs
@@ -8,6 +8,7 @@ use crate::COMPILE_TIME_DISPATCHERS;
#[cfg(feature = "comp")]
use crate::COMPLETIONS;
use crate::HELP_REQUESTS;
+use crate::METADATA;
use crate::PACKED_TYPES;
use crate::RENDERERS;
use crate::RENDERERS_EXIST;
@@ -269,6 +270,38 @@ pub(crate) fn program_final_gen_impl(_input: TokenStream) -> TokenStream {
.map(|s| syn::parse_str::<proc_macro2::TokenStream>(s).unwrap())
.collect();
+ let metadata_tokens: Vec<proc_macro2::TokenStream> = get_global_set(&METADATA)
+ .lock()
+ .unwrap()
+ .clone()
+ .iter()
+ .map(|s| syn::parse_str::<proc_macro2::TokenStream>(s).unwrap())
+ .collect();
+
+ let get_metadata_fn = if metadata_tokens.is_empty() {
+ quote! {
+ fn get_metadata<T: 'static>(_member_id: Self::Enum) -> Option<T> {
+ None
+ }
+ }
+ } else {
+ let metadata_arms = metadata_tokens.iter().map(|entry| {
+ quote! {
+ #entry
+ }
+ });
+ quote! {
+ fn get_metadata<T: 'static>(member_id: Self::Enum) -> Option<T> {
+ let type_id = ::std::any::TypeId::of::<T>();
+ let any = match member_id {
+ #(#metadata_arms)*
+ _ => None,
+ };
+ any.and_then(|b| b.downcast::<T>().ok().map(|b| *b))
+ }
+ }
+ };
+
let num_variants = packed_types.len();
let repr_type = if u8::try_from(num_variants).is_ok() {
quote! { u8 }
@@ -313,6 +346,7 @@ pub(crate) fn program_final_gen_impl(_input: TokenStream) -> TokenStream {
}
#render_fn
#do_chain_fn
+ #get_metadata_fn
fn render_help(any: ::mingling::AnyOutput<Self::Enum>) -> ::mingling::RenderResult {
match any.member_id() {
#(#help_tokens)*
@@ -356,6 +390,7 @@ pub(crate) fn program_final_gen_impl(_input: TokenStream) -> TokenStream {
get_global_set(&RENDERERS).lock().unwrap().clear();
get_global_set(&RENDERERS_EXIST).lock().unwrap().clear();
get_global_set(&HELP_REQUESTS).lock().unwrap().clear();
+ get_global_set(&METADATA).lock().unwrap().clear();
#[cfg(feature = "comp")]
get_global_set(&COMPLETIONS).lock().unwrap().clear();
#[cfg(feature = "dispatch_tree")]