From d1a74ce57e5be72436376a829e9c7e1e7c1c561b Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Fri, 26 Jun 2026 06:27:16 +0800 Subject: refactor(general_renderer): rename to structural_renderer --- mingling_core/src/renderer/general.rs | 268 --------------------- mingling_core/src/renderer/general/error.rs | 68 ------ .../src/renderer/general/structural_data.rs | 15 -- mingling_core/src/renderer/structural.rs | 268 +++++++++++++++++++++ mingling_core/src/renderer/structural/error.rs | 68 ++++++ .../src/renderer/structural/structural_data.rs | 15 ++ 6 files changed, 351 insertions(+), 351 deletions(-) delete mode 100644 mingling_core/src/renderer/general.rs delete mode 100644 mingling_core/src/renderer/general/error.rs delete mode 100644 mingling_core/src/renderer/general/structural_data.rs create mode 100644 mingling_core/src/renderer/structural.rs create mode 100644 mingling_core/src/renderer/structural/error.rs create mode 100644 mingling_core/src/renderer/structural/structural_data.rs (limited to 'mingling_core/src/renderer') diff --git a/mingling_core/src/renderer/general.rs b/mingling_core/src/renderer/general.rs deleted file mode 100644 index e6da06b..0000000 --- a/mingling_core/src/renderer/general.rs +++ /dev/null @@ -1,268 +0,0 @@ -use crate::{ - GeneralRendererSetting, RenderResult, renderer::general::error::GeneralRendererSerializeError, -}; -use serde::Serialize; - -pub mod error; -pub mod structural_data; - -use structural_data::StructuralData; - -/// A general renderer that supports multiple serialization formats. -/// -/// The `GeneralRenderer` provides methods to serialize data into various formats -/// including JSON, YAML, TOML, and RON, with support for both regular and -/// pretty-printed variants. It is designed to work with types that implement -/// the [`StructuralData`] trait (which implies `Serialize`). -pub struct GeneralRenderer; - -impl GeneralRenderer { - /// Renders data in the specified format to the given `RenderResult`. - /// - /// # Errors - /// - /// Returns `Err(GeneralRendererSerializeError)` if serialization fails. - #[allow(unused_variables)] - pub fn render( - data: &T, - setting: &GeneralRendererSetting, - r: &mut RenderResult, - ) -> Result<(), GeneralRendererSerializeError> { - match setting { - GeneralRendererSetting::Disable => Ok(()), - #[cfg(feature = "json_serde_fmt")] - GeneralRendererSetting::Json => Self::render_to_json(data, r), - #[cfg(feature = "json_serde_fmt")] - GeneralRendererSetting::JsonPretty => Self::render_to_json_pretty(data, r), - #[cfg(feature = "yaml_serde_fmt")] - GeneralRendererSetting::Yaml => Self::render_to_yaml(data, r), - #[cfg(feature = "toml_serde_fmt")] - GeneralRendererSetting::Toml => Self::render_to_toml(data, r), - #[cfg(feature = "ron_serde_fmt")] - GeneralRendererSetting::Ron => Self::render_to_ron(data, r), - #[cfg(feature = "ron_serde_fmt")] - GeneralRendererSetting::RonPretty => Self::render_to_ron_pretty(data, r), - } - } - - /// Serializes data to JSON format and writes it to the render result. - /// - /// # Errors - /// - /// Returns `Err(GeneralRendererSerializeError)` if serialization fails. - #[cfg(feature = "json_serde_fmt")] - fn render_to_json( - data: &T, - r: &mut RenderResult, - ) -> Result<(), GeneralRendererSerializeError> { - let json_string = serde_json::to_string(data) - .map_err(|e| GeneralRendererSerializeError::new(e.to_string()))?; - r.print(&json_string); - Ok(()) - } - - /// Serializes data to pretty-printed JSON format and writes it to the render result. - /// - /// # Errors - /// - /// Returns `Err(GeneralRendererSerializeError)` if serialization fails. - #[cfg(feature = "json_serde_fmt")] - fn render_to_json_pretty( - data: &T, - r: &mut RenderResult, - ) -> Result<(), GeneralRendererSerializeError> { - let json_string = serde_json::to_string_pretty(data) - .map_err(|e| GeneralRendererSerializeError::new(e.to_string()))?; - r.print(&json_string); - Ok(()) - } - - /// Serializes data to RON format and writes it to the render result. - /// - /// # Errors - /// - /// Returns `Err(GeneralRendererSerializeError)` if serialization fails. - #[cfg(feature = "ron_serde_fmt")] - fn render_to_ron( - data: &T, - r: &mut RenderResult, - ) -> Result<(), GeneralRendererSerializeError> { - let ron_string = ron::ser::to_string(data) - .map_err(|e| GeneralRendererSerializeError::new(e.to_string()))?; - r.print(&ron_string); - Ok(()) - } - - /// Serializes data to pretty-printed RON format and writes it to the render result. - /// - /// # Errors - /// - /// Returns `Err(GeneralRendererSerializeError)` if serialization fails. - #[cfg(feature = "ron_serde_fmt")] - fn render_to_ron_pretty( - data: &T, - r: &mut RenderResult, - ) -> Result<(), GeneralRendererSerializeError> { - let pretty_config = ron::ser::PrettyConfig::new() - .new_line("\n") - .indentor(" "); - - let ron_string = ron::ser::to_string_pretty(data, pretty_config) - .map_err(|e| GeneralRendererSerializeError::new(e.to_string()))?; - r.print(&ron_string); - Ok(()) - } - - /// Serializes data to TOML format and writes it to the render result. - /// - /// # Errors - /// - /// Returns `Err(GeneralRendererSerializeError)` if serialization fails. - #[cfg(feature = "toml_serde_fmt")] - fn render_to_toml( - data: &T, - r: &mut RenderResult, - ) -> Result<(), GeneralRendererSerializeError> { - let toml_string = - toml::to_string(data).map_err(|e| GeneralRendererSerializeError::new(e.to_string()))?; - r.print(&toml_string); - Ok(()) - } - - /// Serializes data to YAML format and writes it to the render result. - /// - /// # Errors - /// - /// Returns `Err(GeneralRendererSerializeError)` if serialization fails. - #[cfg(feature = "yaml_serde_fmt")] - fn render_to_yaml( - data: &T, - r: &mut RenderResult, - ) -> Result<(), GeneralRendererSerializeError> { - let yaml_string = serde_yaml::to_string(data) - .map_err(|e| GeneralRendererSerializeError::new(e.to_string()))?; - r.print(&yaml_string); - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::RenderResult; - use serde::Serialize; - - #[derive(Debug, Clone, PartialEq, Serialize)] - struct TestData { - name: String, - value: i32, - } - - impl crate::__private::StructuralDataSealed for TestData {} - impl StructuralData for TestData {} - - fn test_data() -> TestData { - TestData { - name: "hello".into(), - value: 42, - } - } - - #[test] - fn test_render_disable_does_nothing() { - let mut r = RenderResult::default(); - let result = - GeneralRenderer::render(&test_data(), &GeneralRendererSetting::Disable, &mut r); - assert!(result.is_ok()); - assert!(r.is_empty()); - } - - #[cfg(feature = "json_serde_fmt")] - #[test] - fn test_render_to_json() { - let mut r = RenderResult::default(); - let result = - GeneralRenderer::render(&test_data(), &GeneralRendererSetting::Json, &mut r); - assert!(result.is_ok()); - assert!(!r.is_empty()); - let output: String = r.into(); - assert!(output.contains("\"name\"")); - assert!(output.contains("\"hello\"")); - assert!(output.contains("\"value\"")); - assert!(output.contains("42")); - } - - #[cfg(feature = "json_serde_fmt")] - #[test] - fn test_render_to_json_pretty() { - let mut r = RenderResult::default(); - let result = - GeneralRenderer::render(&test_data(), &GeneralRendererSetting::JsonPretty, &mut r); - assert!(result.is_ok()); - let output: String = r.into(); - // Pretty JSON has newlines - assert!(output.contains('\n')); - } - - #[cfg(feature = "yaml_serde_fmt")] - #[test] - fn test_render_to_yaml() { - let mut r = RenderResult::default(); - let result = - GeneralRenderer::render(&test_data(), &GeneralRendererSetting::Yaml, &mut r); - assert!(result.is_ok()); - assert!(!r.is_empty()); - } - - #[cfg(feature = "toml_serde_fmt")] - #[test] - fn test_render_to_toml() { - let mut r = RenderResult::default(); - let result = - GeneralRenderer::render(&test_data(), &GeneralRendererSetting::Toml, &mut r); - assert!(result.is_ok()); - assert!(!r.is_empty()); - } - - #[cfg(feature = "ron_serde_fmt")] - #[test] - fn test_render_to_ron() { - let mut r = RenderResult::default(); - let result = - GeneralRenderer::render(&test_data(), &GeneralRendererSetting::Ron, &mut r); - assert!(result.is_ok()); - assert!(!r.is_empty()); - } - - #[cfg(feature = "ron_serde_fmt")] - #[test] - fn test_render_to_ron_pretty() { - let mut r = RenderResult::default(); - let result = - GeneralRenderer::render(&test_data(), &GeneralRendererSetting::RonPretty, &mut r); - assert!(result.is_ok()); - let output: String = r.into(); - assert!(output.contains('\n')); - } - - #[test] - fn test_render_dispatches_correct_format() { - // Test that render dispatches to the right format handler - let mut r = RenderResult::default(); - - // Disable - let result = - GeneralRenderer::render(&test_data(), &GeneralRendererSetting::Disable, &mut r); - assert!(result.is_ok()); - assert!(r.is_empty()); - } - - #[cfg(feature = "json_serde_fmt")] - #[test] - fn test_render_dispatches_json() { - let mut r = RenderResult::default(); - let result = GeneralRenderer::render(&test_data(), &GeneralRendererSetting::Json, &mut r); - assert!(result.is_ok()); - assert!(!r.is_empty()); - } -} diff --git a/mingling_core/src/renderer/general/error.rs b/mingling_core/src/renderer/general/error.rs deleted file mode 100644 index 07ca92b..0000000 --- a/mingling_core/src/renderer/general/error.rs +++ /dev/null @@ -1,68 +0,0 @@ -/// Represents an error that occurs during serialization of a general renderer. -/// -/// This error stores a human-readable message describing what went wrong -/// during the serialization process. -#[derive(Debug)] -pub struct GeneralRendererSerializeError { - /// The underlying error message. - error: String, -} - -impl GeneralRendererSerializeError { - #[must_use] - pub fn new(error: String) -> Self { - Self { error } - } -} - -impl From<&str> for GeneralRendererSerializeError { - fn from(s: &str) -> Self { - Self::new(s.to_string()) - } -} - -impl std::ops::Deref for GeneralRendererSerializeError { - type Target = String; - - fn deref(&self) -> &Self::Target { - &self.error - } -} - -impl From for String { - fn from(val: GeneralRendererSerializeError) -> Self { - val.error - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn new_creates_error_with_message() { - let msg = "serialization failed".to_string(); - let err = GeneralRendererSerializeError::new(msg.clone()); - assert_eq!(err.error, msg); - } - - #[test] - fn from_str_creates_error_from_string_slice() { - let err: GeneralRendererSerializeError = "oops".into(); - assert_eq!(err.error, "oops"); - } - - #[test] - fn deref_accesses_inner_error_string() { - let err = GeneralRendererSerializeError::new("inner message".to_string()); - let derefed: &String = &err; - assert_eq!(derefed, "inner message"); - } - - #[test] - fn into_string_extracts_message() { - let err = GeneralRendererSerializeError::new("extract me".to_string()); - let s: String = err.into(); - assert_eq!(s, "extract me"); - } -} diff --git a/mingling_core/src/renderer/general/structural_data.rs b/mingling_core/src/renderer/general/structural_data.rs deleted file mode 100644 index ac6363e..0000000 --- a/mingling_core/src/renderer/general/structural_data.rs +++ /dev/null @@ -1,15 +0,0 @@ -use serde::Serialize; - -/// Marker trait for types that support structured output (JSON / YAML / TOML / RON). -/// -/// This trait is a **supertrait** of `serde::Serialize` and is sealed via -/// `__private::StructuralDataSealed`. It can only be implemented through: -/// -/// - `#[derive(StructuralData)]` -/// - `pack_structural!` -/// - `group_structural!` -/// -/// These entry points also register the type in the global `STRUCTURED_TYPES` -/// registry, which is required for the `general_render` match arm to be generated. -#[doc(hidden)] -pub trait StructuralData: Serialize + crate::__private::StructuralDataSealed {} diff --git a/mingling_core/src/renderer/structural.rs b/mingling_core/src/renderer/structural.rs new file mode 100644 index 0000000..16ce471 --- /dev/null +++ b/mingling_core/src/renderer/structural.rs @@ -0,0 +1,268 @@ +use crate::{ + StructuralRendererSetting, RenderResult, renderer::structural::error::StructuralRendererSerializeError, +}; +use serde::Serialize; + +pub mod error; +pub mod structural_data; + +use structural_data::StructuralData; + +/// A structural renderer that supports multiple serialization formats. +/// +/// The `StructuralRenderer` provides methods to serialize data into various formats +/// including JSON, YAML, TOML, and RON, with support for both regular and +/// pretty-printed variants. It is designed to work with types that implement +/// the [`StructuralData`] trait (which implies `Serialize`). +pub struct StructuralRenderer; + +impl StructuralRenderer { + /// Renders data in the specified format to the given `RenderResult`. + /// + /// # Errors + /// + /// Returns `Err(StructuralRendererSerializeError)` if serialization fails. + #[allow(unused_variables)] + pub fn render( + data: &T, + setting: &StructuralRendererSetting, + r: &mut RenderResult, + ) -> Result<(), StructuralRendererSerializeError> { + match setting { + StructuralRendererSetting::Disable => Ok(()), + #[cfg(feature = "json_serde_fmt")] + StructuralRendererSetting::Json => Self::render_to_json(data, r), + #[cfg(feature = "json_serde_fmt")] + StructuralRendererSetting::JsonPretty => Self::render_to_json_pretty(data, r), + #[cfg(feature = "yaml_serde_fmt")] + StructuralRendererSetting::Yaml => Self::render_to_yaml(data, r), + #[cfg(feature = "toml_serde_fmt")] + StructuralRendererSetting::Toml => Self::render_to_toml(data, r), + #[cfg(feature = "ron_serde_fmt")] + StructuralRendererSetting::Ron => Self::render_to_ron(data, r), + #[cfg(feature = "ron_serde_fmt")] + StructuralRendererSetting::RonPretty => Self::render_to_ron_pretty(data, r), + } + } + + /// Serializes data to JSON format and writes it to the render result. + /// + /// # Errors + /// + /// Returns `Err(StructuralRendererSerializeError)` if serialization fails. + #[cfg(feature = "json_serde_fmt")] + fn render_to_json( + data: &T, + r: &mut RenderResult, + ) -> Result<(), StructuralRendererSerializeError> { + let json_string = serde_json::to_string(data) + .map_err(|e| StructuralRendererSerializeError::new(e.to_string()))?; + r.print(&json_string); + Ok(()) + } + + /// Serializes data to pretty-printed JSON format and writes it to the render result. + /// + /// # Errors + /// + /// Returns `Err(StructuralRendererSerializeError)` if serialization fails. + #[cfg(feature = "json_serde_fmt")] + fn render_to_json_pretty( + data: &T, + r: &mut RenderResult, + ) -> Result<(), StructuralRendererSerializeError> { + let json_string = serde_json::to_string_pretty(data) + .map_err(|e| StructuralRendererSerializeError::new(e.to_string()))?; + r.print(&json_string); + Ok(()) + } + + /// Serializes data to RON format and writes it to the render result. + /// + /// # Errors + /// + /// Returns `Err(StructuralRendererSerializeError)` if serialization fails. + #[cfg(feature = "ron_serde_fmt")] + fn render_to_ron( + data: &T, + r: &mut RenderResult, + ) -> Result<(), StructuralRendererSerializeError> { + let ron_string = ron::ser::to_string(data) + .map_err(|e| StructuralRendererSerializeError::new(e.to_string()))?; + r.print(&ron_string); + Ok(()) + } + + /// Serializes data to pretty-printed RON format and writes it to the render result. + /// + /// # Errors + /// + /// Returns `Err(StructuralRendererSerializeError)` if serialization fails. + #[cfg(feature = "ron_serde_fmt")] + fn render_to_ron_pretty( + data: &T, + r: &mut RenderResult, + ) -> Result<(), StructuralRendererSerializeError> { + let pretty_config = ron::ser::PrettyConfig::new() + .new_line("\n") + .indentor(" "); + + let ron_string = ron::ser::to_string_pretty(data, pretty_config) + .map_err(|e| StructuralRendererSerializeError::new(e.to_string()))?; + r.print(&ron_string); + Ok(()) + } + + /// Serializes data to TOML format and writes it to the render result. + /// + /// # Errors + /// + /// Returns `Err(StructuralRendererSerializeError)` if serialization fails. + #[cfg(feature = "toml_serde_fmt")] + fn render_to_toml( + data: &T, + r: &mut RenderResult, + ) -> Result<(), StructuralRendererSerializeError> { + let toml_string = + toml::to_string(data).map_err(|e| StructuralRendererSerializeError::new(e.to_string()))?; + r.print(&toml_string); + Ok(()) + } + + /// Serializes data to YAML format and writes it to the render result. + /// + /// # Errors + /// + /// Returns `Err(StructuralRendererSerializeError)` if serialization fails. + #[cfg(feature = "yaml_serde_fmt")] + fn render_to_yaml( + data: &T, + r: &mut RenderResult, + ) -> Result<(), StructuralRendererSerializeError> { + let yaml_string = serde_yaml::to_string(data) + .map_err(|e| StructuralRendererSerializeError::new(e.to_string()))?; + r.print(&yaml_string); + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::RenderResult; + use serde::Serialize; + + #[derive(Debug, Clone, PartialEq, Serialize)] + struct TestData { + name: String, + value: i32, + } + + impl crate::__private::StructuralDataSealed for TestData {} + impl StructuralData for TestData {} + + fn test_data() -> TestData { + TestData { + name: "hello".into(), + value: 42, + } + } + + #[test] + fn test_render_disable_does_nothing() { + let mut r = RenderResult::default(); + let result = + StructuralRenderer::render(&test_data(), &StructuralRendererSetting::Disable, &mut r); + assert!(result.is_ok()); + assert!(r.is_empty()); + } + + #[cfg(feature = "json_serde_fmt")] + #[test] + fn test_render_to_json() { + let mut r = RenderResult::default(); + let result = + StructuralRenderer::render(&test_data(), &StructuralRendererSetting::Json, &mut r); + assert!(result.is_ok()); + assert!(!r.is_empty()); + let output: String = r.into(); + assert!(output.contains("\"name\"")); + assert!(output.contains("\"hello\"")); + assert!(output.contains("\"value\"")); + assert!(output.contains("42")); + } + + #[cfg(feature = "json_serde_fmt")] + #[test] + fn test_render_to_json_pretty() { + let mut r = RenderResult::default(); + let result = + StructuralRenderer::render(&test_data(), &StructuralRendererSetting::JsonPretty, &mut r); + assert!(result.is_ok()); + let output: String = r.into(); + // Pretty JSON has newlines + assert!(output.contains('\n')); + } + + #[cfg(feature = "yaml_serde_fmt")] + #[test] + fn test_render_to_yaml() { + let mut r = RenderResult::default(); + let result = + StructuralRenderer::render(&test_data(), &StructuralRendererSetting::Yaml, &mut r); + assert!(result.is_ok()); + assert!(!r.is_empty()); + } + + #[cfg(feature = "toml_serde_fmt")] + #[test] + fn test_render_to_toml() { + let mut r = RenderResult::default(); + let result = + StructuralRenderer::render(&test_data(), &StructuralRendererSetting::Toml, &mut r); + assert!(result.is_ok()); + assert!(!r.is_empty()); + } + + #[cfg(feature = "ron_serde_fmt")] + #[test] + fn test_render_to_ron() { + let mut r = RenderResult::default(); + let result = + StructuralRenderer::render(&test_data(), &StructuralRendererSetting::Ron, &mut r); + assert!(result.is_ok()); + assert!(!r.is_empty()); + } + + #[cfg(feature = "ron_serde_fmt")] + #[test] + fn test_render_to_ron_pretty() { + let mut r = RenderResult::default(); + let result = + StructuralRenderer::render(&test_data(), &StructuralRendererSetting::RonPretty, &mut r); + assert!(result.is_ok()); + let output: String = r.into(); + assert!(output.contains('\n')); + } + + #[test] + fn test_render_dispatches_correct_format() { + // Test that render dispatches to the right format handler + let mut r = RenderResult::default(); + + // Disable + let result = + StructuralRenderer::render(&test_data(), &StructuralRendererSetting::Disable, &mut r); + assert!(result.is_ok()); + assert!(r.is_empty()); + } + + #[cfg(feature = "json_serde_fmt")] + #[test] + fn test_render_dispatches_json() { + let mut r = RenderResult::default(); + let result = StructuralRenderer::render(&test_data(), &StructuralRendererSetting::Json, &mut r); + assert!(result.is_ok()); + assert!(!r.is_empty()); + } +} diff --git a/mingling_core/src/renderer/structural/error.rs b/mingling_core/src/renderer/structural/error.rs new file mode 100644 index 0000000..a7fbc75 --- /dev/null +++ b/mingling_core/src/renderer/structural/error.rs @@ -0,0 +1,68 @@ +/// Represents an error that occurs during serialization of a structural renderer. +/// +/// This error stores a human-readable message describing what went wrong +/// during the serialization process. +#[derive(Debug)] +pub struct StructuralRendererSerializeError { + /// The underlying error message. + error: String, +} + +impl StructuralRendererSerializeError { + #[must_use] + pub fn new(error: String) -> Self { + Self { error } + } +} + +impl From<&str> for StructuralRendererSerializeError { + fn from(s: &str) -> Self { + Self::new(s.to_string()) + } +} + +impl std::ops::Deref for StructuralRendererSerializeError { + type Target = String; + + fn deref(&self) -> &Self::Target { + &self.error + } +} + +impl From for String { + fn from(val: StructuralRendererSerializeError) -> Self { + val.error + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn new_creates_error_with_message() { + let msg = "serialization failed".to_string(); + let err = StructuralRendererSerializeError::new(msg.clone()); + assert_eq!(err.error, msg); + } + + #[test] + fn from_str_creates_error_from_string_slice() { + let err: StructuralRendererSerializeError = "oops".into(); + assert_eq!(err.error, "oops"); + } + + #[test] + fn deref_accesses_inner_error_string() { + let err = StructuralRendererSerializeError::new("inner message".to_string()); + let derefed: &String = &err; + assert_eq!(derefed, "inner message"); + } + + #[test] + fn into_string_extracts_message() { + let err = StructuralRendererSerializeError::new("extract me".to_string()); + let s: String = err.into(); + assert_eq!(s, "extract me"); + } +} diff --git a/mingling_core/src/renderer/structural/structural_data.rs b/mingling_core/src/renderer/structural/structural_data.rs new file mode 100644 index 0000000..1cafac3 --- /dev/null +++ b/mingling_core/src/renderer/structural/structural_data.rs @@ -0,0 +1,15 @@ +use serde::Serialize; + +/// Marker trait for types that support structured output (JSON / YAML / TOML / RON). +/// +/// This trait is a **supertrait** of `serde::Serialize` and is sealed via +/// `__private::StructuralDataSealed`. It can only be implemented through: +/// +/// - `#[derive(StructuralData)]` +/// - `pack_structural!` +/// - `group_structural!` +/// +/// 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 {} -- cgit