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>,
) -> 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<Self>,
) -> 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))),
};
));

View File

@ -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,

View File

@ -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#"<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());
}