From 72b8a21b4dd42afb32e9529ec85d267cfce779df Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Sat, 26 Nov 2022 14:57:12 -0800 Subject: [PATCH] Add support for elements in unnamed fields --- instant-xml-macros/src/de.rs | 46 ++++++++++++++++++++---------------- instant-xml/src/de.rs | 33 +++++++++++++------------- instant-xml/tests/unnamed.rs | 25 ++++++++++++++++++++ 3 files changed, 67 insertions(+), 37 deletions(-) diff --git a/instant-xml-macros/src/de.rs b/instant-xml-macros/src/de.rs index 7780a82..01e934d 100644 --- a/instant-xml-macros/src/de.rs +++ b/instant-xml-macros/src/de.rs @@ -249,7 +249,7 @@ fn deserialize_struct( into: &mut Option, ) -> Result<(), ::instant_xml::Error> { use ::instant_xml::de::Node; - use ::instant_xml::{Error, Id}; + use ::instant_xml::{Error, Id, Kind}; enum __Elements { #elements_enum @@ -353,9 +353,16 @@ fn named_field( if !field_meta.attribute { tokens.r#match.extend(quote!( - __Elements::#enum_name => { - let mut nested = deserializer.nested(data); - <#no_lifetime_type>::deserialize(&mut nested, &mut #enum_name)?; + __Elements::#enum_name => match <#no_lifetime_type as FromXml>::KIND { + Kind::Element(_) => { + let mut nested = deserializer.nested(data); + FromXml::deserialize(&mut nested, &mut #enum_name)?; + } + Kind::Scalar => { + let mut nested = deserializer.nested(data); + FromXml::deserialize(&mut nested, &mut #enum_name)?; + nested.ignore()?; + } }, )); } else { @@ -418,7 +425,7 @@ fn deserialize_tuple_struct( into: &mut Option, ) -> Result<(), ::instant_xml::Error> { use ::instant_xml::de::Node; - use ::instant_xml::{Error, Id}; + use ::instant_xml::{Error, Id, Kind}; #declare_values @@ -446,25 +453,24 @@ fn unnamed_field( let name = Ident::new(&format!("v{index}"), Span::call_site()); declare_values.extend(quote!( - let node = match deserializer.next() { - Some(result) => result?, - None => return Err(Error::MissingValue(&<#no_lifetime_type as FromXml>::KIND)), - }; - - let #name = match node { - Node::Open(data) => { - let mut nested = deserializer.nested(data); + let #name = match <#no_lifetime_type as FromXml>::KIND { + Kind::Element(_) => match deserializer.next() { + Some(Ok(Node::Open(data))) => { + let mut nested = deserializer.nested(data); + let mut value: Option<#no_lifetime_type> = None; + <#no_lifetime_type>::deserialize(&mut nested, &mut value)?; + value + } + Some(Ok(node)) => return Err(Error::UnexpectedNode(format!("{:?}", node))), + Some(Err(e)) => return Err(e), + None => return Err(Error::MissingValue(&<#no_lifetime_type as FromXml>::KIND)), + } + Kind::Scalar => { + let mut nested = deserializer.for_scalar(); let mut value: Option<#no_lifetime_type> = None; <#no_lifetime_type>::deserialize(&mut nested, &mut value)?; value } - Node::Text(data) => { - let mut nested = deserializer.for_node(Node::Text(data)); - let mut value: Option<#no_lifetime_type> = None; - <#no_lifetime_type>::deserialize(&mut nested, &mut value)?; - value - } - node => return Err(Error::UnexpectedNode(format!("{:?}", node))), }; )); diff --git a/instant-xml/src/de.rs b/instant-xml/src/de.rs index ca53ce9..583660e 100644 --- a/instant-xml/src/de.rs +++ b/instant-xml/src/de.rs @@ -29,27 +29,13 @@ impl<'cx, 'xml> Deserializer<'cx, 'xml> { } pub fn take_str(&mut self) -> Result<&'xml str, Error> { - let (value, element) = match self.next() { - Some(Ok(Node::AttributeValue(s))) => (s, false), - Some(Ok(Node::Text(s))) => (s, true), + match self.next() { + Some(Ok(Node::AttributeValue(s))) => Ok(s), + Some(Ok(Node::Text(s))) => Ok(s), Some(Ok(_)) => return Err(Error::ExpectedScalar), Some(Err(e)) => return Err(e), None => return Err(Error::MissingValue(&Kind::Scalar)), - }; - - if element { - match self.next() { - Some(Ok(_)) => { - return Err(Error::UnexpectedState( - "found element while expecting scalar", - )) - } - Some(Err(e)) => return Err(e), - _ => {} - } } - - Ok(value) } pub fn nested<'a>(&'a mut self, element: Element<'xml>) -> Deserializer<'a, 'xml> @@ -73,6 +59,19 @@ impl<'cx, 'xml> Deserializer<'cx, 'xml> { } } + pub fn for_scalar<'a>(&'a mut self) -> Deserializer<'a, 'xml> + where + 'cx: 'a, + { + Deserializer { + local: self.local, + prefix: self.prefix, + level: self.level, + done: self.done, + context: self.context, + } + } + pub fn for_node<'a>(&'a mut self, node: Node<'xml>) -> Deserializer<'a, 'xml> where 'cx: 'a, diff --git a/instant-xml/tests/unnamed.rs b/instant-xml/tests/unnamed.rs index b93514a..5eea8e0 100644 --- a/instant-xml/tests/unnamed.rs +++ b/instant-xml/tests/unnamed.rs @@ -10,3 +10,28 @@ fn one_number() { assert_eq!(xml, to_string(&v).unwrap()); assert_eq!(v, from_str(xml).unwrap()); } + +#[derive(Debug, Eq, FromXml, PartialEq, ToXml)] +struct OneString(String); + +#[test] +fn one_string() { + let v = OneString("f42".to_owned()); + let xml = r#"f42"#; + assert_eq!(xml, to_string(&v).unwrap()); + assert_eq!(v, from_str(xml).unwrap()); +} + +#[derive(Debug, Eq, FromXml, PartialEq, ToXml)] +struct StringElement(String, Foo); + +#[derive(Debug, Eq, FromXml, PartialEq, ToXml)] +struct Foo; + +#[test] +fn string_element() { + let v = StringElement("f42".to_owned(), Foo); + let xml = r#"f42"#; + assert_eq!(xml, to_string(&v).unwrap()); + assert_eq!(v, from_str(xml).unwrap()); +}