add support for serialization of enum tagged internally via an attribute

This commit is contained in:
yoann beaugnon 2024-04-29 20:36:14 +02:00
parent 0b8a7968f1
commit f8eb0cd2a3
2 changed files with 37 additions and 12 deletions

View File

@ -362,6 +362,7 @@ fn unnamed_enum() {
fn tagged_enum() { fn tagged_enum() {
#[derive(Debug, PartialEq, YaSerialize, YaDeserialize, Default)] #[derive(Debug, PartialEq, YaSerialize, YaDeserialize, Default)]
#[yaserde(tag = "type")] #[yaserde(tag = "type")]
#[yaserde(rename = "foobar")]
enum XmlEnum { enum XmlEnum {
#[default] #[default]
#[yaserde(rename = "foo")] #[yaserde(rename = "foo")]
@ -371,25 +372,26 @@ fn tagged_enum() {
} }
#[derive(Debug, PartialEq, YaSerialize, YaDeserialize, Default)] #[derive(Debug, PartialEq, YaSerialize, YaDeserialize, Default)]
#[yaserde(rename = "base")]
struct XmlStruct { struct XmlStruct {
#[yaserde(rename = "foobar")] #[yaserde(rename = "foobar")]
foo_bar: XmlEnum, foo_bar: XmlEnum,
} }
let model = XmlEnum::Foo; let model = XmlEnum::Foo;
let content = "<base type=\"foo\"/>"; let content = "<foobar type=\"foo\" />";
// serialize_and_validate!(model, content); serialize_and_validate!(model, content);
deserialize_and_validate!(content, model, XmlEnum); deserialize_and_validate!(content, model, XmlEnum);
let model = XmlEnum::Bar; let model = XmlEnum::Bar;
let content = "<base type=\"bar\"/>"; let content = "<foobar type=\"bar\" />";
// serialize_and_validate!(model, content); serialize_and_validate!(model, content);
deserialize_and_validate!(content, model, XmlEnum); deserialize_and_validate!(content, model, XmlEnum);
let model = XmlStruct { let model = XmlStruct {
foo_bar: XmlEnum::Foo, foo_bar: XmlEnum::Foo,
}; };
let content = "<base><foobar type=\"foo\"/></base>"; let content = "<base><foobar type=\"foo\" /></base>";
// serialize_and_validate!(model, content); serialize_and_validate!(model, content);
deserialize_and_validate!(content, model, XmlStruct); deserialize_and_validate!(content, model, XmlStruct);
} }

View File

@ -26,6 +26,21 @@ pub fn serialize(
.map(|variant| -> TokenStream { .map(|variant| -> TokenStream {
let _attrs = crate::common::YaSerdeAttribute::parse(&variant.attrs); let _attrs = crate::common::YaSerdeAttribute::parse(&variant.attrs);
let add_tag = if let Some(tag) = &root_attributes.tag {
let attrs = crate::common::YaSerdeAttribute::parse(&variant.attrs);
let label = variant.ident.clone();
let element_name = attrs.xml_element_name(&variant.ident);
quote! {
match self {
#name::#label { .. } => {
let tag = ::yaserde::__xml::name::OwnedName::local(#tag);
child_attributes.push(::yaserde::__xml::attribute::OwnedAttribute::new(tag, #element_name));
}
_ => {}
}
}
} else { quote!() };
let all_fields = variant let all_fields = variant
.fields .fields
.iter() .iter()
@ -39,7 +54,7 @@ pub fn serialize(
}) })
.collect(); .collect();
attribute_fields let add_attributes : TokenStream = attribute_fields
.iter() .iter()
.map(|field| { .map(|field| {
let label = variant.ident.clone(); let label = variant.ident.clone();
@ -79,7 +94,9 @@ pub fn serialize(
} }
} }
}) })
.collect() .collect();
quote!( #add_attributes #add_tag)
}) })
.collect(); .collect();
@ -109,10 +126,16 @@ fn inner_enum_inspector(
let label_name = build_label_name(label, &variant_attrs, &root_attributes.default_namespace); let label_name = build_label_name(label, &variant_attrs, &root_attributes.default_namespace);
match variant.fields { match variant.fields {
Fields::Unit => quote! { Fields::Unit => {
&#name::#label => { if let Some(_tag) = &root_attributes.tag {
let data_event = ::yaserde::__xml::writer::XmlEvent::characters(#label_name); quote! { #name::#label => {} }
writer.write(data_event).map_err(|e| e.to_string())?; } else {
quote! {
#name::#label => {
let data_event = ::yaserde::__xml::writer::XmlEvent::characters(#label_name);
writer.write(data_event).map_err(|e| e.to_string())?;
}
}
} }
}, },
Fields::Named(ref fields) => { Fields::Named(ref fields) => {