diff --git a/crates/xml/derive/src/field.rs b/crates/xml/derive/src/field.rs index 4cdf408..db38d01 100644 --- a/crates/xml/derive/src/field.rs +++ b/crates/xml/derive/src/field.rs @@ -252,19 +252,34 @@ impl Field { let field_ident = self.field_ident(); let field_name = self.xml_name(); - match self.attrs.xml_ty { - FieldType::Attr => None, - FieldType::Text => Some(quote! { + match (&self.attrs.xml_ty, self.attrs.flatten.is_present()) { + (FieldType::Attr, _) => None, + (FieldType::Text, true) => Some(quote! { + for item in self.#field_ident.iter() { + writer.write_event(Event::Text(BytesText::new(item)))?; + } + }), + (FieldType::Text, false) => Some(quote! { writer.write_event(Event::Text(BytesText::new(&self.#field_ident)))?; }), - FieldType::Tag => Some(quote! { + (FieldType::Tag, true) => Some(quote! { + for item in self.#field_ident.iter() { + ::rustical_xml::XmlSerialize::serialize(item, None, Some(#field_name), writer)?; + } + }), + (FieldType::Tag, false) => Some(quote! { ::rustical_xml::XmlSerialize::serialize(&self.#field_ident, None, Some(#field_name), writer)?; }), - FieldType::Untagged => Some(quote! { + (FieldType::Untagged, true) => Some(quote! { + for item in self.#field_ident.iter() { + ::rustical_xml::XmlSerialize::serialize(item, None, None, writer)?; + } + }), + (FieldType::Untagged, false) => Some(quote! { ::rustical_xml::XmlSerialize::serialize(&self.#field_ident, None, None, writer)?; }), // TODO: Think about what to do here - FieldType::TagName | FieldType::Namespace => None, + (FieldType::TagName | FieldType::Namespace, _) => None, } } } diff --git a/crates/xml/derive/src/xml_enum.rs b/crates/xml/derive/src/xml_enum.rs index 8d77083..71af739 100644 --- a/crates/xml/derive/src/xml_enum.rs +++ b/crates/xml/derive/src/xml_enum.rs @@ -121,8 +121,8 @@ impl Enum { Ok(()) } - fn attributes<'a>(&self) -> Vec<::quick_xml::events::attributes::Attribute<'a>> { - vec![] + fn attributes<'a>(&self) -> Option>> { + None } } } diff --git a/crates/xml/derive/src/xml_struct.rs b/crates/xml/derive/src/xml_struct.rs index 37309b8..f7dd8fb 100644 --- a/crates/xml/derive/src/xml_struct.rs +++ b/crates/xml/derive/src/xml_struct.rs @@ -187,7 +187,11 @@ impl NamedStruct { .filter(|field| field.attrs.xml_ty == FieldType::Untagged) .map(|field| { let field_ident = field.field_ident(); - quote! { bytes_start.extend_attributes(self.#field_ident.attributes()); } + quote! { + if let Some(attrs) = self.#field_ident.attributes() { + bytes_start.extend_attributes(attrs); + } + } }); let attributes = self @@ -219,8 +223,10 @@ impl NamedStruct { if let Some(tag) = &tag_str { let mut bytes_start = BytesStart::new(tag.to_owned()); - bytes_start.extend_attributes(self.attributes()); - #(#untagged_attributes);* + if let Some(attrs) = self.attributes() { + bytes_start.extend_attributes(attrs); + } + // #(#untagged_attributes);* writer.write_event(Event::Start(bytes_start))?; } #(#tag_writers);* @@ -230,8 +236,8 @@ impl NamedStruct { Ok(()) } - fn attributes<'a>(&self) -> Vec<::quick_xml::events::attributes::Attribute<'a>> { - vec![ #(#attributes),* ] + fn attributes<'a>(&self) -> Option>> { + Some(vec![ #(#attributes),* ]) } } } diff --git a/crates/xml/src/lib.rs b/crates/xml/src/lib.rs index a5d6811..562606e 100644 --- a/crates/xml/src/lib.rs +++ b/crates/xml/src/lib.rs @@ -51,8 +51,8 @@ impl XmlSerialize for () { } #[allow(refining_impl_trait)] - fn attributes<'a>(&self) -> Vec> { - vec![] + fn attributes<'a>(&self) -> Option>> { + None } } diff --git a/crates/xml/src/se.rs b/crates/xml/src/se.rs index 38549f2..58b9d62 100644 --- a/crates/xml/src/se.rs +++ b/crates/xml/src/se.rs @@ -11,7 +11,27 @@ pub trait XmlSerialize { writer: &mut quick_xml::Writer, ) -> std::io::Result<()>; - fn attributes<'a>(&self) -> impl IntoIterator>>; + fn attributes<'a>(&self) -> Option>>>; +} + +impl XmlSerialize for Option { + fn serialize( + &self, + ns: Option<&[u8]>, + tag: Option<&[u8]>, + writer: &mut quick_xml::Writer, + ) -> std::io::Result<()> { + if let Some(some) = self { + some.serialize(ns, tag, writer) + } else { + Ok(()) + } + } + + #[allow(refining_impl_trait)] + fn attributes<'a>(&self) -> Option>> { + None + } } pub trait XmlSerializeRoot { diff --git a/crates/xml/src/value.rs b/crates/xml/src/value.rs index 5fbd3bd..3422afb 100644 --- a/crates/xml/src/value.rs +++ b/crates/xml/src/value.rs @@ -101,7 +101,7 @@ impl XmlSerialize for T { } #[allow(refining_impl_trait)] - fn attributes<'a>(&self) -> Vec> { - vec![] + fn attributes<'a>(&self) -> Option>> { + None } } diff --git a/crates/xml/tests/se_struct.rs b/crates/xml/tests/se_struct.rs index e7b53e1..c7b6e42 100644 --- a/crates/xml/tests/se_struct.rs +++ b/crates/xml/tests/se_struct.rs @@ -97,3 +97,26 @@ fn test_struct_value_untagged() { let out = String::from_utf8(buf).unwrap(); assert_eq!(out, "okays"); } + +#[test] +fn test_struct_vec() { + #[derive(Debug, XmlRootTag, XmlSerialize, PartialEq)] + #[xml(root = b"document")] + struct Document { + #[xml(flatten)] + href: Vec, + } + + let mut buf = Vec::new(); + let mut writer = quick_xml::Writer::new(&mut buf); + Document { + href: vec!["okay".to_owned(), "wow".to_owned()], + } + .serialize_root(&mut writer) + .unwrap(); + let out = String::from_utf8(buf).unwrap(); + assert_eq!( + out, + "okaywow" + ); +}