Skip to content

Commit

Permalink
Merge pull request #182 from YBeaugnon/main
Browse files Browse the repository at this point in the history
Support for internally tagged enum
  • Loading branch information
MarcAntoine-Arnaud authored May 29, 2024
2 parents f5cb114 + f8eb0cd commit 177fa8e
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 7 deletions.
38 changes: 38 additions & 0 deletions yaserde/tests/enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,3 +357,41 @@ fn unnamed_enum() {
serialize_and_validate!(model, content);
deserialize_and_validate!(content, model, XmlStruct);
}

#[test]
fn tagged_enum() {
#[derive(Debug, PartialEq, YaSerialize, YaDeserialize, Default)]
#[yaserde(tag = "type")]
#[yaserde(rename = "foobar")]
enum XmlEnum {
#[default]
#[yaserde(rename = "foo")]
Foo,
#[yaserde(rename = "bar")]
Bar,
}

#[derive(Debug, PartialEq, YaSerialize, YaDeserialize, Default)]
#[yaserde(rename = "base")]
struct XmlStruct {
#[yaserde(rename = "foobar")]
foo_bar: XmlEnum,
}

let model = XmlEnum::Foo;
let content = "<foobar type=\"foo\" />";
serialize_and_validate!(model, content);
deserialize_and_validate!(content, model, XmlEnum);

let model = XmlEnum::Bar;
let content = "<foobar type=\"bar\" />";
serialize_and_validate!(model, content);
deserialize_and_validate!(content, model, XmlEnum);

let model = XmlStruct {
foo_bar: XmlEnum::Foo,
};
let content = "<base><foobar type=\"foo\" /></base>";
serialize_and_validate!(model, content);
deserialize_and_validate!(content, model, XmlStruct);
}
10 changes: 10 additions & 0 deletions yaserde_derive/src/common/attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub struct YaSerdeAttribute {
pub namespaces: BTreeMap<Option<String>, String>,
pub prefix: Option<String>,
pub rename: Option<String>,
pub tag: Option<String>,
pub skip_serializing: bool,
pub skip_serializing_if: Option<String>,
pub text: bool,
Expand Down Expand Up @@ -40,6 +41,7 @@ impl YaSerdeAttribute {
let mut namespaces = BTreeMap::new();
let mut prefix = None;
let mut rename = None;
let mut tag = None;
let mut skip_serializing = false;
let mut skip_serializing_if = None;
let mut text = false;
Expand Down Expand Up @@ -82,6 +84,9 @@ impl YaSerdeAttribute {
"rename" => {
rename = get_value(&mut attr_iter);
}
"tag" => {
tag = get_value(&mut attr_iter);
}
"skip_serializing" => {
skip_serializing = true;
}
Expand All @@ -107,6 +112,7 @@ impl YaSerdeAttribute {
namespaces,
prefix,
rename,
tag,
skip_serializing,
skip_serializing_if,
text,
Expand Down Expand Up @@ -182,6 +188,7 @@ fn parse_empty_attributes() {
namespaces: BTreeMap::new(),
prefix: None,
rename: None,
tag: None,
skip_serializing: false,
skip_serializing_if: None,
text: false,
Expand Down Expand Up @@ -232,6 +239,7 @@ fn parse_attributes() {
namespaces: BTreeMap::new(),
prefix: None,
rename: None,
tag: None,
skip_serializing: false,
skip_serializing_if: None,
text: false,
Expand Down Expand Up @@ -282,6 +290,7 @@ fn only_parse_yaserde_attributes() {
namespaces: BTreeMap::new(),
prefix: None,
rename: None,
tag: None,
skip_serializing: false,
skip_serializing_if: None,
text: false,
Expand Down Expand Up @@ -338,6 +347,7 @@ fn parse_attributes_with_values() {
namespaces,
prefix: None,
rename: None,
tag: None,
skip_serializing: false,
skip_serializing_if: None,
text: false,
Expand Down
16 changes: 15 additions & 1 deletion yaserde_derive/src/de/expand_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,20 @@ pub fn parse(

let flatten = root_attributes.flatten;

let element_name = if let Some(tag) = &root_attributes.tag {
quote! {
attributes
.iter()
.find(|attr| attr.name.local_name.as_str() == #tag)
.ok_or(format!("Expected enum tagged with {}, found {:?}", #tag, event))?
.value.as_str()
}
} else {
quote! {
name.local_name.as_str()
}
};

quote! {
impl ::yaserde::YaDeserialize for #name {
#[allow(unused_variables)]
Expand All @@ -50,7 +64,7 @@ pub fn parse(
::yaserde::__derive_trace!("Enum {} @ {}: matching {:?}", stringify!(#name), start_depth, event);
match event {
::yaserde::__xml::reader::XmlEvent::StartElement { ref name, ref attributes, .. } => {
match name.local_name.as_str() {
match #element_name {
#match_to_enum
_named_element => {
let _root = reader.next_event();
Expand Down
35 changes: 29 additions & 6 deletions yaserde_derive/src/ser/expand_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,21 @@ pub fn serialize(
.map(|variant| -> TokenStream {
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
.fields
.iter()
Expand All @@ -39,7 +54,7 @@ pub fn serialize(
})
.collect();

attribute_fields
let add_attributes : TokenStream = attribute_fields
.iter()
.map(|field| {
let label = variant.ident.clone();
Expand Down Expand Up @@ -79,7 +94,9 @@ pub fn serialize(
}
}
})
.collect()
.collect();

quote!( #add_attributes #add_tag)
})
.collect();

Expand Down Expand Up @@ -109,10 +126,16 @@ fn inner_enum_inspector(
let label_name = build_label_name(label, &variant_attrs, &root_attributes.default_namespace);

match variant.fields {
Fields::Unit => quote! {
&#name::#label => {
let data_event = ::yaserde::__xml::writer::XmlEvent::characters(#label_name);
writer.write(data_event).map_err(|e| e.to_string())?;
Fields::Unit => {
if let Some(_tag) = &root_attributes.tag {
quote! { #name::#label => {} }
} 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) => {
Expand Down

0 comments on commit 177fa8e

Please sign in to comment.