Merge pull request #73 from media-io/refactor_code
Restructure unit tests
This commit is contained in:
		
						commit
						e3eee45577
					
				| @ -137,3 +137,76 @@ fn default_visitor() { | |||||||
|   test_type!(visit_u64, "Unexpected u64 \"\""); |   test_type!(visit_u64, "Unexpected u64 \"\""); | ||||||
|   test_type!(visit_str, "Unexpected str \"\""); |   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("<data><item>") + str_value + "</item></data>" | ||||||
|  |       } else { | ||||||
|  |         String::from("<data />") | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  |       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 { | ||||||
|  |         "<data item=\"".to_string() + str_value + "\" />" | ||||||
|  |       } else { | ||||||
|  |         "<data />".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<String, String> = yaserde::ser::to_string(&$model); | ||||||
|  | 
 | ||||||
|  |       let content = String::from(r#"<?xml version="1.0" encoding="utf-8"?>"#) + &$content; | ||||||
|  |       assert_eq!( | ||||||
|  |         data, | ||||||
|  |         Ok( | ||||||
|  |           String::from(content) | ||||||
|  |             .split("\n") | ||||||
|  |             .map(|s| s.trim()) | ||||||
|  |             .collect::<String>() | ||||||
|  |         ) | ||||||
|  |       ); | ||||||
|  |     }; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | |||||||
| @ -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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base />"; |  | ||||||
|   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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base />"; |  | ||||||
|   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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base />"; |  | ||||||
|   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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base />"; |  | ||||||
|   convert_and_validate!( |  | ||||||
|     content, |  | ||||||
|     XmlStruct, |  | ||||||
|     XmlStruct { |  | ||||||
|       background: "my_default_value".to_string(), |  | ||||||
|     } |  | ||||||
|   ); |  | ||||||
| } |  | ||||||
| @ -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#" |  | ||||||
|     <?xml version="1.0" encoding="utf-8"?> |  | ||||||
|     <binary_data>binary</binary_data> |  | ||||||
|     <string_data>string</string_data> |  | ||||||
|   "#;
 |  | ||||||
| 
 |  | ||||||
|   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#" |  | ||||||
|     <?xml version="1.0" encoding="utf-8"?> |  | ||||||
|     <Binary> |  | ||||||
|       <binary_data>binary</binary_data> |  | ||||||
|     </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<OptionalExtra>, |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   #[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<String>), |  | ||||||
|     #[yaserde(rename = "working")] |  | ||||||
|     Working, |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   impl Default for DateKind { |  | ||||||
|     fn default() -> Self { |  | ||||||
|       DateKind::Working |  | ||||||
|     } |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   let content = r#" |  | ||||||
|     <?xml version="1.0" encoding="utf-8"?> |  | ||||||
|     <DateTime> |  | ||||||
|       <year>2020</year> |  | ||||||
|       <month>1</month> |  | ||||||
|       <day>1</day> |  | ||||||
|       <week>1</week> |  | ||||||
|       <century>21</century> |  | ||||||
|       <lunar_day>1</lunar_day> |  | ||||||
|       <time>10:40:03</time> |  | ||||||
|       <holidays>New Year's Day</holidays> |  | ||||||
|       <holidays>Novy God Day</holidays> |  | ||||||
|       <holidays>Polar Bear Swim Day</holidays> |  | ||||||
|     </DateTime> |  | ||||||
|   "#;
 |  | ||||||
|   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() |  | ||||||
|       ]) |  | ||||||
|     } |  | ||||||
|   ); |  | ||||||
| } |  | ||||||
| @ -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#"<?xml version="1.0" encoding="utf-8"?>
 |  | ||||||
|     <ns:book xmlns:ns="http://www.sample.com/ns/domain" xmlns:ns2="http://www.sample.com/ns/domain_2"> |  | ||||||
|       <ns:author>Antoine de Saint-Exupéry</ns:author> |  | ||||||
|       <ns2:title>Little prince</ns2:title> |  | ||||||
|     </ns:book> |  | ||||||
|   "#;
 |  | ||||||
|   convert_and_validate!( |  | ||||||
|     content, |  | ||||||
|     Book, |  | ||||||
|     Book { |  | ||||||
|       author: String::from("Antoine de Saint-Exupéry"), |  | ||||||
|       title: String::from("Little prince"), |  | ||||||
|     } |  | ||||||
|   ); |  | ||||||
| 
 |  | ||||||
|   let content = r#"<?xml version="1.0" encoding="utf-8"?>
 |  | ||||||
|     <ns:book xmlns:ns="http://www.sample.com/ns/domain"> |  | ||||||
|       <ns:author>Antoine de Saint-Exupéry</ns:author> |  | ||||||
|       <ns2:title xmlns:ns2="http://www.sample.com/ns/domain_2">Little prince</ns2:title> |  | ||||||
|     </ns:book> |  | ||||||
|   "#;
 |  | ||||||
|   convert_and_validate!( |  | ||||||
|     content, |  | ||||||
|     Book, |  | ||||||
|     Book { |  | ||||||
|       author: String::from("Antoine de Saint-Exupéry"), |  | ||||||
|       title: String::from("Little prince"), |  | ||||||
|     } |  | ||||||
|   ); |  | ||||||
| 
 |  | ||||||
|   let content = r#"<?xml version="1.0" encoding="utf-8"?>
 |  | ||||||
|     <book xmlns="http://www.sample.com/ns/domain"> |  | ||||||
|       <author>Antoine de Saint-Exupéry</author> |  | ||||||
|       <ns2:title xmlns:ns2="http://www.sample.com/ns/domain_2">Little prince</ns2:title> |  | ||||||
|     </book> |  | ||||||
|   "#;
 |  | ||||||
|   convert_and_validate!( |  | ||||||
|     content, |  | ||||||
|     Book, |  | ||||||
|     Book { |  | ||||||
|       author: String::from("Antoine de Saint-Exupéry"), |  | ||||||
|       title: String::from("Little prince"), |  | ||||||
|     } |  | ||||||
|   ); |  | ||||||
| 
 |  | ||||||
|   let content = r#"<?xml version="1.0" encoding="utf-8"?>
 |  | ||||||
|   <ns:book xmlns:ns="http://www.sample.com/ns/domain2"> |  | ||||||
|     <ns:author>Antoine de Saint-Exupéry</ns:author> |  | ||||||
|     <ns:title>Little prince</ns:title> |  | ||||||
|   </ns:book>"#;
 |  | ||||||
|   let loaded: Result<Book, String> = 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#" |  | ||||||
|     <?xml version="1.0" encoding="utf-8"?> |  | ||||||
|     <nsb:B 
 |  | ||||||
|         xmlns:nsa="http://www.sample.com/ns/a" 
 |  | ||||||
|         xmlns:nsb="http://www.sample.com/ns/b"> |  | ||||||
|       <nsb:nested> |  | ||||||
|         <nsa:alpha>32</nsa:alpha> |  | ||||||
|       </nsb:nested> |  | ||||||
|     </nsb:B> |  | ||||||
|     "#,
 |  | ||||||
|     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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><ns:root xmlns:ns=\"http://www.sample.com/ns/domain\">ns:Item</ns:root>"; |  | ||||||
|   convert_and_validate!(content, XmlStruct, XmlStruct::Item); |  | ||||||
| } |  | ||||||
| @ -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("<?xml version=\"1.0\" encoding=\"utf-8\"?><data><item>") |  | ||||||
|         + content |  | ||||||
|         + "</item></data>" |  | ||||||
|     } else { |  | ||||||
|       String::from("<?xml version=\"1.0\" encoding=\"utf-8\"?><data />") |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     let loaded: Result<Data, String> = 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("<?xml version=\"1.0\" encoding=\"utf-8\"?><data item=\"") |  | ||||||
|         + content |  | ||||||
|         + "\"></data>" |  | ||||||
|     } else { |  | ||||||
|       String::from("<?xml version=\"1.0\" encoding=\"utf-8\"?><data />") |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     let loaded: Result<Data, String> = 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<String>, |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   impl Default for SubTest { |  | ||||||
|     fn default() -> Self { |  | ||||||
|       SubTest { content: None } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   convert_and_validate!( |  | ||||||
|     Test, |  | ||||||
|     Some(Test { |  | ||||||
|       field: SubTest { |  | ||||||
|         content: Some("value".to_string()) |  | ||||||
|       } |  | ||||||
|     }), |  | ||||||
|     Some("<field><content>value</content></field>") |  | ||||||
|   ); |  | ||||||
|   convert_and_validate!(Test, None, None); |  | ||||||
| } |  | ||||||
| @ -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("<?xml version=\"1.0\" encoding=\"utf-8\"?><data><item>") |  | ||||||
|       + $content |  | ||||||
|       + "</item></data>"; |  | ||||||
| 
 |  | ||||||
|     let loaded: Result<Data, String> = 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("<?xml version=\"1.0\" encoding=\"utf-8\"?><data item=\"") + $content + "\" />"; |  | ||||||
| 
 |  | ||||||
|     let loaded: Result<Data, String> = 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"); |  | ||||||
| } |  | ||||||
							
								
								
									
										112
									
								
								yaserde/tests/default.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								yaserde/tests/default.rs
									
									
									
									
									
										Normal file
									
								
							| @ -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 = "<base />"; | ||||||
|  |   serialize_and_validate!(model, content); | ||||||
|  |   deserialize_and_validate!(content, model, XmlStruct); | ||||||
|  | 
 | ||||||
|  |   let content = "<base><background>my_value</background></base>"; | ||||||
|  |   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 = "<base />"; | ||||||
|  |   let model = XmlStruct { background: true }; | ||||||
|  |   serialize_and_validate!(model, content); | ||||||
|  |   deserialize_and_validate!(content, model, XmlStruct); | ||||||
|  | 
 | ||||||
|  |   let content = "<base><background>false</background></base>"; | ||||||
|  |   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 = "<base />"; | ||||||
|  |   let model = XmlStruct { background: 6 }; | ||||||
|  |   serialize_and_validate!(model, content); | ||||||
|  |   deserialize_and_validate!(content, model, XmlStruct); | ||||||
|  | 
 | ||||||
|  |   let content = "<base><background>4</background></base>"; | ||||||
|  |   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 = "<base />"; | ||||||
|  |   let model = XmlStruct { | ||||||
|  |     background: "my_default_value".to_string(), | ||||||
|  |   }; | ||||||
|  |   serialize_and_validate!(model, content); | ||||||
|  |   deserialize_and_validate!(content, model, XmlStruct); | ||||||
|  | 
 | ||||||
|  |   let content = r#"<base background="black" />"#; | ||||||
|  |   let model = XmlStruct { | ||||||
|  |     background: "black".to_string(), | ||||||
|  |   }; | ||||||
|  |   serialize_and_validate!(model, content); | ||||||
|  |   deserialize_and_validate!(content, model, XmlStruct); | ||||||
|  | } | ||||||
							
								
								
									
										300
									
								
								yaserde/tests/enum.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										300
									
								
								yaserde/tests/enum.rs
									
									
									
									
									
										Normal file
									
								
							| @ -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<Alpha>, | ||||||
|  |     }, | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   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 = "<base><color>Black</color></base>"; | ||||||
|  |   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#" | ||||||
|  | <base> | ||||||
|  | <color><enabled>true</enabled> | ||||||
|  | <u8_value>8</u8_value> | ||||||
|  | <i8_value>-8</i8_value> | ||||||
|  | <u16_value>16</u16_value> | ||||||
|  | <i16_value>-16</i16_value> | ||||||
|  | <u32_value>32</u32_value> | ||||||
|  | <i32_value>-32</i32_value> | ||||||
|  | <u64_value>64</u64_value> | ||||||
|  | <i64_value>-64</i64_value> | ||||||
|  | <f32_value>32</f32_value> | ||||||
|  | <f64_value>64</f64_value> | ||||||
|  | <color><red>0</red><green>128</green><blue>255</blue></color> | ||||||
|  | <alpha>Opaque</alpha> | ||||||
|  | <alphas>Opaque</alphas> | ||||||
|  | <alphas>Transparent</alphas> | ||||||
|  | </color> | ||||||
|  | </base>"#;
 | ||||||
|  | 
 | ||||||
|  |   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#"<base color="pink" />"#; | ||||||
|  |   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<String>), | ||||||
|  |     OptionUserStruct(Option<OtherStruct>), | ||||||
|  |     Strings(Vec<String>), | ||||||
|  |     Ints(Vec<i32>), | ||||||
|  |     Structs(Vec<OtherStruct>), | ||||||
|  |     #[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 = "<base><color><Field>some_text</Field></color></base>"; | ||||||
|  |   serialize_and_validate!(model, content); | ||||||
|  |   deserialize_and_validate!(content, model, XmlStruct); | ||||||
|  | 
 | ||||||
