xml: Implement XmlSerialize for enums

This commit is contained in:
Lennart
2024-12-27 13:53:30 +01:00
parent fc8d64220f
commit c787a6e8f3
4 changed files with 96 additions and 2 deletions

View File

@@ -172,4 +172,38 @@ impl Variant {
}
})
}
pub fn se_branch(&self) -> proc_macro2::TokenStream {
let ident = self.ident();
let variant_name = self.xml_name();
match &self.variant.fields {
Fields::Named(_) => {
panic!(
"struct variants are not supported, please use a tuple variant with a struct"
)
}
Fields::Unnamed(FieldsUnnamed { unnamed, .. }) => {
if unnamed.len() != 1 {
panic!("tuple variants should contain exactly one element");
}
quote! {
if let Self::#ident(val) = &self {
if !enum_untagged {
::rustical_xml::XmlSerialize::serialize(val, None, Some(#variant_name), writer)?;
} else {
::rustical_xml::XmlSerialize::serialize(val, None, None, writer)?;
};
}
}
}
Fields::Unit => {
quote! {
if let Self::#ident = self {
::rustical_xml::XmlSerialize::serialize(&(), ns, tag, writer)?;
}
}
}
}
}
}

View File

@@ -92,27 +92,38 @@ impl Enum {
pub fn impl_se(&self) -> proc_macro2::TokenStream {
let (impl_generics, type_generics, where_clause) = self.generics.split_for_impl();
let ident = &self.ident;
let enum_untagged = self.attrs.untagged.is_present();
let variant_serializers = self.variants.iter().map(Variant::se_branch);
// TODO: Implement attributes
quote! {
impl #impl_generics ::rustical_xml::XmlSerialize for #ident #type_generics #where_clause {
fn serialize<W: ::std::io::Write>(
&self,
ns: Option<&[u8]>,
tag: Option<&[u8]>,
writer: &mut ::quick_xml::Writer<W>
) -> ::std::io::Result<()> {
use ::quick_xml::events::{BytesEnd, BytesStart, BytesText, Event};
let tag_str = tag.map(String::from_utf8_lossy);
const enum_untagged: bool = #enum_untagged;
if let Some(tag) = &tag_str {
writer.write_event(Event::Start(BytesStart::new(tag.to_owned())))?;
let bytes_start = BytesStart::new(tag.to_owned());
writer.write_event(Event::Start(bytes_start))?;
}
#(#variant_serializers);*
if let Some(tag) = &tag_str {
writer.write_event(Event::End(BytesEnd::new(tag.to_owned())))?;
}
Ok(())
}
fn attributes<'a>(&self) -> Vec<::quick_xml::events::attributes::Attribute<'a>> {
vec![]
}
}
}
}