Add support for elements in unnamed fields

This commit is contained in:
Dirkjan Ochtman 2022-11-26 14:57:12 -08:00
parent c24d2cdaac
commit 72b8a21b4d
3 changed files with 67 additions and 37 deletions

View File

@ -249,7 +249,7 @@ fn deserialize_struct(
into: &mut Option<Self>, into: &mut Option<Self>,
) -> Result<(), ::instant_xml::Error> { ) -> Result<(), ::instant_xml::Error> {
use ::instant_xml::de::Node; use ::instant_xml::de::Node;
use ::instant_xml::{Error, Id}; use ::instant_xml::{Error, Id, Kind};
enum __Elements { enum __Elements {
#elements_enum #elements_enum
@ -353,9 +353,16 @@ fn named_field(
if !field_meta.attribute { if !field_meta.attribute {
tokens.r#match.extend(quote!( tokens.r#match.extend(quote!(
__Elements::#enum_name => { __Elements::#enum_name => match <#no_lifetime_type as FromXml>::KIND {
let mut nested = deserializer.nested(data); Kind::Element(_) => {
<#no_lifetime_type>::deserialize(&mut nested, &mut #enum_name)?; 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 { } else {
@ -418,7 +425,7 @@ fn deserialize_tuple_struct(
into: &mut Option<Self>, into: &mut Option<Self>,
) -> Result<(), ::instant_xml::Error> { ) -> Result<(), ::instant_xml::Error> {
use ::instant_xml::de::Node; use ::instant_xml::de::Node;
use ::instant_xml::{Error, Id}; use ::instant_xml::{Error, Id, Kind};
#declare_values #declare_values
@ -446,25 +453,24 @@ fn unnamed_field(
let name = Ident::new(&format!("v{index}"), Span::call_site()); let name = Ident::new(&format!("v{index}"), Span::call_site());
declare_values.extend(quote!( declare_values.extend(quote!(
let node = match deserializer.next() { let #name = match <#no_lifetime_type as FromXml>::KIND {
Some(result) => result?, Kind::Element(_) => match deserializer.next() {
None => return Err(Error::MissingValue(&<#no_lifetime_type as FromXml>::KIND)), Some(Ok(Node::Open(data))) => {
}; let mut nested = deserializer.nested(data);
let mut value: Option<#no_lifetime_type> = None;
let #name = match node { <#no_lifetime_type>::deserialize(&mut nested, &mut value)?;
Node::Open(data) => { value
let mut nested = deserializer.nested(data); }
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; let mut value: Option<#no_lifetime_type> = None;
<#no_lifetime_type>::deserialize(&mut nested, &mut value)?; <#no_lifetime_type>::deserialize(&mut nested, &mut value)?;
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))),
}; };
)); ));

View File

@ -29,27 +29,13 @@ impl<'cx, 'xml> Deserializer<'cx, 'xml> {
} }
pub fn take_str(&mut self) -> Result<&'xml str, Error> { pub fn take_str(&mut self) -> Result<&'xml str, Error> {
let (value, element) = match self.next() { match self.next() {
Some(Ok(Node::AttributeValue(s))) => (s, false), Some(Ok(Node::AttributeValue(s))) => Ok(s),
Some(Ok(Node::Text(s))) => (s, true), Some(Ok(Node::Text(s))) => Ok(s),
Some(Ok(_)) => return Err(Error::ExpectedScalar), Some(Ok(_)) => return Err(Error::ExpectedScalar),
Some(Err(e)) => return Err(e), Some(Err(e)) => return Err(e),
None => return Err(Error::MissingValue(&Kind::Scalar)), 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> 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> pub fn for_node<'a>(&'a mut self, node: Node<'xml>) -> Deserializer<'a, 'xml>
where where
'cx: 'a, 'cx: 'a,

View File

@ -10,3 +10,28 @@ fn one_number() {
assert_eq!(xml, to_string(&v).unwrap()); assert_eq!(xml, to_string(&v).unwrap());
assert_eq!(v, from_str(xml).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#"<OneString>f42</OneString>"#;
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#"<StringElement>f42<Foo></Foo></StringElement>"#;
assert_eq!(xml, to_string(&v).unwrap());
assert_eq!(v, from_str(xml).unwrap());
}