Merge branch 'master' of github.com:media-io/yaserde into fix_default_namespace_prefix

This commit is contained in:
Marc-Antoine Arnaud 2020-04-06 14:42:33 +02:00
commit 2c632fe0ee
4 changed files with 84 additions and 49 deletions

View File

@ -18,7 +18,6 @@ pub struct Deserializer<R: Read> {
depth: usize, depth: usize,
reader: EventReader<R>, reader: EventReader<R>,
peeked: Option<XmlEvent>, peeked: Option<XmlEvent>,
is_map_value: bool,
} }
impl<'de, R: Read> Deserializer<R> { impl<'de, R: Read> Deserializer<R> {
@ -27,7 +26,6 @@ impl<'de, R: Read> Deserializer<R> {
depth: 0, depth: 0,
reader, reader,
peeked: None, peeked: None,
is_map_value: false,
} }
} }
@ -105,28 +103,16 @@ impl<'de, R: Read> Deserializer<R> {
self.depth self.depth
} }
pub fn set_map_value(&mut self) {
self.is_map_value = true;
}
pub fn unset_map_value(&mut self) -> bool {
::std::mem::replace(&mut self.is_map_value, false)
}
pub fn read_inner_value<T, F: FnOnce(&mut Self) -> Result<T, String>>( pub fn read_inner_value<T, F: FnOnce(&mut Self) -> Result<T, String>>(
&mut self, &mut self,
f: F, f: F,
) -> Result<T, String> { ) -> Result<T, String> {
if self.unset_map_value() { if let Ok(XmlEvent::StartElement { name, .. }) = self.next_event() {
if let Ok(XmlEvent::StartElement { name, .. }) = self.next_event() { let result = f(self)?;
let result = f(self)?; self.expect_end_element(&name)?;
self.expect_end_element(&name)?; Ok(result)
Ok(result)
} else {
Err("Internal error: Bad Event".to_string())
}
} else { } else {
f(self) Err("Internal error: Bad Event".to_string())
} }
} }

View File

@ -883,3 +883,56 @@ fn de_subitem_issue_12_attributes_with_sub() {
} }
); );
} }
#[test]
fn de_same_field_name_sub() {
#[derive(Default, PartialEq, Debug, YaDeserialize)]
pub struct SubStruct {
sub: Option<i32>,
}
#[derive(Default, PartialEq, Debug, YaDeserialize)]
pub struct Struct {
sub: SubStruct,
}
convert_and_validate!("<Struct><sub /></Struct>", Struct, Struct::default());
convert_and_validate!(
"<Struct><sub><sub>42</sub></sub></Struct>",
Struct,
Struct {
sub: SubStruct { sub: Some(42) }
}
);
}
#[test]
fn de_same_field_name_sub_sub() {
#[derive(Default, PartialEq, Debug, YaDeserialize)]
pub struct SubSubStruct {
sub: i32,
}
#[derive(Default, PartialEq, Debug, YaDeserialize)]
pub struct SubStruct {
sub: Option<SubSubStruct>,
}
#[derive(Default, PartialEq, Debug, YaDeserialize)]
pub struct Struct {
sub: SubStruct,
}
convert_and_validate!("<Struct><sub /></Struct>", Struct, Struct::default());
convert_and_validate!(
"<Struct><sub><sub><sub>42</sub></sub></sub></Struct>",
Struct,
Struct {
sub: SubStruct {
sub: Some(SubSubStruct { sub: 42 })
}
}
);
}

View File

@ -214,18 +214,15 @@ fn build_unnamed_visitor_calls(
Some(quote! { Some(quote! {
let visitor = #visitor_label{}; let visitor = #visitor_label{};
if let XmlEvent::StartElement {name, ..} = reader.peek()?.clone() { if let Some(namespace) = name.namespace.as_ref() {
if let Some(namespace) = name.namespace { match namespace.as_str() {
match namespace.as_str() { bad_ns => {
bad_ns => { let msg = format!("bad field namespace for {}, found {}",
let msg = format!("bad field namespace for {}, found {}", name.local_name.as_str(),
name.local_name.as_str(), bad_ns);
bad_ns); return Err(msg);
return Err(msg);
}
} }
} }
reader.set_map_value()
} }
let result = reader.read_inner_value::<#field_type, _>(|reader| { let result = reader.read_inner_value::<#field_type, _>(|reader| {
@ -248,7 +245,6 @@ fn build_unnamed_visitor_calls(
let call_struct_visitor = |struct_name, action| { let call_struct_visitor = |struct_name, action| {
Some(quote! { Some(quote! {
reader.set_map_value();
match #struct_name::deserialize(reader) { match #struct_name::deserialize(reader) {
Ok(value) => { Ok(value) => {
#action; #action;

View File

@ -179,10 +179,15 @@ pub fn parse(
let visit_struct = |struct_name: syn::Path, action: TokenStream| { let visit_struct = |struct_name: syn::Path, action: TokenStream| {
Some(quote! { Some(quote! {
#label_name => { #label_name => {
reader.set_map_value(); if depth == 0 {
let value = #struct_name::deserialize(reader)?; // Don't count current struct's StartElement as substruct's StartElement
#value_label #action; let _root = reader.next_event();
let _root = reader.next_event(); }
if let Ok(XmlEvent::StartElement { .. }) = reader.peek() {
// If substruct's start element found then deserialize substruct
let value = #struct_name::deserialize(reader)?;
#value_label #action;
}
} }
}) })
}; };
@ -493,26 +498,21 @@ fn build_call_visitor(
#label_name => { #label_name => {
let visitor = #visitor_label{}; let visitor = #visitor_label{};
if let XmlEvent::StartElement {name, ..} = reader.peek()?.clone() { if let Some(namespace) = name.namespace.as_ref() {
if let Some(namespace) = name.namespace { match namespace.as_str() {
match namespace.as_str() { #namespaces_matches
#namespaces_matches bad_ns => {
bad_ns => { let msg = format!("bad field namespace for {}, found {}", name.local_name.as_str(), bad_ns);
let msg = format!("bad field namespace for {}, found {}", name.local_name.as_str(), bad_ns); return Err(msg);
return Err(msg);
}
} }
} }
reader.set_map_value()
} }
let result = reader.read_inner_value::<#field_type, _>(|reader| { let result = reader.read_inner_value::<#field_type, _>(|reader| {
if let XmlEvent::EndElement { .. } = *reader.peek()? { if let Ok(XmlEvent::Characters(s)) = reader.peek() {
return visitor.#visitor(""); let val = visitor.#visitor(&s);
} let _event = reader.next_event()?;
val
if let Ok(XmlEvent::Characters(s)) = reader.next_event() {
visitor.#visitor(&s)
} else { } else {
Err(format!("unable to parse content for {}", #label_name)) Err(format!("unable to parse content for {}", #label_name))
} }