support root flatten deserialization

This commit is contained in:
Marc-Antoine Arnaud
2020-04-19 10:57:40 +02:00
parent 7b53515736
commit 856e271f7f
10 changed files with 297 additions and 210 deletions

View File

@@ -1,7 +1,6 @@
use crate::attribute::*;
use crate::field_type::*;
use proc_macro2::TokenStream;
use std::collections::BTreeMap;
use syn::spanned::Spanned;
use syn::DataEnum;
use syn::Fields;
@@ -11,7 +10,7 @@ pub fn parse(
data_enum: &DataEnum,
name: &Ident,
root: &str,
_namespaces: &BTreeMap<String, String>,
root_attributes: &YaSerdeAttribute,
) -> TokenStream {
let match_to_enum: TokenStream = data_enum
.variants
@@ -20,6 +19,8 @@ pub fn parse(
.filter_map(|f| f)
.collect();
let flatten = root_attributes.flatten;
quote! {
use xml::reader::XmlEvent;
use yaserde::Visitor;
@@ -47,7 +48,7 @@ pub fn parse(
match name.local_name.as_str() {
#match_to_enum
named_element => {
_named_element => {
let _root = reader.next_event();
}
}
@@ -68,6 +69,13 @@ pub fn parse(
XmlEvent::Characters(ref text_content) => {
let _root = reader.next_event();
}
XmlEvent::EndDocument => {
if #flatten {
break;
}
return Err(format!("End of document, missing some content ?"))
}
event => {
return Err(format!("unknown event {:?}", event))
}

View File

@@ -11,13 +11,13 @@ pub fn parse(
data_struct: &DataStruct,
name: &Ident,
root: &str,
prefix: &Option<String>,
namespaces: &BTreeMap<String, String>,
root_attributes: &YaSerdeAttribute,
) -> TokenStream {
let namespaces_matches: TokenStream = namespaces
let namespaces_matches: TokenStream = root_attributes
.namespaces
.iter()
.map(|(p, ns)| {
if prefix.as_ref() == Some(p) {
if root_attributes.prefix.as_ref() == Some(p) {
Some(quote!(#ns => {}))
} else {
None
@@ -199,7 +199,7 @@ pub fn parse(
&action,
&field_attrs,
label,
&namespaces,
&root_attributes.namespaces,
field.span(),
)
};
@@ -368,6 +368,8 @@ pub fn parse(
build_code_for_unused_xml_events(&call_flatten_visitors)
};
let flatten = root_attributes.flatten;
quote! {
use xml::reader::{XmlEvent, EventReader};
use xml::writer::EventWriter;
@@ -407,7 +409,6 @@ pub fn parse(
loop {
let event = reader.peek()?.to_owned();
match event {
XmlEvent::StartElement{ref name, ref attributes, ..} => {
let mut skipped = false;
@@ -443,6 +444,11 @@ pub fn parse(
#write_unused
depth -= 1;
}
XmlEvent::EndDocument => {
if #flatten {
break;
}
}
XmlEvent::Characters(ref text_content) => {
#set_text
let event = reader.next_event()?;

View File

@@ -16,16 +16,10 @@ pub fn expand_derive_deserialize(ast: &syn::DeriveInput) -> Result<TokenStream,
let root = root_attrs.clone().root.unwrap_or_else(|| name.to_string());
let impl_block = match *data {
syn::Data::Struct(ref data_struct) => expand_struct::parse(
data_struct,
name,
&root,
&root_attrs.prefix,
&root_attrs.namespaces,
),
syn::Data::Enum(ref data_enum) => {
expand_enum::parse(data_enum, name, &root, &root_attrs.namespaces)
syn::Data::Struct(ref data_struct) => {
expand_struct::parse(data_struct, name, &root, &root_attrs)
}
syn::Data::Enum(ref data_enum) => expand_enum::parse(data_enum, name, &root, &root_attrs),
syn::Data::Union(ref _data_union) => unimplemented!(),
};

View File

@@ -222,7 +222,8 @@ pub fn serialize(
.filter_map(|x| x)
.collect();
let add_namespaces: TokenStream = root_attributes.namespaces
let add_namespaces: TokenStream = root_attributes
.namespaces
.iter()
.map(|(prefix, namespace)| {
if let Some(dn) = &root_attributes.default_namespace {

View File

@@ -203,7 +203,8 @@ pub fn serialize(
.filter_map(|x| x)
.collect();
let add_namespaces: TokenStream = root_attributes.namespaces
let add_namespaces: TokenStream = root_attributes
.namespaces
.iter()
.map(|(prefix, namespace)| {
if let Some(dn) = &root_attributes.default_namespace {

View File

@@ -18,7 +18,8 @@ pub fn expand_derive_serialize(ast: &syn::DeriveInput) -> Result<TokenStream, St
let prefix = if root_attrs.default_namespace == root_attrs.prefix {
"".to_string()
} else {
root_attrs.clone()
root_attrs
.clone()
.prefix
.map_or("".to_string(), |prefix| prefix + ":")
};
@@ -26,18 +27,10 @@ pub fn expand_derive_serialize(ast: &syn::DeriveInput) -> Result<TokenStream, St
let root = format!("{}{}", prefix, root);
let impl_block = match *data {
syn::Data::Struct(ref data_struct) => expand_struct::serialize(
data_struct,
name,
&root,
&root_attrs,
),
syn::Data::Enum(ref data_enum) => expand_enum::serialize(
data_enum,
name,
&root,
&root_attrs,
),
syn::Data::Struct(ref data_struct) => {
expand_struct::serialize(data_struct, name, &root, &root_attrs)
}
syn::Data::Enum(ref data_enum) => expand_enum::serialize(data_enum, name, &root, &root_attrs),
syn::Data::Union(ref _data_union) => unimplemented!(),
};