diff --git a/yaserde/src/lib.rs b/yaserde/src/lib.rs
index 8796731..6eedc66 100644
--- a/yaserde/src/lib.rs
+++ b/yaserde/src/lib.rs
@@ -137,3 +137,76 @@ fn default_visitor() {
test_type!(visit_u64, "Unexpected u64 \"\"");
test_type!(visit_str, "Unexpected str \"\"");
}
+
+#[doc(hidden)]
+mod testing {
+ #[macro_export]
+ macro_rules! test_for_type {
+ ($type:ty, $value:expr, $content:expr) => {{
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(rename = "data")]
+ pub struct Data {
+ item: $type,
+ }
+
+ let model = Data { item: $value };
+
+ let content = if let Some(str_value) = $content {
+ String::from("- ") + str_value + "
"
+ } else {
+ String::from("")
+ };
+
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(&content, model, Data);
+ }};
+ }
+
+ #[macro_export]
+ macro_rules! test_for_attribute_type {
+ ($type: ty, $value: expr, $content: expr) => {{
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(rename = "data")]
+ pub struct Data {
+ #[yaserde(attribute)]
+ item: $type,
+ }
+ let model = Data { item: $value };
+
+ let content = if let Some(str_value) = $content {
+ ""
+ } else {
+ "".to_string()
+ };
+
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(&content, model, Data);
+ }};
+ }
+
+ #[macro_export]
+ macro_rules! deserialize_and_validate {
+ ($content: expr, $model: expr, $struct: tt) => {
+ let loaded: Result<$struct, String> = yaserde::de::from_str($content);
+ assert_eq!(loaded, Ok($model));
+ };
+ }
+
+ #[macro_export]
+ macro_rules! serialize_and_validate {
+ ($model: expr, $content: expr) => {
+ let data: Result = yaserde::ser::to_string(&$model);
+
+ let content = String::from(r#""#) + &$content;
+ assert_eq!(
+ data,
+ Ok(
+ String::from(content)
+ .split("\n")
+ .map(|s| s.trim())
+ .collect::()
+ )
+ );
+ };
+ }
+}
diff --git a/yaserde/tests/de_default.rs b/yaserde/tests/de_default.rs
deleted file mode 100644
index bb0c406..0000000
--- a/yaserde/tests/de_default.rs
+++ /dev/null
@@ -1,93 +0,0 @@
-#[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_default_field_string() {
- fn default_string() -> String {
- "my_default_value".to_string()
- }
-
- #[derive(YaDeserialize, PartialEq, Debug)]
- #[yaserde(root = "base")]
- pub struct XmlStruct {
- #[yaserde(default = "default_string")]
- background: String,
- }
-
- let content = "";
- convert_and_validate!(
- content,
- XmlStruct,
- XmlStruct {
- background: "my_default_value".to_string(),
- }
- );
-}
-
-#[test]
-fn de_default_field_boolean() {
- fn default_boolean() -> bool {
- true
- }
-
- #[derive(YaDeserialize, PartialEq, Debug)]
- #[yaserde(root = "base")]
- pub struct XmlStruct {
- #[yaserde(default = "default_boolean")]
- background: bool,
- }
-
- let content = "";
- convert_and_validate!(content, XmlStruct, XmlStruct { background: true });
-}
-
-#[test]
-fn de_default_field_number() {
- fn default_number() -> u8 {
- 6
- }
-
- #[derive(YaDeserialize, PartialEq, Debug)]
- #[yaserde(root = "base")]
- pub struct XmlStruct {
- #[yaserde(default = "default_number")]
- background: u8,
- }
-
- let content = "";
- convert_and_validate!(content, XmlStruct, XmlStruct { background: 6 });
-}
-
-#[test]
-fn de_default_attribute_string() {
- fn default_string() -> String {
- "my_default_value".to_string()
- }
-
- #[derive(YaDeserialize, PartialEq, Debug)]
- #[yaserde(root = "base")]
- pub struct XmlStruct {
- #[yaserde(attribute, default = "default_string")]
- background: String,
- }
-
- let content = "";
- convert_and_validate!(
- content,
- XmlStruct,
- XmlStruct {
- background: "my_default_value".to_string(),
- }
- );
-}
diff --git a/yaserde/tests/de_flatten.rs b/yaserde/tests/de_flatten.rs
deleted file mode 100644
index d385430..0000000
--- a/yaserde/tests/de_flatten.rs
+++ /dev/null
@@ -1,166 +0,0 @@
-#[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/de_namespace.rs b/yaserde/tests/de_namespace.rs
deleted file mode 100644
index dd3d94c..0000000
--- a/yaserde/tests/de_namespace.rs
+++ /dev/null
@@ -1,144 +0,0 @@
-#[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_struct_namespace() {
- #[derive(YaDeserialize, PartialEq, Debug)]
- #[yaserde(
- root = "book",
- prefix = "ns",
- namespace = "ns: http://www.sample.com/ns/domain",
- namespace = "ns2: http://www.sample.com/ns/domain_2"
- )]
- pub struct Book {
- #[yaserde(prefix = "ns")]
- author: String,
- #[yaserde(prefix = "ns2")]
- title: String,
- }
-
- let content = r#"
-
- Antoine de Saint-Exupéry
- Little prince
-
- "#;
- convert_and_validate!(
- content,
- Book,
- Book {
- author: String::from("Antoine de Saint-Exupéry"),
- title: String::from("Little prince"),
- }
- );
-
- let content = r#"
-
- Antoine de Saint-Exupéry
- Little prince
-
- "#;
- convert_and_validate!(
- content,
- Book,
- Book {
- author: String::from("Antoine de Saint-Exupéry"),
- title: String::from("Little prince"),
- }
- );
-
- let content = r#"
-
- Antoine de Saint-Exupéry
- Little prince
-
- "#;
- convert_and_validate!(
- content,
- Book,
- Book {
- author: String::from("Antoine de Saint-Exupéry"),
- title: String::from("Little prince"),
- }
- );
-
- let content = r#"
-
- Antoine de Saint-Exupéry
- Little prince
- "#;
- let loaded: Result = from_str(content);
- assert_eq!(
- loaded,
- Err("bad namespace for book, found http://www.sample.com/ns/domain2".to_string())
- );
-}
-
-#[test]
-fn de_struct_namespace_nested() {
- #[derive(YaDeserialize, Default, PartialEq, Debug)]
- #[yaserde(prefix = "nsa", namespace = "nsa: http://www.sample.com/ns/a")]
- struct A {
- #[yaserde(prefix = "nsa")]
- alpha: i32,
- }
-
- #[derive(YaDeserialize, Default, PartialEq, Debug)]
- #[yaserde(prefix = "nsb", namespace = "nsb: http://www.sample.com/ns/b")]
- struct B {
- // Note that name `nested` resides in `nsb` though it has a type from `nsa`
- #[yaserde(prefix = "nsb")]
- nested: A,
- }
-
- convert_and_validate!(
- r#"
-
-
-
- 32
-
-
- "#,
- B,
- B {
- nested: A { alpha: 32 }
- }
- );
-}
-
-#[test]
-fn de_enum_namespace() {
- #[derive(YaDeserialize, PartialEq, Debug)]
- #[yaserde(
- root = "root",
- prefix = "ns",
- namespace = "ns: http://www.sample.com/ns/domain"
- )]
- pub enum XmlStruct {
- #[yaserde(prefix = "ns")]
- Item,
- }
-
- impl Default for XmlStruct {
- fn default() -> XmlStruct {
- XmlStruct::Item
- }
- }
-
- let content = "ns:Item";
- convert_and_validate!(content, XmlStruct, XmlStruct::Item);
-}
diff --git a/yaserde/tests/de_option.rs b/yaserde/tests/de_option.rs
deleted file mode 100644
index a986ce4..0000000
--- a/yaserde/tests/de_option.rs
+++ /dev/null
@@ -1,144 +0,0 @@
-#[macro_use]
-extern crate yaserde_derive;
-
-use std::io::Read;
-use yaserde::de::from_str;
-use yaserde::YaDeserialize;
-
-macro_rules! convert_and_validate {
- ($type: ty, $value: expr, $content: expr) => {{
- #[derive(YaDeserialize, PartialEq, Debug)]
- #[yaserde(root = "data")]
- pub struct Data {
- item: Option<$type>,
- }
-
- let model = Data { item: $value };
-
- let source = if let Some(content) = $content {
- String::from("- ")
- + content
- + "
"
- } else {
- String::from("")
- };
-
- let loaded: Result = from_str(&source);
- assert_eq!(loaded, Ok(model));
- }};
-}
-
-macro_rules! convert_and_validate_for_attribute {
- ($type: ty, $value: expr, $content: expr) => {{
- #[derive(YaDeserialize, PartialEq, Debug)]
- #[yaserde(root = "data")]
- pub struct Data {
- #[yaserde(attribute)]
- item: Option<$type>,
- }
-
- let model = Data { item: $value };
-
- let source = if let Some(content) = $content {
- String::from(""
- } else {
- String::from("")
- };
-
- let loaded: Result = from_str(&source);
- assert_eq!(loaded, Ok(model));
- }};
-}
-
-#[test]
-fn de_option() {
- convert_and_validate!(String, Some("test".to_string()), Some("test"));
- convert_and_validate!(String, None, None);
- convert_and_validate!(bool, Some(true), Some("true"));
- convert_and_validate!(bool, None, None);
- convert_and_validate!(u8, Some(12 as u8), Some("12"));
- convert_and_validate!(u8, None, None);
- convert_and_validate!(i8, Some(12 as i8), Some("12"));
- convert_and_validate!(i8, Some(-12 as i8), Some("-12"));
- convert_and_validate!(i8, None, None);
- convert_and_validate!(u16, Some(12 as u16), Some("12"));
- convert_and_validate!(u16, None, None);
- convert_and_validate!(i16, Some(12 as i16), Some("12"));
- convert_and_validate!(i16, Some(-12 as i16), Some("-12"));
- convert_and_validate!(i16, None, None);
- convert_and_validate!(u32, Some(12 as u32), Some("12"));
- convert_and_validate!(u32, None, None);
- convert_and_validate!(i32, Some(12 as i32), Some("12"));
- convert_and_validate!(i32, Some(-12 as i32), Some("-12"));
- convert_and_validate!(i32, None, None);
- convert_and_validate!(u64, Some(12 as u64), Some("12"));
- convert_and_validate!(u64, None, None);
- convert_and_validate!(i64, Some(12 as i64), Some("12"));
- convert_and_validate!(i64, Some(-12 as i64), Some("-12"));
- convert_and_validate!(i64, None, None);
- convert_and_validate!(f32, Some(-12.5_f32 as f32), Some("-12.5"));
- convert_and_validate!(f32, None, None);
- convert_and_validate!(f64, Some(-12.5 as f64), Some("-12.5"));
- convert_and_validate!(f64, None, None);
-
- convert_and_validate_for_attribute!(String, Some("test".to_string()), Some("test"));
- convert_and_validate_for_attribute!(String, None, None);
- convert_and_validate_for_attribute!(bool, Some(true), Some("true"));
- convert_and_validate_for_attribute!(bool, None, None);
- convert_and_validate_for_attribute!(u8, Some(12 as u8), Some("12"));
- convert_and_validate_for_attribute!(u8, None, None);
- convert_and_validate_for_attribute!(i8, Some(12 as i8), Some("12"));
- convert_and_validate_for_attribute!(i8, Some(-12 as i8), Some("-12"));
- convert_and_validate_for_attribute!(i8, None, None);
- convert_and_validate_for_attribute!(u16, Some(12 as u16), Some("12"));
- convert_and_validate_for_attribute!(u16, None, None);
- convert_and_validate_for_attribute!(i16, Some(12 as i16), Some("12"));
- convert_and_validate_for_attribute!(i16, Some(-12 as i16), Some("-12"));
- convert_and_validate_for_attribute!(i16, None, None);
- convert_and_validate_for_attribute!(u32, Some(12 as u32), Some("12"));
- convert_and_validate_for_attribute!(u32, None, None);
- convert_and_validate_for_attribute!(i32, Some(12 as i32), Some("12"));
- convert_and_validate_for_attribute!(i32, Some(-12 as i32), Some("-12"));
- convert_and_validate_for_attribute!(i32, None, None);
- convert_and_validate_for_attribute!(u64, Some(12 as u64), Some("12"));
- convert_and_validate_for_attribute!(u64, None, None);
- convert_and_validate_for_attribute!(i64, Some(12 as i64), Some("12"));
- convert_and_validate_for_attribute!(i64, Some(-12 as i64), Some("-12"));
- convert_and_validate_for_attribute!(i64, None, None);
- convert_and_validate_for_attribute!(f32, Some(-12.5 as f32), Some("-12.5"));
- convert_and_validate_for_attribute!(f32, None, None);
- convert_and_validate_for_attribute!(f64, Some(-12.5 as f64), Some("-12.5"));
- convert_and_validate_for_attribute!(f64, None, None);
-}
-
-#[test]
-fn de_option_struct() {
- #[derive(YaDeserialize, Debug, PartialEq)]
- struct Test {
- field: SubTest,
- }
-
- #[derive(YaDeserialize, Debug, PartialEq)]
- struct SubTest {
- content: Option,
- }
-
- impl Default for SubTest {
- fn default() -> Self {
- SubTest { content: None }
- }
- }
-
- convert_and_validate!(
- Test,
- Some(Test {
- field: SubTest {
- content: Some("value".to_string())
- }
- }),
- Some("value")
- );
- convert_and_validate!(Test, None, None);
-}
diff --git a/yaserde/tests/de_type.rs b/yaserde/tests/de_type.rs
deleted file mode 100644
index b8775da..0000000
--- a/yaserde/tests/de_type.rs
+++ /dev/null
@@ -1,81 +0,0 @@
-#[macro_use]
-extern crate yaserde_derive;
-
-use std::io::Read;
-use yaserde::de::from_str;
-use yaserde::YaDeserialize;
-
-macro_rules! convert_and_validate {
- ($type:ty, $value:expr, $content:expr) => {{
- #[derive(YaDeserialize, PartialEq, Debug)]
- #[yaserde(root = "data")]
- pub struct Data {
- item: $type,
- }
-
- let model = Data { item: $value };
-
- let content = String::from("- ")
- + $content
- + "
";
-
- let loaded: Result = from_str(&content);
- assert_eq!(loaded, Ok(model));
- }};
-}
-
-macro_rules! convert_and_validate_for_attribute {
- ($type:ty, $value:expr, $content:expr) => {{
- #[derive(YaDeserialize, PartialEq, Debug)]
- #[yaserde(root = "data")]
- pub struct Data {
- #[yaserde(attribute)]
- item: $type,
- }
-
- let model = Data { item: $value };
-
- let content =
- String::from("";
-
- let loaded: Result = from_str(&content);
- assert_eq!(loaded, Ok(model));
- }};
-}
-
-#[test]
-fn de_type() {
- convert_and_validate!(String, "test".to_string(), "test");
- convert_and_validate!(bool, true, "true");
- convert_and_validate!(u8, 12 as u8, "12");
- convert_and_validate!(i8, 12 as i8, "12");
- convert_and_validate!(i8, -12 as i8, "-12");
- convert_and_validate!(u16, 12 as u16, "12");
- convert_and_validate!(i16, 12 as i16, "12");
- convert_and_validate!(i16, -12 as i16, "-12");
- convert_and_validate!(u32, 12 as u32, "12");
- convert_and_validate!(i32, 12 as i32, "12");
- convert_and_validate!(i32, -12 as i32, "-12");
- convert_and_validate!(u64, 12 as u64, "12");
- convert_and_validate!(i64, 12 as i64, "12");
- convert_and_validate!(i64, -12 as i64, "-12");
- convert_and_validate!(f32, -12.5_f32 as f32, "-12.5");
- convert_and_validate!(f64, -12.5 as f64, "-12.5");
-
- convert_and_validate_for_attribute!(String, "test".to_string(), "test");
- convert_and_validate_for_attribute!(bool, true, "true");
- convert_and_validate_for_attribute!(u8, 12 as u8, "12");
- convert_and_validate_for_attribute!(i8, 12 as i8, "12");
- convert_and_validate_for_attribute!(i8, -12 as i8, "-12");
- convert_and_validate_for_attribute!(u16, 12 as u16, "12");
- convert_and_validate_for_attribute!(i16, 12 as i16, "12");
- convert_and_validate_for_attribute!(i16, -12 as i16, "-12");
- convert_and_validate_for_attribute!(u32, 12 as u32, "12");
- convert_and_validate_for_attribute!(i32, 12 as i32, "12");
- convert_and_validate_for_attribute!(i32, -12 as i32, "-12");
- convert_and_validate_for_attribute!(u64, 12 as u64, "12");
- convert_and_validate_for_attribute!(i64, 12 as i64, "12");
- convert_and_validate_for_attribute!(i64, -12 as i64, "-12");
- convert_and_validate_for_attribute!(f32, -12.5 as f32, "-12.5");
- convert_and_validate_for_attribute!(f64, -12.5 as f64, "-12.5");
-}
diff --git a/yaserde/tests/default.rs b/yaserde/tests/default.rs
new file mode 100644
index 0000000..c4ba308
--- /dev/null
+++ b/yaserde/tests/default.rs
@@ -0,0 +1,112 @@
+#[macro_use]
+extern crate yaserde;
+#[macro_use]
+extern crate yaserde_derive;
+
+use std::io::{Read, Write};
+use yaserde::{YaDeserialize, YaSerialize};
+
+#[test]
+fn default_field_string() {
+ fn default_string() -> String {
+ "my_default_value".to_string()
+ }
+
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(rename = "base")]
+ pub struct XmlStruct {
+ #[yaserde(default = "default_string")]
+ background: String,
+ }
+
+ let model = XmlStruct {
+ background: "my_default_value".to_string(),
+ };
+
+ let content = "";
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, XmlStruct);
+
+ let content = "my_value";
+ let model = XmlStruct {
+ background: "my_value".to_string(),
+ };
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, XmlStruct);
+}
+
+#[test]
+fn default_field_boolean() {
+ fn default_boolean() -> bool {
+ true
+ }
+
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(rename = "base")]
+ pub struct XmlStruct {
+ #[yaserde(default = "default_boolean")]
+ background: bool,
+ }
+
+ let content = "";
+ let model = XmlStruct { background: true };
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, XmlStruct);
+
+ let content = "false";
+ let model = XmlStruct { background: false };
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, XmlStruct);
+}
+
+#[test]
+fn default_field_number() {
+ fn default_number() -> u8 {
+ 6
+ }
+
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(rename = "base")]
+ pub struct XmlStruct {
+ #[yaserde(default = "default_number")]
+ background: u8,
+ }
+
+ let content = "";
+ let model = XmlStruct { background: 6 };
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, XmlStruct);
+
+ let content = "4";
+ let model = XmlStruct { background: 4 };
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, XmlStruct);
+}
+
+#[test]
+fn default_attribute_string() {
+ fn default_string() -> String {
+ "my_default_value".to_string()
+ }
+
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(rename = "base")]
+ pub struct XmlStruct {
+ #[yaserde(attribute, default = "default_string")]
+ background: String,
+ }
+
+ let content = "";
+ let model = XmlStruct {
+ background: "my_default_value".to_string(),
+ };
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, XmlStruct);
+
+ let content = r#""#;
+ let model = XmlStruct {
+ background: "black".to_string(),
+ };
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, XmlStruct);
+}
diff --git a/yaserde/tests/enum.rs b/yaserde/tests/enum.rs
new file mode 100644
index 0000000..cca4edf
--- /dev/null
+++ b/yaserde/tests/enum.rs
@@ -0,0 +1,300 @@
+#[macro_use]
+extern crate yaserde;
+#[macro_use]
+extern crate yaserde_derive;
+
+use std::io::{Read, Write};
+use yaserde::{YaDeserialize, YaSerialize};
+
+#[test]
+fn basic_enum() {
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(rename = "base")]
+ pub struct XmlStruct {
+ color: Color,
+ }
+
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(rename = "color")]
+ pub enum Color {
+ White,
+ Black,
+ #[yaserde(rename = "custom")]
+ Custom {
+ enabled: String,
+ u8_value: u8,
+ i8_value: i8,
+ u16_value: u16,
+ i16_value: i16,
+ u32_value: u32,
+ i32_value: i32,
+ u64_value: u64,
+ i64_value: i64,
+ f32_value: f32,
+ f64_value: f64,
+ color: RGBColor,
+ alpha: Alpha,
+ alphas: Vec,
+ },
+ }
+
+ impl Default for Color {
+ fn default() -> Color {
+ Color::White
+ }
+ }
+
+ assert_eq!(Color::default(), Color::White);
+
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ pub struct RGBColor {
+ red: String,
+ green: String,
+ blue: String,
+ }
+
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ pub enum Alpha {
+ Transparent,
+ Opaque,
+ }
+
+ impl Default for Alpha {
+ fn default() -> Alpha {
+ Alpha::Transparent
+ }
+ }
+
+ let model = XmlStruct {
+ color: Color::Black,
+ };
+
+ let content = "Black";
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, XmlStruct);
+
+ let model = XmlStruct {
+ color: Color::Custom {
+ enabled: "true".to_string(),
+ u8_value: 8,
+ i8_value: -8,
+ u16_value: 16,
+ i16_value: -16,
+ u32_value: 32,
+ i32_value: -32,
+ u64_value: 64,
+ i64_value: -64,
+ f32_value: 32.0,
+ f64_value: 64.0,
+ color: RGBColor {
+ red: "0".to_string(),
+ green: "128".to_string(),
+ blue: "255".to_string(),
+ },
+ alpha: Alpha::Opaque,
+ alphas: vec![Alpha::Opaque, Alpha::Transparent],
+ },
+ };
+
+ let content = r#"
+
+true
+8
+-8
+16
+-16
+32
+-32
+64
+-64
+32
+64
+0128255
+Opaque
+Opaque
+Transparent
+
+"#;
+
+ serialize_and_validate!(model, content);
+ // TODO
+ // deserialize_and_validate!(content, model, XmlStruct);
+}
+
+#[test]
+fn attribute_enum() {
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(rename = "base")]
+ pub struct XmlStruct {
+ #[yaserde(attribute)]
+ color: Color,
+ }
+
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(rename = "color")]
+ pub enum Color {
+ #[yaserde(rename = "pink")]
+ Pink,
+ }
+
+ impl Default for Color {
+ fn default() -> Color {
+ Color::Pink
+ }
+ }
+
+ let model = XmlStruct { color: Color::Pink };
+
+ let content = r#""#;
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, XmlStruct);
+}
+
+#[test]
+fn unnamed_enum() {
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(rename = "base")]
+ pub struct XmlStruct {
+ color: Enum,
+ }
+
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ pub struct OtherStruct {
+ fi: i32,
+ se: i32,
+ }
+
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ pub enum Enum {
+ Simple,
+ Field(String),
+ FullPath(std::string::String),
+ Integer(i32),
+ UserStruct(OtherStruct),
+ OptionString(Option),
+ OptionUserStruct(Option),
+ Strings(Vec),
+ Ints(Vec),
+ Structs(Vec),
+ #[yaserde(rename = "renamed")]
+ ToRename(u32),
+ #[yaserde(rename = "renamed.with.dots")]
+ ToRenameDots(u32),
+ }
+
+ impl Default for Enum {
+ fn default() -> Enum {
+ Enum::Simple
+ }
+ }
+
+ let model = XmlStruct {
+ color: Enum::Field(String::from("some_text")),
+ };
+
+ let content = "some_text";
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, XmlStruct);
+
+ let model = XmlStruct {
+ color: Enum::FullPath(String::from("some_text")),
+ };
+
+ let content = "some_text";
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, XmlStruct);
+
+ let model = XmlStruct {
+ color: Enum::Integer(56),
+ };
+
+ let content = "56";
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, XmlStruct);
+
+ let model = XmlStruct {
+ color: Enum::UserStruct(OtherStruct { fi: 24, se: 42 }),
+ };
+
+ let content = "2442";
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, XmlStruct);
+
+ let model = XmlStruct {
+ color: Enum::OptionString(Some(String::from("some_text"))),
+ };
+
+ let content = "some_text";
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, XmlStruct);
+
+ let model = XmlStruct {
+ color: Enum::OptionString(None),
+ };
+
+ let content = "";
+ serialize_and_validate!(model, content);
+ // TODO
+ // deserialize_and_validate!(content, model, XmlStruct);
+
+ let model = XmlStruct {
+ color: Enum::OptionUserStruct(Some(OtherStruct { fi: 12, se: 23 })),
+ };
+
+ let content =
+ "1223";
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, XmlStruct);
+
+ let model = XmlStruct {
+ color: Enum::OptionUserStruct(None),
+ };
+
+ let content = "";
+ serialize_and_validate!(model, content);
+ // TODO
+ // deserialize_and_validate!(content, model, XmlStruct);
+
+ let model = XmlStruct {
+ color: Enum::Strings(vec![String::from("abc"), String::from("def")]),
+ };
+
+ let content = "abcdef";
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, XmlStruct);
+
+ let model = XmlStruct {
+ color: Enum::Ints(vec![23, 45]),
+ };
+
+ let content = "2345";
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, XmlStruct);
+
+ let model = XmlStruct {
+ color: Enum::Structs(vec![
+ OtherStruct { fi: 12, se: 23 },
+ OtherStruct { fi: 34, se: 45 },
+ ]),
+ };
+
+ let content = "12233445";
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, XmlStruct);
+
+ let model = XmlStruct {
+ color: Enum::ToRename(87),
+ };
+
+ let content = "87";
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, XmlStruct);
+
+ let model = XmlStruct {
+ color: Enum::ToRenameDots(84),
+ };
+
+ let content = "84";
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, XmlStruct);
+}
diff --git a/yaserde/tests/ser_flatten.rs b/yaserde/tests/flatten.rs
similarity index 62%
rename from yaserde/tests/ser_flatten.rs
rename to yaserde/tests/flatten.rs
index 0127ed1..71274d6 100644
--- a/yaserde/tests/ser_flatten.rs
+++ b/yaserde/tests/flatten.rs
@@ -1,28 +1,15 @@
#[macro_use]
+extern crate yaserde;
+#[macro_use]
extern crate yaserde_derive;
-use std::io::Write;
-use yaserde::ser::to_string;
-use yaserde::YaSerialize;
+use std::io::{Read, Write};
-macro_rules! convert_and_validate {
- ($model: expr, $content: expr) => {
- let data: Result = to_string(&$model);
- assert_eq!(
- data,
- Ok(
- String::from($content)
- .split("\n")
- .map(|s| s.trim())
- .collect::()
- )
- );
- };
-}
+use yaserde::{YaDeserialize, YaSerialize};
#[test]
-fn ser_flatten() {
- #[derive(Default, PartialEq, Debug, YaSerialize)]
+fn basic_flatten() {
+ #[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)]
struct DateTime {
#[yaserde(flatten)]
date: Date,
@@ -31,7 +18,7 @@ fn ser_flatten() {
kind: DateKind,
}
- #[derive(Default, PartialEq, Debug, YaSerialize)]
+ #[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)]
struct Date {
year: i32,
month: i32,
@@ -42,18 +29,18 @@ fn ser_flatten() {
optional_extra: Option,
}
- #[derive(Default, PartialEq, Debug, YaSerialize)]
+ #[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)]
pub struct Extra {
week: i32,
century: i32,
}
- #[derive(Default, PartialEq, Debug, YaSerialize)]
+ #[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)]
pub struct OptionalExtra {
lunar_day: i32,
}
- #[derive(PartialEq, Debug, YaSerialize)]
+ #[derive(PartialEq, Debug, YaDeserialize, YaSerialize)]
pub enum DateKind {
#[yaserde(rename = "holidays")]
Holidays(Vec),
@@ -87,7 +74,6 @@ fn ser_flatten() {
};
let content = r#"
-
2020
1
@@ -101,12 +87,13 @@ fn ser_flatten() {
Polar Bear Swim Day
"#;
- convert_and_validate!(model, content);
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, DateTime);
}
#[test]
-fn ser_root_flatten_struct() {
- #[derive(YaSerialize, PartialEq, Debug)]
+fn root_flatten_struct() {
+ #[derive(YaDeserialize, YaSerialize, PartialEq, Debug)]
#[yaserde(flatten)]
pub struct Content {
binary_data: String,
@@ -117,12 +104,15 @@ fn ser_root_flatten_struct() {
binary_data: "binary".to_string(),
string_data: "string".to_string(),
};
- let content = r#"binarystring"#;
- convert_and_validate!(model, content);
+
+ let content = "binarystring";
+
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, Content);
}
#[test]
-fn ser_root_flatten_enum() {
+fn root_flatten_enum() {
#[derive(YaSerialize, PartialEq, Debug)]
#[yaserde(flatten)]
pub enum Content {
@@ -143,14 +133,14 @@ fn ser_root_flatten_enum() {
let model = Content::Binary(Binary {
binary_data: "binary".to_string(),
});
- let content =
- r#"binary"#;
- convert_and_validate!(model, content);
+
+ let content = "binary";
+ serialize_and_validate!(model, content);
let model = Content::Data(Data {
string_data: "string".to_string(),
});
- let content =
- r#"string"#;
- convert_and_validate!(model, content);
+
+ let content = "string";
+ serialize_and_validate!(model, content);
}
diff --git a/yaserde/tests/namespace.rs b/yaserde/tests/namespace.rs
new file mode 100644
index 0000000..dd53c9e
--- /dev/null
+++ b/yaserde/tests/namespace.rs
@@ -0,0 +1,442 @@
+#[macro_use]
+extern crate yaserde;
+#[macro_use]
+extern crate yaserde_derive;
+
+use std::io::{Read, Write};
+use yaserde::{YaDeserialize, YaSerialize};
+
+#[test]
+fn struct_simple_namespace() {
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(
+ rename = "book",
+ prefix = "ns",
+ namespace = "ns: http://www.sample.com/ns/domain"
+ )]
+ pub struct Book {
+ #[yaserde(prefix = "ns")]
+ author: String,
+ #[yaserde(prefix = "ns")]
+ title: String,
+ }
+
+ let content = r#"
+
+ Antoine de Saint-Exupéry
+ Little prince
+
+ "#;
+
+ let model = Book {
+ author: String::from("Antoine de Saint-Exupéry"),
+ title: String::from("Little prince"),
+ };
+
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, Book);
+}
+
+#[test]
+fn struct_multiple_namespaces() {
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(
+ rename = "book",
+ prefix = "ns",
+ namespace = "ns: http://www.sample.com/ns/domain",
+ namespace = "ns2: http://www.sample.com/ns/domain_2"
+ )]
+ pub struct Book {
+ #[yaserde(prefix = "ns")]
+ author: String,
+ #[yaserde(prefix = "ns2")]
+ title: String,
+ }
+
+ let content = r#"
+
+ Antoine de Saint-Exupéry
+ Little prince
+
+ "#;
+
+ let model = Book {
+ author: String::from("Antoine de Saint-Exupéry"),
+ title: String::from("Little prince"),
+ };
+
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, Book);
+}
+
+#[test]
+fn struct_partial_namespace() {
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(
+ rename = "book",
+ prefix = "ns",
+ namespace = "ns: http://www.sample.com/ns/domain"
+ )]
+ pub struct Book {
+ author: String,
+ #[yaserde(prefix = "ns")]
+ title: String,
+ }
+
+ let content = r#"
+
+ Antoine de Saint-Exupéry
+ Little prince
+
+ "#;
+
+ let model = Book {
+ author: String::from("Antoine de Saint-Exupéry"),
+ title: String::from("Little prince"),
+ };
+
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, Book);
+}
+
+#[test]
+fn struct_sub_namespace_definition() {
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(
+ rename = "book",
+ prefix = "ns",
+ namespace = "ns: http://www.sample.com/ns/domain",
+ namespace = "ns2: http://www.sample.com/ns/domain_2"
+ )]
+ pub struct Book {
+ #[yaserde(prefix = "ns")]
+ author: String,
+ #[yaserde(prefix = "ns2", namespace = "ns2: http://www.sample.com/ns/domain_2")]
+ title: String,
+ }
+
+ let content = r#"
+
+ Antoine de Saint-Exupéry
+ Little prince
+
+ "#;
+
+ let model = Book {
+ author: String::from("Antoine de Saint-Exupéry"),
+ title: String::from("Little prince"),
+ };
+
+ // TODO support namespace for attribute to specify local namespace
+ // serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, Book);
+}
+
+#[test]
+fn struct_namespace_nested() {
+ #[derive(Debug, Default, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(prefix = "nsa", namespace = "nsa: http://www.sample.com/ns/a")]
+ struct A {
+ #[yaserde(prefix = "nsa")]
+ alpha: i32,
+ }
+
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(prefix = "nsb", namespace = "nsb: http://www.sample.com/ns/b")]
+ struct B {
+ // Note that name `nested` resides in `nsb` though it has a type from `nsa`
+ #[yaserde(prefix = "nsb")]
+ nested: A,
+ }
+
+ let content = r#"
+
+
+ 32
+
+
+ "#;
+
+ let model = B {
+ nested: A { alpha: 32 },
+ };
+
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, B);
+}
+
+#[test]
+fn struct_namespace_nested_defined_at_root() {
+ #[derive(Debug, Default, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(prefix = "nsa", namespace = "nsa: http://www.sample.com/ns/a")]
+ struct A {
+ #[yaserde(prefix = "nsa")]
+ alpha: i32,
+ }
+
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(
+ prefix = "nsb",
+ namespace = "nsb: http://www.sample.com/ns/b"
+ namespace = "nsa: http://www.sample.com/ns/a"
+ )]
+ struct B {
+ // Note that name `nested` resides in `nsb` though it has a type from `nsa`
+ #[yaserde(prefix = "nsb")]
+ nested: A,
+ }
+
+ let content = r#"
+
+
+ 32
+
+
+ "#;
+
+ let model = B {
+ nested: A { alpha: 32 },
+ };
+
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, B);
+}
+
+#[test]
+fn struct_attribute_namespace() {
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(
+ rename = "root",
+ namespace = "ns1: http://www.sample.com/ns/domain1",
+ namespace = "ns2: http://www.sample.com/ns/domain2"
+ )]
+ pub struct XmlStruct {
+ #[yaserde(prefix = "ns1")]
+ item_1: String,
+ #[yaserde(attribute, prefix = "ns2")]
+ item_2: String,
+ }
+
+ let model = XmlStruct {
+ item_1: "something 1".to_string(),
+ item_2: "something 2".to_string(),
+ };
+
+ let content = r#"
+
+ something 1
+
+ "#;
+
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, XmlStruct);
+}
+
+#[test]
+fn struct_implicit_default_namespace() {
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(
+ rename = "tt",
+ namespace = "http://www.w3.org/ns/ttml",
+ namespace = "ttm: http://www.w3.org/ns/ttml#metadata"
+ )]
+ pub struct XmlStruct {
+ item: String,
+ }
+
+ let model = XmlStruct {
+ item: "something".to_string(),
+ };
+
+ let content = r#"- something
"#;
+ serialize_and_validate!(model, content);
+ // TODO
+ // deserialize_and_validate!(content, model, XmlStruct);
+}
+
+#[test]
+fn struct_explicit_default_namespace() {
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(
+ rename = "tt",
+ default_namespace = "ttml",
+ namespace = "ttml: http://www.w3.org/ns/ttml",
+ namespace = "ttm: http://www.w3.org/ns/ttml#metadata"
+ )]
+ pub struct XmlStruct {
+ item: String,
+ }
+
+ let model = XmlStruct {
+ item: "something".to_string(),
+ };
+
+ let content = r#"- something
"#;
+ serialize_and_validate!(model, content);
+ // TODO
+ // deserialize_and_validate!(content, model, XmlStruct);
+}
+
+#[test]
+fn struct_default_namespace_via_attribute_with_prefix() {
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(
+ rename = "tt",
+ prefix = "TTML",
+ default_namespace = "TTML",
+ namespace = "TTML: http://www.w3.org/ns/ttml",
+ namespace = "ttm: http://www.w3.org/ns/ttml#metadata"
+ )]
+ pub struct XmlStruct {
+ #[yaserde(prefix = "TTML")]
+ item: String,
+ }
+
+ let model = XmlStruct {
+ item: "something".to_string(),
+ };
+
+ let content = r#"- something
"#;
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, XmlStruct);
+}
+
+#[test]
+fn enum_namespace() {
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(
+ rename = "root",
+ prefix = "ns",
+ namespace = "ns: http://www.sample.com/ns/domain"
+ )]
+ pub enum XmlStruct {
+ #[yaserde(prefix = "ns")]
+ Item,
+ }
+
+ impl Default for XmlStruct {
+ fn default() -> XmlStruct {
+ XmlStruct::Item
+ }
+ }
+
+ let content = r#"
+
+ ns:Item
+
+ "#;
+
+ let model = XmlStruct::Item;
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, XmlStruct);
+}
+
+#[test]
+fn enum_multi_namespaces() {
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(
+ rename = "root",
+ namespace = "ns1: http://www.sample.com/ns/domain1",
+ namespace = "ns2: http://www.sample.com/ns/domain2"
+ )]
+ pub enum XmlStruct {
+ #[yaserde(prefix = "ns1")]
+ Item1,
+ #[yaserde(prefix = "ns2")]
+ Item2,
+ }
+
+ impl Default for XmlStruct {
+ fn default() -> XmlStruct {
+ XmlStruct::Item1
+ }
+ }
+
+ let model = XmlStruct::Item1;
+ let content = r#"
+
+ ns1:Item1
+
+ "#;
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, XmlStruct);
+
+ let model = XmlStruct::Item2;
+ let content = r#"
+
+ ns2:Item2
+
+ "#;
+ serialize_and_validate!(model, content);
+ // TODO
+ // deserialize_and_validate!(content, model, XmlStruct);
+}
+
+#[test]
+fn enum_attribute_namespace() {
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(
+ rename = "root",
+ prefix = "ns",
+ namespace = "ns: http://www.sample.com/ns/domain"
+ )]
+ pub enum XmlStruct {
+ #[yaserde(prefix = "ns")]
+ Item,
+ #[yaserde(prefix = "ns")]
+ ItemWithField(String),
+ }
+
+ impl Default for XmlStruct {
+ fn default() -> XmlStruct {
+ XmlStruct::Item
+ }
+ }
+
+ let content = r#"
+
+ ns:Item
+
+ "#;
+
+ let model = XmlStruct::Item;
+ serialize_and_validate!(model, content);
+ deserialize_and_validate!(content, model, XmlStruct);
+
+ let model = XmlStruct::ItemWithField("Value".to_string());
+
+ let content = r#"Value"#;
+ serialize_and_validate!(model, content);
+ // TODO
+ // deserialize_and_validate!(content, model, XmlStruct);
+}
+
+#[test]
+fn struct_bad_namespace() {
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ #[yaserde(
+ rename = "book",
+ prefix = "ns",
+ namespace = "ns: http://www.sample.com/ns/domain",
+ namespace = "ns2: http://www.sample.com/ns/domain_2"
+ )]
+ pub struct Book {
+ #[yaserde(prefix = "ns")]
+ author: String,
+ #[yaserde(prefix = "ns2", namespace = "ns2: http://www.sample.com/ns/domain_2")]
+ title: String,
+ }
+
+ let content = r#"
+
+ Antoine de Saint-Exupéry
+ Little prince
+
+ "#;
+
+ let loaded: Result = yaserde::de::from_str(content);
+ assert_eq!(
+ loaded,
+ Err("bad namespace for book, found http://www.sample.com/ns/domain2".to_string())
+ );
+}
diff --git a/yaserde/tests/option.rs b/yaserde/tests/option.rs
new file mode 100644
index 0000000..cc9a4bd
--- /dev/null
+++ b/yaserde/tests/option.rs
@@ -0,0 +1,104 @@
+#[macro_use]
+extern crate yaserde;
+#[macro_use]
+extern crate yaserde_derive;
+
+use std::io::{Read, Write};
+use yaserde::{YaDeserialize, YaSerialize};
+
+#[test]
+fn basic_option_types() {
+ test_for_type!(Option::, Some("test".to_string()), Some("test"));
+ test_for_type!(Option::, None, None);
+ test_for_type!(Option::, Some(true), Some("true"));
+ test_for_type!(Option::, None, None);
+ test_for_type!(Option::, Some(12 as u8), Some("12"));
+ test_for_type!(Option::, None, None);
+ test_for_type!(Option::, Some(12 as i8), Some("12"));
+ test_for_type!(Option::, Some(-12 as i8), Some("-12"));
+ test_for_type!(Option::, None, None);
+ test_for_type!(Option::, Some(12 as u16), Some("12"));
+ test_for_type!(Option::, None, None);
+ test_for_type!(Option::, Some(12 as i16), Some("12"));
+ test_for_type!(Option::, Some(-12 as i16), Some("-12"));
+ test_for_type!(Option::, None, None);
+ test_for_type!(Option::, Some(12 as u32), Some("12"));
+ test_for_type!(Option::, None, None);
+ test_for_type!(Option::, Some(12 as i32), Some("12"));
+ test_for_type!(Option::, Some(-12 as i32), Some("-12"));
+ test_for_type!(Option::, None, None);
+ test_for_type!(Option::, Some(12 as u64), Some("12"));
+ test_for_type!(Option::, None, None);
+ test_for_type!(Option::, Some(12 as i64), Some("12"));
+ test_for_type!(Option::, Some(-12 as i64), Some("-12"));
+ test_for_type!(Option::, None, None);
+ test_for_type!(Option::, Some(-12.5 as f32), Some("-12.5"));
+ test_for_type!(Option::, None, None);
+ test_for_type!(Option::, Some(-12.5 as f64), Some("-12.5"));
+ test_for_type!(Option::, None, None);
+
+ // TODO
+ // test_for_type!(Option::>, None, None);
+ // test_for_type!(Option::>, Some(vec![0]), Some("0"));
+ // test_for_type!(Option::>, None, None);
+ // test_for_type!(Option::>, Some(vec!["test".to_string()]), Some("test"));
+
+ test_for_attribute_type!(Option::, Some("test".to_string()), Some("test"));
+ test_for_attribute_type!(Option::, None, None);
+ test_for_attribute_type!(Option::, Some(true), Some("true"));
+ test_for_attribute_type!(Option::, None, None);
+ test_for_attribute_type!(Option::, Some(12 as u8), Some("12"));
+ test_for_attribute_type!(Option::, None, None);
+ test_for_attribute_type!(Option::, Some(12 as i8), Some("12"));
+ test_for_attribute_type!(Option::, Some(-12 as i8), Some("-12"));
+ test_for_attribute_type!(Option::, None, None);
+ test_for_attribute_type!(Option::, Some(12 as u16), Some("12"));
+ test_for_attribute_type!(Option::, None, None);
+ test_for_attribute_type!(Option::, Some(12 as i16), Some("12"));
+ test_for_attribute_type!(Option::, Some(-12 as i16), Some("-12"));
+ test_for_attribute_type!(Option::, None, None);
+ test_for_attribute_type!(Option::, Some(12 as u32), Some("12"));
+ test_for_attribute_type!(Option::, None, None);
+ test_for_attribute_type!(Option::, Some(12 as i32), Some("12"));
+ test_for_attribute_type!(Option::, Some(-12 as i32), Some("-12"));
+ test_for_attribute_type!(Option::, None, None);
+ test_for_attribute_type!(Option::, Some(12 as u64), Some("12"));
+ test_for_attribute_type!(Option::, None, None);
+ test_for_attribute_type!(Option::, Some(12 as i64), Some("12"));
+ test_for_attribute_type!(Option::, Some(-12 as i64), Some("-12"));
+ test_for_attribute_type!(Option::, None, None);
+ test_for_attribute_type!(Option::, Some(-12.5 as f32), Some("-12.5"));
+ test_for_attribute_type!(Option::, None, None);
+ test_for_attribute_type!(Option::, Some(-12.5 as f64), Some("-12.5"));
+ test_for_attribute_type!(Option::, None, None);
+}
+
+#[test]
+fn option_struct() {
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ struct Test {
+ field: SubTest,
+ }
+
+ #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)]
+ struct SubTest {
+ content: Option,
+ }
+
+ impl Default for SubTest {
+ fn default() -> Self {
+ SubTest { content: None }
+ }
+ }
+
+ test_for_type!(
+ Option::,
+ Some(Test {
+ field: SubTest {
+ content: Some("value".to_string())
+ }
+ }),
+ Some("value")
+ );
+ test_for_type!(Option::, None, None);
+}
diff --git a/yaserde/tests/ser_default.rs b/yaserde/tests/ser_default.rs
deleted file mode 100644
index b461a7e..0000000
--- a/yaserde/tests/ser_default.rs
+++ /dev/null
@@ -1,103 +0,0 @@
-#[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 = to_string(&$model);
- assert_eq!(data, Ok(String::from($content)));
- };
-}
-
-#[test]
-fn ser_default_field_string() {
- fn default_string() -> String {
- "my_default_value".to_string()
- }
-
- #[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(root = "base")]
- pub struct XmlStruct {
- #[yaserde(default = "default_string")]
- background: String,
- }
-
- let content = "";
- convert_and_validate!(
- XmlStruct {
- background: "my_default_value".to_string(),
- },
- content
- );
- let content =
- "my_value";
- convert_and_validate!(
- XmlStruct {
- background: "my_value".to_string(),
- },
- content
- );
-}
-
-#[test]
-fn ser_default_field_boolean() {
- fn default_boolean() -> bool {
- true
- }
-
- #[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(root = "base")]
- pub struct XmlStruct {
- #[yaserde(default = "default_boolean")]
- background: bool,
- }
-
- let content = "";
- convert_and_validate!(XmlStruct { background: true }, content);
-
- let content =
- "false";
- convert_and_validate!(XmlStruct { background: false }, content);
-}
-
-#[test]
-fn ser_default_field_number() {
- fn default_number() -> u8 {
- 6
- }
-
- #[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(root = "base")]
- pub struct XmlStruct {
- #[yaserde(default = "default_number")]
- background: u8,
- }
-
- let content = "";
- convert_and_validate!(XmlStruct { background: 6 }, content);
-}
-
-#[test]
-fn ser_default_attribute_string() {
- fn default_string() -> String {
- "my_default_value".to_string()
- }
-
- #[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(root = "base")]
- pub struct XmlStruct {
- #[yaserde(attribute, default = "default_string")]
- background: String,
- }
-
- let content = "";
- convert_and_validate!(
- XmlStruct {
- background: "my_default_value".to_string(),
- },
- content
- );
-}
diff --git a/yaserde/tests/ser_enum.rs b/yaserde/tests/ser_enum.rs
deleted file mode 100644
index c5c38e3..0000000
--- a/yaserde/tests/ser_enum.rs
+++ /dev/null
@@ -1,285 +0,0 @@
-#[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 = to_string(&$model);
- assert_eq!(
- data,
- Ok(
- String::from($content)
- .split("\n")
- .map(|s| s.trim())
- .collect::()
- )
- );
- };
-}
-
-#[test]
-fn ser_enum() {
- #[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(root = "base")]
- pub struct XmlStruct {
- color: Color,
- }
-
- #[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(root = "color")]
- pub enum Color {
- White,
- Black,
- #[yaserde(rename = "custom")]
- Custom {
- enabled: String,
- u8_value: u8,
- i8_value: i8,
- u16_value: u16,
- i16_value: i16,
- u32_value: u32,
- i32_value: i32,
- u64_value: u64,
- i64_value: i64,
- f32_value: f32,
- f64_value: f64,
- color: RGBColor,
- alpha: Alpha,
- alphas: Vec,
- },
- }
-
- impl Default for Color {
- fn default() -> Color {
- Color::White
- }
- }
-
- assert_eq!(Color::default(), Color::White);
-
- #[derive(YaSerialize, PartialEq, Debug)]
- pub struct RGBColor {
- red: String,
- green: String,
- blue: String,
- }
-
- #[derive(YaSerialize, PartialEq, Debug)]
- pub enum Alpha {
- Transparent,
- Opaque,
- }
-
- let model = XmlStruct {
- color: Color::Black,
- };
-
- let content = r#"Black"#;
- convert_and_validate!(model, content);
-
- let model = XmlStruct {
- color: Color::Custom {
- enabled: "true".to_string(),
- u8_value: 8,
- i8_value: -8,
- u16_value: 16,
- i16_value: -16,
- u32_value: 32,
- i32_value: -32,
- u64_value: 64,
- i64_value: -64,
- f32_value: 32.0,
- f64_value: 64.0,
- color: RGBColor {
- red: "0".to_string(),
- green: "128".to_string(),
- blue: "255".to_string(),
- },
- alpha: Alpha::Opaque,
- alphas: vec![Alpha::Opaque, Alpha::Transparent],
- },
- };
-
- let content = r#"
-
-true
-8
--8
-16
--16
-32
--32
-64
--64
-32
-64
-0128255
-Opaque
-Opaque
-Transparent
-
-"#;
-
- convert_and_validate!(model, content);
-}
-
-#[test]
-fn ser_attribute_enum() {
- #[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(root = "base")]
- pub struct XmlStruct {
- #[yaserde(attribute)]
- color: Color,
- }
-
- #[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(root = "color")]
- pub enum Color {
- #[yaserde(rename = "pink")]
- Pink,
- }
-
- let model = XmlStruct { color: Color::Pink };
-
- let content = r#""#;
- convert_and_validate!(model, content);
-}
-
-#[test]
-fn ser_unnamed_enum() {
- #[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(root = "base")]
- pub struct XmlStruct {
- color: Enum,
- }
-
- #[derive(YaSerialize, PartialEq, Debug, Default)]
- pub struct OtherStruct {
- fi: i32,
- se: i32,
- }
-
- #[derive(YaSerialize, PartialEq, Debug)]
- pub enum Enum {
- Simple,
- Field(String),
- FullPath(std::string::String),
- Integer(i32),
- UserStruct(OtherStruct),
- OptionString(Option),
- OptionUserStruct(Option),
- Strings(Vec),
- Ints(Vec),
- Structs(Vec),
- #[yaserde(rename = "renamed")]
- ToRename(u32),
- #[yaserde(rename = "renamed.with.dots")]
- ToRenameDots(u32),
- }
-
- impl Default for Enum {
- fn default() -> Enum {
- Enum::Simple
- }
- }
-
- let model = XmlStruct {
- color: Enum::Field(String::from("some_text")),
- };
-
- let content =
- r#"some_text"#;
- convert_and_validate!(model, content);
-
- let model = XmlStruct {
- color: Enum::FullPath(String::from("some_text")),
- };
-
- let content = r#"some_text"#;
- convert_and_validate!(model, content);
-
- let model = XmlStruct {
- color: Enum::Integer(56),
- };
-
- let content =
- r#"56"#;
- convert_and_validate!(model, content);
-
- let model = XmlStruct {
- color: Enum::UserStruct(OtherStruct { fi: 24, se: 42 }),
- };
-
- let content = r#"2442"#;
- convert_and_validate!(model, content);
-
- let model = XmlStruct {
- color: Enum::OptionString(Some(String::from("some_text"))),
- };
-
- let content = r#"some_text"#;
- convert_and_validate!(model, content);
-
- let model = XmlStruct {
- color: Enum::OptionString(None),
- };
-
- let content = r#""#;
- convert_and_validate!(model, content);
-
- let model = XmlStruct {
- color: Enum::OptionUserStruct(Some(OtherStruct { fi: 12, se: 23 })),
- };
-
- let content = r#"1223"#;
- convert_and_validate!(model, content);
-
- let model = XmlStruct {
- color: Enum::OptionUserStruct(None),
- };
-
- let content = r#""#;
- convert_and_validate!(model, content);
-
- let model = XmlStruct {
- color: Enum::Strings(vec![String::from("abc"), String::from("def")]),
- };
-
- let content = r#"abcdef"#;
- convert_and_validate!(model, content);
-
- let model = XmlStruct {
- color: Enum::Ints(vec![23, 45]),
- };
-
- let content = r#"2345"#;
- convert_and_validate!(model, content);
-
- let model = XmlStruct {
- color: Enum::Structs(vec![
- OtherStruct { fi: 12, se: 23 },
- OtherStruct { fi: 34, se: 45 },
- ]),
- };
-
- let content = r#"12233445"#;
- convert_and_validate!(model, content);
-
- let model = XmlStruct {
- color: Enum::ToRename(87),
- };
-
- let content =
- r#"87"#;
- convert_and_validate!(model, content);
-
- let model = XmlStruct {
- color: Enum::ToRenameDots(84),
- };
-
- let content = r#"84"#;
- convert_and_validate!(model, content);
-}
diff --git a/yaserde/tests/ser_namespace.rs b/yaserde/tests/ser_namespace.rs
deleted file mode 100644
index 5af32e8..0000000
--- a/yaserde/tests/ser_namespace.rs
+++ /dev/null
@@ -1,235 +0,0 @@
-#[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 = to_string(&$model);
- assert_eq!(
- data,
- Ok(
- String::from($content)
- .split("\n")
- .map(|s| s.trim())
- .collect::()
- )
- );
- };
-}
-
-#[test]
-fn ser_struct_namespace() {
- #[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(
- root = "root",
- prefix = "ns",
- namespace = "ns: http://www.sample.com/ns/domain"
- )]
- pub struct XmlStruct {
- #[yaserde(prefix = "ns")]
- item: String,
- }
-
- let model = XmlStruct {
- item: "something".to_string(),
- };
-
- let content = "something";
- convert_and_validate!(model, content);
-}
-
-#[test]
-fn ser_enum_namespace() {
- #[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(
- root = "root",
- prefix = "ns",
- namespace = "ns: http://www.sample.com/ns/domain"
- )]
- pub enum XmlStruct {
- #[yaserde(prefix = "ns")]
- Item,
- #[yaserde(prefix = "ns")]
- ItemWithField(String),
- }
-
- let model = XmlStruct::Item;
-
- let content = "ns:Item";
- convert_and_validate!(model, content);
-
- let model = XmlStruct::ItemWithField("Value".to_string());
-
- let content = "Value";
- convert_and_validate!(model, content);
-}
-
-#[test]
-fn ser_struct_multi_namespace() {
- #[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(
- root = "root",
- namespace = "ns1: http://www.sample.com/ns/domain1",
- namespace = "ns2: http://www.sample.com/ns/domain2"
- )]
- pub struct XmlStruct {
- #[yaserde(prefix = "ns1")]
- item_1: String,
- #[yaserde(prefix = "ns2")]
- item_2: String,
- }
-
- let model = XmlStruct {
- item_1: "something 1".to_string(),
- item_2: "something 2".to_string(),
- };
-
- let content = "something 1something 2";
- convert_and_validate!(model, content);
-}
-
-#[test]
-fn ser_enum_multi_namespace() {
- #[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(
- root = "root",
- namespace = "ns1: http://www.sample.com/ns/domain1",
- namespace = "ns2: http://www.sample.com/ns/domain2"
- )]
- pub enum XmlStruct {
- #[yaserde(prefix = "ns1")]
- Item1,
- #[yaserde(prefix = "ns2")]
- Item2,
- }
-
- let model1 = XmlStruct::Item1;
- let content = "ns1:Item1";
- convert_and_validate!(model1, content);
- let model2 = XmlStruct::Item2;
- let content = "ns2:Item2";
- convert_and_validate!(model2, content);
-}
-
-#[test]
-fn ser_struct_attribute_namespace() {
- #[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(
- root = "root",
- namespace = "ns1: http://www.sample.com/ns/domain1",
- namespace = "ns2: http://www.sample.com/ns/domain2"
- )]
- pub struct XmlStruct {
- #[yaserde(prefix = "ns1")]
- item_1: String,
- #[yaserde(attribute, prefix = "ns2")]
- item_2: String,
- }
-
- let model = XmlStruct {
- item_1: "something 1".to_string(),
- item_2: "something 2".to_string(),
- };
-
- let content = "something 1";
- convert_and_validate!(model, content);
-}
-
-#[test]
-fn ser_struct_default_namespace() {
- #[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(
- root = "tt",
- namespace = "http://www.w3.org/ns/ttml",
- namespace = "ttm: http://www.w3.org/ns/ttml#metadata"
- )]
- pub struct XmlStruct {
- item: String,
- }
-
- let model = XmlStruct {
- item: "something".to_string(),
- };
-
- let content = "- something
";
- convert_and_validate!(model, content);
-}
-
-#[test]
-fn ser_struct_default_namespace_via_attribute() {
- #[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(
- root = "tt",
- default_namespace = "ttml",
- namespace = "ttml: http://www.w3.org/ns/ttml",
- namespace = "ttm: http://www.w3.org/ns/ttml#metadata"
- )]
- pub struct XmlStruct {
- item: String,
- }
-
- let model = XmlStruct {
- item: "something".to_string(),
- };
-
- let content = "- something
";
- convert_and_validate!(model, content);
-}
-
-#[test]
-fn ser_struct_default_namespace_via_attribute_with_prefix() {
- #[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(
- root = "tt",
- prefix = "TTML",
- default_namespace = "TTML",
- namespace = "TTML: http://www.w3.org/ns/ttml",
- namespace = "ttm: http://www.w3.org/ns/ttml#metadata"
- )]
- pub struct XmlStruct {
- #[yaserde(prefix = "TTML")]
- item: String,
- }
-
- let model = XmlStruct {
- item: "something".to_string(),
- };
-
- let content = "- something
";
- convert_and_validate!(model, content);
-}
-
-#[test]
-fn ser_struct_namespace_nested() {
- #[derive(YaSerialize, Default, PartialEq, Debug)]
- #[yaserde(prefix = "nsa", namespace = "nsa: http://www.sample.com/ns/a")]
- struct A {
- #[yaserde(prefix = "nsa")]
- alpha: i32,
- }
-
- #[derive(YaSerialize, Default, PartialEq, Debug)]
- #[yaserde(prefix = "nsb", namespace = "nsb: http://www.sample.com/ns/b")]
- struct B {
- // Note that name `nested` resides in `nsb` though it has a type from `nsa`
- #[yaserde(prefix = "nsb")]
- nested: A,
- }
-
- convert_and_validate!(
- B {
- nested: A { alpha: 32 }
- },
- r#"
-
-
-
- 32
-
-
- "#
- );
-}
diff --git a/yaserde/tests/ser_option.rs b/yaserde/tests/ser_option.rs
deleted file mode 100644
index 26f1c08..0000000
--- a/yaserde/tests/ser_option.rs
+++ /dev/null
@@ -1,147 +0,0 @@
-#[macro_use]
-extern crate yaserde_derive;
-
-use std::io::Write;
-use yaserde::ser::to_string;
-use yaserde::YaSerialize;
-
-macro_rules! convert_and_validate {
- ($type: ty, $value: expr, $content: expr) => {{
- #[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(root = "data")]
- pub struct Data {
- item: Option<$type>,
- }
- let model = Data { item: $value };
-
- let data: Result = to_string(&model);
-
- let content = if let Some(str_value) = $content {
- "- ".to_string() + str_value + "
"
- } else {
- "".to_string()
- };
-
- let content = String::from("") + &content;
- assert_eq!(data, Ok(content));
- }};
-}
-
-macro_rules! convert_and_validate_as_attribute {
- ($type: ty, $value: expr, $content: expr) => {{
- #[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(root = "data")]
- pub struct Data {
- #[yaserde(attribute)]
- item: Option<$type>,
- }
- let model = Data { item: $value };
-
- let data: Result = to_string(&model);
-
- let content = if let Some(str_value) = $content {
- ""
- } else {
- "".to_string()
- };
-
- let content = String::from("") + &content;
- assert_eq!(data, Ok(content));
- }};
-}
-
-#[test]
-fn ser_option() {
- convert_and_validate!(String, Some("test".to_string()), Some("test"));
- convert_and_validate!(String, None, None);
- convert_and_validate!(bool, Some(true), Some("true"));
- convert_and_validate!(bool, None, None);
- convert_and_validate!(u8, Some(12 as u8), Some("12"));
- convert_and_validate!(u8, None, None);
- convert_and_validate!(i8, Some(12 as i8), Some("12"));
- convert_and_validate!(i8, Some(-12 as i8), Some("-12"));
- convert_and_validate!(i8, None, None);
- convert_and_validate!(u16, Some(12 as u16), Some("12"));
- convert_and_validate!(u16, None, None);
- convert_and_validate!(i16, Some(12 as i16), Some("12"));
- convert_and_validate!(i16, Some(-12 as i16), Some("-12"));
- convert_and_validate!(i16, None, None);
- convert_and_validate!(u32, Some(12 as u32), Some("12"));
- convert_and_validate!(u32, None, None);
- convert_and_validate!(i32, Some(12 as i32), Some("12"));
- convert_and_validate!(i32, Some(-12 as i32), Some("-12"));
- convert_and_validate!(i32, None, None);
- convert_and_validate!(u64, Some(12 as u64), Some("12"));
- convert_and_validate!(u64, None, None);
- convert_and_validate!(i64, Some(12 as i64), Some("12"));
- convert_and_validate!(i64, Some(-12 as i64), Some("-12"));
- convert_and_validate!(i64, None, None);
- convert_and_validate!(f32, Some(-12.5 as f32), Some("-12.5"));
- convert_and_validate!(f32, None, None);
- convert_and_validate!(f64, Some(-12.5 as f64), Some("-12.5"));
- convert_and_validate!(f64, None, None);
-
- convert_and_validate!(Vec, None, None);
- convert_and_validate!(Vec, Some(vec![0]), Some("0"));
- convert_and_validate!(Vec, None, None);
- convert_and_validate!(Vec, Some(vec!["test".to_string()]), Some("test"));
-
- convert_and_validate_as_attribute!(String, Some("test".to_string()), Some("test"));
- convert_and_validate_as_attribute!(String, None, None);
- convert_and_validate_as_attribute!(bool, Some(true), Some("true"));
- convert_and_validate_as_attribute!(bool, None, None);
- convert_and_validate_as_attribute!(u8, Some(12 as u8), Some("12"));
- convert_and_validate_as_attribute!(u8, None, None);
- convert_and_validate_as_attribute!(i8, Some(12 as i8), Some("12"));
- convert_and_validate_as_attribute!(i8, Some(-12 as i8), Some("-12"));
- convert_and_validate_as_attribute!(i8, None, None);
- convert_and_validate_as_attribute!(u16, Some(12 as u16), Some("12"));
- convert_and_validate_as_attribute!(u16, None, None);
- convert_and_validate_as_attribute!(i16, Some(12 as i16), Some("12"));
- convert_and_validate_as_attribute!(i16, Some(-12 as i16), Some("-12"));
- convert_and_validate_as_attribute!(i16, None, None);
- convert_and_validate_as_attribute!(u32, Some(12 as u32), Some("12"));
- convert_and_validate_as_attribute!(u32, None, None);
- convert_and_validate_as_attribute!(i32, Some(12 as i32), Some("12"));
- convert_and_validate_as_attribute!(i32, Some(-12 as i32), Some("-12"));
- convert_and_validate_as_attribute!(i32, None, None);
- convert_and_validate_as_attribute!(u64, Some(12 as u64), Some("12"));
- convert_and_validate_as_attribute!(u64, None, None);
- convert_and_validate_as_attribute!(i64, Some(12 as i64), Some("12"));
- convert_and_validate_as_attribute!(i64, Some(-12 as i64), Some("-12"));
- convert_and_validate_as_attribute!(i64, None, None);
- convert_and_validate_as_attribute!(f32, Some(-12.5 as f32), Some("-12.5"));
- convert_and_validate_as_attribute!(f32, None, None);
- convert_and_validate_as_attribute!(f64, Some(-12.5 as f64), Some("-12.5"));
- convert_and_validate_as_attribute!(f64, None, None);
-}
-
-#[test]
-fn de_option_struct() {
- #[derive(YaSerialize, Debug, PartialEq)]
- struct Test {
- field: SubTest,
- }
-
- #[derive(YaSerialize, Debug, PartialEq)]
- struct SubTest {
- content: Option,
- }
-
- impl Default for SubTest {
- fn default() -> Self {
- SubTest { content: None }
- }
- }
-
- convert_and_validate!(
- Test,
- Some(Test {
- field: SubTest {
- content: Some("value".to_string())
- }
- }),
- Some("value")
- );
- convert_and_validate!(Test, None, None);
-}
diff --git a/yaserde/tests/ser_type.rs b/yaserde/tests/ser_type.rs
deleted file mode 100644
index 1506cc2..0000000
--- a/yaserde/tests/ser_type.rs
+++ /dev/null
@@ -1,83 +0,0 @@
-#[macro_use]
-extern crate yaserde_derive;
-
-use std::io::Write;
-use yaserde::ser::to_string;
-use yaserde::YaSerialize;
-
-macro_rules! convert_and_validate {
- ($type: ty, $value: expr, $content: expr) => {{
- #[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(root = "data")]
- pub struct Data {
- item: $type,
- }
- let model = Data { item: $value };
-
- let data: Result = to_string(&model);
- let content = if $content == "" {
- String::from("")
- } else {
- String::from("- ")
- + $content
- + "
"
- };
- assert_eq!(data, Ok(content));
- }};
-}
-
-macro_rules! convert_and_validate_as_attribute {
- ($type: ty, $value: expr, $content: expr) => {{
- #[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(root = "data")]
- pub struct Data {
- #[yaserde(attribute)]
- item: $type,
- }
- let model = Data { item: $value };
-
- let data: Result = to_string(&model);
- let content =
- String::from("";
- assert_eq!(data, Ok(content));
- }};
-}
-
-#[test]
-fn ser_type() {
- convert_and_validate!(String, "test".to_string(), "test");
- convert_and_validate!(bool, true, "true");
- convert_and_validate!(u8, 12 as u8, "12");
- convert_and_validate!(i8, 12 as i8, "12");
- convert_and_validate!(i8, -12 as i8, "-12");
- convert_and_validate!(u16, 12 as u16, "12");
- convert_and_validate!(i16, 12 as i16, "12");
- convert_and_validate!(i16, -12 as i16, "-12");
- convert_and_validate!(u32, 12 as u32, "12");
- convert_and_validate!(i32, 12 as i32, "12");
- convert_and_validate!(i32, -12 as i32, "-12");
- convert_and_validate!(u64, 12 as u64, "12");
- convert_and_validate!(i64, 12 as i64, "12");
- convert_and_validate!(i64, -12 as i64, "-12");
- convert_and_validate!(f32, -12.5 as f32, "-12.5");
- convert_and_validate!(f64, -12.5 as f64, "-12.5");
- convert_and_validate!(Vec, vec![], "");
- convert_and_validate!(Vec, vec!["test".to_string()], "test");
-
- convert_and_validate_as_attribute!(String, "test".to_string(), "test");
- convert_and_validate_as_attribute!(bool, true, "true");
- convert_and_validate_as_attribute!(u8, 12 as u8, "12");
- convert_and_validate_as_attribute!(i8, 12 as i8, "12");
- convert_and_validate_as_attribute!(i8, -12 as i8, "-12");
- convert_and_validate_as_attribute!(u16, 12 as u16, "12");
- convert_and_validate_as_attribute!(i16, 12 as i16, "12");
- convert_and_validate_as_attribute!(i16, -12 as i16, "-12");
- convert_and_validate_as_attribute!(u32, 12 as u32, "12");
- convert_and_validate_as_attribute!(i32, 12 as i32, "12");
- convert_and_validate_as_attribute!(i32, -12 as i32, "-12");
- convert_and_validate_as_attribute!(u64, 12 as u64, "12");
- convert_and_validate_as_attribute!(i64, 12 as i64, "12");
- convert_and_validate_as_attribute!(i64, -12 as i64, "-12");
- convert_and_validate_as_attribute!(f32, -12.5 as f32, "-12.5");
- convert_and_validate_as_attribute!(f64, -12.5 as f64, "-12.5");
-}
diff --git a/yaserde/tests/serializer.rs b/yaserde/tests/serializer.rs
index c3ff11b..01b7921 100644
--- a/yaserde/tests/serializer.rs
+++ b/yaserde/tests/serializer.rs
@@ -1,29 +1,15 @@
#[macro_use]
+extern crate yaserde;
+#[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 = to_string(&$model);
- assert_eq!(
- data,
- Ok(
- String::from($content)
- .split("\n")
- .map(|s| s.trim())
- .collect::()
- )
- );
- };
-}
-
#[test]
fn ser_basic() {
#[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(root = "base")]
+ #[yaserde(rename = "base")]
pub struct XmlStruct {
item: String,
}
@@ -32,14 +18,14 @@ fn ser_basic() {
item: "something".to_string(),
};
- let content = "- something
";
- convert_and_validate!(model, content);
+ let content = "- something
";
+ serialize_and_validate!(model, content);
}
#[test]
fn ser_list_of_items() {
#[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(root = "base")]
+ #[yaserde(rename = "base")]
pub struct XmlStruct {
items: Vec,
}
@@ -48,17 +34,17 @@ fn ser_list_of_items() {
items: vec!["something1".to_string(), "something2".to_string()],
};
- let content = "something1something2";
- convert_and_validate!(model, content);
+ let content = "something1something2";
+ serialize_and_validate!(model, content);
#[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(root = "base")]
+ #[yaserde(rename = "base")]
pub struct XmlStructOfStruct {
items: Vec,
}
#[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(root = "items")]
+ #[yaserde(rename = "items")]
pub struct SubStruct {
field: String,
}
@@ -74,14 +60,15 @@ fn ser_list_of_items() {
],
};
- let content = "something1something2";
- convert_and_validate!(model2, content);
+ let content =
+ "something1something2";
+ serialize_and_validate!(model2, content);
}
#[test]
fn ser_attributes() {
#[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(root = "base")]
+ #[yaserde(rename = "base")]
pub struct XmlStruct {
#[yaserde(attribute)]
item: String,
@@ -89,7 +76,7 @@ fn ser_attributes() {
}
#[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(root = "sub")]
+ #[yaserde(rename = "sub")]
pub struct SubStruct {
#[yaserde(attribute)]
subitem: String,
@@ -117,8 +104,8 @@ fn ser_attributes() {
},
};
- let content = "";
- convert_and_validate!(model, content);
+ let content = r#""#;
+ serialize_and_validate!(model, content);
}
#[test]
@@ -158,24 +145,20 @@ fn ser_attributes_complex() {
}
}
- convert_and_validate!(
+ serialize_and_validate!(
Struct {
attr_option_string: None,
attr_option_enum: None,
},
- r#"
-
-
- "#
+ ""
);
- convert_and_validate!(
+ serialize_and_validate!(
Struct {
attr_option_string: Some("some value".to_string()),
attr_option_enum: Some(other_mod::AttrEnum::Variant2),
},
r#"
-
"#
);
@@ -184,7 +167,7 @@ fn ser_attributes_complex() {
#[test]
fn ser_rename() {
#[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(root = "base")]
+ #[yaserde(rename = "base")]
pub struct XmlStruct {
#[yaserde(attribute, rename = "Item")]
item: String,
@@ -195,7 +178,7 @@ fn ser_rename() {
}
#[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(root = "sub")]
+ #[yaserde(rename = "sub")]
pub struct SubStruct {
#[yaserde(attribute, rename = "sub_item")]
subitem: String,
@@ -224,14 +207,14 @@ fn ser_rename() {
version: "2.0.2".into(),
};
- let content = "2.0.2";
- convert_and_validate!(model, content);
+ let content = r#"2.0.2"#;
+ serialize_and_validate!(model, content);
}
#[test]
fn ser_text_content_with_attributes() {
#[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(root = "base")]
+ #[yaserde(rename = "base")]
pub struct XmlStruct {
#[yaserde(attribute, rename = "Item")]
item: String,
@@ -240,7 +223,7 @@ fn ser_text_content_with_attributes() {
}
#[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(root = "sub")]
+ #[yaserde(rename = "sub")]
pub struct SubStruct {
#[yaserde(attribute, rename = "sub_item")]
subitem: String,
@@ -273,14 +256,14 @@ fn ser_text_content_with_attributes() {
},
};
- let content = "text_content";
- convert_and_validate!(model, content);
+ let content = r#"text_content"#;
+ serialize_and_validate!(model, content);
}
#[test]
fn ser_name_issue_21() {
#[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(root = "base")]
+ #[yaserde(rename = "base")]
pub struct XmlStruct {
name: String,
}
@@ -289,8 +272,8 @@ fn ser_name_issue_21() {
name: "something".to_string(),
};
- let content = "something";
- convert_and_validate!(model, content);
+ let content = "something";
+ serialize_and_validate!(model, content);
}
#[test]
@@ -326,6 +309,6 @@ fn ser_custom() {
month: 1,
day: Day { value: 5 },
};
- let content = "2020110";
- convert_and_validate!(model, content);
+ let content = "2020110";
+ serialize_and_validate!(model, content);
}
diff --git a/yaserde/tests/ser_skip.rs b/yaserde/tests/skip_if.rs
similarity index 68%
rename from yaserde/tests/ser_skip.rs
rename to yaserde/tests/skip_if.rs
index 53c6be0..e7c853e 100644
--- a/yaserde/tests/ser_skip.rs
+++ b/yaserde/tests/skip_if.rs
@@ -1,30 +1,25 @@
#[macro_use]
+extern crate yaserde;
+#[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 = to_string(&$model);
- assert_eq!(
- data,
- Ok(
- String::from($content)
- .split("\n")
- .map(|s| s.trim())
- .collect::()
- )
- );
- };
-}
-
#[test]
-fn ser_skip_serializing_if_for_struct() {
+fn skip_serializing_if_for_struct() {
+ fn default_string_function() -> String {
+ "mask_default".to_string()
+ }
+
#[derive(YaSerialize, PartialEq, Debug)]
- #[yaserde(root = "base")]
+ #[yaserde(rename = "base")]
pub struct XmlStruct {
+ #[yaserde(
+ skip_serializing_if = "check_string_function",
+ default = "default_string_function"
+ )]
+ string_with_default_item: String,
#[yaserde(skip_serializing_if = "check_string_function")]
string_item: String,
#[yaserde(skip_serializing_if = "check_bool_function")]
@@ -54,12 +49,13 @@ fn ser_skip_serializing_if_for_struct() {
}
let model = XmlStruct {
+ string_with_default_item: "mask_default".to_string(),
string_item: "something".to_string(),
bool_item: true,
f32_item: 0.0,
option_string_item: Some("something".to_string()),
};
- let content = "";
- convert_and_validate!(model, content);
+ let content = "";
+ serialize_and_validate!(model, content);
}
diff --git a/yaserde/tests/types.rs b/yaserde/tests/types.rs
new file mode 100644
index 0000000..de5e2d4
--- /dev/null
+++ b/yaserde/tests/types.rs
@@ -0,0 +1,46 @@
+#[macro_use]
+extern crate yaserde;
+#[macro_use]
+extern crate yaserde_derive;
+
+use std::io::{Read, Write};
+use yaserde::{YaDeserialize, YaSerialize};
+
+#[test]
+fn ser_type() {
+ test_for_type!(String, "test".to_string(), Some("test"));
+ test_for_type!(bool, true, Some("true"));
+ test_for_type!(u8, 12 as u8, Some("12"));
+ test_for_type!(i8, 12 as i8, Some("12"));
+ test_for_type!(i8, -12 as i8, Some("-12"));
+ test_for_type!(u16, 12 as u16, Some("12"));
+ test_for_type!(i16, 12 as i16, Some("12"));
+ test_for_type!(i16, -12 as i16, Some("-12"));
+ test_for_type!(u32, 12 as u32, Some("12"));
+ test_for_type!(i32, 12 as i32, Some("12"));
+ test_for_type!(i32, -12 as i32, Some("-12"));
+ test_for_type!(u64, 12 as u64, Some("12"));
+ test_for_type!(i64, 12 as i64, Some("12"));
+ test_for_type!(i64, -12 as i64, Some("-12"));
+ test_for_type!(f32, -12.5 as f32, Some("-12.5"));
+ test_for_type!(f64, -12.5 as f64, Some("-12.5"));
+ test_for_type!(Vec::, vec![], None);
+ test_for_type!(Vec::, vec!["test".to_string()], Some("test"));
+
+ test_for_attribute_type!(String, "test".to_string(), Some("test"));
+ test_for_attribute_type!(bool, true, Some("true"));
+ test_for_attribute_type!(u8, 12 as u8, Some("12"));
+ test_for_attribute_type!(i8, 12 as i8, Some("12"));
+ test_for_attribute_type!(i8, -12 as i8, Some("-12"));
+ test_for_attribute_type!(u16, 12 as u16, Some("12"));
+ test_for_attribute_type!(i16, 12 as i16, Some("12"));
+ test_for_attribute_type!(i16, -12 as i16, Some("-12"));
+ test_for_attribute_type!(u32, 12 as u32, Some("12"));
+ test_for_attribute_type!(i32, 12 as i32, Some("12"));
+ test_for_attribute_type!(i32, -12 as i32, Some("-12"));
+ test_for_attribute_type!(u64, 12 as u64, Some("12"));
+ test_for_attribute_type!(i64, 12 as i64, Some("12"));
+ test_for_attribute_type!(i64, -12 as i64, Some("-12"));
+ test_for_attribute_type!(f32, -12.5 as f32, Some("-12.5"));
+ test_for_attribute_type!(f64, -12.5 as f64, Some("-12.5"));
+}
diff --git a/yaserde_derive/src/attribute.rs b/yaserde_derive/src/common/attribute.rs
similarity index 85%
rename from yaserde_derive/src/attribute.rs
rename to yaserde_derive/src/common/attribute.rs
index 6504dad..2896bab 100644
--- a/yaserde_derive/src/attribute.rs
+++ b/yaserde_derive/src/common/attribute.rs
@@ -1,6 +1,4 @@
-use proc_macro2::token_stream::IntoIter;
-use proc_macro2::Delimiter;
-use proc_macro2::TokenTree;
+use proc_macro2::{token_stream::IntoIter, Delimiter, TokenStream, TokenTree};
use std::collections::BTreeMap;
use syn::Attribute;
@@ -12,7 +10,6 @@ pub struct YaSerdeAttribute {
pub flatten: bool,
pub namespaces: BTreeMap,
pub prefix: Option,
- pub root: Option,
pub rename: Option,
pub skip_serializing_if: Option,
pub text: bool,
@@ -41,7 +38,6 @@ impl YaSerdeAttribute {
let mut namespaces = BTreeMap::new();
let mut prefix = None;
let mut rename = None;
- let mut root = None;
let mut skip_serializing_if = None;
let mut text = false;
@@ -84,9 +80,6 @@ impl YaSerdeAttribute {
"rename" => {
rename = get_value(&mut attr_iter);
}
- "root" => {
- root = get_value(&mut attr_iter);
- }
"skip_serializing_if" => {
skip_serializing_if = get_value(&mut attr_iter);
}
@@ -110,11 +103,49 @@ impl YaSerdeAttribute {
namespaces,
prefix,
rename,
- root,
skip_serializing_if,
text,
}
}
+
+ pub fn get_namespace_matching(
+ &self,
+ prefix: &Option,
+ element_namespace: TokenStream,
+ element_name: TokenStream,
+ take_root_prefix: bool,
+ ) -> TokenStream {
+ let configured_prefix = if take_root_prefix {
+ self.prefix.clone()
+ } else {
+ prefix.clone()
+ };
+
+ let namespaces_matches: TokenStream = self
+ .namespaces
+ .iter()
+ .map(|(prefix, namespace)| {
+ if configured_prefix == Some(prefix.to_string()) {
+ Some(quote!(#namespace => {}))
+ } else {
+ None
+ }
+ })
+ .filter_map(|x| x)
+ .collect();
+
+ quote!(
+ if let Some(namespace) = #element_namespace {
+ match namespace.as_str() {
+ #namespaces_matches
+ bad_namespace => {
+ let msg = format!("bad namespace for {}, found {}", #element_name, bad_namespace);
+ return Err(msg);
+ }
+ }
+ }
+ )
+ }
}
#[test]
@@ -130,7 +161,6 @@ fn parse_empty_attributes() {
flatten: false,
namespaces: BTreeMap::new(),
prefix: None,
- root: None,
rename: None,
skip_serializing_if: None,
text: false,
@@ -180,7 +210,6 @@ fn parse_attributes() {
flatten: false,
namespaces: BTreeMap::new(),
prefix: None,
- root: None,
rename: None,
skip_serializing_if: None,
text: false,
@@ -205,7 +234,6 @@ fn parse_attributes_with_values() {
arguments: PathArguments::None,
});
- // #[()]
let attributes = vec![Attribute {
pound_token: Pound {
spans: [Span::call_site()],
@@ -234,7 +262,6 @@ fn parse_attributes_with_values() {
flatten: true,
namespaces,
prefix: None,
- root: None,
rename: None,
skip_serializing_if: None,
text: false,
diff --git a/yaserde_derive/src/common/field.rs b/yaserde_derive/src/common/field.rs
new file mode 100644
index 0000000..0a00087
--- /dev/null
+++ b/yaserde_derive/src/common/field.rs
@@ -0,0 +1,295 @@
+use crate::common::attribute::YaSerdeAttribute;
+use proc_macro2::Span;
+use proc_macro2::{Ident, TokenStream};
+use std::fmt;
+use syn;
+use syn::spanned::Spanned;
+use syn::Type::Path;
+
+#[derive(Debug)]
+pub struct YaSerdeField {
+ syn_field: syn::Field,
+ attributes: YaSerdeAttribute,
+}
+
+impl YaSerdeField {
+ pub fn new(syn_field: syn::Field) -> Self {
+ let attributes = YaSerdeAttribute::parse(&syn_field.attrs);
+
+ YaSerdeField {
+ syn_field,
+ attributes,
+ }
+ }
+
+ pub fn is_attribute(&self) -> bool {
+ self.attributes.attribute
+ }
+
+ pub fn is_text_content(&self) -> bool {
+ self.attributes.text
+ }
+
+ pub fn is_flatten(&self) -> bool {
+ self.attributes.flatten
+ }
+
+ // pub fn get_attributes(&self) -> YaSerdeAttribute {
+ // self.attributes.clone()
+ // }
+
+ pub fn label(&self) -> Option {
+ self.syn_field.ident.clone()
+ }
+
+ pub fn get_value_label(&self) -> Option {
+ self
+ .syn_field
+ .ident
+ .clone()
+ .map(|ident| syn::Ident::new(&format!("__{}_value", ident.to_string()), ident.span()))
+ }
+
+ pub fn renamed_label_without_namespace(&self) -> String {
+ self
+ .attributes
+ .rename
+ .clone()
+ .unwrap_or_else(|| self.label().as_ref().unwrap().to_string())
+ }
+
+ pub fn renamed_label(&self, root_attributes: &YaSerdeAttribute) -> String {
+ let prefix = if root_attributes.default_namespace == self.attributes.prefix {
+ "".to_string()
+ } else {
+ self
+ .attributes
+ .prefix
+ .clone()
+ .map_or("".to_string(), |prefix| prefix + ":")
+ };
+
+ let label = self.renamed_label_without_namespace();
+
+ format!("{}{}", prefix, label)
+ }
+
+ pub fn get_visitor_ident(&self, struct_name: Option<&syn::Path>) -> Ident {
+ let label = self.renamed_label_without_namespace();
+
+ let struct_id = struct_name.map_or_else(
+ || "".to_string(),
+ |struct_name| {
+ struct_name
+ .segments
+ .iter()
+ .map(|s| s.ident.to_string())
+ .collect()
+ },
+ );
+
+ Ident::new(
+ &format!("__Visitor_{}_{}", label.replace(".", "_"), struct_id),
+ self.get_span(),
+ )
+ }
+
+ pub fn get_type(&self) -> Field {
+ Field::from(&self.syn_field)
+ }
+
+ pub fn get_span(&self) -> Span {
+ self.syn_field.span()
+ }
+
+ pub fn get_default_function(&self) -> Option {
+ self
+ .attributes
+ .default
+ .as_ref()
+ .map(|default| Ident::new(&default, self.get_span()))
+ }
+
+ pub fn get_skip_serializing_if_function(&self) -> Option {
+ self
+ .attributes
+ .skip_serializing_if
+ .as_ref()
+ .map(|skip_serializing_if| Ident::new(&skip_serializing_if, self.get_span()))
+ }
+
+ pub fn get_namespace_matching(
+ &self,
+ root_attributes: &YaSerdeAttribute,
+ element_namespace: TokenStream,
+ element_name: TokenStream,
+ ) -> TokenStream {
+ root_attributes.get_namespace_matching(
+ &self.attributes.prefix,
+ element_namespace,
+ element_name,
+ false,
+ )
+ }
+
+ pub fn ser_wrap_default_attribute(
+ &self,
+ builder: Option,
+ setter: TokenStream,
+ ) -> TokenStream {
+ let label = self.label();
+
+ let yaserde_inner_definition = builder
+ .map(|builder| quote!(let yaserde_inner = #builder;))
+ .unwrap_or(quote!());
+
+ self
+ .get_default_function()
+ .map(|default_function| {
+ quote! {
+ #yaserde_inner_definition
+ let struct_start_event =
+ if self.#label != #default_function() {
+ #setter
+ } else {
+ struct_start_event
+ };
+ }
+ })
+ .unwrap_or(quote! {
+ #yaserde_inner_definition
+ let struct_start_event = #setter;
+ })
+ }
+}
+
+#[derive(Debug)]
+pub enum Field {
+ FieldString,
+ FieldBool,
+ FieldI8,
+ FieldU8,
+ FieldI16,
+ FieldU16,
+ FieldI32,
+ FieldU32,
+ FieldI64,
+ FieldU64,
+ FieldF32,
+ FieldF64,
+ FieldOption { data_type: Box },
+ FieldVec { data_type: Box },
+ FieldStruct { struct_name: syn::Path },
+}
+
+impl Field {
+ pub fn get_simple_type_visitor(&self) -> TokenStream {
+ let ident = format_ident!("visit_{}", self.to_string());
+ quote! {#ident}
+ }
+}
+
+impl From<&syn::Path> for Field {
+ fn from(path: &syn::Path) -> Self {
+ let result = if let Some(segment) = path.segments.last() {
+ match segment.ident.to_string().as_str() {
+ "String" => Some(Field::FieldString),
+ "bool" => Some(Field::FieldBool),
+ "i8" => Some(Field::FieldI8),
+ "u8" => Some(Field::FieldU8),
+ "i16" => Some(Field::FieldI16),
+ "u16" => Some(Field::FieldU16),
+ "i32" => Some(Field::FieldI32),
+ "u32" => Some(Field::FieldU32),
+ "i64" => Some(Field::FieldI64),
+ "u64" => Some(Field::FieldU64),
+ "f32" => Some(Field::FieldF32),
+ "f64" => Some(Field::FieldF64),
+ "Option" => Some(Field::FieldOption {
+ data_type: Box::new(Field::from(segment)),
+ }),
+ "Vec" => Some(Field::FieldVec {
+ data_type: Box::new(Field::from(segment)),
+ }),
+ _ => None,
+ }
+ } else {
+ None
+ };
+
+ result.unwrap_or_else(|| Field::FieldStruct {
+ struct_name: path.clone(),
+ })
+ }
+}
+
+impl From<&syn::Field> for Field {
+ fn from(field: &syn::Field) -> Self {
+ match field.ty {
+ Path(ref path) => Field::from(&path.path),
+ _ => panic!("unable to match {:?}", field.ty),
+ }
+ }
+}
+
+impl From<&syn::PathSegment> for Field {
+ fn from(path_segment: &syn::PathSegment) -> Self {
+ if let syn::PathArguments::AngleBracketed(ref args) = path_segment.arguments {
+ if let Some(tt) = args.args.first() {
+ if let syn::GenericArgument::Type(ref argument) = *tt {
+ if let Path(ref path) = *argument {
+ return Field::from(&path.path);
+ }
+ }
+ }
+ }
+ unimplemented!()
+ }
+}
+
+impl Into for Field {
+ fn into(self) -> proc_macro2::TokenStream {
+ match self {
+ Field::FieldString => quote! {String},
+ Field::FieldBool => quote! {bool},
+ Field::FieldI8 => quote! {i8},
+ Field::FieldU8 => quote! {u8},
+ Field::FieldI16 => quote! {i16},
+ Field::FieldU16 => quote! {u16},
+ Field::FieldI32 => quote! {i32},
+ Field::FieldU32 => quote! {u32},
+ Field::FieldI64 => quote! {i64},
+ Field::FieldU64 => quote! {u64},
+ Field::FieldF32 => quote! {f32},
+ Field::FieldF64 => quote! {f64},
+ _ => panic!("Not a simple type: {:?}", self),
+ }
+ }
+}
+
+impl Into for &Field {
+ fn into(self) -> String {
+ match self {
+ Field::FieldString => "str".to_string(),
+ Field::FieldBool => "bool".to_string(),
+ Field::FieldI8 => "i8".to_string(),
+ Field::FieldU8 => "u8".to_string(),
+ Field::FieldI16 => "i16".to_string(),
+ Field::FieldU16 => "u16".to_string(),
+ Field::FieldI32 => "i32".to_string(),
+ Field::FieldU32 => "u32".to_string(),
+ Field::FieldI64 => "i64".to_string(),
+ Field::FieldU64 => "u64".to_string(),
+ Field::FieldF32 => "f32".to_string(),
+ Field::FieldF64 => "f64".to_string(),
+ _ => panic!("Not a simple type: {:?}", self),
+ }
+ }
+}
+
+impl fmt::Display for Field {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let string_representation: String = self.into();
+ write!(f, "{}", string_representation)
+ }
+}
diff --git a/yaserde_derive/src/common/mod.rs b/yaserde_derive/src/common/mod.rs
new file mode 100644
index 0000000..cee0625
--- /dev/null
+++ b/yaserde_derive/src/common/mod.rs
@@ -0,0 +1,5 @@
+mod attribute;
+mod field;
+
+pub use attribute::YaSerdeAttribute;
+pub use field::{Field, YaSerdeField};
diff --git a/yaserde_derive/src/de/build_default_value.rs b/yaserde_derive/src/de/build_default_value.rs
index 22a024e..cd1484d 100644
--- a/yaserde_derive/src/de/build_default_value.rs
+++ b/yaserde_derive/src/de/build_default_value.rs
@@ -1,28 +1,24 @@
-use proc_macro2::{Span, TokenStream};
-use syn::Ident;
+use crate::common::YaSerdeField;
+use proc_macro2::TokenStream;
pub fn build_default_value(
- label: &Option,
- field_type: &TokenStream,
- value: &TokenStream,
- default: &Option,
+ field: &YaSerdeField,
+ field_type: Option,
+ value: TokenStream,
) -> Option {
- let value = default
- .as_ref()
- .map(|d| {
- let default_function = Ident::new(
- &d,
- label
- .as_ref()
- .map_or(Span::call_site(), |ident| ident.span()),
- );
+ let label = field.get_value_label();
- quote!(#default_function())
- })
+ let default_value = field
+ .get_default_function()
+ .map(|default_function| quote!(#default_function()))
.unwrap_or_else(|| quote!(#value));
+ let field_type = field_type
+ .map(|field_type| quote!(: #field_type))
+ .unwrap_or(quote!());
+
Some(quote! {
#[allow(unused_mut)]
- let mut #label : #field_type = #value;
+ let mut #label #field_type = #default_value;
})
}
diff --git a/yaserde_derive/src/de/expand_enum.rs b/yaserde_derive/src/de/expand_enum.rs
index c43d246..76a110d 100644
--- a/yaserde_derive/src/de/expand_enum.rs
+++ b/yaserde_derive/src/de/expand_enum.rs
@@ -1,10 +1,6 @@
-use crate::attribute::*;
-use crate::field_type::*;
+use crate::common::{Field, YaSerdeAttribute, YaSerdeField};
use proc_macro2::TokenStream;
-use syn::spanned::Spanned;
-use syn::DataEnum;
-use syn::Fields;
-use syn::Ident;
+use syn::{DataEnum, Fields, Ident};
pub fn parse(
data_enum: &DataEnum,
@@ -141,9 +137,10 @@ fn build_unnamed_field_visitors(fields: &syn::FieldsUnnamed) -> TokenStream {
fields
.unnamed
.iter()
+ .map(|field| YaSerdeField::new(field.clone()))
.enumerate()
.map(|(idx, field)| {
- let visitor_label = Ident::new(&format!("__Visitor_{}", idx), field.span());
+ let visitor_label = Ident::new(&format!("__Visitor_{}", idx), field.get_span());
let make_visitor =
|visitor: &TokenStream, field_type: &TokenStream, fn_body: &TokenStream| {
@@ -160,9 +157,9 @@ fn build_unnamed_field_visitors(fields: &syn::FieldsUnnamed) -> TokenStream {
})
};
- let simple_type_visitor = |simple_type| {
- let field_type = get_simple_type_token(&simple_type);
- let visitor = get_simple_type_visitor(&simple_type);
+ let simple_type_visitor = |simple_type: Field| {
+ let visitor = simple_type.get_simple_type_visitor();
+ let field_type = simple_type.into();
make_visitor(
&visitor,
@@ -171,8 +168,8 @@ fn build_unnamed_field_visitors(fields: &syn::FieldsUnnamed) -> TokenStream {
)
};
- get_field_type(field).and_then(|f| match f {
- FieldType::FieldTypeStruct { struct_name } => {
+ match field.get_type() {
+ Field::FieldStruct { struct_name } => {
let struct_id: String = struct_name
.segments
.iter()
@@ -189,14 +186,12 @@ fn build_unnamed_field_visitors(fields: &syn::FieldsUnnamed) -> TokenStream {
},
)
}
- FieldType::FieldTypeOption { data_type } | FieldType::FieldTypeVec { data_type } => {
- match *data_type {
- FieldType::FieldTypeStruct { .. } => None,
- simple_type => simple_type_visitor(simple_type),
- }
- }
+ Field::FieldOption { data_type } | Field::FieldVec { data_type } => match *data_type {
+ Field::FieldStruct { .. } => None,
+ simple_type => simple_type_visitor(simple_type),
+ },
simple_type => simple_type_visitor(simple_type),
- })
+ }
})
.filter_map(|f| f)
.collect()
@@ -209,13 +204,14 @@ fn build_unnamed_visitor_calls(
fields
.unnamed
.iter()
+ .map(|field| YaSerdeField::new(field.clone()))
.enumerate()
.map(|(idx, field)| {
- let visitor_label = Ident::new(&format!("__Visitor_{}", idx), field.span());
+ let visitor_label = Ident::new(&format!("__Visitor_{}", idx), field.get_span());
- let call_simple_type_visitor = |simple_type, action| {
- let field_type = get_simple_type_token(&simple_type);
- let visitor = get_simple_type_visitor(&simple_type);
+ let call_simple_type_visitor = |simple_type: Field, action| {
+ let visitor = simple_type.get_simple_type_visitor();
+ let field_type: TokenStream = simple_type.into();
let label_name = format!("field_{}", idx);
@@ -279,19 +275,19 @@ fn build_unnamed_visitor_calls(
}
};
- get_field_type(field).and_then(|f| match f {
- FieldType::FieldTypeStruct { struct_name } => call_struct_visitor(struct_name, set_val),
- FieldType::FieldTypeOption { data_type } => match *data_type {
- FieldType::FieldTypeStruct { struct_name } => call_struct_visitor(struct_name, set_opt),
+ match field.get_type() {
+ Field::FieldStruct { struct_name } => call_struct_visitor(struct_name, set_val),
+ Field::FieldOption { data_type } => match *data_type {
+ Field::FieldStruct { struct_name } => call_struct_visitor(struct_name, set_opt),
simple_type => call_simple_type_visitor(simple_type, set_opt),
},
- FieldType::FieldTypeVec { data_type } => match *data_type {
- FieldType::FieldTypeStruct { struct_name } => call_struct_visitor(struct_name, set_vec),
+ Field::FieldVec { data_type } => match *data_type {
+ Field::FieldStruct { struct_name } => call_struct_visitor(struct_name, set_vec),
simple_type => call_simple_type_visitor(simple_type, set_vec),
},
simple_type => call_simple_type_visitor(simple_type, set_val),
- })
+ }
})
.filter_map(|f| f)
.collect()
diff --git a/yaserde_derive/src/de/expand_struct.rs b/yaserde_derive/src/de/expand_struct.rs
index 3c48215..bd9c718 100644
--- a/yaserde_derive/src/de/expand_struct.rs
+++ b/yaserde_derive/src/de/expand_struct.rs
@@ -1,11 +1,7 @@
-use crate::attribute::*;
+use crate::common::{Field, YaSerdeAttribute, YaSerdeField};
use crate::de::build_default_value::build_default_value;
-use crate::field_type::*;
use proc_macro2::{Span, TokenStream};
-use std::collections::BTreeMap;
-use syn::spanned::Spanned;
-use syn::DataStruct;
-use syn::Ident;
+use syn::{DataStruct, Ident};
pub fn parse(
data_struct: &DataStruct,
@@ -13,79 +9,43 @@ pub fn parse(
root: &str,
root_attributes: &YaSerdeAttribute,
) -> TokenStream {
- let namespaces_matches: TokenStream = root_attributes
- .namespaces
- .iter()
- .map(|(p, ns)| {
- if root_attributes.prefix.as_ref() == Some(p) {
- Some(quote!(#ns => {}))
- } else {
- None
- }
- })
- .filter_map(|x| x)
- .collect();
+ let namespaces_matching = root_attributes.get_namespace_matching(
+ &None,
+ quote!(struct_namespace),
+ quote!(named_element),
+ true,
+ );
let variables: TokenStream = data_struct
.fields
.iter()
- .map(|field| {
- let label = &get_value_label(&field.ident);
- let field_attrs = YaSerdeAttribute::parse(&field.attrs);
-
- get_field_type(field).and_then(|f| match f {
- FieldType::FieldTypeStruct { struct_name } => build_default_value(
- label,
- "e! {#struct_name},
- "e! {#struct_name::default()},
- &field_attrs.default,
- ),
- FieldType::FieldTypeOption { .. } => {
- if let Some(d) = &field_attrs.default {
- let default_function = Ident::new(&d, field.span());
-
- Some(quote! {
- #[allow(unused_mut, non_snake_case, non_camel_case_types)]
- let mut #label = #default_function();
- })
- } else {
- Some(quote! {
- #[allow(unused_mut, non_snake_case, non_camel_case_types)]
- let mut #label = None;
- })
- }
+ .map(|field| YaSerdeField::new(field.clone()))
+ .map(|field| match field.get_type() {
+ Field::FieldStruct { struct_name } => build_default_value(
+ &field,
+ Some(quote!(#struct_name)),
+ quote!(#struct_name::default()),
+ ),
+ Field::FieldOption { .. } => build_default_value(&field, None, quote!(None)),
+ Field::FieldVec { data_type } => match *data_type {
+ Field::FieldStruct { ref struct_name } => {
+ build_default_value(&field, Some(quote!(Vec<#struct_name>)), quote!(vec![]))
+ }
+ Field::FieldOption { .. } | Field::FieldVec { .. } => {
+ unimplemented!();
}
- FieldType::FieldTypeVec { data_type } => match *data_type {
- FieldType::FieldTypeStruct { ref struct_name } => build_default_value(
- label,
- "e! {Vec<#struct_name>},
- "e! {vec![]},
- &field_attrs.default,
- ),
- FieldType::FieldTypeOption { .. } | FieldType::FieldTypeVec { .. } => {
- unimplemented!();
- }
- simple_type => {
- let type_token = get_simple_type_token(&simple_type);
-
- build_default_value(
- label,
- "e! {Vec<#type_token>},
- "e! {vec![]},
- &field_attrs.default,
- )
- }
- },
simple_type => {
- let type_token = get_simple_type_token(&simple_type);
- build_default_value(
- label,
- &type_token,
- "e! {#type_token::default()},
- &field_attrs.default,
- )
+ let type_token: TokenStream = simple_type.into();
+
+ build_default_value(&field, Some(quote!(Vec<#type_token>)), quote!(vec![]))
}
- })
+ },
+ simple_type => {
+ let type_token: TokenStream = simple_type.into();
+ let value_builder = quote!(#type_token::default());
+
+ build_default_value(&field, Some(type_token), value_builder)
+ }
})
.filter_map(|x| x)
.collect();
@@ -93,12 +53,8 @@ pub fn parse(
let field_visitors: TokenStream = data_struct
.fields
.iter()
+ .map(|field| YaSerdeField::new(field.clone()))
.map(|field| {
- let field_attrs = YaSerdeAttribute::parse(&field.attrs);
- let label_name = field_attrs
- .rename
- .unwrap_or_else(|| field.ident.as_ref().unwrap().to_string());
-
let struct_visitor = |struct_name: syn::Path| {
let struct_id: String = struct_name
.segments
@@ -106,7 +62,7 @@ pub fn parse(
.map(|s| s.ident.to_string())
.collect();
- let visitor_label = build_visitor_ident(&label_name, field.span(), Some(&struct_name));
+ let visitor_label = field.get_visitor_ident(Some(&struct_name));
Some(quote! {
#[allow(non_snake_case, non_camel_case_types)]
@@ -123,10 +79,10 @@ pub fn parse(
})
};
- let simple_type_visitor = |simple_type: FieldType| {
- let field_type = get_simple_type_token(&simple_type);
- let visitor = get_simple_type_visitor(&simple_type);
- let visitor_label = build_visitor_ident(&label_name, field.span(), None);
+ let simple_type_visitor = |simple_type: Field| {
+ let visitor = simple_type.get_simple_type_visitor();
+ let visitor_label = field.get_visitor_ident(None);
+ let field_type: TokenStream = simple_type.into();
Some(quote! {
#[allow(non_snake_case, non_camel_case_types)]
@@ -141,20 +97,20 @@ pub fn parse(
})
};
- get_field_type(field).and_then(|f| match f {
- FieldType::FieldTypeStruct { struct_name } => struct_visitor(struct_name),
- FieldType::FieldTypeOption { data_type } => match *data_type {
- FieldType::FieldTypeStruct { struct_name } => struct_visitor(struct_name),
- FieldType::FieldTypeOption { .. } | FieldType::FieldTypeVec { .. } => None,
+ match field.get_type() {
+ Field::FieldStruct { struct_name } => struct_visitor(struct_name),
+ Field::FieldOption { data_type } => match *data_type {
+ Field::FieldStruct { struct_name } => struct_visitor(struct_name),
+ Field::FieldOption { .. } | Field::FieldVec { .. } => None,
simple_type => simple_type_visitor(simple_type),
},
- FieldType::FieldTypeVec { data_type } => match *data_type {
- FieldType::FieldTypeStruct { struct_name } => struct_visitor(struct_name),
- FieldType::FieldTypeOption { .. } | FieldType::FieldTypeVec { .. } => None,
+ Field::FieldVec { data_type } => match *data_type {
+ Field::FieldStruct { struct_name } => struct_visitor(struct_name),
+ Field::FieldOption { .. } | Field::FieldVec { .. } => None,
simple_type => simple_type_visitor(simple_type),
},
simple_type => simple_type_visitor(simple_type),
- })
+ }
})
.filter_map(|x| x)
.collect();
@@ -162,19 +118,11 @@ pub fn parse(
let call_visitors: TokenStream = data_struct
.fields
.iter()
+ .map(|field| YaSerdeField::new(field.clone()))
+ .filter(|field| !field.is_attribute() || !field.is_flatten())
.map(|field| {
- let field_attrs = YaSerdeAttribute::parse(&field.attrs);
- let label = &field.ident;
- let value_label = &get_value_label(&field.ident);
-
- if field_attrs.attribute || field_attrs.flatten {
- return None;
- }
-
- let label_name = field_attrs
- .rename
- .clone()
- .unwrap_or_else(|| label.as_ref().unwrap().to_string());
+ let value_label = field.get_value_label();
+ let label_name = field.renamed_label_without_namespace();
let visit_struct = |struct_name: syn::Path, action: TokenStream| {
Some(quote! {
@@ -192,30 +140,30 @@ pub fn parse(
})
};
- let visit_simple = |simple_type: FieldType, action: TokenStream| {
+ let visit_simple = |simple_type: Field, action: TokenStream| {
+ let field_visitor = simple_type.get_simple_type_visitor();
+ let field_type: TokenStream = simple_type.into();
build_call_visitor(
- &get_simple_type_token(&simple_type),
- &get_simple_type_visitor(&simple_type),
+ &field_type,
+ &field_visitor,
&action,
- &field_attrs,
- label,
- &root_attributes.namespaces,
- field.span(),
+ &field,
+ &root_attributes,
)
};
- let visit_sub = |sub_type: Box, action: TokenStream| match *sub_type {
- FieldType::FieldTypeOption { .. } | FieldType::FieldTypeVec { .. } => unimplemented!(),
- FieldType::FieldTypeStruct { struct_name } => visit_struct(struct_name, action),
+ let visit_sub = |sub_type: Box, action: TokenStream| match *sub_type {
+ Field::FieldOption { .. } | Field::FieldVec { .. } => unimplemented!(),
+ Field::FieldStruct { struct_name } => visit_struct(struct_name, action),
simple_type => visit_simple(simple_type, action),
};
- get_field_type(field).and_then(|f| match f {
- FieldType::FieldTypeStruct { struct_name } => visit_struct(struct_name, quote! {= value}),
- FieldType::FieldTypeOption { data_type } => visit_sub(data_type, quote! {= Some(value)}),
- FieldType::FieldTypeVec { data_type } => visit_sub(data_type, quote! {.push(value)}),
+ match field.get_type() {
+ Field::FieldStruct { struct_name } => visit_struct(struct_name, quote! {= value}),
+ Field::FieldOption { data_type } => visit_sub(data_type, quote! {= Some(value)}),
+ Field::FieldVec { data_type } => visit_sub(data_type, quote! {.push(value)}),
simple_type => visit_simple(simple_type, quote! {= value}),
- })
+ }
})
.filter_map(|x| x)
.collect();
@@ -223,26 +171,23 @@ pub fn parse(
let call_flatten_visitors: TokenStream = data_struct
.fields
.iter()
+ .map(|field| YaSerdeField::new(field.clone()))
+ .filter(|field| !field.is_attribute() && field.is_flatten())
.map(|field| {
- let field_attrs = YaSerdeAttribute::parse(&field.attrs);
- let value_label = &get_value_label(&field.ident);
+ let value_label = field.get_value_label();
- if field_attrs.attribute || !field_attrs.flatten {
- return None;
- }
-
- get_field_type(field).and_then(|f| match f {
- FieldType::FieldTypeStruct { .. } => Some(quote! {
+ match field.get_type() {
+ Field::FieldStruct { .. } => Some(quote! {
#value_label = yaserde::de::from_str(&unused_xml_elements)?;
}),
- FieldType::FieldTypeOption { data_type } => match *data_type {
- FieldType::FieldTypeStruct { .. } => Some(quote! {
+ Field::FieldOption { data_type } => match *data_type {
+ Field::FieldStruct { .. } => Some(quote! {
#value_label = yaserde::de::from_str(&unused_xml_elements).ok();
}),
- field_type => unimplemented!("\"flatten\" is not implemented for {:?}", field_type),
+ field_type => unimplemented!(r#""flatten" is not implemented for {:?}"#, field_type),
},
- field_type => unimplemented!("\"flatten\" is not implemented for {:?}", field_type),
- })
+ field_type => unimplemented!(r#""flatten" is not implemented for {:?}"#, field_type),
+ }
})
.filter_map(|x| x)
.collect();
@@ -250,19 +195,12 @@ pub fn parse(
let attributes_loading: TokenStream = data_struct
.fields
.iter()
+ .map(|field| YaSerdeField::new(field.clone()))
+ .filter(|field| field.is_attribute())
.map(|field| {
- let field_attrs = YaSerdeAttribute::parse(&field.attrs);
- if !field_attrs.attribute {
- return None;
- }
-
- let label = &get_value_label(&field.ident);
-
- let label_name = field_attrs
- .rename
- .unwrap_or_else(|| field.ident.as_ref().unwrap().to_string());
-
- let visitor_label = build_visitor_ident(&label_name, field.span(), None);
+ let label = field.get_value_label();
+ let label_name = field.renamed_label_without_namespace();
+ let visitor_label = build_visitor_ident(&label_name, field.get_span(), None);
let visit = |action: &TokenStream, visitor: &TokenStream, visitor_label: &Ident| {
Some(quote! {
@@ -290,31 +228,31 @@ pub fn parse(
visit(
&action,
"e! {visit_str},
- &build_visitor_ident(&label_name, field.span(), Some(&struct_name)),
+ &build_visitor_ident(&label_name, field.get_span(), Some(&struct_name)),
)
};
- let visit_simple = |simple_type: FieldType, action: TokenStream| {
+ let visit_simple = |simple_type: Field, action: TokenStream| {
visit(
&action,
- &get_simple_type_visitor(&simple_type),
+ &simple_type.get_simple_type_visitor(),
&visitor_label,
)
};
- let visit_sub = |sub_type: Box, action: TokenStream| match *sub_type {
- FieldType::FieldTypeOption { .. } | FieldType::FieldTypeVec { .. } => unimplemented!(),
- FieldType::FieldTypeStruct { struct_name } => visit_struct(struct_name, action),
+ let visit_sub = |sub_type: Box, action: TokenStream| match *sub_type {
+ Field::FieldOption { .. } | Field::FieldVec { .. } => unimplemented!(),
+ Field::FieldStruct { struct_name } => visit_struct(struct_name, action),
simple_type => visit_simple(simple_type, action),
};
- get_field_type(field).and_then(|f| match f {
- FieldType::FieldTypeString => visit_string(),
- FieldType::FieldTypeOption { data_type } => visit_sub(data_type, quote! {= Some(value)}),
- FieldType::FieldTypeVec { .. } => unimplemented!(),
- FieldType::FieldTypeStruct { struct_name } => visit_struct(struct_name, quote! {= value}),
+ match field.get_type() {
+ Field::FieldString => visit_string(),
+ Field::FieldOption { data_type } => visit_sub(data_type, quote! {= Some(value)}),
+ Field::FieldVec { .. } => unimplemented!(),
+ Field::FieldStruct { struct_name } => visit_struct(struct_name, quote! {= value}),
simple_type => visit_simple(simple_type, quote! {= value}),
- })
+ }
})
.filter_map(|x| x)
.collect();
@@ -322,28 +260,26 @@ pub fn parse(
let set_text: TokenStream = data_struct
.fields
.iter()
+ .map(|field| YaSerdeField::new(field.clone()))
.map(|field| {
- let label = &get_value_label(&field.ident);
- let field_attrs = YaSerdeAttribute::parse(&field.attrs);
+ let label = field.get_value_label();
let set_text = |action: &TokenStream| {
- if field_attrs.text {
+ if field.is_text_content() {
Some(quote! {#label = #action;})
} else {
None
}
};
- get_field_type(field).and_then(|f| match f {
- FieldType::FieldTypeString => set_text("e! {text_content.to_owned()}),
- FieldType::FieldTypeStruct { .. }
- | FieldType::FieldTypeOption { .. }
- | FieldType::FieldTypeVec { .. } => None,
+ match field.get_type() {
+ Field::FieldString => set_text("e! {text_content.to_owned()}),
+ Field::FieldStruct { .. } | Field::FieldOption { .. } | Field::FieldVec { .. } => None,
simple_type => {
- let type_token = get_simple_type_token(&simple_type);
+ let type_token: TokenStream = simple_type.into();
set_text("e! {#type_token::from_str(text_content).unwrap()})
}
- })
+ }
})
.filter_map(|x| x)
.collect();
@@ -351,15 +287,13 @@ pub fn parse(
let struct_builder: TokenStream = data_struct
.fields
.iter()
+ .map(|field| YaSerdeField::new(field.clone()))
.map(|field| {
- let label = &field.ident;
- let value_label = &get_value_label(&field.ident);
+ let label = &field.label();
+ let value_label = field.get_value_label();
- get_field_type(field).map(|_| {
- quote! { #label: #value_label, }
- })
+ quote! { #label: #value_label, }
})
- .filter_map(|x| x)
.collect();
let (init_unused, write_unused, visit_unused) = if call_flatten_visitors.is_empty() {
@@ -390,15 +324,7 @@ pub fn parse(
debug!("Struct: start to parse {:?}", named_element);
if reader.depth() == 0 {
- if let Some(ref namespace) = struct_namespace {
- match namespace.as_str() {
- #namespaces_matches
- bad_ns => {
- let msg = format!("bad namespace for {}, found {}", named_element, bad_ns);
- return Err(msg);
- }
- }
- }
+ #namespaces_matching
}
#variables
@@ -472,47 +398,24 @@ fn build_call_visitor(
field_type: &TokenStream,
visitor: &TokenStream,
action: &TokenStream,
- field_attrs: &YaSerdeAttribute,
- label: &Option,
- namespaces: &BTreeMap,
- span: Span,
+ field: &YaSerdeField,
+ root_attributes: &YaSerdeAttribute,
) -> Option {
- let prefix = field_attrs.prefix.clone();
+ let value_label = field.get_value_label();
+ let label_name = field.renamed_label_without_namespace();
+ let visitor_label = build_visitor_ident(&label_name, field.get_span(), None);
- // let label = &field.ident;
- let value_label = get_value_label(label);
- let label_name = field_attrs
- .rename
- .clone()
- .unwrap_or_else(|| label.as_ref().unwrap().to_string());
-
- let visitor_label = build_visitor_ident(&label_name, span, None);
-
- let namespaces_matches: TokenStream = namespaces
- .iter()
- .map(|(p, ns)| {
- if prefix == Some(p.to_string()) {
- Some(quote!(#ns => {}))
- } else {
- None
- }
- })
- .filter_map(|x| x)
- .collect();
+ let namespaces_matching = field.get_namespace_matching(
+ root_attributes,
+ quote!(name.namespace.as_ref()),
+ quote!(name.local_name.as_str()),
+ );
Some(quote! {
#label_name => {
let visitor = #visitor_label{};
- if let Some(namespace) = name.namespace.as_ref() {
- match namespace.as_str() {
- #namespaces_matches
- bad_ns => {
- let msg = format!("bad field namespace for {}, found {}", name.local_name.as_str(), bad_ns);
- return Err(msg);
- }
- }
- }
+ #namespaces_matching
let result = reader.read_inner_value::<#field_type, _>(|reader| {
if let Ok(XmlEvent::Characters(s)) = reader.peek() {
@@ -531,12 +434,6 @@ fn build_call_visitor(
})
}
-fn get_value_label(ident: &Option) -> Option {
- ident
- .clone()
- .map(|ident| syn::Ident::new(&format!("__{}_value", ident.to_string()), ident.span()))
-}
-
fn build_visitor_ident(label: &str, span: Span, struct_name: Option<&syn::Path>) -> Ident {
let struct_id = struct_name.map_or_else(
|| "".to_string(),
diff --git a/yaserde_derive/src/de/mod.rs b/yaserde_derive/src/de/mod.rs
index 84f1f17..a6df2b3 100644
--- a/yaserde_derive/src/de/mod.rs
+++ b/yaserde_derive/src/de/mod.rs
@@ -2,7 +2,7 @@ pub mod build_default_value;
pub mod expand_enum;
pub mod expand_struct;
-use crate::attribute;
+use crate::common::YaSerdeAttribute;
use proc_macro2::TokenStream;
use syn;
use syn::Ident;
@@ -12,14 +12,19 @@ pub fn expand_derive_deserialize(ast: &syn::DeriveInput) -> Result {
- expand_struct::parse(data_struct, name, &root, &root_attrs)
+ expand_struct::parse(data_struct, name, &root_name, &root_attributes)
+ }
+ syn::Data::Enum(ref data_enum) => {
+ expand_enum::parse(data_enum, name, &root_name, &root_attributes)
}
- 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/field_type.rs b/yaserde_derive/src/field_type.rs
deleted file mode 100644
index b9b55c6..0000000
--- a/yaserde_derive/src/field_type.rs
+++ /dev/null
@@ -1,102 +0,0 @@
-use syn;
-use syn::Type::Path;
-
-#[derive(Debug)]
-pub enum FieldType {
- FieldTypeString,
- FieldTypeBool,
- FieldTypeI8,
- FieldTypeU8,
- FieldTypeI16,
- FieldTypeU16,
- FieldTypeI32,
- FieldTypeU32,
- FieldTypeI64,
- FieldTypeU64,
- FieldTypeF32,
- FieldTypeF64,
- FieldTypeOption { data_type: Box },
- FieldTypeVec { data_type: Box },
- FieldTypeStruct { struct_name: syn::Path },
-}
-
-impl FieldType {
- fn from_ident(path: &syn::Path) -> Option {
- match path.segments.last() {
- Some(t) => match t.ident.to_string().as_str() {
- "String" => Some(FieldType::FieldTypeString),
- "bool" => Some(FieldType::FieldTypeBool),
- "i8" => Some(FieldType::FieldTypeI8),
- "u8" => Some(FieldType::FieldTypeU8),
- "i16" => Some(FieldType::FieldTypeI16),
- "u16" => Some(FieldType::FieldTypeU16),
- "i32" => Some(FieldType::FieldTypeI32),
- "u32" => Some(FieldType::FieldTypeU32),
- "i64" => Some(FieldType::FieldTypeI64),
- "u64" => Some(FieldType::FieldTypeU64),
- "f32" => Some(FieldType::FieldTypeF32),
- "f64" => Some(FieldType::FieldTypeF64),
- "Option" => get_sub_type(t).map(|data_type| FieldType::FieldTypeOption {
- data_type: Box::new(FieldType::from_ident(&data_type).unwrap()),
- }),
- "Vec" => get_sub_type(t).map(|data_type| FieldType::FieldTypeVec {
- data_type: Box::new(FieldType::from_ident(&data_type).unwrap()),
- }),
- _ => Some(FieldType::FieldTypeStruct {
- struct_name: path.clone(),
- }),
- },
- _ => None,
- }
- }
-}
-
-pub fn get_field_type(field: &syn::Field) -> Option {
- match field.ty {
- Path(ref path) => FieldType::from_ident(&path.path),
- _ => None,
- }
-}
-
-fn get_sub_type(t: &syn::PathSegment) -> Option {
- if let syn::PathArguments::AngleBracketed(ref args) = t.arguments {
- if let Some(tt) = args.args.first() {
- if let syn::GenericArgument::Type(ref argument) = *tt {
- if let Path(ref path) = *argument {
- return Some(path.path.clone());
- }
- }
- }
- }
-
- None
-}
-
-pub fn get_simple_type_token(field_type: &FieldType) -> proc_macro2::TokenStream {
- match field_type {
- FieldType::FieldTypeString => quote! {String},
- FieldType::FieldTypeBool => quote! {bool},
- FieldType::FieldTypeI8 => quote! {i8},
- FieldType::FieldTypeU8 => quote! {u8},
- FieldType::FieldTypeI16 => quote! {i16},
- FieldType::FieldTypeU16 => quote! {u16},
- FieldType::FieldTypeI32 => quote! {i32},
- FieldType::FieldTypeU32 => quote! {u32},
- FieldType::FieldTypeI64 => quote! {i64},
- FieldType::FieldTypeU64 => quote! {u64},
- FieldType::FieldTypeF32 => quote! {f32},
- FieldType::FieldTypeF64 => quote! {f64},
- _ => panic!("Not a simple type: {:?}", field_type),
- }
-}
-
-pub fn get_simple_type_visitor(field_type: &FieldType) -> proc_macro2::TokenStream {
- let ident = format_ident!(
- "visit_{}",
- get_simple_type_token(field_type)
- .to_string()
- .replace("String", "str")
- );
-
- quote! {#ident}
-}
diff --git a/yaserde_derive/src/lib.rs b/yaserde_derive/src/lib.rs
index 527a439..7fd17fa 100644
--- a/yaserde_derive/src/lib.rs
+++ b/yaserde_derive/src/lib.rs
@@ -6,9 +6,8 @@ extern crate proc_macro2;
extern crate quote;
extern crate syn;
-mod attribute;
+mod common;
mod de;
-mod field_type;
mod ser;
use proc_macro::TokenStream;
diff --git a/yaserde_derive/src/ser/element.rs b/yaserde_derive/src/ser/element.rs
index 313be33..d00e832 100644
--- a/yaserde_derive/src/ser/element.rs
+++ b/yaserde_derive/src/ser/element.rs
@@ -1,5 +1,5 @@
-use crate::attribute::*;
-use proc_macro2::{Ident, Span, TokenStream};
+use crate::common::YaSerdeField;
+use proc_macro2::{Ident, TokenStream};
pub fn enclose_formatted_characters(label: &Ident, label_name: String) -> TokenStream {
enclose_xml_event(label_name, quote!(format!("{}", &self.#label)))
@@ -13,7 +13,7 @@ pub fn enclose_characters(label: &Option, label_name: String) -> TokenStr
enclose_xml_event(label_name, quote!(format!("{}", self.#label)))
}
-pub fn enclose_xml_event(label_name: String, yaserde_format: TokenStream) -> TokenStream {
+fn enclose_xml_event(label_name: String, yaserde_format: TokenStream) -> TokenStream {
quote! {
let start_event = XmlEvent::start_element(#label_name);
writer.write(start_event).map_err(|e| e.to_string())?;
@@ -41,34 +41,23 @@ pub fn serialize_element(
})
}
-pub fn condition_generator(label: &Option, attributes: &YaSerdeAttribute) -> TokenStream {
- let mut conditions = None;
+pub fn condition_generator(label: &Option, field: &YaSerdeField) -> TokenStream {
+ let default_condition = field
+ .get_default_function()
+ .map(|default_function| quote!(self.#label != #default_function()));
- if let Some(ref d) = attributes.default {
- let default_function = Ident::new(
- &d,
- label
- .as_ref()
- .map_or(Span::call_site(), |ident| ident.span()),
- );
-
- conditions = Some(quote!(self.#label != #default_function()))
- }
-
- if let Some(ref s) = attributes.skip_serializing_if {
- let skip_if_function = Ident::new(
- &s,
- label
- .as_ref()
- .map_or(Span::call_site(), |ident| ident.span()),
- );
-
- conditions = if let Some(prev_conditions) = conditions {
- Some(quote!(!#skip_if_function() && #prev_conditions))
- } else {
- Some(quote!(!self.#skip_if_function(&self.#label)))
- };
- }
-
- conditions.map(|c| quote!(if #c)).unwrap_or(quote!())
+ field
+ .get_skip_serializing_if_function()
+ .map(|skip_if_function| {
+ if let Some(prev_conditions) = &default_condition {
+ quote!(if !self.#skip_if_function(&self.#label) && #prev_conditions)
+ } else {
+ quote!(if !self.#skip_if_function(&self.#label))
+ }
+ })
+ .unwrap_or_else(|| {
+ default_condition
+ .map(|condition| quote!(if #condition))
+ .unwrap_or(quote!())
+ })
}
diff --git a/yaserde_derive/src/ser/expand_enum.rs b/yaserde_derive/src/ser/expand_enum.rs
index fb42821..eb9521c 100644
--- a/yaserde_derive/src/ser/expand_enum.rs
+++ b/yaserde_derive/src/ser/expand_enum.rs
@@ -1,8 +1,6 @@
-use crate::attribute::*;
-use crate::field_type::*;
+use crate::common::{Field, YaSerdeAttribute, YaSerdeField};
use crate::ser::{implement_deserializer::implement_deserializer, label::build_label_name};
use proc_macro2::TokenStream;
-use syn::spanned::Spanned;
use syn::DataEnum;
use syn::Fields;
use syn::Ident;
@@ -51,39 +49,33 @@ fn inner_enum_inspector(
let enum_fields: TokenStream = fields
.named
.iter()
+ .map(|field| YaSerdeField::new(field.clone()))
+ .filter(|field| !field.is_attribute())
.map(|field| {
- let field_attrs = YaSerdeAttribute::parse(&field.attrs);
- if field_attrs.attribute {
- return None;
- }
+ let field_label = field.label();
- let field_label = &field.ident;
- if field_attrs.text {
+ if field.is_text_content() {
return Some(quote!(
let data_event = XmlEvent::characters(&self.#field_label);
writer.write(data_event).map_err(|e| e.to_string())?;
));
}
- let renamed_field_label = match field_attrs.rename {
- Some(value) => Some(Ident::new(&value.replace("\"", ""), field.span())),
- None => field.ident.clone(),
- };
- let field_label_name = renamed_field_label.unwrap().to_string();
+ let field_label_name = field.renamed_label(root_attributes);
- match get_field_type(field) {
- Some(FieldType::FieldTypeString)
- | Some(FieldType::FieldTypeBool)
- | Some(FieldType::FieldTypeU8)
- | Some(FieldType::FieldTypeI8)
- | Some(FieldType::FieldTypeU16)
- | Some(FieldType::FieldTypeI16)
- | Some(FieldType::FieldTypeU32)
- | Some(FieldType::FieldTypeI32)
- | Some(FieldType::FieldTypeF32)
- | Some(FieldType::FieldTypeU64)
- | Some(FieldType::FieldTypeI64)
- | Some(FieldType::FieldTypeF64) => Some({
+ match field.get_type() {
+ Field::FieldString
+ | Field::FieldBool
+ | Field::FieldU8
+ | Field::FieldI8
+ | Field::FieldU16
+ | Field::FieldI16
+ | Field::FieldU32
+ | Field::FieldI32
+ | Field::FieldF32
+ | Field::FieldU64
+ | Field::FieldI64
+ | Field::FieldF64 => Some({
quote! {
match self {
name::#label{ref #field_label, ..} => {
@@ -101,7 +93,7 @@ fn inner_enum_inspector(
}
}
}),
- Some(FieldType::FieldTypeStruct { .. }) => Some(quote! {
+ Field::FieldStruct { .. } => Some(quote! {
match self {
name::#label{ref #field_label, ..} => {
writer.set_start_event_name(Some(#field_label_name.to_string()));
@@ -111,7 +103,7 @@ fn inner_enum_inspector(
_ => {}
}
}),
- Some(FieldType::FieldTypeVec { .. }) => Some(quote! {
+ Field::FieldVec { .. } => Some(quote! {
match self {
name::#label{ref #field_label, ..} => {
for item in #field_label {
@@ -123,7 +115,7 @@ fn inner_enum_inspector(
_ => {}
}
}),
- _ => None,
+ Field::FieldOption { .. } => None,
}
})
.filter_map(|x| x)
@@ -139,12 +131,9 @@ fn inner_enum_inspector(
let enum_fields: TokenStream = fields
.unnamed
.iter()
+ .map(|field| YaSerdeField::new(field.clone()))
+ .filter(|field| !field.is_attribute())
.map(|field| {
- let field_attrs = YaSerdeAttribute::parse(&field.attrs);
- if field_attrs.attribute {
- return None;
- }
-
let write_element = |action: &TokenStream| {
quote! {
let struct_start_event = XmlEvent::start_element(#label_name);
@@ -176,7 +165,7 @@ fn inner_enum_inspector(
let write_sub_type = |data_type| {
write_element(match data_type {
- FieldType::FieldTypeString => &write_string_chars,
+ Field::FieldString => &write_string_chars,
_ => &serialize,
})
};
@@ -192,8 +181,8 @@ fn inner_enum_inspector(
}
};
- match get_field_type(field) {
- Some(FieldType::FieldTypeOption { data_type }) => {
+ match field.get_type() {
+ Field::FieldOption { data_type } => {
let write = write_sub_type(*data_type);
Some(match_field("e! {
@@ -202,7 +191,7 @@ fn inner_enum_inspector(
}
}))
}
- Some(FieldType::FieldTypeVec { data_type }) => {
+ Field::FieldVec { data_type } => {
let write = write_sub_type(*data_type);
Some(match_field("e! {
@@ -211,14 +200,9 @@ fn inner_enum_inspector(
}
}))
}
- Some(FieldType::FieldTypeStruct { .. }) => {
- Some(write_element(&match_field(&serialize)))
- }
- Some(FieldType::FieldTypeString) => {
- Some(match_field(&write_element(&write_string_chars)))
- }
- Some(_simple_type) => Some(match_field(&write_simple_type)),
- _ => None,
+ Field::FieldStruct { .. } => Some(write_element(&match_field(&serialize))),
+ Field::FieldString => Some(match_field(&write_element(&write_string_chars))),
+ _simple_type => Some(match_field(&write_simple_type)),
}
})
.filter_map(|x| x)
diff --git a/yaserde_derive/src/ser/expand_struct.rs b/yaserde_derive/src/ser/expand_struct.rs
index 16bfed5..1201df4 100644
--- a/yaserde_derive/src/ser/expand_struct.rs
+++ b/yaserde_derive/src/ser/expand_struct.rs
@@ -1,10 +1,7 @@
-use crate::attribute::*;
-use crate::field_type::*;
-use crate::ser::{
- element::*, implement_deserializer::implement_deserializer, label::build_label_name,
-};
+use crate::common::{Field, YaSerdeAttribute, YaSerdeField};
+
+use crate::ser::{element::*, implement_deserializer::implement_deserializer};
use proc_macro2::TokenStream;
-use syn::spanned::Spanned;
use syn::DataStruct;
use syn::Ident;
@@ -17,193 +14,98 @@ pub fn serialize(
let build_attributes: TokenStream = data_struct
.fields
.iter()
+ .map(|field| YaSerdeField::new(field.clone()))
+ .filter(|field| field.is_attribute())
.map(|field| {
- let field_attrs = YaSerdeAttribute::parse(&field.attrs);
- if !field_attrs.attribute {
- return None;
- }
+ let label = field.label();
+ let label_name = field.renamed_label(root_attributes);
- let label = &field.ident;
-
- let label_name = build_label_name(
- &label.as_ref().unwrap(),
- &field_attrs,
- &root_attributes.default_namespace,
- );
-
- get_field_type(field).and_then(|f| match f {
- FieldType::FieldTypeString
- | FieldType::FieldTypeBool
- | FieldType::FieldTypeI8
- | FieldType::FieldTypeU8
- | FieldType::FieldTypeI16
- | FieldType::FieldTypeU16
- | FieldType::FieldTypeI32
- | FieldType::FieldTypeU32
- | FieldType::FieldTypeI64
- | FieldType::FieldTypeU64
- | FieldType::FieldTypeF32
- | FieldType::FieldTypeF64 => {
- if let Some(ref d) = field_attrs.default {
- let default_function = Ident::new(&d, field.span());
- Some(quote! {
- let content = self.#label.to_string();
- let struct_start_event =
- if self.#label != #default_function() {
- struct_start_event.attr(#label_name, &content)
- } else {
- struct_start_event
- };
- })
- } else {
- Some(quote! {
- let content = self.#label.to_string();
- let struct_start_event = struct_start_event.attr(#label_name, &content);
- })
- }
- }
- FieldType::FieldTypeOption { data_type } => match *data_type {
- FieldType::FieldTypeString => {
- if let Some(ref d) = field_attrs.default {
- let default_function = Ident::new(&d, field.span());
- Some(quote! {
- let struct_start_event =
- if self.#label != #default_function() {
- if let Some(ref value) = self.#label {
- struct_start_event.attr(#label_name, &value)
- } else {
- struct_start_event
- }
- } else {
- struct_start_event
- };
- })
- } else {
- Some(quote! {
- let struct_start_event =
- if let Some(ref value) = self.#label {
- struct_start_event.attr(#label_name, &value)
- } else {
- struct_start_event
- };
- })
- }
- }
- FieldType::FieldTypeBool
- | FieldType::FieldTypeI8
- | FieldType::FieldTypeU8
- | FieldType::FieldTypeI16
- | FieldType::FieldTypeU16
- | FieldType::FieldTypeI32
- | FieldType::FieldTypeU32
- | FieldType::FieldTypeI64
- | FieldType::FieldTypeU64
- | FieldType::FieldTypeF32
- | FieldType::FieldTypeF64 => {
- if let Some(ref d) = field_attrs.default {
- let default_function = Ident::new(&d, field.span());
- Some(quote! {
- let content = self.#label.map_or_else(|| String::new(), |v| v.to_string());
- let struct_start_event =
- if self.#label != #default_function() {
- if let Some(ref value) = self.#label {
- struct_start_event.attr(#label_name, &content)
- } else {
- struct_start_event
- }
- } else {
- struct_start_event
- };
- })
- } else {
- Some(quote! {
- let content = self.#label.map_or_else(|| String::new(), |v| v.to_string());
- let struct_start_event =
- if let Some(ref value) = self.#label {
- struct_start_event.attr(#label_name, &content)
- } else {
- struct_start_event
- };
- })
- }
- }
- FieldType::FieldTypeVec { .. } => {
- let item_ident = Ident::new("yaserde_item", field.span());
+ match field.get_type() {
+ Field::FieldString
+ | Field::FieldBool
+ | Field::FieldI8
+ | Field::FieldU8
+ | Field::FieldI16
+ | Field::FieldU16
+ | Field::FieldI32
+ | Field::FieldU32
+ | Field::FieldI64
+ | Field::FieldU64
+ | Field::FieldF32
+ | Field::FieldF64 => Some(field.ser_wrap_default_attribute(
+ Some(quote!(self.#label.to_string())),
+ quote!({
+ struct_start_event.attr(#label_name, &yaserde_inner)
+ }),
+ )),
+ Field::FieldOption { data_type } => match *data_type {
+ Field::FieldString => Some(field.ser_wrap_default_attribute(
+ None,
+ quote!({
+ if let Some(ref value) = self.#label {
+ struct_start_event.attr(#label_name, value)
+ } else {
+ struct_start_event
+ }
+ }),
+ )),
+ Field::FieldBool
+ | Field::FieldI8
+ | Field::FieldU8
+ | Field::FieldI16
+ | Field::FieldU16
+ | Field::FieldI32
+ | Field::FieldU32
+ | Field::FieldI64
+ | Field::FieldU64
+ | Field::FieldF32
+ | Field::FieldF64 => Some(field.ser_wrap_default_attribute(
+ Some(quote!(self.#label.map_or_else(|| String::new(), |v| v.to_string()))),
+ quote!({
+ if let Some(ref value) = self.#label {
+ struct_start_event.attr(#label_name, &yaserde_inner)
+ } else {
+ struct_start_event
+ }
+ }),
+ )),
+ Field::FieldVec { .. } => {
+ let item_ident = Ident::new("yaserde_item", field.get_span());
let inner = enclose_formatted_characters(&item_ident, label_name);
- if let Some(ref d) = field_attrs.default {
- let default_function = Ident::new(&d, field.span());
-
- Some(quote! {
- if self.#label != #default_function() {
- if let Some(ref yaserde_list) = self.#label {
- for yaserde_item in yaserde_list.iter() {
- #inner
- }
+ Some(field.ser_wrap_default_attribute(
+ None,
+ quote!({
+ if let Some(ref yaserde_list) = self.#label {
+ for yaserde_item in yaserde_list.iter() {
+ #inner
}
}
- })
- } else {
- Some(quote! {
- for yaserde_item in &self.#label {
- #inner
- }
- })
- }
+ }),
+ ))
}
- FieldType::FieldTypeStruct { .. } => {
- if let Some(ref d) = field_attrs.default {
- let default_function = Ident::new(&d, field.span());
- Some(quote! {
- let content = self.#label
+ Field::FieldStruct { .. } => Some(field.ser_wrap_default_attribute(
+ Some(quote!(self.#label
.as_ref()
- .map_or_else(|| Ok(String::new()), |v| yaserde::ser::to_string_content(v))?;
- let struct_start_event = if let Some(ref value) = self.#label {
- if *value != #default_function() {
- struct_start_event.attr(#label_name, &content)
- } else {
- struct_start_event
- }
- } else {
- struct_start_event
- };
- })
- } else {
- Some(quote! {
- let content = self.#label
- .as_ref()
- .map_or_else(|| Ok(String::new()), |v| yaserde::ser::to_string_content(v))?;
- let struct_start_event = if let Some(ref value) = self.#label {
- struct_start_event.attr(#label_name, &content)
- } else {
- struct_start_event
- };
- })
- }
- }
- _ => unimplemented!(),
+ .map_or_else(|| Ok(String::new()), |v| yaserde::ser::to_string_content(v))?)),
+ quote!({
+ if let Some(ref yaserde_struct) = self.#label {
+ struct_start_event.attr(#label_name, &yaserde_inner)
+ } else {
+ struct_start_event
+ }
+ }),
+ )),
+ Field::FieldOption { .. } => unimplemented!(),
},
- FieldType::FieldTypeStruct { .. } => {
- if let Some(ref d) = field_attrs.default {
- let default_function = Ident::new(&d, field.span());
- Some(quote! {
- let content = yaserde::ser::to_string_content(&self.#label)?;
- let struct_start_event =
- if self.#label != #default_function() {
- struct_start_event.attr(#label_name, &content)
- } else {
- struct_start_event
- };
- })
- } else {
- Some(quote! {
- let content = yaserde::ser::to_string_content(&self.#label)?;
- let struct_start_event = struct_start_event.attr(#label_name, &content);
- })
- }
- }
- _ => None,
- })
+ Field::FieldStruct { .. } => Some(field.ser_wrap_default_attribute(
+ Some(quote!(yaserde::ser::to_string_content(&self.#label)?)),
+ quote!({
+ struct_start_event.attr(#label_name, &yaserde_inner)
+ }),
+ )),
+ Field::FieldVec { .. } => None,
+ }
})
.filter_map(|x| x)
.collect();
@@ -211,54 +113,48 @@ pub fn serialize(
let struct_inspector: TokenStream = data_struct
.fields
.iter()
+ .map(|field| YaSerdeField::new(field.clone()))
+ .filter(|field| !field.is_attribute())
.map(|field| {
- let field_attrs = YaSerdeAttribute::parse(&field.attrs);
- if field_attrs.attribute {
- return None;
- }
-
- let label = &field.ident;
- if field_attrs.text {
+ let label = field.label();
+ if field.is_text_content() {
return Some(quote!(
let data_event = XmlEvent::characters(&self.#label);
writer.write(data_event).map_err(|e| e.to_string())?;
));
}
- let label_name = build_label_name(
- &label.as_ref().unwrap(),
- &field_attrs,
- &root_attributes.default_namespace,
- );
- let conditions = condition_generator(label, &field_attrs);
+ let label_name = field.renamed_label(root_attributes);
+ let conditions = condition_generator(&label, &field);
- get_field_type(field).and_then(|f| match f {
- FieldType::FieldTypeString
- | FieldType::FieldTypeBool
- | FieldType::FieldTypeI8
- | FieldType::FieldTypeU8
- | FieldType::FieldTypeI16
- | FieldType::FieldTypeU16
- | FieldType::FieldTypeI32
- | FieldType::FieldTypeU32
- | FieldType::FieldTypeI64
- | FieldType::FieldTypeU64
- | FieldType::FieldTypeF32
- | FieldType::FieldTypeF64 => serialize_element(label, label_name, &conditions),
- FieldType::FieldTypeOption { data_type } => match *data_type {
- FieldType::FieldTypeString
- | FieldType::FieldTypeBool
- | FieldType::FieldTypeI8
- | FieldType::FieldTypeU8
- | FieldType::FieldTypeI16
- | FieldType::FieldTypeU16
- | FieldType::FieldTypeI32
- | FieldType::FieldTypeU32
- | FieldType::FieldTypeI64
- | FieldType::FieldTypeU64
- | FieldType::FieldTypeF32
- | FieldType::FieldTypeF64 => {
- let item_ident = Ident::new("yaserde_item", field.span());
+ match field.get_type() {
+ Field::FieldString
+ | Field::FieldBool
+ | Field::FieldI8
+ | Field::FieldU8
+ | Field::FieldI16
+ | Field::FieldU16
+ | Field::FieldI32
+ | Field::FieldU32
+ | Field::FieldI64
+ | Field::FieldU64
+ | Field::FieldF32
+ | Field::FieldF64 => serialize_element(&label, label_name, &conditions),
+
+ Field::FieldOption { data_type } => match *data_type {
+ Field::FieldString
+ | Field::FieldBool
+ | Field::FieldI8
+ | Field::FieldU8
+ | Field::FieldI16
+ | Field::FieldU16
+ | Field::FieldI32
+ | Field::FieldU32
+ | Field::FieldI64
+ | Field::FieldU64
+ | Field::FieldF32
+ | Field::FieldF64 => {
+ let item_ident = Ident::new("yaserde_item", field.get_span());
let inner = enclose_formatted_characters_for_value(&item_ident, label_name);
Some(quote! {
@@ -269,8 +165,8 @@ pub fn serialize(
}
})
}
- FieldType::FieldTypeVec { .. } => {
- let item_ident = Ident::new("yaserde_item", field.span());
+ Field::FieldVec { .. } => {
+ let item_ident = Ident::new("yaserde_item", field.get_span());
let inner = enclose_formatted_characters_for_value(&item_ident, label_name);
Some(quote! {
@@ -283,7 +179,7 @@ pub fn serialize(
}
})
}
- FieldType::FieldTypeStruct { .. } => Some(if field_attrs.flatten {
+ Field::FieldStruct { .. } => Some(if field.is_flatten() {
quote! {
if let Some(ref item) = &self.#label {
writer.set_start_event_name(None);
@@ -302,8 +198,8 @@ pub fn serialize(
}),
_ => unimplemented!(),
},
- FieldType::FieldTypeStruct { .. } => {
- let (start_event, skip_start) = if field_attrs.flatten {
+ Field::FieldStruct { .. } => {
+ let (start_event, skip_start) = if field.is_flatten() {
(quote!(None), true)
} else {
(quote!(Some(#label_name.to_string())), false)
@@ -315,9 +211,9 @@ pub fn serialize(
self.#label.serialize(writer)?;
})
}
- FieldType::FieldTypeVec { data_type } => match *data_type {
- FieldType::FieldTypeString => {
- let item_ident = Ident::new("yaserde_item", field.span());
+ Field::FieldVec { data_type } => match *data_type {
+ Field::FieldString => {
+ let item_ident = Ident::new("yaserde_item", field.get_span());
let inner = enclose_formatted_characters_for_value(&item_ident, label_name);
Some(quote! {
@@ -326,18 +222,18 @@ pub fn serialize(
}
})
}
- FieldType::FieldTypeBool
- | FieldType::FieldTypeI8
- | FieldType::FieldTypeU8
- | FieldType::FieldTypeI16
- | FieldType::FieldTypeU16
- | FieldType::FieldTypeI32
- | FieldType::FieldTypeU32
- | FieldType::FieldTypeI64
- | FieldType::FieldTypeU64
- | FieldType::FieldTypeF32
- | FieldType::FieldTypeF64 => {
- let item_ident = Ident::new("yaserde_item", field.span());
+ Field::FieldBool
+ | Field::FieldI8
+ | Field::FieldU8
+ | Field::FieldI16
+ | Field::FieldU16
+ | Field::FieldI32
+ | Field::FieldU32
+ | Field::FieldI64
+ | Field::FieldU64
+ | Field::FieldF32
+ | Field::FieldF64 => {
+ let item_ident = Ident::new("yaserde_item", field.get_span());
let inner = enclose_formatted_characters_for_value(&item_ident, label_name);
Some(quote! {
@@ -346,7 +242,7 @@ pub fn serialize(
}
})
}
- FieldType::FieldTypeOption { .. } => Some(quote! {
+ Field::FieldOption { .. } => Some(quote! {
for item in &self.#label {
if let Some(value) = item {
writer.set_start_event_name(None);
@@ -355,18 +251,18 @@ pub fn serialize(
}
}
}),
- FieldType::FieldTypeStruct { .. } => Some(quote! {
+ Field::FieldStruct { .. } => Some(quote! {
for item in &self.#label {
writer.set_start_event_name(None);
writer.set_skip_start_end(false);
item.serialize(writer)?;
}
}),
- FieldType::FieldTypeVec { .. } => {
+ Field::FieldVec { .. } => {
unimplemented!();
}
},
- })
+ }
})
.filter_map(|x| x)
.collect();
diff --git a/yaserde_derive/src/ser/implement_deserializer.rs b/yaserde_derive/src/ser/implement_deserializer.rs
index b128d7b..645b4ed 100644
--- a/yaserde_derive/src/ser/implement_deserializer.rs
+++ b/yaserde_derive/src/ser/implement_deserializer.rs
@@ -1,4 +1,4 @@
-use crate::attribute::YaSerdeAttribute;
+use crate::common::YaSerdeAttribute;
use crate::ser::namespace::generate_namespaces_definition;
use proc_macro2::Ident;
use proc_macro2::TokenStream;
diff --git a/yaserde_derive/src/ser/label.rs b/yaserde_derive/src/ser/label.rs
index b77ee2e..89998a5 100644
--- a/yaserde_derive/src/ser/label.rs
+++ b/yaserde_derive/src/ser/label.rs
@@ -1,4 +1,4 @@
-use crate::attribute::YaSerdeAttribute;
+use crate::common::YaSerdeAttribute;
use proc_macro2::Ident;
pub fn build_label_name(
diff --git a/yaserde_derive/src/ser/mod.rs b/yaserde_derive/src/ser/mod.rs
index 6e5e8c1..23d8353 100644
--- a/yaserde_derive/src/ser/mod.rs
+++ b/yaserde_derive/src/ser/mod.rs
@@ -5,7 +5,7 @@ pub mod implement_deserializer;
pub mod label;
pub mod namespace;
-use crate::attribute::YaSerdeAttribute;
+use crate::common::YaSerdeAttribute;
use proc_macro2::TokenStream;
use syn;
use syn::Ident;
@@ -15,25 +15,30 @@ pub fn expand_derive_serialize(ast: &syn::DeriveInput) -> Result {
- expand_struct::serialize(data_struct, name, &root, &root_attrs)
+ expand_struct::serialize(data_struct, name, &root_name, &root_attributes)
+ }
+ syn::Data::Enum(ref data_enum) => {
+ expand_enum::serialize(data_enum, name, &root_name, &root_attributes)
}
- syn::Data::Enum(ref data_enum) => expand_enum::serialize(data_enum, name, &root, &root_attrs),
syn::Data::Union(ref _data_union) => unimplemented!(),
};
diff --git a/yaserde_derive/src/ser/namespace.rs b/yaserde_derive/src/ser/namespace.rs
index 6a7bf5a..3127531 100644
--- a/yaserde_derive/src/ser/namespace.rs
+++ b/yaserde_derive/src/ser/namespace.rs
@@ -1,4 +1,4 @@
-use crate::attribute::YaSerdeAttribute;
+use crate::common::YaSerdeAttribute;
use proc_macro2::TokenStream;
pub fn generate_namespaces_definition(attributes: &YaSerdeAttribute) -> TokenStream {