From 4588e17f7ddacd8391a5c881a209735e08d48797 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Tue, 4 Aug 2026 13:26:48 +0800 Subject: feat: add entry metadata system with compile-time typed values Add `Metadata` trait and `#[metadata(Entry)]` attribute macro to attach arbitrary, compile-time-typed metadata to entries. Implement `ProgramCollect::get_metadata()` 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. --- .../example-combine-pathf-metadata/src/sub/mod.rs | 71 ++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 examples/example-combine-pathf-metadata/src/sub/mod.rs (limited to 'examples/example-combine-pathf-metadata/src/sub/mod.rs') diff --git a/examples/example-combine-pathf-metadata/src/sub/mod.rs b/examples/example-combine-pathf-metadata/src/sub/mod.rs new file mode 100644 index 0000000..2e6776e --- /dev/null +++ b/examples/example-combine-pathf-metadata/src/sub/mod.rs @@ -0,0 +1,71 @@ +use crate::Next; +use crate::ThisProgram; +use mingling::ProgramCollect; +use mingling::macros::metadata; +use mingling::prelude::*; +use std::io::Write; + +// Implicit dispatcher form — creates `CMDHello` / `EntryHello` in this module +dispatcher!("hello"); +// Creates `CMDDescription` / `EntryDescription` in this module +dispatcher!("desc", CMDDescription => EntryDescription); + +/// The metadata type attached to an entry (`DataType`). +#[derive(Debug, PartialEq, Eq)] +pub struct Description { + pub desc: String, +} + +/// Attach a `Description` to `EntryHello`. +/// +/// - `BindType` = `EntryHello` (the enum variant / entry type) +/// - `DataType` = `Description` (the function's return type) +#[metadata(EntryHello)] +pub fn hello_desc() -> Description { + Description { + desc: "okay".to_string(), + } +} + +pack!(ResultName = String); +pack!(DescResult = String); + +/// Chain for `hello` — reads the name and produces a `ResultName`. +#[chain] +pub fn handle_hello(args: EntryHello) -> Next { + let name: ResultName = args + .inner + .first() + .cloned() + .unwrap_or_else(|| "World".to_string()) + .into(); + name.into() +} + +/// Chain for `desc` — looks up the metadata bound to `EntryHello`. +#[chain] +pub fn handle_desc(_args: EntryDescription) -> Next { + // --------- IMPORTANT --------- + let msg = match ThisProgram::get_metadata::(ThisProgram::EntryHello) { + Some(d) => format!("EntryHello desc = {}", d.desc), + None => "EntryHello has no description".to_string(), + }; + // --------- IMPORTANT --------- + DescResult::new(msg).to_render() +} + +/// Renders the greeting message with the provided name. +#[renderer] +pub fn render_name(name: ResultName) -> RenderResult { + let mut render_result = RenderResult::new(); + writeln!(render_result, "Hello, {}!", *name).ok(); + render_result +} + +/// Renders the metadata query result. +#[renderer] +pub fn render_desc(msg: DescResult) -> RenderResult { + let mut render_result = RenderResult::new(); + writeln!(render_result, "{}", *msg).ok(); + render_result +} -- cgit