From 26ef5d88f36f69bb856aedc7bb50138933d1e036 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Tue, 4 Aug 2026 13:37:19 +0800 Subject: feat(metadata): add Description convention metadata type --- CHANGELOG.md | 27 +++++++++++++++++ mingling/src/lib.rs | 4 +++ mingling/src/metadata.rs | 2 ++ mingling/src/metadata/description.rs | 57 ++++++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+) create mode 100644 mingling/src/metadata.rs create mode 100644 mingling/src/metadata/description.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f4276d..1608466 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -240,6 +240,33 @@ None The `#[metadata]` attribute and `Metadata` trait are re-exported as `mingling::macros::metadata` and `mingling::Metadata` respectively. +10. **[`metadata:description`]** Added the `mingling::metadata` module and the `Description` convention metadata type. The `Description` type provides a human-readable description for any `Grouped` type, designed to be attached via the `#[metadata]` attribute macro introduced in item 9 above. + + The `Description` struct wraps a `String` and provides: + + - **`Description::new>(desc: S) -> Description`** — Constructs a new `Description` from any value convertible to `String`. + - **`From`** / **`From<&str>`** — Constructs a `Description` from an owned `String` or a string slice. + - **`From for String`** / **`From<&Description> for String`** — Extracts the inner `String` (or a clone) from a `Description` value. + - **`Deref`** / **`DerefMut`** — Allows `Description` to be used transparently as a `str`, so string methods (`len()`, `contains()`, etc.) work directly on it. + - **`Display`** — Formats the description as its inner string, so `Description` can be used directly with `format!`, `print!`, and `String::from`-style operations. + + Usage: + + ```rust,ignore + use mingling::metadata::Description; + + #[metadata(EntryGreet)] + pub fn greet_desc() -> Description { + Description::new("Greets the user by name.") + } + + // Later, at runtime: + let desc = ThisProgram::get_metadata::(ThisProgram::EntryGreet); + println!("{desc}"); // "Greets the user by name." + ``` + + The module is gated behind the `core` feature and re-exported as `mingling::metadata`. This type is designed to work hand-in-hand with the compile-time entry metadata system from item 9, providing a first-party convention metadata for describing entries in generated documentation and help output. + #### **BREAKING CHANGES** (API CHANGES): 1. **[`macros`]** **[BREAKING]** Renamed the `extra_macros` feature to `extras`. All feature-gated macro re-exports in `mingling/src/lib.rs` (and throughout the codebase) have been updated from `#[cfg(feature = "extra_macros")]` to `#[cfg(feature = "extras")]`. diff --git a/mingling/src/lib.rs b/mingling/src/lib.rs index 01edae9..470c64b 100644 --- a/mingling/src/lib.rs +++ b/mingling/src/lib.rs @@ -16,6 +16,10 @@ pub mod CRATE_ROOT { pub use crate::gen_program::*; } +/// Mingling's convention metadatas, which can be bound to types using `#[metadata]`, to provide identification for types +#[cfg(feature = "core")] +pub mod metadata; + #[cfg(feature = "core")] mod example_docs; diff --git a/mingling/src/metadata.rs b/mingling/src/metadata.rs new file mode 100644 index 0000000..329576c --- /dev/null +++ b/mingling/src/metadata.rs @@ -0,0 +1,2 @@ +mod description; +pub use description::*; diff --git a/mingling/src/metadata/description.rs b/mingling/src/metadata/description.rs new file mode 100644 index 0000000..48bf095 --- /dev/null +++ b/mingling/src/metadata/description.rs @@ -0,0 +1,57 @@ +/// Provides a description for any Grouped type. +pub struct Description { + desc: String, +} + +impl Description { + /// Creates a new `Description` instance. + pub fn new>(desc: S) -> Self { + Self { desc: desc.into() } + } +} + +impl From for Description { + fn from(desc: String) -> Self { + Self { desc } + } +} + +impl From<&str> for Description { + fn from(desc: &str) -> Self { + Self { + desc: desc.to_string(), + } + } +} + +impl From for String { + fn from(desc: Description) -> Self { + desc.desc + } +} + +impl From<&Description> for String { + fn from(desc: &Description) -> Self { + desc.desc.clone() + } +} + +impl std::ops::Deref for Description { + type Target = str; + + fn deref(&self) -> &Self::Target { + &self.desc + } +} + +impl std::ops::DerefMut for Description { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.desc + } +} + +impl std::fmt::Display for Description { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.desc) + } +} -- cgit