diff --git a/crates/xml/derive/src/attrs.rs b/crates/xml/derive/src/attrs.rs index bf5bf34..bc2f732 100644 --- a/crates/xml/derive/src/attrs.rs +++ b/crates/xml/derive/src/attrs.rs @@ -59,6 +59,7 @@ pub struct FieldAttrs { pub common: TagAttrs, pub flatten: Flag, pub default: Option, + pub serialize_with: Option, #[darling(default, rename = "ty")] pub xml_ty: FieldType, } diff --git a/crates/xml/derive/src/field.rs b/crates/xml/derive/src/field.rs index db38d01..783a054 100644 --- a/crates/xml/derive/src/field.rs +++ b/crates/xml/derive/src/field.rs @@ -251,6 +251,11 @@ impl Field { pub fn tag_writer(&self) -> Option { let field_ident = self.field_ident(); let field_name = self.xml_name(); + let serializer = if let Some(serialize_with) = &self.attrs.serialize_with { + quote! { #serialize_with } + } else { + quote! { ::rustical_xml::XmlSerialize::serialize } + }; match (&self.attrs.xml_ty, self.attrs.flatten.is_present()) { (FieldType::Attr, _) => None, @@ -264,19 +269,19 @@ impl Field { }), (FieldType::Tag, true) => Some(quote! { for item in self.#field_ident.iter() { - ::rustical_xml::XmlSerialize::serialize(item, None, Some(#field_name), writer)?; + #serializer(item, None, Some(#field_name), writer)?; } }), (FieldType::Tag, false) => Some(quote! { - ::rustical_xml::XmlSerialize::serialize(&self.#field_ident, None, Some(#field_name), writer)?; + #serializer(&self.#field_ident, None, Some(#field_name), writer)?; }), (FieldType::Untagged, true) => Some(quote! { for item in self.#field_ident.iter() { - ::rustical_xml::XmlSerialize::serialize(item, None, None, writer)?; + #serializer(item, None, None, writer)?; } }), (FieldType::Untagged, false) => Some(quote! { - ::rustical_xml::XmlSerialize::serialize(&self.#field_ident, None, None, writer)?; + #serializer(&self.#field_ident, None, None, writer)?; }), // TODO: Think about what to do here (FieldType::TagName | FieldType::Namespace, _) => None, diff --git a/crates/xml/tests/se_struct.rs b/crates/xml/tests/se_struct.rs index c7b6e42..ed53f2c 100644 --- a/crates/xml/tests/se_struct.rs +++ b/crates/xml/tests/se_struct.rs @@ -1,3 +1,4 @@ +use quick_xml::Writer; use rustical_xml::{XmlRootTag, XmlSerialize, XmlSerializeRoot}; use xml_derive::XmlDeserialize; @@ -120,3 +121,32 @@ fn test_struct_vec() { "okaywow" ); } + +#[test] +fn test_struct_serialize_with() { + #[derive(Debug, XmlRootTag, XmlSerialize, PartialEq)] + #[xml(root = b"document")] + struct Document { + #[xml(serialize_with = "serialize_href")] + href: String, + } + + fn serialize_href( + val: &String, + ns: Option<&[u8]>, + tag: Option<&[u8]>, + writer: &mut Writer, + ) -> std::io::Result<()> { + val.to_uppercase().serialize(ns, tag, writer) + } + + let mut buf = Vec::new(); + let mut writer = quick_xml::Writer::new(&mut buf); + Document { + href: "okay".to_owned(), + } + .serialize_root(&mut writer) + .unwrap(); + let out = String::from_utf8(buf).unwrap(); + assert_eq!(out, "OKAY"); +}