Skip to content

Commit

Permalink
add flatten support for root elements (Enum and Structs)
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcAntoine-Arnaud committed Apr 19, 2020
1 parent 38e5d32 commit 7b53515
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 23 deletions.
68 changes: 68 additions & 0 deletions yaserde/tests/ser_flatten.rs
@@ -0,0 +1,68 @@
#[macro_use]
extern crate yaserde_derive;

use std::io::Write;
use yaserde::ser::to_string;
use yaserde::YaSerialize;

macro_rules! convert_and_validate {
($model: expr, $content: expr) => {
let data: Result<String, String> = to_string(&$model);
assert_eq!(
data,
Ok(
String::from($content)
.split("\n")
.map(|s| s.trim())
.collect::<String>()
)
);
};
}

#[test]
fn ser_root_flatten_struct() {

#[derive(YaSerialize, PartialEq, Debug)]
#[yaserde(flatten)]
pub struct Content {
binary_data: String,
string_data: String,
}

let model = Content{
binary_data: "binary".to_string(),
string_data: "string".to_string(),
};
let content = r#"<?xml version="1.0" encoding="utf-8"?><binary_data>binary</binary_data><string_data>string</string_data>"#;
convert_and_validate!(model, content);
}

#[test]
fn ser_root_flatten_enum() {
#[derive(YaSerialize, PartialEq, Debug)]
#[yaserde(flatten)]
pub enum Content {
Binary(Binary),
Data(Data),
}

#[derive(YaSerialize, PartialEq, Debug)]
pub struct Binary {
binary_data: String,
}

#[derive(YaSerialize, PartialEq, Debug)]
pub struct Data {
string_data: String,
}

let model = Content::Binary(Binary{binary_data: "binary".to_string()});
let content = r#"<?xml version="1.0" encoding="utf-8"?><Binary><binary_data>binary</binary_data></Binary>"#;
convert_and_validate!(model, content);


let model = Content::Data(Data{string_data: "string".to_string()});
let content = r#"<?xml version="1.0" encoding="utf-8"?><Data><string_data>string</string_data></Data>"#;
convert_and_validate!(model, content);
}
14 changes: 7 additions & 7 deletions yaserde_derive/src/ser/expand_enum.rs
@@ -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;
Expand All @@ -11,8 +10,7 @@ pub fn serialize(
data_enum: &DataEnum,
name: &Ident,
root: &str,
namespaces: &BTreeMap<String, String>,
default_namespace: &Option<String>,
root_attributes: &YaSerdeAttribute,
) -> TokenStream {
let write_enum_content: TokenStream = data_enum
.variants
Expand Down Expand Up @@ -224,10 +222,10 @@ pub fn serialize(
.filter_map(|x| x)
.collect();

let add_namespaces: TokenStream = namespaces
let add_namespaces: TokenStream = root_attributes.namespaces
.iter()
.map(|(prefix, namespace)| {
if let Some(dn) = default_namespace {
if let Some(dn) = &root_attributes.default_namespace {
if dn == prefix {
return Some(quote!(
.default_ns(#namespace)
Expand All @@ -241,6 +239,8 @@ pub fn serialize(
.filter_map(|x| x)
.collect();

let flatten = root_attributes.flatten;

quote! {
use xml::writer::XmlEvent;

Expand All @@ -250,7 +250,7 @@ pub fn serialize(
-> Result<(), String> {
let skip = writer.skip_start_end();

if !skip {
if !#flatten && !skip {
if let Some(label) = writer.get_start_event_name() {
let struct_start_event = XmlEvent::start_element(label.as_ref());
writer.write(struct_start_event).map_err(|e| e.to_string())?;
Expand All @@ -264,7 +264,7 @@ pub fn serialize(
#write_enum_content
}

if !skip {
if !#flatten && !skip {
let struct_end_event = XmlEvent::end_element();
writer.write(struct_end_event).map_err(|e| e.to_string())?;
}
Expand Down
18 changes: 9 additions & 9 deletions yaserde_derive/src/ser/expand_struct.rs
Expand Up @@ -2,7 +2,6 @@ use crate::attribute::*;
use crate::field_type::*;
use crate::ser::element::*;
use proc_macro2::TokenStream;
use std::collections::BTreeMap;
use std::string::ToString;
use syn::spanned::Spanned;
use syn::DataStruct;
Expand All @@ -12,8 +11,7 @@ pub fn serialize(
data_struct: &DataStruct,
name: &Ident,
root: &str,
namespaces: &BTreeMap<String, String>,
default_namespace: &Option<String>,
root_attributes: &YaSerdeAttribute,
) -> TokenStream {
let build_attributes: TokenStream = data_struct
.fields
Expand All @@ -26,7 +24,7 @@ pub fn serialize(

let label = &field.ident;

let label_name = build_label_name(&field, &field_attrs, default_namespace);
let label_name = build_label_name(&field, &field_attrs, &root_attributes.default_namespace);

get_field_type(field).and_then(|f| match f {
FieldType::FieldTypeString
Expand Down Expand Up @@ -205,10 +203,10 @@ pub fn serialize(
.filter_map(|x| x)
.collect();

let add_namespaces: TokenStream = namespaces
let add_namespaces: TokenStream = root_attributes.namespaces
.iter()
.map(|(prefix, namespace)| {
if let Some(dn) = default_namespace {
if let Some(dn) = &root_attributes.default_namespace {
if dn == prefix {
return Some(quote!(
.default_ns(#namespace)
Expand Down Expand Up @@ -239,7 +237,7 @@ pub fn serialize(
));
}

let label_name = build_label_name(&field, &field_attrs, default_namespace);
let label_name = build_label_name(&field, &field_attrs, &root_attributes.default_namespace);
let conditions = condition_generator(label, &field_attrs);

get_field_type(field).and_then(|f| match f {
Expand Down Expand Up @@ -381,6 +379,8 @@ pub fn serialize(
.filter_map(|x| x)
.collect();

let flatten = root_attributes.flatten;

quote! {
use xml::writer::XmlEvent;

Expand All @@ -390,7 +390,7 @@ pub fn serialize(
-> Result<(), String> {
let skip = writer.skip_start_end();

if !skip {
if !#flatten && !skip {
let yaserde_label = writer.get_start_event_name().unwrap_or_else(|| #root.to_string());
let struct_start_event = XmlEvent::start_element(yaserde_label.as_ref())#add_namespaces;
#build_attributes
Expand All @@ -399,7 +399,7 @@ pub fn serialize(

#struct_inspector

if !skip {
if !#flatten && !skip {
let struct_end_event = XmlEvent::end_element();
writer.write(struct_end_event).map_err(|e| e.to_string())?;
}
Expand Down
12 changes: 5 additions & 7 deletions yaserde_derive/src/ser/mod.rs
Expand Up @@ -2,7 +2,7 @@ pub mod element;
pub mod expand_enum;
pub mod expand_struct;

use crate::attribute;
use crate::attribute::YaSerdeAttribute;
use proc_macro2::TokenStream;
use syn;
use syn::Ident;
Expand All @@ -12,13 +12,13 @@ pub fn expand_derive_serialize(ast: &syn::DeriveInput) -> Result<TokenStream, St
let attrs = &ast.attrs;
let data = &ast.data;

let root_attrs = attribute::YaSerdeAttribute::parse(attrs);
let root_attrs = YaSerdeAttribute::parse(attrs);
let root = root_attrs.clone().root.unwrap_or_else(|| name.to_string());

let prefix = if root_attrs.default_namespace == root_attrs.prefix {
"".to_string()
} else {
root_attrs
root_attrs.clone()
.prefix
.map_or("".to_string(), |prefix| prefix + ":")
};
Expand All @@ -30,15 +30,13 @@ pub fn expand_derive_serialize(ast: &syn::DeriveInput) -> Result<TokenStream, St
data_struct,
name,
&root,
&root_attrs.namespaces,
&root_attrs.default_namespace,
&root_attrs,
),
syn::Data::Enum(ref data_enum) => expand_enum::serialize(
data_enum,
name,
&root,
&root_attrs.namespaces,
&root_attrs.default_namespace,
&root_attrs,
),
syn::Data::Union(ref _data_union) => unimplemented!(),
};
Expand Down

0 comments on commit 7b53515

Please sign in to comment.