diff --git a/yaserde/tests/de_flatten.rs b/yaserde/tests/de_flatten.rs
new file mode 100644
index 0000000..d385430
--- /dev/null
+++ b/yaserde/tests/de_flatten.rs
@@ -0,0 +1,166 @@
+#[macro_use]
+extern crate yaserde_derive;
+
+use std::io::Read;
+use yaserde::de::from_str;
+use yaserde::YaDeserialize;
+
+macro_rules! convert_and_validate {
+ ($content: expr, $struct: tt, $model: expr) => {
+ let loaded: Result<$struct, String> = from_str($content);
+ assert_eq!(loaded, Ok($model));
+ };
+}
+
+#[test]
+fn de_root_flatten_struct() {
+ #[derive(Default, PartialEq, Debug, YaDeserialize)]
+ #[yaserde(flatten)]
+ struct Content {
+ binary_data: String,
+ string_data: String,
+ }
+
+ let content = r#"
+
+ binary
+ string
+ "#;
+
+ convert_and_validate!(
+ content,
+ Content,
+ Content {
+ binary_data: "binary".to_string(),
+ string_data: "string".to_string(),
+ }
+ );
+}
+
+#[test]
+fn de_root_flatten_enum() {
+ #[derive(PartialEq, Debug, YaDeserialize)]
+ #[yaserde(flatten)]
+ pub enum Content {
+ Binary(Binary),
+ Data(Data),
+ Unknown,
+ }
+
+ impl Default for Content {
+ fn default() -> Self {
+ Content::Unknown
+ }
+ }
+
+ #[derive(Default, PartialEq, Debug, YaDeserialize)]
+ pub struct Binary {
+ binary_data: String,
+ }
+
+ #[derive(Default, PartialEq, Debug, YaDeserialize)]
+ pub struct Data {
+ string_data: String,
+ }
+
+ let content = r#"
+
+
+ binary
+
+ "#;
+
+ convert_and_validate!(
+ content,
+ Content,
+ Content::Binary(Binary {
+ binary_data: "binary".to_string(),
+ })
+ );
+}
+
+#[test]
+fn de_flatten() {
+ #[derive(Default, PartialEq, Debug, YaDeserialize)]
+ struct DateTime {
+ #[yaserde(flatten)]
+ date: Date,
+ time: String,
+ #[yaserde(flatten)]
+ kind: DateKind,
+ }
+
+ #[derive(Default, PartialEq, Debug, YaDeserialize)]
+ struct Date {
+ year: i32,
+ month: i32,
+ day: i32,
+ #[yaserde(flatten)]
+ extra: Extra,
+ #[yaserde(flatten)]
+ optional_extra: Option,
+ }
+
+ #[derive(Default, PartialEq, Debug, YaDeserialize)]
+ pub struct Extra {
+ week: i32,
+ century: i32,
+ }
+
+ #[derive(Default, PartialEq, Debug, YaDeserialize)]
+ pub struct OptionalExtra {
+ lunar_day: i32,
+ }
+
+ #[derive(PartialEq, Debug, YaDeserialize)]
+ pub enum DateKind {
+ #[yaserde(rename = "holidays")]
+ Holidays(Vec),
+ #[yaserde(rename = "working")]
+ Working,
+ }
+
+ impl Default for DateKind {
+ fn default() -> Self {
+ DateKind::Working
+ }
+ };
+
+ let content = r#"
+
+
+ 2020
+ 1
+ 1
+ 1
+ 21
+ 1
+
+ New Year's Day
+ Novy God Day
+ Polar Bear Swim Day
+
+ "#;
+ convert_and_validate!(
+ content,
+ DateTime,
+ DateTime {
+ date: Date {
+ year: 2020,
+ month: 1,
+ day: 1,
+ extra: Extra {
+ week: 1,
+ century: 21,
+ },
+ optional_extra: Some(OptionalExtra { lunar_day: 1 }),
+ },
+ time: "10:40:03".to_string(),
+ kind: DateKind::Holidays(vec![
+ "New Year's Day".into(),
+ "Novy God Day".into(),
+ "Polar Bear Swim Day".into()
+ ])
+ }
+ );
+}
diff --git a/yaserde/tests/deserializer.rs b/yaserde/tests/deserializer.rs
index 21df4c0..dd212ce 100644
--- a/yaserde/tests/deserializer.rs
+++ b/yaserde/tests/deserializer.rs
@@ -691,92 +691,6 @@ fn de_custom() {
);
}
-#[test]
-fn de_flatten() {
- #[derive(Default, PartialEq, Debug, YaDeserialize)]
- struct DateTime {
- #[yaserde(flatten)]
- date: Date,
- time: String,
- #[yaserde(flatten)]
- kind: DateKind,
- }
-
- #[derive(Default, PartialEq, Debug, YaDeserialize)]
- struct Date {
- year: i32,
- month: i32,
- day: i32,
- #[yaserde(flatten)]
- extra: Extra,
- #[yaserde(flatten)]
- optional_extra: Option,
- }
-
- #[derive(Default, PartialEq, Debug, YaDeserialize)]
- pub struct Extra {
- week: i32,
- century: i32,
- }
-
- #[derive(Default, PartialEq, Debug, YaDeserialize)]
- pub struct OptionalExtra {
- lunar_day: i32,
- }
-
- #[derive(PartialEq, Debug, YaDeserialize)]
- pub enum DateKind {
- #[yaserde(rename = "holidays")]
- Holidays(Vec),
- #[yaserde(rename = "working")]
- Working,
- }
-
- impl Default for DateKind {
- fn default() -> Self {
- DateKind::Working
- }
- };
-
- let content = r#"
-
-
- 2020
- 1
- 1
- 1
- 21
- 1
-
- New Year's Day
- Novy God Day
- Polar Bear Swim Day
-
- "#;
- convert_and_validate!(
- content,
- DateTime,
- DateTime {
- date: Date {
- year: 2020,
- month: 1,
- day: 1,
- extra: Extra {
- week: 1,
- century: 21,
- },
- optional_extra: Some(OptionalExtra { lunar_day: 1 }),
- },
- time: "10:40:03".to_string(),
- kind: DateKind::Holidays(vec![
- "New Year's Day".into(),
- "Novy God Day".into(),
- "Polar Bear Swim Day".into()
- ])
- }
- );
-}
-
#[test]
fn de_subitem_issue_12() {
#[derive(Default, PartialEq, Debug, YaDeserialize)]
diff --git a/yaserde/tests/ser_flatten.rs b/yaserde/tests/ser_flatten.rs
index 850251a..0127ed1 100644
--- a/yaserde/tests/ser_flatten.rs
+++ b/yaserde/tests/ser_flatten.rs
@@ -21,8 +21,91 @@ macro_rules! convert_and_validate {
}
#[test]
-fn ser_root_flatten_struct() {
+fn ser_flatten() {
+ #[derive(Default, PartialEq, Debug, YaSerialize)]
+ struct DateTime {
+ #[yaserde(flatten)]
+ date: Date,
+ time: String,
+ #[yaserde(flatten)]
+ kind: DateKind,
+ }
+ #[derive(Default, PartialEq, Debug, YaSerialize)]
+ struct Date {
+ year: i32,
+ month: i32,
+ day: i32,
+ #[yaserde(flatten)]
+ extra: Extra,
+ #[yaserde(flatten)]
+ optional_extra: Option,
+ }
+
+ #[derive(Default, PartialEq, Debug, YaSerialize)]
+ pub struct Extra {
+ week: i32,
+ century: i32,
+ }
+
+ #[derive(Default, PartialEq, Debug, YaSerialize)]
+ pub struct OptionalExtra {
+ lunar_day: i32,
+ }
+
+ #[derive(PartialEq, Debug, YaSerialize)]
+ pub enum DateKind {
+ #[yaserde(rename = "holidays")]
+ Holidays(Vec),
+ #[yaserde(rename = "working")]
+ Working,
+ }
+
+ impl Default for DateKind {
+ fn default() -> Self {
+ DateKind::Working
+ }
+ };
+
+ let model = DateTime {
+ date: Date {
+ year: 2020,
+ month: 1,
+ day: 1,
+ extra: Extra {
+ week: 1,
+ century: 21,
+ },
+ optional_extra: Some(OptionalExtra { lunar_day: 1 }),
+ },
+ time: "10:40:03".to_string(),
+ kind: DateKind::Holidays(vec![
+ "New Year's Day".into(),
+ "Novy God Day".into(),
+ "Polar Bear Swim Day".into(),
+ ]),
+ };
+
+ let content = r#"
+
+
+ 2020
+ 1
+ 1
+ 1
+ 21
+ 1
+
+ New Year's Day
+ Novy God Day
+ Polar Bear Swim Day
+ "#;
+
+ convert_and_validate!(model, content);
+}
+
+#[test]
+fn ser_root_flatten_struct() {
#[derive(YaSerialize, PartialEq, Debug)]
#[yaserde(flatten)]
pub struct Content {
@@ -30,7 +113,7 @@ fn ser_root_flatten_struct() {
string_data: String,
}
- let model = Content{
+ let model = Content {
binary_data: "binary".to_string(),
string_data: "string".to_string(),
};
@@ -57,12 +140,17 @@ fn ser_root_flatten_enum() {
string_data: String,
}
- let model = Content::Binary(Binary{binary_data: "binary".to_string()});
- let content = r#"binary"#;
+ let model = Content::Binary(Binary {
+ binary_data: "binary".to_string(),
+ });
+ let content =
+ r#"binary"#;
convert_and_validate!(model, content);
-
- let model = Content::Data(Data{string_data: "string".to_string()});
- let content = r#"string"#;
+ let model = Content::Data(Data {
+ string_data: "string".to_string(),
+ });
+ let content =
+ r#"string"#;
convert_and_validate!(model, content);
}
diff --git a/yaserde/tests/serializer.rs b/yaserde/tests/serializer.rs
index 0e1e8a1..c3ff11b 100644
--- a/yaserde/tests/serializer.rs
+++ b/yaserde/tests/serializer.rs
@@ -329,87 +329,3 @@ fn ser_custom() {
let content = "2020110";
convert_and_validate!(model, content);
}
-
-#[test]
-fn ser_flatten() {
- #[derive(Default, PartialEq, Debug, YaSerialize)]
- struct DateTime {
- #[yaserde(flatten)]
- date: Date,
- time: String,
- #[yaserde(flatten)]
- kind: DateKind,
- }
-
- #[derive(Default, PartialEq, Debug, YaSerialize)]
- struct Date {
- year: i32,
- month: i32,
- day: i32,
- #[yaserde(flatten)]
- extra: Extra,
- #[yaserde(flatten)]
- optional_extra: Option,
- }
-
- #[derive(Default, PartialEq, Debug, YaSerialize)]
- pub struct Extra {
- week: i32,
- century: i32,
- }
-
- #[derive(Default, PartialEq, Debug, YaSerialize)]
- pub struct OptionalExtra {
- lunar_day: i32,
- }
-
- #[derive(PartialEq, Debug, YaSerialize)]
- pub enum DateKind {
- #[yaserde(rename = "holidays")]
- Holidays(Vec),
- #[yaserde(rename = "working")]
- Working,
- }
-
- impl Default for DateKind {
- fn default() -> Self {
- DateKind::Working
- }
- };
-
- let model = DateTime {
- date: Date {
- year: 2020,
- month: 1,
- day: 1,
- extra: Extra {
- week: 1,
- century: 21,
- },
- optional_extra: Some(OptionalExtra { lunar_day: 1 }),
- },
- time: "10:40:03".to_string(),
- kind: DateKind::Holidays(vec![
- "New Year's Day".into(),
- "Novy God Day".into(),
- "Polar Bear Swim Day".into(),
- ]),
- };
-
- let content = r#"
-
-
- 2020
- 1
- 1
- 1
- 21
- 1
-
- New Year's Day
- Novy God Day
- Polar Bear Swim Day
- "#;
-
- convert_and_validate!(model, content);
-}
diff --git a/yaserde_derive/src/de/expand_enum.rs b/yaserde_derive/src/de/expand_enum.rs
index 4fdb0ed..c43d246 100644
--- a/yaserde_derive/src/de/expand_enum.rs
+++ b/yaserde_derive/src/de/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;
@@ -11,7 +10,7 @@ pub fn parse(
data_enum: &DataEnum,
name: &Ident,
root: &str,
- _namespaces: &BTreeMap,
+ 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))
}
diff --git a/yaserde_derive/src/de/expand_struct.rs b/yaserde_derive/src/de/expand_struct.rs
index 1f1d51e..3c48215 100644
--- a/yaserde_derive/src/de/expand_struct.rs
+++ b/yaserde_derive/src/de/expand_struct.rs
@@ -11,13 +11,13 @@ pub fn parse(
data_struct: &DataStruct,
name: &Ident,
root: &str,
- prefix: &Option,
- namespaces: &BTreeMap,
+ 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()?;
diff --git a/yaserde_derive/src/de/mod.rs b/yaserde_derive/src/de/mod.rs
index 4e3e8ab..84f1f17 100644
--- a/yaserde_derive/src/de/mod.rs
+++ b/yaserde_derive/src/de/mod.rs
@@ -16,16 +16,10 @@ pub fn expand_derive_deserialize(ast: &syn::DeriveInput) -> Result 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!(),
};
diff --git a/yaserde_derive/src/ser/expand_enum.rs b/yaserde_derive/src/ser/expand_enum.rs
index f776d49..a357272 100644
--- a/yaserde_derive/src/ser/expand_enum.rs
+++ b/yaserde_derive/src/ser/expand_enum.rs
@@ -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 {
diff --git a/yaserde_derive/src/ser/expand_struct.rs b/yaserde_derive/src/ser/expand_struct.rs
index 38c2ce0..83bbd19 100644
--- a/yaserde_derive/src/ser/expand_struct.rs
+++ b/yaserde_derive/src/ser/expand_struct.rs
@@ -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 {
diff --git a/yaserde_derive/src/ser/mod.rs b/yaserde_derive/src/ser/mod.rs
index 8df059e..dec8dfa 100644
--- a/yaserde_derive/src/ser/mod.rs
+++ b/yaserde_derive/src/ser/mod.rs
@@ -18,7 +18,8 @@ pub fn expand_derive_serialize(ast: &syn::DeriveInput) -> Result Result 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!(),
};