diff --git a/yaserde/tests/enum.rs b/yaserde/tests/enum.rs index 95991bd..dd2e5fa 100644 --- a/yaserde/tests/enum.rs +++ b/yaserde/tests/enum.rs @@ -357,3 +357,39 @@ 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")] + enum XmlEnum { + #[default] + #[yaserde(rename = "foo")] + Foo, + #[yaserde(rename = "bar")] + Bar, + } + + #[derive(Debug, PartialEq, YaSerialize, YaDeserialize, Default)] + struct XmlStruct { + #[yaserde(rename = "foobar")] + foo_bar: XmlEnum, + } + + let model = XmlEnum::Foo; + let content = ""; + // serialize_and_validate!(model, content); + deserialize_and_validate!(content, model, XmlEnum); + + let model = XmlEnum::Bar; + let content = ""; + // serialize_and_validate!(model, content); + deserialize_and_validate!(content, model, XmlEnum); + + let model = XmlStruct { + foo_bar: XmlEnum::Foo, + }; + let content = ""; + // serialize_and_validate!(model, content); + deserialize_and_validate!(content, model, XmlStruct); +} diff --git a/yaserde_derive/src/common/attribute.rs b/yaserde_derive/src/common/attribute.rs index be4361f..bf5bcdb 100644 --- a/yaserde_derive/src/common/attribute.rs +++ b/yaserde_derive/src/common/attribute.rs @@ -12,6 +12,7 @@ pub struct YaSerdeAttribute { pub namespaces: BTreeMap, String>, pub prefix: Option, pub rename: Option, + pub tag: Option, pub skip_serializing: bool, pub skip_serializing_if: Option, pub text: bool, @@ -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; @@ -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; } @@ -107,6 +112,7 @@ impl YaSerdeAttribute { namespaces, prefix, rename, + tag, skip_serializing, skip_serializing_if, text, @@ -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, @@ -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, @@ -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, @@ -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, diff --git a/yaserde_derive/src/de/expand_enum.rs b/yaserde_derive/src/de/expand_enum.rs index a8994f9..5a41c57 100644 --- a/yaserde_derive/src/de/expand_enum.rs +++ b/yaserde_derive/src/de/expand_enum.rs @@ -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)] @@ -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();