|  |   let model = XmlStruct { | ||||||
|  |     color: Enum::FullPath(String::from("some_text")), | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   let content = "<base><color><FullPath>some_text</FullPath></color></base>"; | ||||||
|  |   serialize_and_validate!(model, content); | ||||||
|  |   deserialize_and_validate!(content, model, XmlStruct); | ||||||
|  | 
 | ||||||
|  |   let model = XmlStruct { | ||||||
|  |     color: Enum::Integer(56), | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   let content = "<base><color><Integer>56</Integer></color></base>"; | ||||||
|  |   serialize_and_validate!(model, content); | ||||||
|  |   deserialize_and_validate!(content, model, XmlStruct); | ||||||
|  | 
 | ||||||
|  |   let model = XmlStruct { | ||||||
|  |     color: Enum::UserStruct(OtherStruct { fi: 24, se: 42 }), | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   let content = "<base><color><UserStruct><fi>24</fi><se>42</se></UserStruct></color></base>"; | ||||||
|  |   serialize_and_validate!(model, content); | ||||||
|  |   deserialize_and_validate!(content, model, XmlStruct); | ||||||
|  | 
 | ||||||
|  |   let model = XmlStruct { | ||||||
|  |     color: Enum::OptionString(Some(String::from("some_text"))), | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   let content = "<base><color><OptionString>some_text</OptionString></color></base>"; | ||||||
|  |   serialize_and_validate!(model, content); | ||||||
|  |   deserialize_and_validate!(content, model, XmlStruct); | ||||||
|  | 
 | ||||||
|  |   let model = XmlStruct { | ||||||
|  |     color: Enum::OptionString(None), | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   let content = "<base><color /></base>"; | ||||||
|  |   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 = | ||||||
|  |     "<base><color><OptionUserStruct><fi>12</fi><se>23</se></OptionUserStruct></color></base>"; | ||||||
|  |   serialize_and_validate!(model, content); | ||||||
|  |   deserialize_and_validate!(content, model, XmlStruct); | ||||||
|  | 
 | ||||||
|  |   let model = XmlStruct { | ||||||
|  |     color: Enum::OptionUserStruct(None), | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   let content = "<base><color /></base>"; | ||||||
|  |   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 = "<base><color><Strings>abc</Strings><Strings>def</Strings></color></base>"; | ||||||
|  |   serialize_and_validate!(model, content); | ||||||
|  |   deserialize_and_validate!(content, model, XmlStruct); | ||||||
|  | 
 | ||||||
|  |   let model = XmlStruct { | ||||||
|  |     color: Enum::Ints(vec![23, 45]), | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   let content = "<base><color><Ints>23</Ints><Ints>45</Ints></color></base>"; | ||||||
|  |   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 = "<base><color><Structs><fi>12</fi><se>23</se></Structs><Structs><fi>34</fi><se>45</se></Structs></color></base>"; | ||||||
|  |   serialize_and_validate!(model, content); | ||||||
|  |   deserialize_and_validate!(content, model, XmlStruct); | ||||||
|  | 
 | ||||||
|  |   let model = XmlStruct { | ||||||
|  |     color: Enum::ToRename(87), | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   let content = "<base><color><renamed>87</renamed></color></base>"; | ||||||
|  |   serialize_and_validate!(model, content); | ||||||
|  |   deserialize_and_validate!(content, model, XmlStruct); | ||||||
|  | 
 | ||||||
|  |   let model = XmlStruct { | ||||||
|  |     color: Enum::ToRenameDots(84), | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   let content = "<base><color><renamed.with.dots>84</renamed.with.dots></color></base>"; | ||||||
|  |   serialize_and_validate!(model, content); | ||||||
|  |   deserialize_and_validate!(content, model, XmlStruct); | ||||||
|  | } | ||||||
| @ -1,28 +1,15 @@ | |||||||
| #[macro_use] | #[macro_use] | ||||||
|  | extern crate yaserde; | ||||||
|  | #[macro_use] | ||||||
| extern crate yaserde_derive; | extern crate yaserde_derive; | ||||||
| 
 | 
 | ||||||
| use std::io::Write; | use std::io::{Read, Write}; | ||||||
| use yaserde::ser::to_string; |  | ||||||
| use yaserde::YaSerialize; |  | ||||||
| 
 | 
 | ||||||
| macro_rules! convert_and_validate { | use yaserde::{YaDeserialize, YaSerialize}; | ||||||
|   ($model: expr, $content: expr) => { |  | ||||||
|     let data: Result<String, String> = to_string(&$model); |  | ||||||
|     assert_eq!( |  | ||||||
|       data, |  | ||||||
|       Ok( |  | ||||||
|         String::from($content) |  | ||||||
|           .split("\n") |  | ||||||
|           .map(|s| s.trim()) |  | ||||||
|           .collect::<String>() |  | ||||||
|       ) |  | ||||||
|     ); |  | ||||||
|   }; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| #[test] | #[test] | ||||||
| fn ser_flatten() { | fn basic_flatten() { | ||||||
|   #[derive(Default, PartialEq, Debug, YaSerialize)] |   #[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)] | ||||||
|   struct DateTime { |   struct DateTime { | ||||||
|     #[yaserde(flatten)] |     #[yaserde(flatten)] | ||||||
|     date: Date, |     date: Date, | ||||||
| @ -31,7 +18,7 @@ fn ser_flatten() { | |||||||
|     kind: DateKind, |     kind: DateKind, | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   #[derive(Default, PartialEq, Debug, YaSerialize)] |   #[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)] | ||||||
|   struct Date { |   struct Date { | ||||||
|     year: i32, |     year: i32, | ||||||
|     month: i32, |     month: i32, | ||||||
| @ -42,18 +29,18 @@ fn ser_flatten() { | |||||||
|     optional_extra: Option<OptionalExtra>, |     optional_extra: Option<OptionalExtra>, | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   #[derive(Default, PartialEq, Debug, YaSerialize)] |   #[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)] | ||||||
|   pub struct Extra { |   pub struct Extra { | ||||||
|     week: i32, |     week: i32, | ||||||
|     century: i32, |     century: i32, | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   #[derive(Default, PartialEq, Debug, YaSerialize)] |   #[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)] | ||||||
|   pub struct OptionalExtra { |   pub struct OptionalExtra { | ||||||
|     lunar_day: i32, |     lunar_day: i32, | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   #[derive(PartialEq, Debug, YaSerialize)] |   #[derive(PartialEq, Debug, YaDeserialize, YaSerialize)] | ||||||
|   pub enum DateKind { |   pub enum DateKind { | ||||||
|     #[yaserde(rename = "holidays")] |     #[yaserde(rename = "holidays")] | ||||||
|     Holidays(Vec<String>), |     Holidays(Vec<String>), | ||||||
| @ -87,7 +74,6 @@ fn ser_flatten() { | |||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   let content = r#" |   let content = r#" | ||||||
|     <?xml version="1.0" encoding="utf-8"?> |  | ||||||
|     <DateTime> |     <DateTime> | ||||||
|       <year>2020</year> |       <year>2020</year> | ||||||
|       <month>1</month> |       <month>1</month> | ||||||
| @ -101,12 +87,13 @@ fn ser_flatten() { | |||||||
|       <holidays>Polar Bear Swim Day</holidays> |       <holidays>Polar Bear Swim Day</holidays> | ||||||
|     </DateTime>"#;
 |     </DateTime>"#;
 | ||||||
| 
 | 
 | ||||||
|   convert_and_validate!(model, content); |   serialize_and_validate!(model, content); | ||||||
|  |   deserialize_and_validate!(content, model, DateTime); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[test] | #[test] | ||||||
| fn ser_root_flatten_struct() { | fn root_flatten_struct() { | ||||||
|   #[derive(YaSerialize, PartialEq, Debug)] |   #[derive(YaDeserialize, YaSerialize, PartialEq, Debug)] | ||||||
|   #[yaserde(flatten)] |   #[yaserde(flatten)] | ||||||
|   pub struct Content { |   pub struct Content { | ||||||
|     binary_data: String, |     binary_data: String, | ||||||
| @ -117,12 +104,15 @@ fn ser_root_flatten_struct() { | |||||||
|     binary_data: "binary".to_string(), |     binary_data: "binary".to_string(), | ||||||
|     string_data: "string".to_string(), |     string_data: "string".to_string(), | ||||||
|   }; |   }; | ||||||
|   let content = r#"<?xml version="1.0" encoding="utf-8"?><binary_data>binary</binary_data><string_data>string</string_data>"#; | 
 | ||||||
|   convert_and_validate!(model, content); |   let content = "<binary_data>binary</binary_data><string_data>string</string_data>"; | ||||||
|  | 
 | ||||||
|  |   serialize_and_validate!(model, content); | ||||||
|  |   deserialize_and_validate!(content, model, Content); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[test] | #[test] | ||||||
| fn ser_root_flatten_enum() { | fn root_flatten_enum() { | ||||||
|   #[derive(YaSerialize, PartialEq, Debug)] |   #[derive(YaSerialize, PartialEq, Debug)] | ||||||
|   #[yaserde(flatten)] |   #[yaserde(flatten)] | ||||||
|   pub enum Content { |   pub enum Content { | ||||||
| @ -143,14 +133,14 @@ fn ser_root_flatten_enum() { | |||||||
|   let model = Content::Binary(Binary { |   let model = Content::Binary(Binary { | ||||||
|     binary_data: "binary".to_string(), |     binary_data: "binary".to_string(), | ||||||
|   }); |   }); | ||||||
|   let content = | 
 | ||||||
|     r#"<?xml version="1.0" encoding="utf-8"?><Binary><binary_data>binary</binary_data></Binary>"#; |   let content = "<Binary><binary_data>binary</binary_data></Binary>"; | ||||||
|   convert_and_validate!(model, content); |   serialize_and_validate!(model, content); | ||||||
| 
 | 
 | ||||||
|   let model = Content::Data(Data { |   let model = Content::Data(Data { | ||||||
|     string_data: "string".to_string(), |     string_data: "string".to_string(), | ||||||
|   }); |   }); | ||||||
|   let content = | 
 | ||||||
|     r#"<?xml version="1.0" encoding="utf-8"?><Data><string_data>string</string_data></Data>"#; |   let content = "<Data><string_data>string</string_data></Data>"; | ||||||
|   convert_and_validate!(model, content); |   serialize_and_validate!(model, content); | ||||||
| } | } | ||||||
							
								
								
									
										442
									
								
								yaserde/tests/namespace.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										442
									
								
								yaserde/tests/namespace.rs
									
									
									
									
									
										Normal file
									
								
							| @ -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#" | ||||||
|  |     <ns:book xmlns:ns="http://www.sample.com/ns/domain"> | ||||||
|  |       <ns:author>Antoine de Saint-Exupéry</ns:author> | ||||||
|  |       <ns:title>Little prince</ns:title> | ||||||
|  |     </ns:book> | ||||||
|  |   "#;
 | ||||||
|  | 
 | ||||||
|  |   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#" | ||||||
|  |     <ns:book xmlns:ns="http://www.sample.com/ns/domain" xmlns:ns2="http://www.sample.com/ns/domain_2"> | ||||||
|  |       <ns:author>Antoine de Saint-Exupéry</ns:author> | ||||||
|  |       <ns2:title>Little prince</ns2:title> | ||||||
|  |     </ns:book> | ||||||
|  |   "#;
 | ||||||
|  | 
 | ||||||
|  |   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#" | ||||||
|  |     <ns:book xmlns:ns="http://www.sample.com/ns/domain"> | ||||||
|  |       <author>Antoine de Saint-Exupéry</author> | ||||||
|  |       <ns:title>Little prince</ns:title> | ||||||
|  |     </ns:book> | ||||||
|  |   "#;
 | ||||||
|  | 
 | ||||||
|  |   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#" | ||||||
|  |     <ns:book xmlns:ns="http://www.sample.com/ns/domain"> | ||||||
|  |       <ns:author>Antoine de Saint-Exupéry</ns:author> | ||||||
|  |       <ns2:title xmlns:ns2="http://www.sample.com/ns/domain_2">Little prince</ns2:title> | ||||||
|  |     </ns:book> | ||||||
|  |   "#;
 | ||||||
|  | 
 | ||||||
|  |   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#" | ||||||
|  |     <nsb:B xmlns:nsb="http://www.sample.com/ns/b"> | ||||||
|  |       <nsb:nested xmlns:nsa="http://www.sample.com/ns/a"> | ||||||
|  |         <nsa:alpha>32</nsa:alpha> | ||||||
|  |       </nsb:nested> | ||||||
|  |     </nsb:B> | ||||||
|  |   "#;
 | ||||||
|  | 
 | ||||||
|  |   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#" | ||||||
|  |     <nsb:B xmlns:nsa="http://www.sample.com/ns/a" xmlns:nsb="http://www.sample.com/ns/b"> | ||||||
|  |       <nsb:nested> | ||||||
|  |         <nsa:alpha>32</nsa:alpha> | ||||||
|  |       </nsb:nested> | ||||||
|  |     </nsb:B> | ||||||
|  |   "#;
 | ||||||
|  | 
 | ||||||
|  |   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#" | ||||||
|  |     <root xmlns:ns1="http://www.sample.com/ns/domain1" xmlns:ns2="http://www.sample.com/ns/domain2" ns2:item_2="something 2"> | ||||||
|  |       <ns1:item_1>something 1</ns1:item_1> | ||||||
|  |     </root> | ||||||
|  |   "#;
 | ||||||
|  | 
 | ||||||
|  |   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#"<tt xmlns="http://www.w3.org/ns/ttml" xmlns:ttm="http://www.w3.org/ns/ttml#metadata"><item>something</item></tt>"#; | ||||||
|  |   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#"<tt xmlns="http://www.w3.org/ns/ttml" xmlns:ttm="http://www.w3.org/ns/ttml#metadata"><item>something</item></tt>"#; | ||||||
|  |   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#"<tt xmlns="http://www.w3.org/ns/ttml" xmlns:ttm="http://www.w3.org/ns/ttml#metadata"><item>something</item></tt>"#; | ||||||
|  |   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:root xmlns:ns="http://www.sample.com/ns/domain"> | ||||||
|  |       ns:Item | ||||||
|  |     </ns:root> | ||||||
|  |   "#;
 | ||||||
|  | 
 | ||||||
|  |   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#" | ||||||
|  |     <root xmlns:ns1="http://www.sample.com/ns/domain1" xmlns:ns2="http://www.sample.com/ns/domain2"> | ||||||
|  |       ns1:Item1 | ||||||
|  |     </root> | ||||||
|  |   "#;
 | ||||||
|  |   serialize_and_validate!(model, content); | ||||||
|  |   deserialize_and_validate!(content, model, XmlStruct); | ||||||
|  | 
 | ||||||
|  |   let model = XmlStruct::Item2; | ||||||
|  |   let content = r#" | ||||||
|  |     <root xmlns:ns1="http://www.sample.com/ns/domain1" xmlns:ns2="http://www.sample.com/ns/domain2"> | ||||||
|  |       ns2:Item2 | ||||||
|  |     </root> | ||||||
|  |   "#;
 | ||||||
|  |   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:root xmlns:ns="http://www.sample.com/ns/domain"> | ||||||
|  |       ns:Item | ||||||
|  |     </ns:root> | ||||||
|  |   "#;
 | ||||||
|  | 
 | ||||||
|  |   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#"<ns:root xmlns:ns="http://www.sample.com/ns/domain"><ns:ItemWithField>Value</ns:ItemWithField></ns:root>"#; | ||||||
|  |   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#" | ||||||
|  |     <ns:book xmlns:ns="http://www.sample.com/ns/domain2"> | ||||||
|  |       <ns:author>Antoine de Saint-Exupéry</ns:author> | ||||||
|  |       <ns:title>Little prince</ns:title> | ||||||
|  |     </ns:book> | ||||||
|  |   "#;
 | ||||||
|  | 
 | ||||||
|  |   let loaded: Result<Book, String> = yaserde::de::from_str(content); | ||||||
|  |   assert_eq!( | ||||||
|  |     loaded, | ||||||
|  |     Err("bad namespace for book, found http://www.sample.com/ns/domain2".to_string()) | ||||||
|  |   ); | ||||||
|  | } | ||||||
							
								
								
									
										104
									
								
								yaserde/tests/option.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								yaserde/tests/option.rs
									
									
									
									
									
										Normal file
									
								
							| @ -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::<String>, Some("test".to_string()), Some("test")); | ||||||
|  |   test_for_type!(Option::<String>, None, None); | ||||||
|  |   test_for_type!(Option::<bool>, Some(true), Some("true")); | ||||||
|  |   test_for_type!(Option::<bool>, None, None); | ||||||
|  |   test_for_type!(Option::<u8>, Some(12 as u8), Some("12")); | ||||||
|  |   test_for_type!(Option::<u8>, None, None); | ||||||
|  |   test_for_type!(Option::<i8>, Some(12 as i8), Some("12")); | ||||||
|  |   test_for_type!(Option::<i8>, Some(-12 as i8), Some("-12")); | ||||||
|  |   test_for_type!(Option::<i8>, None, None); | ||||||
|  |   test_for_type!(Option::<u16>, Some(12 as u16), Some("12")); | ||||||
|  |   test_for_type!(Option::<u16>, None, None); | ||||||
|  |   test_for_type!(Option::<i16>, Some(12 as i16), Some("12")); | ||||||
|  |   test_for_type!(Option::<i16>, Some(-12 as i16), Some("-12")); | ||||||
|  |   test_for_type!(Option::<i16>, None, None); | ||||||
|  |   test_for_type!(Option::<u32>, Some(12 as u32), Some("12")); | ||||||
|  |   test_for_type!(Option::<u32>, None, None); | ||||||
|  |   test_for_type!(Option::<i32>, Some(12 as i32), Some("12")); | ||||||
|  |   test_for_type!(Option::<i32>, Some(-12 as i32), Some("-12")); | ||||||
|  |   test_for_type!(Option::<i32>, None, None); | ||||||
|  |   test_for_type!(Option::<u64>, Some(12 as u64), Some("12")); | ||||||
|  |   test_for_type!(Option::<u64>, None, None); | ||||||
|  |   test_for_type!(Option::<i64>, Some(12 as i64), Some("12")); | ||||||
|  |   test_for_type!(Option::<i64>, Some(-12 as i64), Some("-12")); | ||||||
|  |   test_for_type!(Option::<i64>, None, None); | ||||||
|  |   test_for_type!(Option::<f32>, Some(-12.5 as f32), Some("-12.5")); | ||||||
|  |   test_for_type!(Option::<f32>, None, None); | ||||||
|  |   test_for_type!(Option::<f64>, Some(-12.5 as f64), Some("-12.5")); | ||||||
|  |   test_for_type!(Option::<f64>, None, None); | ||||||
|  | 
 | ||||||
|  |   // TODO
 | ||||||
|  |   // test_for_type!(Option::<Vec::<u8>>, None, None);
 | ||||||
|  |   // test_for_type!(Option::<Vec::<u8>>, Some(vec![0]), Some("0"));
 | ||||||
|  |   // test_for_type!(Option::<Vec::<String>>, None, None);
 | ||||||
|  |   // test_for_type!(Option::<Vec::<String>>, Some(vec!["test".to_string()]), Some("test"));
 | ||||||
|  | 
 | ||||||
|  |   test_for_attribute_type!(Option::<String>, Some("test".to_string()), Some("test")); | ||||||
|  |   test_for_attribute_type!(Option::<String>, None, None); | ||||||
|  |   test_for_attribute_type!(Option::<bool>, Some(true), Some("true")); | ||||||
|  |   test_for_attribute_type!(Option::<bool>, None, None); | ||||||
|  |   test_for_attribute_type!(Option::<u8>, Some(12 as u8), Some("12")); | ||||||
|  |   test_for_attribute_type!(Option::<u8>, None, None); | ||||||
|  |   test_for_attribute_type!(Option::<i8>, Some(12 as i8), Some("12")); | ||||||
|  |   test_for_attribute_type!(Option::<i8>, Some(-12 as i8), Some("-12")); | ||||||
|  |   test_for_attribute_type!(Option::<i8>, None, None); | ||||||
|  |   test_for_attribute_type!(Option::<u16>, Some(12 as u16), Some("12")); | ||||||
|  |   test_for_attribute_type!(Option::<u16>, None, None); | ||||||
|  |   test_for_attribute_type!(Option::<i16>, Some(12 as i16), Some("12")); | ||||||
|  |   test_for_attribute_type!(Option::<i16>, Some(-12 as i16), Some("-12")); | ||||||
|  |   test_for_attribute_type!(Option::<i16>, None, None); | ||||||
|  |   test_for_attribute_type!(Option::<u32>, Some(12 as u32), Some("12")); | ||||||
|  |   test_for_attribute_type!(Option::<u32>, None, None); | ||||||
|  |   test_for_attribute_type!(Option::<i32>, Some(12 as i32), Some("12")); | ||||||
|  |   test_for_attribute_type!(Option::<i32>, Some(-12 as i32), Some("-12")); | ||||||
|  |   test_for_attribute_type!(Option::<i32>, None, None); | ||||||
|  |   test_for_attribute_type!(Option::<u64>, Some(12 as u64), Some("12")); | ||||||
|  |   test_for_attribute_type!(Option::<u64>, None, None); | ||||||
|  |   test_for_attribute_type!(Option::<i64>, Some(12 as i64), Some("12")); | ||||||
|  |   test_for_attribute_type!(Option::<i64>, Some(-12 as i64), Some("-12")); | ||||||
|  |   test_for_attribute_type!(Option::<i64>, None, None); | ||||||
|  |   test_for_attribute_type!(Option::<f32>, Some(-12.5 as f32), Some("-12.5")); | ||||||
|  |   test_for_attribute_type!(Option::<f32>, None, None); | ||||||
|  |   test_for_attribute_type!(Option::<f64>, Some(-12.5 as f64), Some("-12.5")); | ||||||
|  |   test_for_attribute_type!(Option::<f64>, None, None); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[test] | ||||||
|  | fn option_struct() { | ||||||
|  |   #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)] | ||||||
|  |   struct Test { | ||||||
|  |     field: SubTest, | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   #[derive(Debug, PartialEq, YaDeserialize, YaSerialize)] | ||||||
|  |   struct SubTest { | ||||||
|  |     content: Option<String>, | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   impl Default for SubTest { | ||||||
|  |     fn default() -> Self { | ||||||
|  |       SubTest { content: None } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   test_for_type!( | ||||||
|  |     Option::<Test>, | ||||||
|  |     Some(Test { | ||||||
|  |       field: SubTest { | ||||||
|  |         content: Some("value".to_string()) | ||||||
|  |       } | ||||||
|  |     }), | ||||||
|  |     Some("<field><content>value</content></field>") | ||||||
|  |   ); | ||||||
|  |   test_for_type!(Option::<Test>, None, None); | ||||||
|  | } | ||||||
| @ -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<String, String> = 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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base />"; |  | ||||||
|   convert_and_validate!( |  | ||||||
|     XmlStruct { |  | ||||||
|       background: "my_default_value".to_string(), |  | ||||||
|     }, |  | ||||||
|     content |  | ||||||
|   ); |  | ||||||
|   let content = |  | ||||||
|     "<?xml version=\"1.0\" encoding=\"utf-8\"?><base><background>my_value</background></base>"; |  | ||||||
|   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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base />"; |  | ||||||
|   convert_and_validate!(XmlStruct { background: true }, content); |  | ||||||
| 
 |  | ||||||
|   let content = |  | ||||||
|     "<?xml version=\"1.0\" encoding=\"utf-8\"?><base><background>false</background></base>"; |  | ||||||
|   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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base />"; |  | ||||||
|   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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base />"; |  | ||||||
|   convert_and_validate!( |  | ||||||
|     XmlStruct { |  | ||||||
|       background: "my_default_value".to_string(), |  | ||||||
|     }, |  | ||||||
|     content |  | ||||||
|   ); |  | ||||||
| } |  | ||||||
| @ -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<String, String> = to_string(&$model); |  | ||||||
|     assert_eq!( |  | ||||||
|       data, |  | ||||||
|       Ok( |  | ||||||
|         String::from($content) |  | ||||||
|           .split("\n") |  | ||||||
|           .map(|s| s.trim()) |  | ||||||
|           .collect::<String>() |  | ||||||
|       ) |  | ||||||
|     ); |  | ||||||
|   }; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[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<Alpha>, |  | ||||||
|     }, |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   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#"<?xml version="1.0" encoding="utf-8"?><base><color>Black</color></base>"#; |  | ||||||
|   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#"<?xml version="1.0" encoding="utf-8"?>
 |  | ||||||
| <base> |  | ||||||
| <color><enabled>true</enabled> |  | ||||||
| <u8_value>8</u8_value> |  | ||||||
| <i8_value>-8</i8_value> |  | ||||||
| <u16_value>16</u16_value> |  | ||||||
| <i16_value>-16</i16_value> |  | ||||||
| <u32_value>32</u32_value> |  | ||||||
| <i32_value>-32</i32_value> |  | ||||||
| <u64_value>64</u64_value> |  | ||||||
| <i64_value>-64</i64_value> |  | ||||||
| <f32_value>32</f32_value> |  | ||||||
| <f64_value>64</f64_value> |  | ||||||
| <color><red>0</red><green>128</green><blue>255</blue></color> |  | ||||||
| <alpha>Opaque</alpha> |  | ||||||
| <alphas>Opaque</alphas> |  | ||||||
| <alphas>Transparent</alphas> |  | ||||||
| </color> |  | ||||||
| </base>"#;
 |  | ||||||
| 
 |  | ||||||
|   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#"<?xml version="1.0" encoding="utf-8"?><base color="pink" />"#; |  | ||||||
|   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<String>), |  | ||||||
|     OptionUserStruct(Option<OtherStruct>), |  | ||||||
|     Strings(Vec<String>), |  | ||||||
|     Ints(Vec<i32>), |  | ||||||
|     Structs(Vec<OtherStruct>), |  | ||||||
|     #[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#"<?xml version="1.0" encoding="utf-8"?><base><color><Field>some_text</Field></color></base>"#; |  | ||||||
|   convert_and_validate!(model, content); |  | ||||||
| 
 |  | ||||||
|   let model = XmlStruct { |  | ||||||
|     color: Enum::FullPath(String::from("some_text")), |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   let content = r#"<?xml version="1.0" encoding="utf-8"?><base><color><FullPath>some_text</FullPath></color></base>"#; |  | ||||||
|   convert_and_validate!(model, content); |  | ||||||
| 
 |  | ||||||
|   let model = XmlStruct { |  | ||||||
|     color: Enum::Integer(56), |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   let content = |  | ||||||
|     r#"<?xml version="1.0" encoding="utf-8"?><base><color><Integer>56</Integer></color></base>"#; |  | ||||||
|   convert_and_validate!(model, content); |  | ||||||
| 
 |  | ||||||
|   let model = XmlStruct { |  | ||||||
|     color: Enum::UserStruct(OtherStruct { fi: 24, se: 42 }), |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   let content = r#"<?xml version="1.0" encoding="utf-8"?><base><color><UserStruct><fi>24</fi><se>42</se></UserStruct></color></base>"#; |  | ||||||
|   convert_and_validate!(model, content); |  | ||||||
| 
 |  | ||||||
|   let model = XmlStruct { |  | ||||||
|     color: Enum::OptionString(Some(String::from("some_text"))), |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   let content = r#"<?xml version="1.0" encoding="utf-8"?><base><color><OptionString>some_text</OptionString></color></base>"#; |  | ||||||
|   convert_and_validate!(model, content); |  | ||||||
| 
 |  | ||||||
|   let model = XmlStruct { |  | ||||||
|     color: Enum::OptionString(None), |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   let content = r#"<?xml version="1.0" encoding="utf-8"?><base><color /></base>"#; |  | ||||||
|   convert_and_validate!(model, content); |  | ||||||
| 
 |  | ||||||
|   let model = XmlStruct { |  | ||||||
|     color: Enum::OptionUserStruct(Some(OtherStruct { fi: 12, se: 23 })), |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   let content = r#"<?xml version="1.0" encoding="utf-8"?><base><color><OptionUserStruct><fi>12</fi><se>23</se></OptionUserStruct></color></base>"#; |  | ||||||
|   convert_and_validate!(model, content); |  | ||||||
| 
 |  | ||||||
|   let model = XmlStruct { |  | ||||||
|     color: Enum::OptionUserStruct(None), |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   let content = r#"<?xml version="1.0" encoding="utf-8"?><base><color /></base>"#; |  | ||||||
|   convert_and_validate!(model, content); |  | ||||||
| 
 |  | ||||||
|   let model = XmlStruct { |  | ||||||
|     color: Enum::Strings(vec![String::from("abc"), String::from("def")]), |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   let content = r#"<?xml version="1.0" encoding="utf-8"?><base><color><Strings>abc</Strings><Strings>def</Strings></color></base>"#; |  | ||||||
|   convert_and_validate!(model, content); |  | ||||||
| 
 |  | ||||||
|   let model = XmlStruct { |  | ||||||
|     color: Enum::Ints(vec![23, 45]), |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   let content = r#"<?xml version="1.0" encoding="utf-8"?><base><color><Ints>23</Ints><Ints>45</Ints></color></base>"#; |  | ||||||
|   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#"<?xml version="1.0" encoding="utf-8"?><base><color><Structs><fi>12</fi><se>23</se></Structs><Structs><fi>34</fi><se>45</se></Structs></color></base>"#; |  | ||||||
|   convert_and_validate!(model, content); |  | ||||||
| 
 |  | ||||||
|   let model = XmlStruct { |  | ||||||
|     color: Enum::ToRename(87), |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   let content = |  | ||||||
|     r#"<?xml version="1.0" encoding="utf-8"?><base><color><renamed>87</renamed></color></base>"#; |  | ||||||
|   convert_and_validate!(model, content); |  | ||||||
| 
 |  | ||||||
|   let model = XmlStruct { |  | ||||||
|     color: Enum::ToRenameDots(84), |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   let content = r#"<?xml version="1.0" encoding="utf-8"?><base><color><renamed.with.dots>84</renamed.with.dots></color></base>"#; |  | ||||||
|   convert_and_validate!(model, content); |  | ||||||
| } |  | ||||||
| @ -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<String, String> = to_string(&$model); |  | ||||||
|     assert_eq!( |  | ||||||
|       data, |  | ||||||
|       Ok( |  | ||||||
|         String::from($content) |  | ||||||
|           .split("\n") |  | ||||||
|           .map(|s| s.trim()) |  | ||||||
|           .collect::<String>() |  | ||||||
|       ) |  | ||||||
|     ); |  | ||||||
|   }; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><ns:root xmlns:ns=\"http://www.sample.com/ns/domain\"><ns:item>something</ns:item></ns:root>"; |  | ||||||
|   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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><ns:root xmlns:ns=\"http://www.sample.com/ns/domain\">ns:Item</ns:root>"; |  | ||||||
|   convert_and_validate!(model, content); |  | ||||||
| 
 |  | ||||||
|   let model = XmlStruct::ItemWithField("Value".to_string()); |  | ||||||
| 
 |  | ||||||
|   let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><ns:root xmlns:ns=\"http://www.sample.com/ns/domain\"><ns:ItemWithField>Value</ns:ItemWithField></ns:root>"; |  | ||||||
|   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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><root xmlns:ns1=\"http://www.sample.com/ns/domain1\" xmlns:ns2=\"http://www.sample.com/ns/domain2\"><ns1:item_1>something 1</ns1:item_1><ns2:item_2>something 2</ns2:item_2></root>"; |  | ||||||
|   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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><root xmlns:ns1=\"http://www.sample.com/ns/domain1\" xmlns:ns2=\"http://www.sample.com/ns/domain2\">ns1:Item1</root>"; |  | ||||||
|   convert_and_validate!(model1, content); |  | ||||||
|   let model2 = XmlStruct::Item2; |  | ||||||
|   let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><root xmlns:ns1=\"http://www.sample.com/ns/domain1\" xmlns:ns2=\"http://www.sample.com/ns/domain2\">ns2:Item2</root>"; |  | ||||||
|   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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><root xmlns:ns1=\"http://www.sample.com/ns/domain1\" xmlns:ns2=\"http://www.sample.com/ns/domain2\" ns2:item_2=\"something 2\"><ns1:item_1>something 1</ns1:item_1></root>"; |  | ||||||
|   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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><tt xmlns=\"http://www.w3.org/ns/ttml\" xmlns:ttm=\"http://www.w3.org/ns/ttml#metadata\"><item>something</item></tt>"; |  | ||||||
|   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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><tt xmlns=\"http://www.w3.org/ns/ttml\" xmlns:ttm=\"http://www.w3.org/ns/ttml#metadata\"><item>something</item></tt>"; |  | ||||||
|   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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><tt xmlns=\"http://www.w3.org/ns/ttml\" xmlns:ttm=\"http://www.w3.org/ns/ttml#metadata\"><item>something</item></tt>"; |  | ||||||
|   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#" |  | ||||||
|     <?xml version="1.0" encoding="utf-8"?> |  | ||||||
|     <nsb:B xmlns:nsb="http://www.sample.com/ns/b"> |  | ||||||
|       <nsb:nested xmlns:nsa="http://www.sample.com/ns/a"> |  | ||||||
|         <nsa:alpha>32</nsa:alpha> |  | ||||||
|       </nsb:nested> |  | ||||||
|     </nsb:B> |  | ||||||
|     "#
 |  | ||||||
|   ); |  | ||||||
| } |  | ||||||
| @ -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<String, String> = to_string(&model); |  | ||||||
| 
 |  | ||||||
|     let content = if let Some(str_value) = $content { |  | ||||||
|       "<data><item>".to_string() + str_value + "</item></data>" |  | ||||||
|     } else { |  | ||||||
|       "<data />".to_string() |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     let content = String::from("<?xml version=\"1.0\" encoding=\"utf-8\"?>") + &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<String, String> = to_string(&model); |  | ||||||
| 
 |  | ||||||
|     let content = if let Some(str_value) = $content { |  | ||||||
|       "<data item=\"".to_string() + str_value + "\" />" |  | ||||||
|     } else { |  | ||||||
|       "<data />".to_string() |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     let content = String::from("<?xml version=\"1.0\" encoding=\"utf-8\"?>") + &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<u8>, None, None); |  | ||||||
|   convert_and_validate!(Vec<u8>, Some(vec![0]), Some("0")); |  | ||||||
|   convert_and_validate!(Vec<String>, None, None); |  | ||||||
|   convert_and_validate!(Vec<String>, 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<String>, |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   impl Default for SubTest { |  | ||||||
|     fn default() -> Self { |  | ||||||
|       SubTest { content: None } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   convert_and_validate!( |  | ||||||
|     Test, |  | ||||||
|     Some(Test { |  | ||||||
|       field: SubTest { |  | ||||||
|         content: Some("value".to_string()) |  | ||||||
|       } |  | ||||||
|     }), |  | ||||||
|     Some("<field><content>value</content></field>") |  | ||||||
|   ); |  | ||||||
|   convert_and_validate!(Test, None, None); |  | ||||||
| } |  | ||||||
| @ -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<String, String> = to_string(&model); |  | ||||||
|     let content = if $content == "" { |  | ||||||
|       String::from("<?xml version=\"1.0\" encoding=\"utf-8\"?><data />") |  | ||||||
|     } else { |  | ||||||
|       String::from("<?xml version=\"1.0\" encoding=\"utf-8\"?><data><item>") |  | ||||||
|         + $content |  | ||||||
|         + "</item></data>" |  | ||||||
|     }; |  | ||||||
|     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<String, String> = to_string(&model); |  | ||||||
|     let content = |  | ||||||
|       String::from("<?xml version=\"1.0\" encoding=\"utf-8\"?><data item=\"") + $content + "\" />"; |  | ||||||
|     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<String>, vec![], ""); |  | ||||||
|   convert_and_validate!(Vec<String>, 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"); |  | ||||||
| } |  | ||||||
| @ -1,29 +1,15 @@ | |||||||
| #[macro_use] | #[macro_use] | ||||||
|  | extern crate yaserde; | ||||||
|  | #[macro_use] | ||||||
| extern crate yaserde_derive; | extern crate yaserde_derive; | ||||||
| 
 | 
 | ||||||
| use std::io::Write; | use std::io::Write; | ||||||
| use yaserde::ser::to_string; |  | ||||||
| use yaserde::YaSerialize; | use yaserde::YaSerialize; | ||||||
| 
 | 
 | ||||||
| macro_rules! convert_and_validate { |  | ||||||
|   ($model: expr, $content: expr) => { |  | ||||||
|     let data: Result<String, String> = to_string(&$model); |  | ||||||
|     assert_eq!( |  | ||||||
|       data, |  | ||||||
|       Ok( |  | ||||||
|         String::from($content) |  | ||||||
|           .split("\n") |  | ||||||
|           .map(|s| s.trim()) |  | ||||||
|           .collect::<String>() |  | ||||||
|       ) |  | ||||||
|     ); |  | ||||||
|   }; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[test] | #[test] | ||||||
| fn ser_basic() { | fn ser_basic() { | ||||||
|   #[derive(YaSerialize, PartialEq, Debug)] |   #[derive(YaSerialize, PartialEq, Debug)] | ||||||
|   #[yaserde(root = "base")] |   #[yaserde(rename = "base")] | ||||||
|   pub struct XmlStruct { |   pub struct XmlStruct { | ||||||
|     item: String, |     item: String, | ||||||
|   } |   } | ||||||
| @ -32,14 +18,14 @@ fn ser_basic() { | |||||||
|     item: "something".to_string(), |     item: "something".to_string(), | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base><item>something</item></base>"; |   let content = "<base><item>something</item></base>"; | ||||||
|   convert_and_validate!(model, content); |   serialize_and_validate!(model, content); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[test] | #[test] | ||||||
| fn ser_list_of_items() { | fn ser_list_of_items() { | ||||||
|   #[derive(YaSerialize, PartialEq, Debug)] |   #[derive(YaSerialize, PartialEq, Debug)] | ||||||
|   #[yaserde(root = "base")] |   #[yaserde(rename = "base")] | ||||||
|   pub struct XmlStruct { |   pub struct XmlStruct { | ||||||
|     items: Vec<String>, |     items: Vec<String>, | ||||||
|   } |   } | ||||||
| @ -48,17 +34,17 @@ fn ser_list_of_items() { | |||||||
|     items: vec!["something1".to_string(), "something2".to_string()], |     items: vec!["something1".to_string(), "something2".to_string()], | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base><items>something1</items><items>something2</items></base>"; |   let content = "<base><items>something1</items><items>something2</items></base>"; | ||||||
|   convert_and_validate!(model, content); |   serialize_and_validate!(model, content); | ||||||
| 
 | 
 | ||||||
|   #[derive(YaSerialize, PartialEq, Debug)] |   #[derive(YaSerialize, PartialEq, Debug)] | ||||||
|   #[yaserde(root = "base")] |   #[yaserde(rename = "base")] | ||||||
|   pub struct XmlStructOfStruct { |   pub struct XmlStructOfStruct { | ||||||
|     items: Vec<SubStruct>, |     items: Vec<SubStruct>, | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   #[derive(YaSerialize, PartialEq, Debug)] |   #[derive(YaSerialize, PartialEq, Debug)] | ||||||
|   #[yaserde(root = "items")] |   #[yaserde(rename = "items")] | ||||||
|   pub struct SubStruct { |   pub struct SubStruct { | ||||||
|     field: String, |     field: String, | ||||||
|   } |   } | ||||||
| @ -74,14 +60,15 @@ fn ser_list_of_items() { | |||||||
|     ], |     ], | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base><items><field>something1</field></items><items><field>something2</field></items></base>"; |   let content = | ||||||
|   convert_and_validate!(model2, content); |     "<base><items><field>something1</field></items><items><field>something2</field></items></base>"; | ||||||
|  |   serialize_and_validate!(model2, content); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[test] | #[test] | ||||||
| fn ser_attributes() { | fn ser_attributes() { | ||||||
|   #[derive(YaSerialize, PartialEq, Debug)] |   #[derive(YaSerialize, PartialEq, Debug)] | ||||||
|   #[yaserde(root = "base")] |   #[yaserde(rename = "base")] | ||||||
|   pub struct XmlStruct { |   pub struct XmlStruct { | ||||||
|     #[yaserde(attribute)] |     #[yaserde(attribute)] | ||||||
|     item: String, |     item: String, | ||||||
| @ -89,7 +76,7 @@ fn ser_attributes() { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   #[derive(YaSerialize, PartialEq, Debug)] |   #[derive(YaSerialize, PartialEq, Debug)] | ||||||
|   #[yaserde(root = "sub")] |   #[yaserde(rename = "sub")] | ||||||
|   pub struct SubStruct { |   pub struct SubStruct { | ||||||
|     #[yaserde(attribute)] |     #[yaserde(attribute)] | ||||||
|     subitem: String, |     subitem: String, | ||||||
| @ -117,8 +104,8 @@ fn ser_attributes() { | |||||||
|     }, |     }, | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base item=\"something\"><sub subitem=\"sub-something\" /></base>"; |   let content = r#"<base item="something"><sub subitem="sub-something" /></base>"#; | ||||||
|   convert_and_validate!(model, content); |   serialize_and_validate!(model, content); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[test] | #[test] | ||||||
| @ -158,24 +145,20 @@ fn ser_attributes_complex() { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   convert_and_validate!( |   serialize_and_validate!( | ||||||
|     Struct { |     Struct { | ||||||
|       attr_option_string: None, |       attr_option_string: None, | ||||||
|       attr_option_enum: None, |       attr_option_enum: None, | ||||||
|     }, |     }, | ||||||
|     r#" |     "<Struct />" | ||||||
|     <?xml version="1.0" encoding="utf-8"?> |  | ||||||
|     <Struct /> |  | ||||||
|     "#
 |  | ||||||
|   ); |   ); | ||||||
| 
 | 
 | ||||||
|   convert_and_validate!( |   serialize_and_validate!( | ||||||
|     Struct { |     Struct { | ||||||
|       attr_option_string: Some("some value".to_string()), |       attr_option_string: Some("some value".to_string()), | ||||||
|       attr_option_enum: Some(other_mod::AttrEnum::Variant2), |       attr_option_enum: Some(other_mod::AttrEnum::Variant2), | ||||||
|     }, |     }, | ||||||
|     r#" |     r#" | ||||||
|     <?xml version="1.0" encoding="utf-8"?> |  | ||||||
|     <Struct attr_option_string="some value" attr_option_enum="variant 2" /> |     <Struct attr_option_string="some value" attr_option_enum="variant 2" /> | ||||||
|     "#
 |     "#
 | ||||||
|   ); |   ); | ||||||
| @ -184,7 +167,7 @@ fn ser_attributes_complex() { | |||||||
| #[test] | #[test] | ||||||
| fn ser_rename() { | fn ser_rename() { | ||||||
|   #[derive(YaSerialize, PartialEq, Debug)] |   #[derive(YaSerialize, PartialEq, Debug)] | ||||||
|   #[yaserde(root = "base")] |   #[yaserde(rename = "base")] | ||||||
|   pub struct XmlStruct { |   pub struct XmlStruct { | ||||||
|     #[yaserde(attribute, rename = "Item")] |     #[yaserde(attribute, rename = "Item")] | ||||||
|     item: String, |     item: String, | ||||||
| @ -195,7 +178,7 @@ fn ser_rename() { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   #[derive(YaSerialize, PartialEq, Debug)] |   #[derive(YaSerialize, PartialEq, Debug)] | ||||||
|   #[yaserde(root = "sub")] |   #[yaserde(rename = "sub")] | ||||||
|   pub struct SubStruct { |   pub struct SubStruct { | ||||||
|     #[yaserde(attribute, rename = "sub_item")] |     #[yaserde(attribute, rename = "sub_item")] | ||||||
|     subitem: String, |     subitem: String, | ||||||
| @ -224,14 +207,14 @@ fn ser_rename() { | |||||||
|     version: "2.0.2".into(), |     version: "2.0.2".into(), | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base Item=\"something\"><sub sub_item=\"sub_something\" /><maj.min.bug>2.0.2</maj.min.bug></base>"; |   let content = r#"<base Item="something"><sub sub_item="sub_something" /><maj.min.bug>2.0.2</maj.min.bug></base>"#; | ||||||
|   convert_and_validate!(model, content); |   serialize_and_validate!(model, content); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[test] | #[test] | ||||||
| fn ser_text_content_with_attributes() { | fn ser_text_content_with_attributes() { | ||||||
|   #[derive(YaSerialize, PartialEq, Debug)] |   #[derive(YaSerialize, PartialEq, Debug)] | ||||||
|   #[yaserde(root = "base")] |   #[yaserde(rename = "base")] | ||||||
|   pub struct XmlStruct { |   pub struct XmlStruct { | ||||||
|     #[yaserde(attribute, rename = "Item")] |     #[yaserde(attribute, rename = "Item")] | ||||||
|     item: String, |     item: String, | ||||||
| @ -240,7 +223,7 @@ fn ser_text_content_with_attributes() { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   #[derive(YaSerialize, PartialEq, Debug)] |   #[derive(YaSerialize, PartialEq, Debug)] | ||||||
|   #[yaserde(root = "sub")] |   #[yaserde(rename = "sub")] | ||||||
|   pub struct SubStruct { |   pub struct SubStruct { | ||||||
|     #[yaserde(attribute, rename = "sub_item")] |     #[yaserde(attribute, rename = "sub_item")] | ||||||
|     subitem: String, |     subitem: String, | ||||||
| @ -273,14 +256,14 @@ fn ser_text_content_with_attributes() { | |||||||
|     }, |     }, | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base Item=\"something\"><sub sub_item=\"sub_something\">text_content</sub></base>"; |   let content = r#"<base Item="something"><sub sub_item="sub_something">text_content</sub></base>"#; | ||||||
|   convert_and_validate!(model, content); |   serialize_and_validate!(model, content); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[test] | #[test] | ||||||
| fn ser_name_issue_21() { | fn ser_name_issue_21() { | ||||||
|   #[derive(YaSerialize, PartialEq, Debug)] |   #[derive(YaSerialize, PartialEq, Debug)] | ||||||
|   #[yaserde(root = "base")] |   #[yaserde(rename = "base")] | ||||||
|   pub struct XmlStruct { |   pub struct XmlStruct { | ||||||
|     name: String, |     name: String, | ||||||
|   } |   } | ||||||
| @ -289,8 +272,8 @@ fn ser_name_issue_21() { | |||||||
|     name: "something".to_string(), |     name: "something".to_string(), | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base><name>something</name></base>"; |   let content = "<base><name>something</name></base>"; | ||||||
|   convert_and_validate!(model, content); |   serialize_and_validate!(model, content); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[test] | #[test] | ||||||
| @ -326,6 +309,6 @@ fn ser_custom() { | |||||||
|     month: 1, |     month: 1, | ||||||
|     day: Day { value: 5 }, |     day: Day { value: 5 }, | ||||||
|   }; |   }; | ||||||
|   let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Date><Year>2020</Year><Month>1</Month><DoubleDay>10</DoubleDay></Date>"; |   let content = "<Date><Year>2020</Year><Month>1</Month><DoubleDay>10</DoubleDay></Date>"; | ||||||
|   convert_and_validate!(model, content); |   serialize_and_validate!(model, content); | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,30 +1,25 @@ | |||||||
| #[macro_use] | #[macro_use] | ||||||
|  | extern crate yaserde; | ||||||
|  | #[macro_use] | ||||||
| extern crate yaserde_derive; | extern crate yaserde_derive; | ||||||
| 
 | 
 | ||||||
| use std::io::Write; | use std::io::Write; | ||||||
| use yaserde::ser::to_string; |  | ||||||
| use yaserde::YaSerialize; | use yaserde::YaSerialize; | ||||||
| 
 | 
 | ||||||
| macro_rules! convert_and_validate { | #[test] | ||||||
|   ($model: expr, $content: expr) => { | fn skip_serializing_if_for_struct() { | ||||||
|     let data: Result<String, String> = to_string(&$model); |   fn default_string_function() -> String { | ||||||
|     assert_eq!( |     "mask_default".to_string() | ||||||
|       data, |  | ||||||
|       Ok( |  | ||||||
|         String::from($content) |  | ||||||
|           .split("\n") |  | ||||||
|           .map(|s| s.trim()) |  | ||||||
|           .collect::<String>() |  | ||||||
|       ) |  | ||||||
|     ); |  | ||||||
|   }; |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| #[test] |  | ||||||
| fn ser_skip_serializing_if_for_struct() { |  | ||||||
|   #[derive(YaSerialize, PartialEq, Debug)] |   #[derive(YaSerialize, PartialEq, Debug)] | ||||||
|   #[yaserde(root = "base")] |   #[yaserde(rename = "base")] | ||||||
|   pub struct XmlStruct { |   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")] |     #[yaserde(skip_serializing_if = "check_string_function")] | ||||||
|     string_item: String, |     string_item: String, | ||||||
|     #[yaserde(skip_serializing_if = "check_bool_function")] |     #[yaserde(skip_serializing_if = "check_bool_function")] | ||||||
| @ -54,12 +49,13 @@ fn ser_skip_serializing_if_for_struct() { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   let model = XmlStruct { |   let model = XmlStruct { | ||||||
|  |     string_with_default_item: "mask_default".to_string(), | ||||||
|     string_item: "something".to_string(), |     string_item: "something".to_string(), | ||||||
|     bool_item: true, |     bool_item: true, | ||||||
|     f32_item: 0.0, |     f32_item: 0.0, | ||||||
|     option_string_item: Some("something".to_string()), |     option_string_item: Some("something".to_string()), | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base />"; |   let content = "<base />"; | ||||||
|   convert_and_validate!(model, content); |   serialize_and_validate!(model, content); | ||||||
| } | } | ||||||
							
								
								
									
										46
									
								
								yaserde/tests/types.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								yaserde/tests/types.rs
									
									
									
									
									
										Normal file
									
								
							| @ -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::<String>, vec![], None); | ||||||
|  |   test_for_type!(Vec::<String>, 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")); | ||||||
|  | } | ||||||
| @ -1,6 +1,4 @@ | |||||||
| use proc_macro2::token_stream::IntoIter; | use proc_macro2::{token_stream::IntoIter, Delimiter, TokenStream, TokenTree}; | ||||||
| use proc_macro2::Delimiter; |  | ||||||
| use proc_macro2::TokenTree; |  | ||||||
| use std::collections::BTreeMap; | use std::collections::BTreeMap; | ||||||
| use syn::Attribute; | use syn::Attribute; | ||||||
| 
 | 
 | ||||||
| @ -12,7 +10,6 @@ pub struct YaSerdeAttribute { | |||||||
|   pub flatten: bool, |   pub flatten: bool, | ||||||
|   pub namespaces: BTreeMap<String, String>, |   pub namespaces: BTreeMap<String, String>, | ||||||
|   pub prefix: Option<String>, |   pub prefix: Option<String>, | ||||||
|   pub root: Option<String>, |  | ||||||
|   pub rename: Option<String>, |   pub rename: Option<String>, | ||||||
|   pub skip_serializing_if: Option<String>, |   pub skip_serializing_if: Option<String>, | ||||||
|   pub text: bool, |   pub text: bool, | ||||||
| @ -41,7 +38,6 @@ impl YaSerdeAttribute { | |||||||
|     let mut namespaces = BTreeMap::new(); |     let mut namespaces = BTreeMap::new(); | ||||||
|     let mut prefix = None; |     let mut prefix = None; | ||||||
|     let mut rename = None; |     let mut rename = None; | ||||||
|     let mut root = None; |  | ||||||
|     let mut skip_serializing_if = None; |     let mut skip_serializing_if = None; | ||||||
|     let mut text = false; |     let mut text = false; | ||||||
| 
 | 
 | ||||||
| @ -84,9 +80,6 @@ impl YaSerdeAttribute { | |||||||
|                   "rename" => { |                   "rename" => { | ||||||
|                     rename = get_value(&mut attr_iter); |                     rename = get_value(&mut attr_iter); | ||||||
|                   } |                   } | ||||||
|                   "root" => { |  | ||||||
|                     root = get_value(&mut attr_iter); |  | ||||||
|                   } |  | ||||||
|                   "skip_serializing_if" => { |                   "skip_serializing_if" => { | ||||||
|                     skip_serializing_if = get_value(&mut attr_iter); |                     skip_serializing_if = get_value(&mut attr_iter); | ||||||
|                   } |                   } | ||||||
| @ -110,11 +103,49 @@ impl YaSerdeAttribute { | |||||||
|       namespaces, |       namespaces, | ||||||
|       prefix, |       prefix, | ||||||
|       rename, |       rename, | ||||||
|       root, |  | ||||||
|       skip_serializing_if, |       skip_serializing_if, | ||||||
|       text, |       text, | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |   pub fn get_namespace_matching( | ||||||
|  |     &self, | ||||||
|  |     prefix: &Option<String>, | ||||||
|  |     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] | #[test] | ||||||
| @ -130,7 +161,6 @@ fn parse_empty_attributes() { | |||||||
|       flatten: false, |       flatten: false, | ||||||
|       namespaces: BTreeMap::new(), |       namespaces: BTreeMap::new(), | ||||||
|       prefix: None, |       prefix: None, | ||||||
|       root: None, |  | ||||||
|       rename: None, |       rename: None, | ||||||
|       skip_serializing_if: None, |       skip_serializing_if: None, | ||||||
|       text: false, |       text: false, | ||||||
| @ -180,7 +210,6 @@ fn parse_attributes() { | |||||||
|       flatten: false, |       flatten: false, | ||||||
|       namespaces: BTreeMap::new(), |       namespaces: BTreeMap::new(), | ||||||
|       prefix: None, |       prefix: None, | ||||||
|       root: None, |  | ||||||
|       rename: None, |       rename: None, | ||||||
|       skip_serializing_if: None, |       skip_serializing_if: None, | ||||||
|       text: false, |       text: false, | ||||||
| @ -205,7 +234,6 @@ fn parse_attributes_with_values() { | |||||||
|     arguments: PathArguments::None, |     arguments: PathArguments::None, | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|   // #[()]
 |  | ||||||
|   let attributes = vec![Attribute { |   let attributes = vec![Attribute { | ||||||
|     pound_token: Pound { |     pound_token: Pound { | ||||||
|       spans: [Span::call_site()], |       spans: [Span::call_site()], | ||||||
| @ -234,7 +262,6 @@ fn parse_attributes_with_values() { | |||||||
|       flatten: true, |       flatten: true, | ||||||
|       namespaces, |       namespaces, | ||||||
|       prefix: None, |       prefix: None, | ||||||
|       root: None, |  | ||||||
|       rename: None, |       rename: None, | ||||||
|       skip_serializing_if: None, |       skip_serializing_if: None, | ||||||
|       text: false, |       text: false, | ||||||
							
								
								
									
										295
									
								
								yaserde_derive/src/common/field.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										295
									
								
								yaserde_derive/src/common/field.rs
									
									
									
									
									
										Normal file
									
								
							| @ -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<Ident> { | ||||||
|  |     self.syn_field.ident.clone() | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   pub fn get_value_label(&self) -> Option<syn::Ident> { | ||||||
|  |     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<Ident> { | ||||||
|  |     self | ||||||
|  |       .attributes | ||||||
|  |       .default | ||||||
|  |       .as_ref() | ||||||
|  |       .map(|default| Ident::new(&default, self.get_span())) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   pub fn get_skip_serializing_if_function(&self) -> Option<Ident> { | ||||||
|  |     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<TokenStream>, | ||||||
|  |     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<Field> }, | ||||||
|  |   FieldVec { data_type: Box<Field> }, | ||||||
|  |   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<proc_macro2::TokenStream> 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<String> 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) | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										5
									
								
								yaserde_derive/src/common/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								yaserde_derive/src/common/mod.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | |||||||
|  | mod attribute; | ||||||
|  | mod field; | ||||||
|  | 
 | ||||||
|  | pub use attribute::YaSerdeAttribute; | ||||||
|  | pub use field::{Field, YaSerdeField}; | ||||||
| @ -1,28 +1,24 @@ | |||||||
| use proc_macro2::{Span, TokenStream}; | use crate::common::YaSerdeField; | ||||||
| use syn::Ident; | use proc_macro2::TokenStream; | ||||||
| 
 | 
 | ||||||
| pub fn build_default_value( | pub fn build_default_value( | ||||||
|   label: &Option<Ident>, |   field: &YaSerdeField, | ||||||
|   field_type: &TokenStream, |   field_type: Option<TokenStream>, | ||||||
|   value: &TokenStream, |   value: TokenStream, | ||||||
|   default: &Option<String>, |  | ||||||
| ) -> Option<TokenStream> { | ) -> Option<TokenStream> { | ||||||
|   let value = default |   let label = field.get_value_label(); | ||||||
|     .as_ref() |  | ||||||
|     .map(|d| { |  | ||||||
|       let default_function = Ident::new( |  | ||||||
|         &d, |  | ||||||
|         label |  | ||||||
|           .as_ref() |  | ||||||
|           .map_or(Span::call_site(), |ident| ident.span()), |  | ||||||
|       ); |  | ||||||
| 
 | 
 | ||||||
|       quote!(#default_function()) |   let default_value = field | ||||||
|     }) |     .get_default_function() | ||||||
|  |     .map(|default_function| quote!(#default_function())) | ||||||
|     .unwrap_or_else(|| quote!(#value)); |     .unwrap_or_else(|| quote!(#value)); | ||||||
| 
 | 
 | ||||||
|  |   let field_type = field_type | ||||||
|  |     .map(|field_type| quote!(: #field_type)) | ||||||
|  |     .unwrap_or(quote!()); | ||||||
|  | 
 | ||||||
|   Some(quote! { |   Some(quote! { | ||||||
|     #[allow(unused_mut)] |     #[allow(unused_mut)] | ||||||
|     let mut #label : #field_type = #value; |     let mut #label #field_type = #default_value; | ||||||
|   }) |   }) | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,10 +1,6 @@ | |||||||
| use crate::attribute::*; | use crate::common::{Field, YaSerdeAttribute, YaSerdeField}; | ||||||
| use crate::field_type::*; |  | ||||||
| use proc_macro2::TokenStream; | use proc_macro2::TokenStream; | ||||||
| use syn::spanned::Spanned; | use syn::{DataEnum, Fields, Ident}; | ||||||
| use syn::DataEnum; |  | ||||||
| use syn::Fields; |  | ||||||
| use syn::Ident; |  | ||||||
| 
 | 
 | ||||||
| pub fn parse( | pub fn parse( | ||||||
|   data_enum: &DataEnum, |   data_enum: &DataEnum, | ||||||
| @ -141,9 +137,10 @@ fn build_unnamed_field_visitors(fields: &syn::FieldsUnnamed) -> TokenStream { | |||||||
|   fields |   fields | ||||||
|     .unnamed |     .unnamed | ||||||
|     .iter() |     .iter() | ||||||
|  |     .map(|field| YaSerdeField::new(field.clone())) | ||||||
|     .enumerate() |     .enumerate() | ||||||
|     .map(|(idx, field)| { |     .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 = |       let make_visitor = | ||||||
|         |visitor: &TokenStream, field_type: &TokenStream, fn_body: &TokenStream| { |         |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 simple_type_visitor = |simple_type: Field| { | ||||||
|         let field_type = get_simple_type_token(&simple_type); |         let visitor = simple_type.get_simple_type_visitor(); | ||||||
|         let visitor = get_simple_type_visitor(&simple_type); |         let field_type = simple_type.into(); | ||||||
| 
 | 
 | ||||||
|         make_visitor( |         make_visitor( | ||||||
|           &visitor, |           &visitor, | ||||||
| @ -171,8 +168,8 @@ fn build_unnamed_field_visitors(fields: &syn::FieldsUnnamed) -> TokenStream { | |||||||
|         ) |         ) | ||||||
|       }; |       }; | ||||||
| 
 | 
 | ||||||
|       get_field_type(field).and_then(|f| match f { |       match field.get_type() { | ||||||
|         FieldType::FieldTypeStruct { struct_name } => { |         Field::FieldStruct { struct_name } => { | ||||||
|           let struct_id: String = struct_name |           let struct_id: String = struct_name | ||||||
|             .segments |             .segments | ||||||
|             .iter() |             .iter() | ||||||
| @ -189,14 +186,12 @@ fn build_unnamed_field_visitors(fields: &syn::FieldsUnnamed) -> TokenStream { | |||||||
|             }, |             }, | ||||||
|           ) |           ) | ||||||
|         } |         } | ||||||
|         FieldType::FieldTypeOption { data_type } | FieldType::FieldTypeVec { data_type } => { |         Field::FieldOption { data_type } | Field::FieldVec { data_type } => match *data_type { | ||||||
|           match *data_type { |           Field::FieldStruct { .. } => None, | ||||||
|             FieldType::FieldTypeStruct { .. } => None, |           simple_type => simple_type_visitor(simple_type), | ||||||
|  |         }, | ||||||
|         simple_type => simple_type_visitor(simple_type), |         simple_type => simple_type_visitor(simple_type), | ||||||
|       } |       } | ||||||
|         } |  | ||||||
|         simple_type => simple_type_visitor(simple_type), |  | ||||||
|       }) |  | ||||||
|     }) |     }) | ||||||
|     .filter_map(|f| f) |     .filter_map(|f| f) | ||||||
|     .collect() |     .collect() | ||||||
| @ -209,13 +204,14 @@ fn build_unnamed_visitor_calls( | |||||||
|   fields |   fields | ||||||
|     .unnamed |     .unnamed | ||||||
|     .iter() |     .iter() | ||||||
|  |     .map(|field| YaSerdeField::new(field.clone())) | ||||||
|     .enumerate() |     .enumerate() | ||||||
|     .map(|(idx, field)| { |     .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 call_simple_type_visitor = |simple_type: Field, action| { | ||||||
|         let field_type = get_simple_type_token(&simple_type); |         let visitor = simple_type.get_simple_type_visitor(); | ||||||
|         let visitor = get_simple_type_visitor(&simple_type); |         let field_type: TokenStream = simple_type.into(); | ||||||
| 
 | 
 | ||||||
|         let label_name = format!("field_{}", idx); |         let label_name = format!("field_{}", idx); | ||||||
| 
 | 
 | ||||||
| @ -279,19 +275,19 @@ fn build_unnamed_visitor_calls( | |||||||
|         } |         } | ||||||
|       }; |       }; | ||||||
| 
 | 
 | ||||||
|       get_field_type(field).and_then(|f| match f { |       match field.get_type() { | ||||||
|         FieldType::FieldTypeStruct { struct_name } => call_struct_visitor(struct_name, set_val), |         Field::FieldStruct { struct_name } => call_struct_visitor(struct_name, set_val), | ||||||
|         FieldType::FieldTypeOption { data_type } => match *data_type { |         Field::FieldOption { data_type } => match *data_type { | ||||||
|           FieldType::FieldTypeStruct { struct_name } => call_struct_visitor(struct_name, set_opt), |           Field::FieldStruct { struct_name } => call_struct_visitor(struct_name, set_opt), | ||||||
|           simple_type => call_simple_type_visitor(simple_type, set_opt), |           simple_type => call_simple_type_visitor(simple_type, set_opt), | ||||||
|         }, |         }, | ||||||
|         FieldType::FieldTypeVec { data_type } => match *data_type { |         Field::FieldVec { data_type } => match *data_type { | ||||||
|           FieldType::FieldTypeStruct { struct_name } => call_struct_visitor(struct_name, set_vec), |           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_vec), | ||||||
|         }, |         }, | ||||||
| 
 | 
 | ||||||
|         simple_type => call_simple_type_visitor(simple_type, set_val), |         simple_type => call_simple_type_visitor(simple_type, set_val), | ||||||
|       }) |       } | ||||||
|     }) |     }) | ||||||
|     .filter_map(|f| f) |     .filter_map(|f| f) | ||||||
|     .collect() |     .collect() | ||||||
|  | |||||||
| @ -1,11 +1,7 @@ | |||||||
| use crate::attribute::*; | use crate::common::{Field, YaSerdeAttribute, YaSerdeField}; | ||||||
| use crate::de::build_default_value::build_default_value; | use crate::de::build_default_value::build_default_value; | ||||||
| use crate::field_type::*; |  | ||||||
| use proc_macro2::{Span, TokenStream}; | use proc_macro2::{Span, TokenStream}; | ||||||
| use std::collections::BTreeMap; | use syn::{DataStruct, Ident}; | ||||||
| use syn::spanned::Spanned; |  | ||||||
| use syn::DataStruct; |  | ||||||
| use syn::Ident; |  | ||||||
| 
 | 
 | ||||||
| pub fn parse( | pub fn parse( | ||||||
|   data_struct: &DataStruct, |   data_struct: &DataStruct, | ||||||
| @ -13,92 +9,52 @@ pub fn parse( | |||||||
|   root: &str, |   root: &str, | ||||||
|   root_attributes: &YaSerdeAttribute, |   root_attributes: &YaSerdeAttribute, | ||||||
| ) -> TokenStream { | ) -> TokenStream { | ||||||
|   let namespaces_matches: TokenStream = root_attributes |   let namespaces_matching = root_attributes.get_namespace_matching( | ||||||
|     .namespaces |     &None, | ||||||
|     .iter() |     quote!(struct_namespace), | ||||||
|     .map(|(p, ns)| { |     quote!(named_element), | ||||||
|       if root_attributes.prefix.as_ref() == Some(p) { |     true, | ||||||
|         Some(quote!(#ns => {})) |   ); | ||||||
|       } else { |  | ||||||
|         None |  | ||||||
|       } |  | ||||||
|     }) |  | ||||||
|     .filter_map(|x| x) |  | ||||||
|     .collect(); |  | ||||||
| 
 | 
 | ||||||
|   let variables: TokenStream = data_struct |   let variables: TokenStream = data_struct | ||||||
|     .fields |     .fields | ||||||
|     .iter() |     .iter() | ||||||
|     .map(|field| { |     .map(|field| YaSerdeField::new(field.clone())) | ||||||
|       let label = &get_value_label(&field.ident); |     .map(|field| match field.get_type() { | ||||||
|       let field_attrs = YaSerdeAttribute::parse(&field.attrs); |       Field::FieldStruct { struct_name } => build_default_value( | ||||||
| 
 |         &field, | ||||||
|       get_field_type(field).and_then(|f| match f { |         Some(quote!(#struct_name)), | ||||||
|         FieldType::FieldTypeStruct { struct_name } => build_default_value( |         quote!(#struct_name::default()), | ||||||
|           label, |  | ||||||
|           "e! {#struct_name}, |  | ||||||
|           "e! {#struct_name::default()}, |  | ||||||
|           &field_attrs.default, |  | ||||||
|       ), |       ), | ||||||
|         FieldType::FieldTypeOption { .. } => { |       Field::FieldOption { .. } => build_default_value(&field, None, quote!(None)), | ||||||
|           if let Some(d) = &field_attrs.default { |       Field::FieldVec { data_type } => match *data_type { | ||||||
|             let default_function = Ident::new(&d, field.span()); |         Field::FieldStruct { ref struct_name } => { | ||||||
| 
 |           build_default_value(&field, Some(quote!(Vec<#struct_name>)), quote!(vec![])) | ||||||
|             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; |  | ||||||
|             }) |  | ||||||
|         } |         } | ||||||
|         } |         Field::FieldOption { .. } | Field::FieldVec { .. } => { | ||||||
|         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!(); |           unimplemented!(); | ||||||
|         } |         } | ||||||
|         simple_type => { |         simple_type => { | ||||||
|             let type_token = get_simple_type_token(&simple_type); |           let type_token: TokenStream = simple_type.into(); | ||||||
| 
 | 
 | ||||||
|             build_default_value( |           build_default_value(&field, Some(quote!(Vec<#type_token>)), quote!(vec![])) | ||||||
|               label, |  | ||||||
|               "e! {Vec<#type_token>}, |  | ||||||
|               "e! {vec![]}, |  | ||||||
|               &field_attrs.default, |  | ||||||
|             ) |  | ||||||
|         } |         } | ||||||
|       }, |       }, | ||||||
|       simple_type => { |       simple_type => { | ||||||
|           let type_token = get_simple_type_token(&simple_type); |         let type_token: TokenStream = simple_type.into(); | ||||||
|           build_default_value( |         let value_builder = quote!(#type_token::default()); | ||||||
|             label, | 
 | ||||||
|             &type_token, |         build_default_value(&field, Some(type_token), value_builder) | ||||||
|             "e! {#type_token::default()}, |  | ||||||
|             &field_attrs.default, |  | ||||||
|           ) |  | ||||||
|       } |       } | ||||||
|     }) |     }) | ||||||
|     }) |  | ||||||
|     .filter_map(|x| x) |     .filter_map(|x| x) | ||||||
|     .collect(); |     .collect(); | ||||||
| 
 | 
 | ||||||
|   let field_visitors: TokenStream = data_struct |   let field_visitors: TokenStream = data_struct | ||||||
|     .fields |     .fields | ||||||
|     .iter() |     .iter() | ||||||
|  |     .map(|field| YaSerdeField::new(field.clone())) | ||||||
|     .map(|field| { |     .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_visitor = |struct_name: syn::Path| { | ||||||
|         let struct_id: String = struct_name |         let struct_id: String = struct_name | ||||||
|           .segments |           .segments | ||||||
| @ -106,7 +62,7 @@ pub fn parse( | |||||||
|           .map(|s| s.ident.to_string()) |           .map(|s| s.ident.to_string()) | ||||||
|           .collect(); |           .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! { |         Some(quote! { | ||||||
|           #[allow(non_snake_case, non_camel_case_types)] |           #[allow(non_snake_case, non_camel_case_types)] | ||||||
| @ -123,10 +79,10 @@ pub fn parse( | |||||||
|         }) |         }) | ||||||
|       }; |       }; | ||||||
| 
 | 
 | ||||||
|       let simple_type_visitor = |simple_type: FieldType| { |       let simple_type_visitor = |simple_type: Field| { | ||||||
|         let field_type = get_simple_type_token(&simple_type); |         let visitor = simple_type.get_simple_type_visitor(); | ||||||
|         let visitor = get_simple_type_visitor(&simple_type); |         let visitor_label = field.get_visitor_ident(None); | ||||||
|         let visitor_label = build_visitor_ident(&label_name, field.span(), None); |         let field_type: TokenStream = simple_type.into(); | ||||||
| 
 | 
 | ||||||
|         Some(quote! { |         Some(quote! { | ||||||
|           #[allow(non_snake_case, non_camel_case_types)] |           #[allow(non_snake_case, non_camel_case_types)] | ||||||
| @ -141,20 +97,20 @@ pub fn parse( | |||||||
|         }) |         }) | ||||||
|       }; |       }; | ||||||
| 
 | 
 | ||||||
|       get_field_type(field).and_then(|f| match f { |       match field.get_type() { | ||||||
|         FieldType::FieldTypeStruct { struct_name } => struct_visitor(struct_name), |         Field::FieldStruct { struct_name } => struct_visitor(struct_name), | ||||||
|         FieldType::FieldTypeOption { data_type } => match *data_type { |         Field::FieldOption { data_type } => match *data_type { | ||||||
|           FieldType::FieldTypeStruct { struct_name } => struct_visitor(struct_name), |           Field::FieldStruct { struct_name } => struct_visitor(struct_name), | ||||||
|           FieldType::FieldTypeOption { .. } | FieldType::FieldTypeVec { .. } => None, |           Field::FieldOption { .. } | Field::FieldVec { .. } => None, | ||||||
|           simple_type => simple_type_visitor(simple_type), |           simple_type => simple_type_visitor(simple_type), | ||||||
|         }, |         }, | ||||||
|         FieldType::FieldTypeVec { data_type } => match *data_type { |         Field::FieldVec { data_type } => match *data_type { | ||||||
|           FieldType::FieldTypeStruct { struct_name } => struct_visitor(struct_name), |           Field::FieldStruct { struct_name } => struct_visitor(struct_name), | ||||||
|           FieldType::FieldTypeOption { .. } | FieldType::FieldTypeVec { .. } => None, |           Field::FieldOption { .. } | Field::FieldVec { .. } => None, | ||||||
|           simple_type => simple_type_visitor(simple_type), |           simple_type => simple_type_visitor(simple_type), | ||||||
|         }, |         }, | ||||||
|         simple_type => simple_type_visitor(simple_type), |         simple_type => simple_type_visitor(simple_type), | ||||||
|       }) |       } | ||||||
|     }) |     }) | ||||||
|     .filter_map(|x| x) |     .filter_map(|x| x) | ||||||
|     .collect(); |     .collect(); | ||||||
| @ -162,19 +118,11 @@ pub fn parse( | |||||||
|   let call_visitors: TokenStream = data_struct |   let call_visitors: TokenStream = data_struct | ||||||
|     .fields |     .fields | ||||||
|     .iter() |     .iter() | ||||||
|  |     .map(|field| YaSerdeField::new(field.clone())) | ||||||
|  |     .filter(|field| !field.is_attribute() || !field.is_flatten()) | ||||||
|     .map(|field| { |     .map(|field| { | ||||||
|       let field_attrs = YaSerdeAttribute::parse(&field.attrs); |       let value_label = field.get_value_label(); | ||||||
|       let label = &field.ident; |       let label_name = field.renamed_label_without_namespace(); | ||||||
|       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 visit_struct = |struct_name: syn::Path, action: TokenStream| { |       let visit_struct = |struct_name: syn::Path, action: TokenStream| { | ||||||
|         Some(quote! { |         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( |         build_call_visitor( | ||||||
|           &get_simple_type_token(&simple_type), |           &field_type, | ||||||
|           &get_simple_type_visitor(&simple_type), |           &field_visitor, | ||||||
|           &action, |           &action, | ||||||
|           &field_attrs, |           &field, | ||||||
|           label, |           &root_attributes, | ||||||
|           &root_attributes.namespaces, |  | ||||||
|           field.span(), |  | ||||||
|         ) |         ) | ||||||
|       }; |       }; | ||||||
| 
 | 
 | ||||||
|       let visit_sub = |sub_type: Box<FieldType>, action: TokenStream| match *sub_type { |       let visit_sub = |sub_type: Box<Field>, action: TokenStream| match *sub_type { | ||||||
|         FieldType::FieldTypeOption { .. } | FieldType::FieldTypeVec { .. } => unimplemented!(), |         Field::FieldOption { .. } | Field::FieldVec { .. } => unimplemented!(), | ||||||
|         FieldType::FieldTypeStruct { struct_name } => visit_struct(struct_name, action), |         Field::FieldStruct { struct_name } => visit_struct(struct_name, action), | ||||||
|         simple_type => visit_simple(simple_type, action), |         simple_type => visit_simple(simple_type, action), | ||||||
|       }; |       }; | ||||||
| 
 | 
 | ||||||
|       get_field_type(field).and_then(|f| match f { |       match field.get_type() { | ||||||
|         FieldType::FieldTypeStruct { struct_name } => visit_struct(struct_name, quote! {= value}), |         Field::FieldStruct { struct_name } => visit_struct(struct_name, quote! {= value}), | ||||||
|         FieldType::FieldTypeOption { data_type } => visit_sub(data_type, quote! {= Some(value)}), |         Field::FieldOption { data_type } => visit_sub(data_type, quote! {= Some(value)}), | ||||||
|         FieldType::FieldTypeVec { data_type } => visit_sub(data_type, quote! {.push(value)}), |         Field::FieldVec { data_type } => visit_sub(data_type, quote! {.push(value)}), | ||||||
|         simple_type => visit_simple(simple_type, quote! {= value}), |         simple_type => visit_simple(simple_type, quote! {= value}), | ||||||
|       }) |       } | ||||||
|     }) |     }) | ||||||
|     .filter_map(|x| x) |     .filter_map(|x| x) | ||||||
|     .collect(); |     .collect(); | ||||||
| @ -223,26 +171,23 @@ pub fn parse( | |||||||
|   let call_flatten_visitors: TokenStream = data_struct |   let call_flatten_visitors: TokenStream = data_struct | ||||||
|     .fields |     .fields | ||||||
|     .iter() |     .iter() | ||||||
|  |     .map(|field| YaSerdeField::new(field.clone())) | ||||||
|  |     .filter(|field| !field.is_attribute() && field.is_flatten()) | ||||||
|     .map(|field| { |     .map(|field| { | ||||||
|       let field_attrs = YaSerdeAttribute::parse(&field.attrs); |       let value_label = field.get_value_label(); | ||||||
|       let value_label = &get_value_label(&field.ident); |  | ||||||
| 
 | 
 | ||||||
|       if field_attrs.attribute || !field_attrs.flatten { |       match field.get_type() { | ||||||
|         return None; |         Field::FieldStruct { .. } => Some(quote! { | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       get_field_type(field).and_then(|f| match f { |  | ||||||
|         FieldType::FieldTypeStruct { .. } => Some(quote! { |  | ||||||
|           #value_label = yaserde::de::from_str(&unused_xml_elements)?; |           #value_label = yaserde::de::from_str(&unused_xml_elements)?; | ||||||
|         }), |         }), | ||||||
|         FieldType::FieldTypeOption { data_type } => match *data_type { |         Field::FieldOption { data_type } => match *data_type { | ||||||
|           FieldType::FieldTypeStruct { .. } => Some(quote! { |           Field::FieldStruct { .. } => Some(quote! { | ||||||
|             #value_label = yaserde::de::from_str(&unused_xml_elements).ok(); |             #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) |     .filter_map(|x| x) | ||||||
|     .collect(); |     .collect(); | ||||||
| @ -250,19 +195,12 @@ pub fn parse( | |||||||
|   let attributes_loading: TokenStream = data_struct |   let attributes_loading: TokenStream = data_struct | ||||||
|     .fields |     .fields | ||||||
|     .iter() |     .iter() | ||||||
|  |     .map(|field| YaSerdeField::new(field.clone())) | ||||||
|  |     .filter(|field| field.is_attribute()) | ||||||
|     .map(|field| { |     .map(|field| { | ||||||
|       let field_attrs = YaSerdeAttribute::parse(&field.attrs); |       let label = field.get_value_label(); | ||||||
|       if !field_attrs.attribute { |       let label_name = field.renamed_label_without_namespace(); | ||||||
|         return None; |       let visitor_label = build_visitor_ident(&label_name, field.get_span(), 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 visit = |action: &TokenStream, visitor: &TokenStream, visitor_label: &Ident| { |       let visit = |action: &TokenStream, visitor: &TokenStream, visitor_label: &Ident| { | ||||||
|         Some(quote! { |         Some(quote! { | ||||||
| @ -290,31 +228,31 @@ pub fn parse( | |||||||
|         visit( |         visit( | ||||||
|           &action, |           &action, | ||||||
|           "e! {visit_str}, |           "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( |         visit( | ||||||
|           &action, |           &action, | ||||||
|           &get_simple_type_visitor(&simple_type), |           &simple_type.get_simple_type_visitor(), | ||||||
|           &visitor_label, |           &visitor_label, | ||||||
|         ) |         ) | ||||||
|       }; |       }; | ||||||
| 
 | 
 | ||||||
|       let visit_sub = |sub_type: Box<FieldType>, action: TokenStream| match *sub_type { |       let visit_sub = |sub_type: Box<Field>, action: TokenStream| match *sub_type { | ||||||
|         FieldType::FieldTypeOption { .. } | FieldType::FieldTypeVec { .. } => unimplemented!(), |         Field::FieldOption { .. } | Field::FieldVec { .. } => unimplemented!(), | ||||||
|         FieldType::FieldTypeStruct { struct_name } => visit_struct(struct_name, action), |         Field::FieldStruct { struct_name } => visit_struct(struct_name, action), | ||||||
|         simple_type => visit_simple(simple_type, action), |         simple_type => visit_simple(simple_type, action), | ||||||
|       }; |       }; | ||||||
| 
 | 
 | ||||||
|       get_field_type(field).and_then(|f| match f { |       match field.get_type() { | ||||||
|         FieldType::FieldTypeString => visit_string(), |         Field::FieldString => visit_string(), | ||||||
|         FieldType::FieldTypeOption { data_type } => visit_sub(data_type, quote! {= Some(value)}), |         Field::FieldOption { data_type } => visit_sub(data_type, quote! {= Some(value)}), | ||||||
|         FieldType::FieldTypeVec { .. } => unimplemented!(), |         Field::FieldVec { .. } => unimplemented!(), | ||||||
|         FieldType::FieldTypeStruct { struct_name } => visit_struct(struct_name, quote! {= value}), |         Field::FieldStruct { struct_name } => visit_struct(struct_name, quote! {= value}), | ||||||
|         simple_type => visit_simple(simple_type, quote! {= value}), |         simple_type => visit_simple(simple_type, quote! {= value}), | ||||||
|       }) |       } | ||||||
|     }) |     }) | ||||||
|     .filter_map(|x| x) |     .filter_map(|x| x) | ||||||
|     .collect(); |     .collect(); | ||||||
| @ -322,28 +260,26 @@ pub fn parse( | |||||||
|   let set_text: TokenStream = data_struct |   let set_text: TokenStream = data_struct | ||||||
|     .fields |     .fields | ||||||
|     .iter() |     .iter() | ||||||
|  |     .map(|field| YaSerdeField::new(field.clone())) | ||||||
|     .map(|field| { |     .map(|field| { | ||||||
|       let label = &get_value_label(&field.ident); |       let label = field.get_value_label(); | ||||||
|       let field_attrs = YaSerdeAttribute::parse(&field.attrs); |  | ||||||
| 
 | 
 | ||||||
|       let set_text = |action: &TokenStream| { |       let set_text = |action: &TokenStream| { | ||||||
|         if field_attrs.text { |         if field.is_text_content() { | ||||||
|           Some(quote! {#label = #action;}) |           Some(quote! {#label = #action;}) | ||||||
|         } else { |         } else { | ||||||
|           None |           None | ||||||
|         } |         } | ||||||
|       }; |       }; | ||||||
| 
 | 
 | ||||||
|       get_field_type(field).and_then(|f| match f { |       match field.get_type() { | ||||||
|         FieldType::FieldTypeString => set_text("e! {text_content.to_owned()}), |         Field::FieldString => set_text("e! {text_content.to_owned()}), | ||||||
|         FieldType::FieldTypeStruct { .. } |         Field::FieldStruct { .. } | Field::FieldOption { .. } | Field::FieldVec { .. } => None, | ||||||
|         | FieldType::FieldTypeOption { .. } |  | ||||||
|         | FieldType::FieldTypeVec { .. } => None, |  | ||||||
|         simple_type => { |         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()}) |           set_text("e! {#type_token::from_str(text_content).unwrap()}) | ||||||
|         } |         } | ||||||
|       }) |       } | ||||||
|     }) |     }) | ||||||
|     .filter_map(|x| x) |     .filter_map(|x| x) | ||||||
|     .collect(); |     .collect(); | ||||||
| @ -351,15 +287,13 @@ pub fn parse( | |||||||
|   let struct_builder: TokenStream = data_struct |   let struct_builder: TokenStream = data_struct | ||||||
|     .fields |     .fields | ||||||
|     .iter() |     .iter() | ||||||
|  |     .map(|field| YaSerdeField::new(field.clone())) | ||||||
|     .map(|field| { |     .map(|field| { | ||||||
|       let label = &field.ident; |       let label = &field.label(); | ||||||
|       let value_label = &get_value_label(&field.ident); |       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(); |     .collect(); | ||||||
| 
 | 
 | ||||||
|   let (init_unused, write_unused, visit_unused) = if call_flatten_visitors.is_empty() { |   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); |         debug!("Struct: start to parse {:?}", named_element); | ||||||
| 
 | 
 | ||||||
|         if reader.depth() == 0 { |         if reader.depth() == 0 { | ||||||
|           if let Some(ref namespace) = struct_namespace { |           #namespaces_matching | ||||||
|             match namespace.as_str() { |  | ||||||
|               #namespaces_matches |  | ||||||
|               bad_ns => { |  | ||||||
|                 let msg = format!("bad namespace for {}, found {}", named_element, bad_ns); |  | ||||||
|                 return Err(msg); |  | ||||||
|               } |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         #variables |         #variables | ||||||
| @ -472,47 +398,24 @@ fn build_call_visitor( | |||||||
|   field_type: &TokenStream, |   field_type: &TokenStream, | ||||||
|   visitor: &TokenStream, |   visitor: &TokenStream, | ||||||
|   action: &TokenStream, |   action: &TokenStream, | ||||||
|   field_attrs: &YaSerdeAttribute, |   field: &YaSerdeField, | ||||||
|   label: &Option<Ident>, |   root_attributes: &YaSerdeAttribute, | ||||||
|   namespaces: &BTreeMap<String, String>, |  | ||||||
|   span: Span, |  | ||||||
| ) -> Option<TokenStream> { | ) -> Option<TokenStream> { | ||||||
|   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 namespaces_matching = field.get_namespace_matching( | ||||||
|   let value_label = get_value_label(label); |     root_attributes, | ||||||
|   let label_name = field_attrs |     quote!(name.namespace.as_ref()), | ||||||
|     .rename |     quote!(name.local_name.as_str()), | ||||||
|     .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(); |  | ||||||
| 
 | 
 | ||||||
|   Some(quote! { |   Some(quote! { | ||||||
|     #label_name => { |     #label_name => { | ||||||
|       let visitor = #visitor_label{}; |       let visitor = #visitor_label{}; | ||||||
| 
 | 
 | ||||||
|       if let Some(namespace) = name.namespace.as_ref() { |       #namespaces_matching | ||||||
|         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); |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
| 
 | 
 | ||||||
|       let result = reader.read_inner_value::<#field_type, _>(|reader| { |       let result = reader.read_inner_value::<#field_type, _>(|reader| { | ||||||
|         if let Ok(XmlEvent::Characters(s)) = reader.peek() { |         if let Ok(XmlEvent::Characters(s)) = reader.peek() { | ||||||
| @ -531,12 +434,6 @@ fn build_call_visitor( | |||||||
|   }) |   }) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn get_value_label(ident: &Option<syn::Ident>) -> Option<syn::Ident> { |  | ||||||
|   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 { | fn build_visitor_ident(label: &str, span: Span, struct_name: Option<&syn::Path>) -> Ident { | ||||||
|   let struct_id = struct_name.map_or_else( |   let struct_id = struct_name.map_or_else( | ||||||
|     || "".to_string(), |     || "".to_string(), | ||||||
|  | |||||||
| @ -2,7 +2,7 @@ pub mod build_default_value; | |||||||
| pub mod expand_enum; | pub mod expand_enum; | ||||||
| pub mod expand_struct; | pub mod expand_struct; | ||||||
| 
 | 
 | ||||||
| use crate::attribute; | use crate::common::YaSerdeAttribute; | ||||||
| use proc_macro2::TokenStream; | use proc_macro2::TokenStream; | ||||||
| use syn; | use syn; | ||||||
| use syn::Ident; | use syn::Ident; | ||||||
| @ -12,14 +12,19 @@ pub fn expand_derive_deserialize(ast: &syn::DeriveInput) -> Result<TokenStream, | |||||||
|   let attrs = &ast.attrs; |   let attrs = &ast.attrs; | ||||||
|   let data = &ast.data; |   let data = &ast.data; | ||||||
| 
 | 
 | ||||||
|   let root_attrs = attribute::YaSerdeAttribute::parse(attrs); |   let root_attributes = YaSerdeAttribute::parse(attrs); | ||||||
|   let root = root_attrs.clone().root.unwrap_or_else(|| name.to_string()); |   let root_name = root_attributes | ||||||
|  |     .clone() | ||||||
|  |     .rename | ||||||
|  |     .unwrap_or_else(|| name.to_string()); | ||||||
| 
 | 
 | ||||||
|   let impl_block = match *data { |   let impl_block = match *data { | ||||||
|     syn::Data::Struct(ref data_struct) => { |     syn::Data::Struct(ref data_struct) => { | ||||||
|       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!(), |     syn::Data::Union(ref _data_union) => unimplemented!(), | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -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<FieldType> }, |  | ||||||
|   FieldTypeVec { data_type: Box<FieldType> }, |  | ||||||
|   FieldTypeStruct { struct_name: syn::Path }, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl FieldType { |  | ||||||
|   fn from_ident(path: &syn::Path) -> Option<FieldType> { |  | ||||||
|     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<FieldType> { |  | ||||||
|   match field.ty { |  | ||||||
|     Path(ref path) => FieldType::from_ident(&path.path), |  | ||||||
|     _ => None, |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn get_sub_type(t: &syn::PathSegment) -> Option<syn::Path> { |  | ||||||
|   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} |  | ||||||
| } |  | ||||||
| @ -6,9 +6,8 @@ extern crate proc_macro2; | |||||||
| extern crate quote; | extern crate quote; | ||||||
| extern crate syn; | extern crate syn; | ||||||
| 
 | 
 | ||||||
| mod attribute; | mod common; | ||||||
| mod de; | mod de; | ||||||
| mod field_type; |  | ||||||
| mod ser; | mod ser; | ||||||
| 
 | 
 | ||||||
| use proc_macro::TokenStream; | use proc_macro::TokenStream; | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| use crate::attribute::*; | use crate::common::YaSerdeField; | ||||||
| use proc_macro2::{Ident, Span, TokenStream}; | use proc_macro2::{Ident, TokenStream}; | ||||||
| 
 | 
 | ||||||
| pub fn enclose_formatted_characters(label: &Ident, label_name: String) -> TokenStream { | pub fn enclose_formatted_characters(label: &Ident, label_name: String) -> TokenStream { | ||||||
|   enclose_xml_event(label_name, quote!(format!("{}", &self.#label))) |   enclose_xml_event(label_name, quote!(format!("{}", &self.#label))) | ||||||
| @ -13,7 +13,7 @@ pub fn enclose_characters(label: &Option<Ident>, label_name: String) -> TokenStr | |||||||
|   enclose_xml_event(label_name, quote!(format!("{}", self.#label))) |   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! { |   quote! { | ||||||
|     let start_event = XmlEvent::start_element(#label_name); |     let start_event = XmlEvent::start_element(#label_name); | ||||||
|     writer.write(start_event).map_err(|e| e.to_string())?; |     writer.write(start_event).map_err(|e| e.to_string())?; | ||||||
| @ -41,34 +41,23 @@ pub fn serialize_element( | |||||||
|   }) |   }) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn condition_generator(label: &Option<Ident>, attributes: &YaSerdeAttribute) -> TokenStream { | pub fn condition_generator(label: &Option<Ident>, field: &YaSerdeField) -> TokenStream { | ||||||
|   let mut conditions = None; |   let default_condition = field | ||||||
|  |     .get_default_function() | ||||||
|  |     .map(|default_function| quote!(self.#label != #default_function())); | ||||||
| 
 | 
 | ||||||
|   if let Some(ref d) = attributes.default { |   field | ||||||
|     let default_function = Ident::new( |     .get_skip_serializing_if_function() | ||||||
|       &d, |     .map(|skip_if_function| { | ||||||
|       label |       if let Some(prev_conditions) = &default_condition { | ||||||
|         .as_ref() |         quote!(if !self.#skip_if_function(&self.#label) && #prev_conditions) | ||||||
|         .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 { |       } else { | ||||||
|       Some(quote!(!self.#skip_if_function(&self.#label))) |         quote!(if !self.#skip_if_function(&self.#label)) | ||||||
|     }; |  | ||||||
|       } |       } | ||||||
| 
 |     }) | ||||||
|   conditions.map(|c| quote!(if #c)).unwrap_or(quote!()) |     .unwrap_or_else(|| { | ||||||
|  |       default_condition | ||||||
|  |         .map(|condition| quote!(if #condition)) | ||||||
|  |         .unwrap_or(quote!()) | ||||||
|  |     }) | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,8 +1,6 @@ | |||||||
| use crate::attribute::*; | use crate::common::{Field, YaSerdeAttribute, YaSerdeField}; | ||||||
| use crate::field_type::*; |  | ||||||
| use crate::ser::{implement_deserializer::implement_deserializer, label::build_label_name}; | use crate::ser::{implement_deserializer::implement_deserializer, label::build_label_name}; | ||||||
| use proc_macro2::TokenStream; | use proc_macro2::TokenStream; | ||||||
| use syn::spanned::Spanned; |  | ||||||
| use syn::DataEnum; | use syn::DataEnum; | ||||||
| use syn::Fields; | use syn::Fields; | ||||||
| use syn::Ident; | use syn::Ident; | ||||||
| @ -51,39 +49,33 @@ fn inner_enum_inspector( | |||||||
|           let enum_fields: TokenStream = fields |           let enum_fields: TokenStream = fields | ||||||
|             .named |             .named | ||||||
|             .iter() |             .iter() | ||||||
|  |             .map(|field| YaSerdeField::new(field.clone())) | ||||||
|  |             .filter(|field| !field.is_attribute()) | ||||||
|             .map(|field| { |             .map(|field| { | ||||||
|               let field_attrs = YaSerdeAttribute::parse(&field.attrs); |               let field_label = field.label(); | ||||||
|               if field_attrs.attribute { |  | ||||||
|                 return None; |  | ||||||
|               } |  | ||||||
| 
 | 
 | ||||||
|               let field_label = &field.ident; |               if field.is_text_content() { | ||||||
|               if field_attrs.text { |  | ||||||
|                 return Some(quote!( |                 return Some(quote!( | ||||||
|                   let data_event = XmlEvent::characters(&self.#field_label); |                   let data_event = XmlEvent::characters(&self.#field_label); | ||||||
|                   writer.write(data_event).map_err(|e| e.to_string())?; |                   writer.write(data_event).map_err(|e| e.to_string())?; | ||||||
|                 )); |                 )); | ||||||
|               } |               } | ||||||
| 
 | 
 | ||||||
|               let renamed_field_label = match field_attrs.rename { |               let field_label_name = field.renamed_label(root_attributes); | ||||||
|                 Some(value) => Some(Ident::new(&value.replace("\"", ""), field.span())), |  | ||||||
|                 None => field.ident.clone(), |  | ||||||
|               }; |  | ||||||
|               let field_label_name = renamed_field_label.unwrap().to_string(); |  | ||||||
| 
 | 
 | ||||||
|               match get_field_type(field) { |               match field.get_type() { | ||||||
|                 Some(FieldType::FieldTypeString) |                 Field::FieldString | ||||||
|                 | Some(FieldType::FieldTypeBool) |                 | Field::FieldBool | ||||||
|                 | Some(FieldType::FieldTypeU8) |                 | Field::FieldU8 | ||||||
|                 | Some(FieldType::FieldTypeI8) |                 | Field::FieldI8 | ||||||
|                 | Some(FieldType::FieldTypeU16) |                 | Field::FieldU16 | ||||||
|                 | Some(FieldType::FieldTypeI16) |                 | Field::FieldI16 | ||||||
|                 | Some(FieldType::FieldTypeU32) |                 | Field::FieldU32 | ||||||
|                 | Some(FieldType::FieldTypeI32) |                 | Field::FieldI32 | ||||||
|                 | Some(FieldType::FieldTypeF32) |                 | Field::FieldF32 | ||||||
|                 | Some(FieldType::FieldTypeU64) |                 | Field::FieldU64 | ||||||
|                 | Some(FieldType::FieldTypeI64) |                 | Field::FieldI64 | ||||||
|                 | Some(FieldType::FieldTypeF64) => Some({ |                 | Field::FieldF64 => Some({ | ||||||
|                   quote! { |                   quote! { | ||||||
|                     match self { |                     match self { | ||||||
|                       &#name::#label{ref #field_label, ..} => { |                       &#name::#label{ref #field_label, ..} => { | ||||||
| @ -101,7 +93,7 @@ fn inner_enum_inspector( | |||||||
|                     } |                     } | ||||||
|                   } |                   } | ||||||
|                 }), |                 }), | ||||||
|                 Some(FieldType::FieldTypeStruct { .. }) => Some(quote! { |                 Field::FieldStruct { .. } => Some(quote! { | ||||||
|                   match self { |                   match self { | ||||||
|                     &#name::#label{ref #field_label, ..} => { |                     &#name::#label{ref #field_label, ..} => { | ||||||
|                       writer.set_start_event_name(Some(#field_label_name.to_string())); |                       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 { |                   match self { | ||||||
|                     &#name::#label{ref #field_label, ..} => { |                     &#name::#label{ref #field_label, ..} => { | ||||||
|                       for item in #field_label { |                       for item in #field_label { | ||||||
| @ -123,7 +115,7 @@ fn inner_enum_inspector( | |||||||
|                     _ => {} |                     _ => {} | ||||||
|                   } |                   } | ||||||
|                 }), |                 }), | ||||||
|                 _ => None, |                 Field::FieldOption { .. } => None, | ||||||
|               } |               } | ||||||
|             }) |             }) | ||||||
|             .filter_map(|x| x) |             .filter_map(|x| x) | ||||||
| @ -139,12 +131,9 @@ fn inner_enum_inspector( | |||||||
|           let enum_fields: TokenStream = fields |           let enum_fields: TokenStream = fields | ||||||
|             .unnamed |             .unnamed | ||||||
|             .iter() |             .iter() | ||||||
|  |             .map(|field| YaSerdeField::new(field.clone())) | ||||||
|  |             .filter(|field| !field.is_attribute()) | ||||||
|             .map(|field| { |             .map(|field| { | ||||||
|               let field_attrs = YaSerdeAttribute::parse(&field.attrs); |  | ||||||
|               if field_attrs.attribute { |  | ||||||
|                 return None; |  | ||||||
|               } |  | ||||||
| 
 |  | ||||||
|               let write_element = |action: &TokenStream| { |               let write_element = |action: &TokenStream| { | ||||||
|                 quote! { |                 quote! { | ||||||
|                   let struct_start_event = XmlEvent::start_element(#label_name); |                   let struct_start_event = XmlEvent::start_element(#label_name); | ||||||
| @ -176,7 +165,7 @@ fn inner_enum_inspector( | |||||||
| 
 | 
 | ||||||
|               let write_sub_type = |data_type| { |               let write_sub_type = |data_type| { | ||||||
|                 write_element(match data_type { |                 write_element(match data_type { | ||||||
|                   FieldType::FieldTypeString => &write_string_chars, |                   Field::FieldString => &write_string_chars, | ||||||
|                   _ => &serialize, |                   _ => &serialize, | ||||||
|                 }) |                 }) | ||||||
|               }; |               }; | ||||||
| @ -192,8 +181,8 @@ fn inner_enum_inspector( | |||||||
|                 } |                 } | ||||||
|               }; |               }; | ||||||
| 
 | 
 | ||||||
|               match get_field_type(field) { |               match field.get_type() { | ||||||
|                 Some(FieldType::FieldTypeOption { data_type }) => { |                 Field::FieldOption { data_type } => { | ||||||
|                   let write = write_sub_type(*data_type); |                   let write = write_sub_type(*data_type); | ||||||
| 
 | 
 | ||||||
|                   Some(match_field("e! { |                   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); |                   let write = write_sub_type(*data_type); | ||||||
| 
 | 
 | ||||||
|                   Some(match_field("e! { |                   Some(match_field("e! { | ||||||
| @ -211,14 +200,9 @@ fn inner_enum_inspector( | |||||||
|                     } |                     } | ||||||
|                   })) |                   })) | ||||||
|                 } |                 } | ||||||
|                 Some(FieldType::FieldTypeStruct { .. }) => { |                 Field::FieldStruct { .. } => Some(write_element(&match_field(&serialize))), | ||||||
|                   Some(write_element(&match_field(&serialize))) |                 Field::FieldString => Some(match_field(&write_element(&write_string_chars))), | ||||||
|                 } |                 _simple_type => Some(match_field(&write_simple_type)), | ||||||
|                 Some(FieldType::FieldTypeString) => { |  | ||||||
|                   Some(match_field(&write_element(&write_string_chars))) |  | ||||||
|                 } |  | ||||||
|                 Some(_simple_type) => Some(match_field(&write_simple_type)), |  | ||||||
|                 _ => None, |  | ||||||
|               } |               } | ||||||
|             }) |             }) | ||||||
|             .filter_map(|x| x) |             .filter_map(|x| x) | ||||||
|  | |||||||
| @ -1,10 +1,7 @@ | |||||||
| use crate::attribute::*; | use crate::common::{Field, YaSerdeAttribute, YaSerdeField}; | ||||||
| use crate::field_type::*; | 
 | ||||||
| use crate::ser::{ | use crate::ser::{element::*, implement_deserializer::implement_deserializer}; | ||||||
|   element::*, implement_deserializer::implement_deserializer, label::build_label_name, |  | ||||||
| }; |  | ||||||
| use proc_macro2::TokenStream; | use proc_macro2::TokenStream; | ||||||
| use syn::spanned::Spanned; |  | ||||||
| use syn::DataStruct; | use syn::DataStruct; | ||||||
| use syn::Ident; | use syn::Ident; | ||||||
| 
 | 
 | ||||||
| @ -17,193 +14,98 @@ pub fn serialize( | |||||||
|   let build_attributes: TokenStream = data_struct |   let build_attributes: TokenStream = data_struct | ||||||
|     .fields |     .fields | ||||||
|     .iter() |     .iter() | ||||||
|  |     .map(|field| YaSerdeField::new(field.clone())) | ||||||
|  |     .filter(|field| field.is_attribute()) | ||||||
|     .map(|field| { |     .map(|field| { | ||||||
|       let field_attrs = YaSerdeAttribute::parse(&field.attrs); |       let label = field.label(); | ||||||
|       if !field_attrs.attribute { |       let label_name = field.renamed_label(root_attributes); | ||||||
|         return None; |  | ||||||
|       } |  | ||||||
| 
 | 
 | ||||||
|       let label = &field.ident; |       match field.get_type() { | ||||||
| 
 |         Field::FieldString | ||||||
|       let label_name = build_label_name( |         | Field::FieldBool | ||||||
|         &label.as_ref().unwrap(), |         | Field::FieldI8 | ||||||
|         &field_attrs, |         | Field::FieldU8 | ||||||
|         &root_attributes.default_namespace, |         | Field::FieldI16 | ||||||
|       ); |         | Field::FieldU16 | ||||||
| 
 |         | Field::FieldI32 | ||||||
|       get_field_type(field).and_then(|f| match f { |         | Field::FieldU32 | ||||||
|         FieldType::FieldTypeString |         | Field::FieldI64 | ||||||
|         | FieldType::FieldTypeBool |         | Field::FieldU64 | ||||||
|         | FieldType::FieldTypeI8 |         | Field::FieldF32 | ||||||
|         | FieldType::FieldTypeU8 |         | Field::FieldF64 => Some(field.ser_wrap_default_attribute( | ||||||
|         | FieldType::FieldTypeI16 |           Some(quote!(self.#label.to_string())), | ||||||
|         | FieldType::FieldTypeU16 |           quote!({ | ||||||
|         | FieldType::FieldTypeI32 |             struct_start_event.attr(#label_name, &yaserde_inner) | ||||||
|         | FieldType::FieldTypeU32 |           }), | ||||||
|         | FieldType::FieldTypeI64 |         )), | ||||||
|         | FieldType::FieldTypeU64 |         Field::FieldOption { data_type } => match *data_type { | ||||||
|         | FieldType::FieldTypeF32 |           Field::FieldString => Some(field.ser_wrap_default_attribute( | ||||||
|         | FieldType::FieldTypeF64 => { |             None, | ||||||
|           if let Some(ref d) = field_attrs.default { |             quote!({ | ||||||
|             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 { |               if let Some(ref value) = self.#label { | ||||||
|                       struct_start_event.attr(#label_name, &value) |                 struct_start_event.attr(#label_name, value) | ||||||
|               } else { |               } else { | ||||||
|                 struct_start_event |                 struct_start_event | ||||||
|               } |               } | ||||||
|                   } else { |             }), | ||||||
|                     struct_start_event |           )), | ||||||
|                   }; |           Field::FieldBool | ||||||
|               }) |           | Field::FieldI8 | ||||||
|             } else { |           | Field::FieldU8 | ||||||
|               Some(quote! { |           | Field::FieldI16 | ||||||
|                 let struct_start_event = |           | 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 { |               if let Some(ref value) = self.#label { | ||||||
|                     struct_start_event.attr(#label_name, &value) |                 struct_start_event.attr(#label_name, &yaserde_inner) | ||||||
|                   } 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 { |               } else { | ||||||
|                 struct_start_event |                 struct_start_event | ||||||
|               } |               } | ||||||
|                   } else { |             }), | ||||||
|                     struct_start_event |           )), | ||||||
|                   }; |           Field::FieldVec { .. } => { | ||||||
|               }) |             let item_ident = Ident::new("yaserde_item", field.get_span()); | ||||||
|             } 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()); |  | ||||||
|             let inner = enclose_formatted_characters(&item_ident, label_name); |             let inner = enclose_formatted_characters(&item_ident, label_name); | ||||||
| 
 | 
 | ||||||
|             if let Some(ref d) = field_attrs.default { |             Some(field.ser_wrap_default_attribute( | ||||||
|               let default_function = Ident::new(&d, field.span()); |               None, | ||||||
| 
 |               quote!({ | ||||||
|               Some(quote! { |  | ||||||
|                 if self.#label != #default_function() { |  | ||||||
|                 if let Some(ref yaserde_list) = self.#label { |                 if let Some(ref yaserde_list) = self.#label { | ||||||
|                   for yaserde_item in yaserde_list.iter() { |                   for yaserde_item in yaserde_list.iter() { | ||||||
|                     #inner |                     #inner | ||||||
|                   } |                   } | ||||||
|                 } |                 } | ||||||
|  |               }), | ||||||
|  |             )) | ||||||
|           } |           } | ||||||
|               }) |           Field::FieldStruct { .. } => Some(field.ser_wrap_default_attribute( | ||||||
|             } else { |             Some(quote!(self.#label | ||||||
|               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 |  | ||||||
|                   .as_ref() |                   .as_ref() | ||||||
|                   .map_or_else(|| Ok(String::new()), |v| yaserde::ser::to_string_content(v))?; |                   .map_or_else(|| Ok(String::new()), |v| yaserde::ser::to_string_content(v))?)), | ||||||
|                 let struct_start_event = if let Some(ref value) = self.#label { |             quote!({ | ||||||
|                   if *value != #default_function() { |               if let Some(ref yaserde_struct) = self.#label { | ||||||
|                     struct_start_event.attr(#label_name, &content) |                 struct_start_event.attr(#label_name, &yaserde_inner) | ||||||
|               } else { |               } else { | ||||||
|                 struct_start_event |                 struct_start_event | ||||||
|               } |               } | ||||||
|                 } else { |             }), | ||||||
|                   struct_start_event |           )), | ||||||
|                 }; |           Field::FieldOption { .. } => unimplemented!(), | ||||||
|               }) |  | ||||||
|             } 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!(), |  | ||||||
|         }, |         }, | ||||||
|         FieldType::FieldTypeStruct { .. } => { |         Field::FieldStruct { .. } => Some(field.ser_wrap_default_attribute( | ||||||
|           if let Some(ref d) = field_attrs.default { |           Some(quote!(yaserde::ser::to_string_content(&self.#label)?)), | ||||||
|             let default_function = Ident::new(&d, field.span()); |           quote!({ | ||||||
|             Some(quote! { |             struct_start_event.attr(#label_name, &yaserde_inner) | ||||||
|               let content = yaserde::ser::to_string_content(&self.#label)?; |           }), | ||||||
|               let struct_start_event = |         )), | ||||||
|                 if self.#label != #default_function() { |         Field::FieldVec { .. } => None, | ||||||
|                   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, |  | ||||||
|       }) |  | ||||||
|     }) |     }) | ||||||
|     .filter_map(|x| x) |     .filter_map(|x| x) | ||||||
|     .collect(); |     .collect(); | ||||||
| @ -211,54 +113,48 @@ pub fn serialize( | |||||||
|   let struct_inspector: TokenStream = data_struct |   let struct_inspector: TokenStream = data_struct | ||||||
|     .fields |     .fields | ||||||
|     .iter() |     .iter() | ||||||
|  |     .map(|field| YaSerdeField::new(field.clone())) | ||||||
|  |     .filter(|field| !field.is_attribute()) | ||||||
|     .map(|field| { |     .map(|field| { | ||||||
|       let field_attrs = YaSerdeAttribute::parse(&field.attrs); |       let label = field.label(); | ||||||
|       if field_attrs.attribute { |       if field.is_text_content() { | ||||||
|         return None; |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       let label = &field.ident; |  | ||||||
|       if field_attrs.text { |  | ||||||
|         return Some(quote!( |         return Some(quote!( | ||||||
|           let data_event = XmlEvent::characters(&self.#label); |           let data_event = XmlEvent::characters(&self.#label); | ||||||
|           writer.write(data_event).map_err(|e| e.to_string())?; |           writer.write(data_event).map_err(|e| e.to_string())?; | ||||||
|         )); |         )); | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       let label_name = build_label_name( |       let label_name = field.renamed_label(root_attributes); | ||||||
|         &label.as_ref().unwrap(), |       let conditions = condition_generator(&label, &field); | ||||||
|         &field_attrs, |  | ||||||
|         &root_attributes.default_namespace, |  | ||||||
|       ); |  | ||||||
|       let conditions = condition_generator(label, &field_attrs); |  | ||||||
| 
 | 
 | ||||||
|       get_field_type(field).and_then(|f| match f { |       match field.get_type() { | ||||||
|         FieldType::FieldTypeString |         Field::FieldString | ||||||
|         | FieldType::FieldTypeBool |         | Field::FieldBool | ||||||
|         | FieldType::FieldTypeI8 |         | Field::FieldI8 | ||||||
|         | FieldType::FieldTypeU8 |         | Field::FieldU8 | ||||||
|         | FieldType::FieldTypeI16 |         | Field::FieldI16 | ||||||
|         | FieldType::FieldTypeU16 |         | Field::FieldU16 | ||||||
|         | FieldType::FieldTypeI32 |         | Field::FieldI32 | ||||||
|         | FieldType::FieldTypeU32 |         | Field::FieldU32 | ||||||
|         | FieldType::FieldTypeI64 |         | Field::FieldI64 | ||||||
|         | FieldType::FieldTypeU64 |         | Field::FieldU64 | ||||||
|         | FieldType::FieldTypeF32 |         | Field::FieldF32 | ||||||
|         | FieldType::FieldTypeF64 => serialize_element(label, label_name, &conditions), |         | Field::FieldF64 => serialize_element(&label, label_name, &conditions), | ||||||
|         FieldType::FieldTypeOption { data_type } => match *data_type { | 
 | ||||||
|           FieldType::FieldTypeString |         Field::FieldOption { data_type } => match *data_type { | ||||||
|           | FieldType::FieldTypeBool |           Field::FieldString | ||||||
|           | FieldType::FieldTypeI8 |           | Field::FieldBool | ||||||
|           | FieldType::FieldTypeU8 |           | Field::FieldI8 | ||||||
|           | FieldType::FieldTypeI16 |           | Field::FieldU8 | ||||||
|           | FieldType::FieldTypeU16 |           | Field::FieldI16 | ||||||
|           | FieldType::FieldTypeI32 |           | Field::FieldU16 | ||||||
|           | FieldType::FieldTypeU32 |           | Field::FieldI32 | ||||||
|           | FieldType::FieldTypeI64 |           | Field::FieldU32 | ||||||
|           | FieldType::FieldTypeU64 |           | Field::FieldI64 | ||||||
|           | FieldType::FieldTypeF32 |           | Field::FieldU64 | ||||||
|           | FieldType::FieldTypeF64 => { |           | Field::FieldF32 | ||||||
|             let item_ident = Ident::new("yaserde_item", field.span()); |           | Field::FieldF64 => { | ||||||
|  |             let item_ident = Ident::new("yaserde_item", field.get_span()); | ||||||
|             let inner = enclose_formatted_characters_for_value(&item_ident, label_name); |             let inner = enclose_formatted_characters_for_value(&item_ident, label_name); | ||||||
| 
 | 
 | ||||||
|             Some(quote! { |             Some(quote! { | ||||||
| @ -269,8 +165,8 @@ pub fn serialize( | |||||||
|               } |               } | ||||||
|             }) |             }) | ||||||
|           } |           } | ||||||
|           FieldType::FieldTypeVec { .. } => { |           Field::FieldVec { .. } => { | ||||||
|             let item_ident = Ident::new("yaserde_item", field.span()); |             let item_ident = Ident::new("yaserde_item", field.get_span()); | ||||||
|             let inner = enclose_formatted_characters_for_value(&item_ident, label_name); |             let inner = enclose_formatted_characters_for_value(&item_ident, label_name); | ||||||
| 
 | 
 | ||||||
|             Some(quote! { |             Some(quote! { | ||||||
| @ -283,7 +179,7 @@ pub fn serialize( | |||||||
|               } |               } | ||||||
|             }) |             }) | ||||||
|           } |           } | ||||||
|           FieldType::FieldTypeStruct { .. } => Some(if field_attrs.flatten { |           Field::FieldStruct { .. } => Some(if field.is_flatten() { | ||||||
|             quote! { |             quote! { | ||||||
|               if let Some(ref item) = &self.#label { |               if let Some(ref item) = &self.#label { | ||||||
|                 writer.set_start_event_name(None); |                 writer.set_start_event_name(None); | ||||||
| @ -302,8 +198,8 @@ pub fn serialize( | |||||||
|           }), |           }), | ||||||
|           _ => unimplemented!(), |           _ => unimplemented!(), | ||||||
|         }, |         }, | ||||||
|         FieldType::FieldTypeStruct { .. } => { |         Field::FieldStruct { .. } => { | ||||||
|           let (start_event, skip_start) = if field_attrs.flatten { |           let (start_event, skip_start) = if field.is_flatten() { | ||||||
|             (quote!(None), true) |             (quote!(None), true) | ||||||
|           } else { |           } else { | ||||||
|             (quote!(Some(#label_name.to_string())), false) |             (quote!(Some(#label_name.to_string())), false) | ||||||
| @ -315,9 +211,9 @@ pub fn serialize( | |||||||
|             self.#label.serialize(writer)?; |             self.#label.serialize(writer)?; | ||||||
|           }) |           }) | ||||||
|         } |         } | ||||||
|         FieldType::FieldTypeVec { data_type } => match *data_type { |         Field::FieldVec { data_type } => match *data_type { | ||||||
|           FieldType::FieldTypeString => { |           Field::FieldString => { | ||||||
|             let item_ident = Ident::new("yaserde_item", field.span()); |             let item_ident = Ident::new("yaserde_item", field.get_span()); | ||||||
|             let inner = enclose_formatted_characters_for_value(&item_ident, label_name); |             let inner = enclose_formatted_characters_for_value(&item_ident, label_name); | ||||||
| 
 | 
 | ||||||
|             Some(quote! { |             Some(quote! { | ||||||
| @ -326,18 +222,18 @@ pub fn serialize( | |||||||
|               } |               } | ||||||
|             }) |             }) | ||||||
|           } |           } | ||||||
|           FieldType::FieldTypeBool |           Field::FieldBool | ||||||
|           | FieldType::FieldTypeI8 |           | Field::FieldI8 | ||||||
|           | FieldType::FieldTypeU8 |           | Field::FieldU8 | ||||||
|           | FieldType::FieldTypeI16 |           | Field::FieldI16 | ||||||
|           | FieldType::FieldTypeU16 |           | Field::FieldU16 | ||||||
|           | FieldType::FieldTypeI32 |           | Field::FieldI32 | ||||||
|           | FieldType::FieldTypeU32 |           | Field::FieldU32 | ||||||
|           | FieldType::FieldTypeI64 |           | Field::FieldI64 | ||||||
|           | FieldType::FieldTypeU64 |           | Field::FieldU64 | ||||||
|           | FieldType::FieldTypeF32 |           | Field::FieldF32 | ||||||
|           | FieldType::FieldTypeF64 => { |           | Field::FieldF64 => { | ||||||
|             let item_ident = Ident::new("yaserde_item", field.span()); |             let item_ident = Ident::new("yaserde_item", field.get_span()); | ||||||
|             let inner = enclose_formatted_characters_for_value(&item_ident, label_name); |             let inner = enclose_formatted_characters_for_value(&item_ident, label_name); | ||||||
| 
 | 
 | ||||||
|             Some(quote! { |             Some(quote! { | ||||||
| @ -346,7 +242,7 @@ pub fn serialize( | |||||||
|               } |               } | ||||||
|             }) |             }) | ||||||
|           } |           } | ||||||
|           FieldType::FieldTypeOption { .. } => Some(quote! { |           Field::FieldOption { .. } => Some(quote! { | ||||||
|             for item in &self.#label { |             for item in &self.#label { | ||||||
|               if let Some(value) = item { |               if let Some(value) = item { | ||||||
|                 writer.set_start_event_name(None); |                 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 { |             for item in &self.#label { | ||||||
|               writer.set_start_event_name(None); |               writer.set_start_event_name(None); | ||||||
|               writer.set_skip_start_end(false); |               writer.set_skip_start_end(false); | ||||||
|               item.serialize(writer)?; |               item.serialize(writer)?; | ||||||
|             } |             } | ||||||
|           }), |           }), | ||||||
|           FieldType::FieldTypeVec { .. } => { |           Field::FieldVec { .. } => { | ||||||
|             unimplemented!(); |             unimplemented!(); | ||||||
|           } |           } | ||||||
|         }, |         }, | ||||||
|       }) |       } | ||||||
|     }) |     }) | ||||||
|     .filter_map(|x| x) |     .filter_map(|x| x) | ||||||
|     .collect(); |     .collect(); | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| use crate::attribute::YaSerdeAttribute; | use crate::common::YaSerdeAttribute; | ||||||
| use crate::ser::namespace::generate_namespaces_definition; | use crate::ser::namespace::generate_namespaces_definition; | ||||||
| use proc_macro2::Ident; | use proc_macro2::Ident; | ||||||
| use proc_macro2::TokenStream; | use proc_macro2::TokenStream; | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| use crate::attribute::YaSerdeAttribute; | use crate::common::YaSerdeAttribute; | ||||||
| use proc_macro2::Ident; | use proc_macro2::Ident; | ||||||
| 
 | 
 | ||||||
| pub fn build_label_name( | pub fn build_label_name( | ||||||
|  | |||||||
| @ -5,7 +5,7 @@ pub mod implement_deserializer; | |||||||
| pub mod label; | pub mod label; | ||||||
| pub mod namespace; | pub mod namespace; | ||||||
| 
 | 
 | ||||||
| use crate::attribute::YaSerdeAttribute; | use crate::common::YaSerdeAttribute; | ||||||
| use proc_macro2::TokenStream; | use proc_macro2::TokenStream; | ||||||
| use syn; | use syn; | ||||||
| use syn::Ident; | use syn::Ident; | ||||||
| @ -15,25 +15,30 @@ pub fn expand_derive_serialize(ast: &syn::DeriveInput) -> Result<TokenStream, St | |||||||
|   let attrs = &ast.attrs; |   let attrs = &ast.attrs; | ||||||
|   let data = &ast.data; |   let data = &ast.data; | ||||||
| 
 | 
 | ||||||
|   let root_attrs = YaSerdeAttribute::parse(attrs); |   let root_attributes = YaSerdeAttribute::parse(attrs); | ||||||
|   let root = root_attrs.clone().root.unwrap_or_else(|| name.to_string()); |   let root_name = root_attributes | ||||||
|  |     .clone() | ||||||
|  |     .rename | ||||||
|  |     .unwrap_or_else(|| name.to_string()); | ||||||
| 
 | 
 | ||||||
|   let prefix = if root_attrs.default_namespace == root_attrs.prefix { |   let prefix = if root_attributes.default_namespace == root_attributes.prefix { | ||||||
|     "".to_string() |     "".to_string() | ||||||
|   } else { |   } else { | ||||||
|     root_attrs |     root_attributes | ||||||
|       .clone() |       .clone() | ||||||
|       .prefix |       .prefix | ||||||
|       .map_or("".to_string(), |prefix| prefix + ":") |       .map_or("".to_string(), |prefix| prefix + ":") | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   let root = format!("{}{}", prefix, root); |   let root_name = format!("{}{}", prefix, root_name); | ||||||
| 
 | 
 | ||||||
|   let impl_block = match *data { |   let impl_block = match *data { | ||||||
|     syn::Data::Struct(ref data_struct) => { |     syn::Data::Struct(ref data_struct) => { | ||||||
|       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!(), |     syn::Data::Union(ref _data_union) => unimplemented!(), | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| use crate::attribute::YaSerdeAttribute; | use crate::common::YaSerdeAttribute; | ||||||
| use proc_macro2::TokenStream; | use proc_macro2::TokenStream; | ||||||
| 
 | 
 | ||||||
| pub fn generate_namespaces_definition(attributes: &YaSerdeAttribute) -> TokenStream { | pub fn generate_namespaces_definition(attributes: &YaSerdeAttribute) -> TokenStream { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user