aboutsummaryrefslogtreecommitdiff
path: root/mingling_core
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-07-21 05:49:00 +0800
committer魏曹先生 <1992414357@qq.com>2026-07-21 05:49:00 +0800
commit700c049f64b66f424cda5da3021dfce4462655ca (patch)
treeb4fd21e5e6f82be29b18c47d8617814b28c159a6 /mingling_core
parent2097238b57810d78989d3ecab8bc97ce1b8a6aa1 (diff)
feat(core): add generic parameter `C` to `StructuralData` trait
Make `StructuralData` and `StructuralDataSealed` generic over a program collector type to bypass the orphan rule for `group_structural!`. This enables external types to implement `StructuralData<crate::ThisProgram>` without violating coherence.
Diffstat (limited to 'mingling_core')
-rw-r--r--mingling_core/src/lib.rs8
-rw-r--r--mingling_core/src/renderer/structural.rs16
-rw-r--r--mingling_core/src/renderer/structural/structural_data.rs8
-rw-r--r--mingling_core/tests/test-all/tests/integration.rs9
-rw-r--r--mingling_core/tests/test-structural-renderer/tests/integration.rs3
5 files changed, 32 insertions, 12 deletions
diff --git a/mingling_core/src/lib.rs b/mingling_core/src/lib.rs
index 2cb24b9..31476c9 100644
--- a/mingling_core/src/lib.rs
+++ b/mingling_core/src/lib.rs
@@ -90,8 +90,14 @@ pub mod setup {
/// Private API — not intended for direct use.
#[doc(hidden)]
pub mod __private {
+ use crate::ProgramCollect;
+
/// Sealed trait for `StructuralData` — only implementable via derive macro.
- pub trait StructuralDataSealed {}
+ pub trait StructuralDataSealed<C>
+ where
+ C: ProgramCollect<Enum = C>,
+ {
+ }
/// Re-export so the derive macro can reference the trait without
/// conflicting with the derive macro name at `::mingling::StructuralData`.
diff --git a/mingling_core/src/renderer/structural.rs b/mingling_core/src/renderer/structural.rs
index 30255aa..0449e72 100644
--- a/mingling_core/src/renderer/structural.rs
+++ b/mingling_core/src/renderer/structural.rs
@@ -1,5 +1,5 @@
use crate::{
- RenderResult, StructuralRendererSetting,
+ ProgramCollect, RenderResult, StructuralRendererSetting,
renderer::structural::error::StructuralRendererSerializeError,
};
use serde::Serialize;
@@ -24,11 +24,15 @@ impl StructuralRenderer {
///
/// Returns `Err(StructuralRendererSerializeError)` if serialization fails.
#[allow(unused_variables)]
- pub fn render<T: StructuralData + Send>(
+ pub fn render<T, C>(
data: &T,
setting: &StructuralRendererSetting,
r: &mut RenderResult,
- ) -> Result<(), StructuralRendererSerializeError> {
+ ) -> Result<(), StructuralRendererSerializeError>
+ where
+ T: StructuralData<C> + Send,
+ C: ProgramCollect<Enum = C>,
+ {
match setting {
StructuralRendererSetting::Disable => Ok(()),
#[cfg(feature = "json_serde_fmt")]
@@ -148,7 +152,7 @@ impl StructuralRenderer {
#[cfg(test)]
mod tests {
use super::*;
- use crate::RenderResult;
+ use crate::{MockProgramCollect, RenderResult};
use serde::Serialize;
#[derive(Debug, Clone, PartialEq, Serialize)]
@@ -157,8 +161,8 @@ mod tests {
value: i32,
}
- impl crate::__private::StructuralDataSealed for TestData {}
- impl StructuralData for TestData {}
+ impl crate::__private::StructuralDataSealed<MockProgramCollect> for TestData {}
+ impl StructuralData<MockProgramCollect> for TestData {}
fn test_data() -> TestData {
TestData {
diff --git a/mingling_core/src/renderer/structural/structural_data.rs b/mingling_core/src/renderer/structural/structural_data.rs
index 1cafac3..583808c 100644
--- a/mingling_core/src/renderer/structural/structural_data.rs
+++ b/mingling_core/src/renderer/structural/structural_data.rs
@@ -1,5 +1,7 @@
use serde::Serialize;
+use crate::ProgramCollect;
+
/// Marker trait for types that support structured output (JSON / YAML / TOML / RON).
///
/// This trait is a **supertrait** of `serde::Serialize` and is sealed via
@@ -12,4 +14,8 @@ use serde::Serialize;
/// These entry points also register the type in the global `STRUCTURED_TYPES`
/// registry, which is required for the `structural_render` match arm to be generated.
#[doc(hidden)]
-pub trait StructuralData: Serialize + crate::__private::StructuralDataSealed {}
+pub trait StructuralData<C>: Serialize + crate::__private::StructuralDataSealed<C>
+where
+ C: ProgramCollect<Enum = C>,
+{
+}
diff --git a/mingling_core/tests/test-all/tests/integration.rs b/mingling_core/tests/test-all/tests/integration.rs
index 08703b0..d36b9df 100644
--- a/mingling_core/tests/test-all/tests/integration.rs
+++ b/mingling_core/tests/test-all/tests/integration.rs
@@ -1,5 +1,4 @@
use mingling::Flag;
-use mingling::MockProgramCollect;
use mingling::NextProcess;
use mingling::Node;
use mingling::Program;
@@ -125,13 +124,13 @@ fn test_structural_renderer_json() {
#[test]
fn test_is_completing() {
- let program: Program<MockProgramCollect> = Program::new_with_args(["app", "__comp"]);
+ let program: Program<crate::ThisProgram> = Program::new_with_args(["app", "__comp"]);
assert!(program.is_completing());
}
#[test]
fn test_is_not_completing() {
- let program: Program<MockProgramCollect> = Program::new_with_args(["app", "greet"]);
+ let program: Program<crate::ThisProgram> = Program::new_with_args(["app", "greet"]);
assert!(!program.is_completing());
}
@@ -141,7 +140,7 @@ fn test_is_not_completing() {
fn test_hook_setup() {
static CALLED: AtomicBool = AtomicBool::new(false);
- let hook = ProgramHook::<MockProgramCollect>::empty().on_begin::<_, ()>(|_| {
+ let hook = ProgramHook::<crate::ThisProgram>::empty().on_begin::<_, ()>(|_| {
CALLED.store(true, Ordering::SeqCst);
});
@@ -166,3 +165,5 @@ fn test_string_vec_from_array() {
let v: Vec<String> = sv.into();
assert_eq!(v, vec!["a", "b", "c"]);
}
+
+mingling::macros::gen_program!();
diff --git a/mingling_core/tests/test-structural-renderer/tests/integration.rs b/mingling_core/tests/test-structural-renderer/tests/integration.rs
index 0bcf53a..e4057f8 100644
--- a/mingling_core/tests/test-structural-renderer/tests/integration.rs
+++ b/mingling_core/tests/test-structural-renderer/tests/integration.rs
@@ -74,3 +74,6 @@ fn test_render_ron() {
assert!(output.contains("value:"));
assert!(output.contains("42"));
}
+
+mingling::macros::gen_program!();
+