From 559034b64aad36e2a0a6b7954b4131cc0c1987f7 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Tue, 13 Jan 2026 11:58:39 +0100 Subject: [PATCH 1/2] Add support for serializing as CDATA --- instant-xml/src/impls.rs | 43 +++++++++++++++++++++++++++++++++++ instant-xml/src/lib.rs | 2 +- instant-xml/tests/escaping.rs | 29 ++++++++++++++++++++++- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/instant-xml/src/impls.rs b/instant-xml/src/impls.rs index 49c0ad8..7dcd17b 100644 --- a/instant-xml/src/impls.rs +++ b/instant-xml/src/impls.rs @@ -873,6 +873,49 @@ impl<'xml> FromXml<'xml> for IpAddr { const KIND: Kind = Kind::Scalar; } +#[derive(Debug, PartialEq, Eq)] +pub struct CData(pub T); + +impl<'xml, T: FromXml<'xml>> FromXml<'xml> for CData { + fn matches(id: Id<'_>, field: Option>) -> bool { + T::matches(id, field) + } + + fn deserialize<'cx>( + into: &mut Self::Accumulator, + field: &'static str, + deserializer: &mut Deserializer<'cx, 'xml>, + ) -> Result<(), Error> { + if into.is_some() { + return Err(Error::DuplicateValue(field)); + } + + let mut accumulator = T::Accumulator::default(); + T::deserialize(&mut accumulator, field, deserializer)?; + *into = Some(CData(accumulator.try_done(field)?)); + Ok(()) + } + + type Accumulator = Option>; + const KIND: Kind = Kind::Scalar; +} + +impl ToXml for CData { + fn serialize( + &self, + field: Option>, + serializer: &mut Serializer, + ) -> Result<(), Error> { + DisplayToXml(self).serialize(field, serializer) + } +} + +impl fmt::Display for CData { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "", self.0) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/instant-xml/src/lib.rs b/instant-xml/src/lib.rs index ccb6f32..4cab852 100644 --- a/instant-xml/src/lib.rs +++ b/instant-xml/src/lib.rs @@ -288,7 +288,7 @@ pub mod de; mod impls; use de::Context; pub use de::Deserializer; -pub use impls::{display_to_xml, from_xml_str, OptionAccumulator}; +pub use impls::{display_to_xml, from_xml_str, CData, OptionAccumulator}; #[doc(hidden)] pub mod ser; pub use ser::Serializer; diff --git a/instant-xml/tests/escaping.rs b/instant-xml/tests/escaping.rs index 4d3de50..f862b9b 100644 --- a/instant-xml/tests/escaping.rs +++ b/instant-xml/tests/escaping.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use similar_asserts::assert_eq; -use instant_xml::{from_str, to_string, FromXml, ToXml}; +use instant_xml::{from_str, to_string, CData, FromXml, ToXml}; #[derive(Debug, PartialEq, Eq, FromXml, ToXml)] #[xml(ns("URI"))] @@ -80,3 +80,30 @@ fn simple_cdata() { "<foo>", ); } + +#[derive(Debug, PartialEq, Eq, FromXml, ToXml)] +struct SerializeCData<'a> { + #[xml(borrow)] + foo: CData>, +} + +#[test] +fn serialize_cdata() { + assert_eq!( + from_str::( + "]]>" + ) + .unwrap(), + SerializeCData { + foo: CData(Cow::Borrowed("")), + } + ); + + assert_eq!( + to_string(&SerializeCData { + foo: CData(Cow::Borrowed("")), + }) + .unwrap(), + "]]>", + ); +} From 5bd8a1e47b827ed913d903a90d05ea95b912b669 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Tue, 13 Jan 2026 11:58:53 +0100 Subject: [PATCH 2/2] Bump version to 0.6.2 --- instant-xml/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instant-xml/Cargo.toml b/instant-xml/Cargo.toml index 87224c0..c77db7a 100644 --- a/instant-xml/Cargo.toml +++ b/instant-xml/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "instant-xml" -version = "0.6.1" +version = "0.6.2" edition = "2021" rust-version = "1.68" workspace = ".."