Merge pull request #30 from DmitrySamoylov/feature-complex-enum
(De)serializtion for enums with unnamed fields
This commit is contained in:
		
						commit
						3771a95feb
					
				| @ -351,6 +351,208 @@ fn de_attribute_enum() { | |||||||
|   ); |   ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #[test] | ||||||
|  | fn de_complex_enum() { | ||||||
|  |   #[derive(YaDeserialize, PartialEq, Debug)] | ||||||
|  |   pub struct XmlStruct { | ||||||
|  |     background: Color, | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   #[derive(YaDeserialize, PartialEq, Debug, Default)] | ||||||
|  |   pub struct OtherStruct { | ||||||
|  |     fi: i32, | ||||||
|  |     se: i32, | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   #[derive(YaDeserialize, PartialEq, Debug)] | ||||||
|  |   pub enum Color { | ||||||
|  |     White, | ||||||
|  |     Black(String), | ||||||
|  |     Orange(std::string::String), | ||||||
|  |     Red(i32), | ||||||
|  |     Green(OtherStruct), | ||||||
|  |     Yellow(Option<String>), | ||||||
|  |     Brown(Option<OtherStruct>), | ||||||
|  |     Blue(Vec<String>), | ||||||
|  |     Purple(Vec<i32>), | ||||||
|  |     Magenta(Vec<OtherStruct>), | ||||||
|  |     #[yaserde(rename = "NotSoCyan")] | ||||||
|  |     Cyan(Vec<OtherStruct>), | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   impl Default for Color { | ||||||
|  |     fn default() -> Color { | ||||||
|  |       Color::White | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   let content = r#"<?xml version="1.0" encoding="utf-8"?>
 | ||||||
|  |     <base> | ||||||
|  |       <background> | ||||||
|  |         <Black>text</Black> | ||||||
|  |       </background> | ||||||
|  |     </base> | ||||||
|  |   "#;
 | ||||||
|  |   convert_and_validate!( | ||||||
|  |     content, | ||||||
|  |     XmlStruct, | ||||||
|  |     XmlStruct { | ||||||
|  |       background: Color::Black(String::from("text")), | ||||||
|  |     } | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  |   let content = r#"<?xml version="1.0" encoding="utf-8"?>
 | ||||||
|  |     <base> | ||||||
|  |       <background> | ||||||
|  |         <Orange>text</Orange> | ||||||
|  |       </background> | ||||||
|  |     </base> | ||||||
|  |   "#;
 | ||||||
|  |   convert_and_validate!( | ||||||
|  |     content, | ||||||
|  |     XmlStruct, | ||||||
|  |     XmlStruct { | ||||||
|  |       background: Color::Orange(String::from("text")), | ||||||
|  |     } | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  |   let content = r#"<?xml version="1.0" encoding="utf-8"?>
 | ||||||
|  |     <base> | ||||||
|  |       <background> | ||||||
|  |         <Red>56</Red> | ||||||
|  |       </background> | ||||||
|  |     </base> | ||||||
|  |   "#;
 | ||||||
|  |   convert_and_validate!( | ||||||
|  |     content, | ||||||
|  |     XmlStruct, | ||||||
|  |     XmlStruct { | ||||||
|  |       background: Color::Red(56), | ||||||
|  |     } | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  |   let content = r#"<?xml version="1.0" encoding="utf-8"?>
 | ||||||
|  |     <base> | ||||||
|  |       <background> | ||||||
|  |         <Green> | ||||||
|  |           <fi>12</fi> | ||||||
|  |           <se>23</se> | ||||||
|  |         </Green> | ||||||
|  |       </background> | ||||||
|  |     </base> | ||||||
|  |   "#;
 | ||||||
|  |   convert_and_validate!( | ||||||
|  |     content, | ||||||
|  |     XmlStruct, | ||||||
|  |     XmlStruct { | ||||||
|  |       background: Color::Green(OtherStruct { fi: 12, se: 23 }), | ||||||
|  |     } | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  |   let content = r#"<?xml version="1.0" encoding="utf-8"?>
 | ||||||
|  |     <base> | ||||||
|  |       <background> | ||||||
|  |         <Yellow>text</Yellow> | ||||||
|  |       </background> | ||||||
|  |     </base> | ||||||
|  |   "#;
 | ||||||
|  |   convert_and_validate!( | ||||||
|  |     content, | ||||||
|  |     XmlStruct, | ||||||
|  |     XmlStruct { | ||||||
|  |       background: Color::Yellow(Some(String::from("text"))), | ||||||
|  |     } | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  |   let content = r#"<?xml version="1.0" encoding="utf-8"?>
 | ||||||
|  |     <base> | ||||||
|  |       <background> | ||||||
|  |         <Brown> | ||||||
|  |           <fi>12</fi> | ||||||
|  |           <se>23</se> | ||||||
|  |         </Brown> | ||||||
|  |       </background> | ||||||
|  |     </base> | ||||||
|  |   "#;
 | ||||||
|  |   convert_and_validate!( | ||||||
|  |     content, | ||||||
|  |     XmlStruct, | ||||||
|  |     XmlStruct { | ||||||
|  |       background: Color::Brown(Some(OtherStruct { fi: 12, se: 23 })), | ||||||
|  |     } | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  |   let content = r#"<?xml version="1.0" encoding="utf-8"?>
 | ||||||
|  |     <base> | ||||||
|  |       <background> | ||||||
|  |         <Blue>abc</Blue> | ||||||
|  |         <Blue>def</Blue> | ||||||
|  |       </background> | ||||||
|  |     </base> | ||||||
|  |   "#;
 | ||||||
|  |   convert_and_validate!( | ||||||
|  |     content, | ||||||
|  |     XmlStruct, | ||||||
|  |     XmlStruct { | ||||||
|  |       background: Color::Blue(vec![String::from("abc"), String::from("def")]), | ||||||
|  |     } | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  |   let content = r#"<?xml version="1.0" encoding="utf-8"?>
 | ||||||
|  |     <base> | ||||||
|  |       <background> | ||||||
|  |         <Purple>12</Purple> | ||||||
|  |         <Purple>43</Purple> | ||||||
|  |       </background> | ||||||
|  |     </base> | ||||||
|  |   "#;
 | ||||||
|  |   convert_and_validate!( | ||||||
|  |     content, | ||||||
|  |     XmlStruct, | ||||||
|  |     XmlStruct { | ||||||
|  |       background: Color::Purple(vec![12, 43]), | ||||||
|  |     } | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  |   let content = r#"<?xml version="1.0" encoding="utf-8"?>
 | ||||||
|  |     <base> | ||||||
|  |       <background> | ||||||
|  |         <Magenta><fi>12</fi><se>23</se></Magenta> | ||||||
|  |         <Magenta><fi>63</fi><se>98</se></Magenta> | ||||||
|  |       </background> | ||||||
|  |     </base> | ||||||
|  |   "#;
 | ||||||
|  |   convert_and_validate!( | ||||||
|  |     content, | ||||||
|  |     XmlStruct, | ||||||
|  |     XmlStruct { | ||||||
|  |       background: Color::Magenta(vec![ | ||||||
|  |         OtherStruct { fi: 12, se: 23 }, | ||||||
|  |         OtherStruct { fi: 63, se: 98 } | ||||||
|  |       ]), | ||||||
|  |     } | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  |   let content = r#"<?xml version="1.0" encoding="utf-8"?>
 | ||||||
|  |     <base xmlns:ns="http://www.sample.com/ns/domain"> | ||||||
|  |       <background> | ||||||
|  |         <NotSoCyan><fi>12</fi><se>23</se></NotSoCyan> | ||||||
|  |         <NotSoCyan><fi>63</fi><se>98</se></NotSoCyan> | ||||||
|  |       </background> | ||||||
|  |     </base> | ||||||
|  |   "#;
 | ||||||
|  |   convert_and_validate!( | ||||||
|  |     content, | ||||||
|  |     XmlStruct, | ||||||
|  |     XmlStruct { | ||||||
|  |       background: Color::Cyan(vec![ | ||||||
|  |         OtherStruct { fi: 12, se: 23 }, | ||||||
|  |         OtherStruct { fi: 63, se: 98 } | ||||||
|  |       ]) | ||||||
|  |     } | ||||||
|  |   ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #[test] | #[test] | ||||||
| fn de_name_issue_21() { | fn de_name_issue_21() { | ||||||
|   #[derive(YaDeserialize, PartialEq, Debug)] |   #[derive(YaDeserialize, PartialEq, Debug)] | ||||||
|  | |||||||
| @ -299,6 +299,132 @@ fn ser_attribute_enum() { | |||||||
|   convert_and_validate!(model, content); |   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), | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   impl Default for Enum { | ||||||
|  |     fn default() -> Enum { | ||||||
|  |       Enum::Simple | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   let model = XmlStruct { | ||||||
|  |     color: Enum::Field(String::from("some_text")), | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   let content = "<?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 = "<?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 = | ||||||
|  |     "<?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 = "<?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 = "<?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 = "<?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 = "<?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 = "<?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 = "<?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 = "<?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 = "<?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 = | ||||||
|  |     "<?xml version=\"1.0\" encoding=\"utf-8\"?><base><color><renamed>87</renamed></color></base>"; | ||||||
|  |   convert_and_validate!(model, content); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #[test] | #[test] | ||||||
| fn ser_name_issue_21() { | fn ser_name_issue_21() { | ||||||
|   #[derive(YaSerialize, PartialEq, Debug)] |   #[derive(YaSerialize, PartialEq, Debug)] | ||||||
|  | |||||||
| @ -1,8 +1,6 @@ | |||||||
| use attribute::*; | use attribute::*; | ||||||
| use de::build_default_value::build_default_value; |  | ||||||
| use field_type::*; | use field_type::*; | ||||||
| use proc_macro2::{Span, TokenStream}; | use proc_macro2::{Span, TokenStream}; | ||||||
| use quote::TokenStreamExt; |  | ||||||
| use std::collections::BTreeMap; | use std::collections::BTreeMap; | ||||||
| use syn::DataEnum; | use syn::DataEnum; | ||||||
| use syn::Fields; | use syn::Fields; | ||||||
| @ -14,250 +12,18 @@ pub fn parse( | |||||||
|   root: &str, |   root: &str, | ||||||
|   _namespaces: &BTreeMap<String, String>, |   _namespaces: &BTreeMap<String, String>, | ||||||
| ) -> TokenStream { | ) -> TokenStream { | ||||||
|   let variables: TokenStream = data_enum |  | ||||||
|     .variants |  | ||||||
|     .iter() |  | ||||||
|     .map(|variant| match variant.fields { |  | ||||||
|       Fields::Unit => None, |  | ||||||
|       Fields::Named(ref fields) => { |  | ||||||
|         let enum_fields = fields |  | ||||||
|           .named |  | ||||||
|           .iter() |  | ||||||
|           .map(|field| { |  | ||||||
|             let field_label = &field.ident; |  | ||||||
|             let field_attrs = YaSerdeAttribute::parse(&field.attrs); |  | ||||||
| 
 |  | ||||||
|             match get_field_type(field) { |  | ||||||
|               Some(FieldType::FieldTypeString) => build_default_value( |  | ||||||
|                 field_label, |  | ||||||
|                 "e! {String}, |  | ||||||
|                 "e! {"".to_string()}, |  | ||||||
|                 &field_attrs.default, |  | ||||||
|               ), |  | ||||||
|               Some(FieldType::FieldTypeBool) => build_default_value( |  | ||||||
|                 field_label, |  | ||||||
|                 "e! {bool}, |  | ||||||
|                 "e! {false}, |  | ||||||
|                 &field_attrs.default, |  | ||||||
|               ), |  | ||||||
|               Some(FieldType::FieldTypeI8) => { |  | ||||||
|                 build_default_value(field_label, "e! {i8}, "e! {0}, &field_attrs.default) |  | ||||||
|               } |  | ||||||
|               Some(FieldType::FieldTypeU8) => { |  | ||||||
|                 build_default_value(field_label, "e! {u8}, "e! {0}, &field_attrs.default) |  | ||||||
|               } |  | ||||||
|               Some(FieldType::FieldTypeI16) => build_default_value( |  | ||||||
|                 field_label, |  | ||||||
|                 "e! {i16}, |  | ||||||
|                 "e! {0}, |  | ||||||
|                 &field_attrs.default, |  | ||||||
|               ), |  | ||||||
|               Some(FieldType::FieldTypeU16) => build_default_value( |  | ||||||
|                 field_label, |  | ||||||
|                 "e! {u16}, |  | ||||||
|                 "e! {0}, |  | ||||||
|                 &field_attrs.default, |  | ||||||
|               ), |  | ||||||
|               Some(FieldType::FieldTypeI32) => build_default_value( |  | ||||||
|                 field_label, |  | ||||||
|                 "e! {i32}, |  | ||||||
|                 "e! {0}, |  | ||||||
|                 &field_attrs.default, |  | ||||||
|               ), |  | ||||||
|               Some(FieldType::FieldTypeU32) => build_default_value( |  | ||||||
|                 field_label, |  | ||||||
|                 "e! {u32}, |  | ||||||
|                 "e! {0}, |  | ||||||
|                 &field_attrs.default, |  | ||||||
|               ), |  | ||||||
|               Some(FieldType::FieldTypeI64) => build_default_value( |  | ||||||
|                 field_label, |  | ||||||
|                 "e! {i64}, |  | ||||||
|                 "e! {0}, |  | ||||||
|                 &field_attrs.default, |  | ||||||
|               ), |  | ||||||
|               Some(FieldType::FieldTypeU64) => build_default_value( |  | ||||||
|                 field_label, |  | ||||||
|                 "e! {u64}, |  | ||||||
|                 "e! {0}, |  | ||||||
|                 &field_attrs.default, |  | ||||||
|               ), |  | ||||||
|               Some(FieldType::FieldTypeF32) => build_default_value( |  | ||||||
|                 field_label, |  | ||||||
|                 "e! {f32}, |  | ||||||
|                 "e! {0}, |  | ||||||
|                 &field_attrs.default, |  | ||||||
|               ), |  | ||||||
|               Some(FieldType::FieldTypeF64) => build_default_value( |  | ||||||
|                 field_label, |  | ||||||
|                 "e! {f64}, |  | ||||||
|                 "e! {0}, |  | ||||||
|                 &field_attrs.default, |  | ||||||
|               ), |  | ||||||
|               Some(FieldType::FieldTypeStruct { struct_name }) => build_default_value( |  | ||||||
|                 field_label, |  | ||||||
|                 "e! {#struct_name}, |  | ||||||
|                 "e! {#struct_name::default()}, |  | ||||||
|                 &field_attrs.default, |  | ||||||
|               ), |  | ||||||
|               Some(FieldType::FieldTypeOption { .. }) => { |  | ||||||
|                 if let Some(d) = &field_attrs.default { |  | ||||||
|                   let default_function = Ident::new(&d, Span::call_site()); |  | ||||||
| 
 |  | ||||||
|                   Some(quote! { |  | ||||||
|                     #[allow(unused_mut, non_snake_case, non_camel_case_types)] |  | ||||||
|                     let mut #field_label = #default_function(); |  | ||||||
|                   }) |  | ||||||
|                 } else { |  | ||||||
|                   Some(quote! { |  | ||||||
|                     #[allow(unused_mut, non_snake_case, non_camel_case_types)] |  | ||||||
|                     let mut #field_label = None; |  | ||||||
|                   }) |  | ||||||
|                 } |  | ||||||
|               } |  | ||||||
|               Some(FieldType::FieldTypeVec { data_type }) => { |  | ||||||
|                 let dt = Box::into_raw(data_type); |  | ||||||
|                 match unsafe { dt.as_ref() } { |  | ||||||
|                   Some(&FieldType::FieldTypeString) => build_default_value( |  | ||||||
|                     field_label, |  | ||||||
|                     "e! {Vec<String>}, |  | ||||||
|                     "e! {vec![]}, |  | ||||||
|                     &field_attrs.default, |  | ||||||
|                   ), |  | ||||||
|                   Some(&FieldType::FieldTypeBool) => build_default_value( |  | ||||||
|                     field_label, |  | ||||||
|                     "e! {Vec<bool>}, |  | ||||||
|                     "e! {vec![]}, |  | ||||||
|                     &field_attrs.default, |  | ||||||
|                   ), |  | ||||||
|                   Some(&FieldType::FieldTypeI8) => build_default_value( |  | ||||||
|                     field_label, |  | ||||||
|                     "e! {Vec<i8>}, |  | ||||||
|                     "e! {vec![]}, |  | ||||||
|                     &field_attrs.default, |  | ||||||
|                   ), |  | ||||||
|                   Some(&FieldType::FieldTypeU8) => build_default_value( |  | ||||||
|                     field_label, |  | ||||||
|                     "e! {Vec<u8>}, |  | ||||||
|                     "e! {vec![]}, |  | ||||||
|                     &field_attrs.default, |  | ||||||
|                   ), |  | ||||||
|                   Some(&FieldType::FieldTypeI16) => build_default_value( |  | ||||||
|                     field_label, |  | ||||||
|                     "e! {Vec<i16>}, |  | ||||||
|                     "e! {vec![]}, |  | ||||||
|                     &field_attrs.default, |  | ||||||
|                   ), |  | ||||||
|                   Some(&FieldType::FieldTypeU16) => build_default_value( |  | ||||||
|                     field_label, |  | ||||||
|                     "e! {Vec<u16>}, |  | ||||||
|                     "e! {vec![]}, |  | ||||||
|                     &field_attrs.default, |  | ||||||
|                   ), |  | ||||||
|                   Some(&FieldType::FieldTypeI32) => build_default_value( |  | ||||||
|                     field_label, |  | ||||||
|                     "e! {Vec<i32>}, |  | ||||||
|                     "e! {vec![]}, |  | ||||||
|                     &field_attrs.default, |  | ||||||
|                   ), |  | ||||||
|                   Some(&FieldType::FieldTypeU32) => build_default_value( |  | ||||||
|                     field_label, |  | ||||||
|                     "e! {Vec<u32>}, |  | ||||||
|                     "e! {vec![]}, |  | ||||||
|                     &field_attrs.default, |  | ||||||
|                   ), |  | ||||||
|                   Some(&FieldType::FieldTypeI64) => build_default_value( |  | ||||||
|                     field_label, |  | ||||||
|                     "e! {Vec<i64>}, |  | ||||||
|                     "e! {vec![]}, |  | ||||||
|                     &field_attrs.default, |  | ||||||
|                   ), |  | ||||||
|                   Some(&FieldType::FieldTypeU64) => build_default_value( |  | ||||||
|                     field_label, |  | ||||||
|                     "e! {Vec<u64>}, |  | ||||||
|                     "e! {vec![]}, |  | ||||||
|                     &field_attrs.default, |  | ||||||
|                   ), |  | ||||||
|                   Some(&FieldType::FieldTypeF32) => build_default_value( |  | ||||||
|                     field_label, |  | ||||||
|                     "e! {Vec<f32>}, |  | ||||||
|                     "e! {vec![]}, |  | ||||||
|                     &field_attrs.default, |  | ||||||
|                   ), |  | ||||||
|                   Some(&FieldType::FieldTypeF64) => build_default_value( |  | ||||||
|                     field_label, |  | ||||||
|                     "e! {Vec<f64>}, |  | ||||||
|                     "e! {vec![]}, |  | ||||||
|                     &field_attrs.default, |  | ||||||
|                   ), |  | ||||||
|                   Some(&FieldType::FieldTypeStruct { ref struct_name }) => build_default_value( |  | ||||||
|                     field_label, |  | ||||||
|                     "e! {Vec<#struct_name>}, |  | ||||||
|                     "e! {vec![]}, |  | ||||||
|                     &field_attrs.default, |  | ||||||
|                   ), |  | ||||||
|                   Some(&FieldType::FieldTypeOption { .. }) |  | ||||||
|                   | Some(&FieldType::FieldTypeVec { .. }) => { |  | ||||||
|                     unimplemented!(); |  | ||||||
|                   } |  | ||||||
|                   None => { |  | ||||||
|                     unimplemented!(); |  | ||||||
|                   } |  | ||||||
|                 } |  | ||||||
|               } |  | ||||||
|               None => None, |  | ||||||
|             } |  | ||||||
|           }) |  | ||||||
|           .filter(|x| x.is_some()) |  | ||||||
|           .map(|x| x.unwrap()) |  | ||||||
|           .fold(TokenStream::new(), |mut sum, val| { |  | ||||||
|             sum.append_all(val); |  | ||||||
|             sum |  | ||||||
|           }); |  | ||||||
| 
 |  | ||||||
|         Some(enum_fields) |  | ||||||
|       } |  | ||||||
|       Fields::Unnamed(ref _fields) => { |  | ||||||
|         unimplemented!(); |  | ||||||
|       } |  | ||||||
|     }) |  | ||||||
|     .filter(|x| x.is_some()) |  | ||||||
|     .map(|x| x.unwrap()) |  | ||||||
|     .fold(TokenStream::new(), |mut sum, val| { |  | ||||||
|       sum.append_all(val); |  | ||||||
|       sum |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|   let match_to_enum: TokenStream = data_enum |   let match_to_enum: TokenStream = data_enum | ||||||
|     .variants |     .variants | ||||||
|     .iter() |     .iter() | ||||||
|     .map(|variant| { |     .map(|variant| parse_variant(variant, name)) | ||||||
|       let field_attrs = YaSerdeAttribute::parse(&variant.attrs); |     .filter_map(|f| f) | ||||||
|       let renamed_label = match field_attrs.rename { |     .collect(); | ||||||
|         Some(value) => Ident::new(&value.to_string(), Span::call_site()), |  | ||||||
|         None => variant.ident.clone(), |  | ||||||
|       }; |  | ||||||
|       let label = &variant.ident; |  | ||||||
|       let label_name = renamed_label.to_string(); |  | ||||||
| 
 |  | ||||||
|       match variant.fields { |  | ||||||
|         Fields::Unit => Some(quote! { |  | ||||||
|           #label_name => { |  | ||||||
|             simple_enum_value = Some(#name::#label); |  | ||||||
|           } |  | ||||||
|         }), |  | ||||||
|         _ => None, |  | ||||||
|       } |  | ||||||
|     }) |  | ||||||
|     .filter(|x| x.is_some()) |  | ||||||
|     .map(|x| x.unwrap()) |  | ||||||
|     .fold(TokenStream::new(), |mut tokens, token| { |  | ||||||
|       tokens.append_all(token); |  | ||||||
|       tokens |  | ||||||
|     }); |  | ||||||
| 
 | 
 | ||||||
|   quote! { |   quote! { | ||||||
|     use xml::reader::XmlEvent; |     use xml::reader::XmlEvent; | ||||||
|  |     use yaserde::Visitor; | ||||||
|  |     #[allow(unknown_lints, unused_imports)] | ||||||
|  |     use std::str::FromStr; | ||||||
| 
 | 
 | ||||||
|     impl YaDeserialize for #name { |     impl YaDeserialize for #name { | ||||||
|       #[allow(unused_variables)] |       #[allow(unused_variables)] | ||||||
| @ -271,16 +37,18 @@ pub fn parse( | |||||||
|         debug!("Enum: start to parse {:?}", named_element); |         debug!("Enum: start to parse {:?}", named_element); | ||||||
| 
 | 
 | ||||||
|         #[allow(unused_assignments, unused_mut)] |         #[allow(unused_assignments, unused_mut)] | ||||||
|         let mut simple_enum_value = None; |         let mut enum_value = None; | ||||||
| 
 |  | ||||||
|         #variables |  | ||||||
| 
 | 
 | ||||||
|         loop { |         loop { | ||||||
|           match reader.peek()?.to_owned() { |           match reader.peek()?.to_owned() { | ||||||
|             XmlEvent::StartElement{name, attributes, namespace: _namespace} => { |             XmlEvent::StartElement{ref name, ref attributes, ..} => { | ||||||
|               debug!("Enum: {}: {}", named_element, name.local_name.as_str()); | 
 | ||||||
|               if name.local_name == named_element { |               match name.local_name.as_str() { | ||||||
|                 let _next = reader.next_event(); |                 #match_to_enum | ||||||
|  |                 named_element => { | ||||||
|  |                   let _root = reader.next_event(); | ||||||
|  |                 } | ||||||
|  |               } | ||||||
| 
 | 
 | ||||||
|               if let XmlEvent::Characters(content) = reader.peek()?.to_owned() { |               if let XmlEvent::Characters(content) = reader.peek()?.to_owned() { | ||||||
|                 match content.as_str() { |                 match content.as_str() { | ||||||
| @ -289,23 +57,22 @@ pub fn parse( | |||||||
|                 } |                 } | ||||||
|               } |               } | ||||||
|             } |             } | ||||||
|             }, |             XmlEvent::EndElement{ref name} => { | ||||||
|             XmlEvent::EndElement{name} => { |               if name.local_name == named_element { | ||||||
|               if name.local_name.as_str() == named_element { |  | ||||||
|                 break; |                 break; | ||||||
|               } |               } | ||||||
|               let _root = reader.next_event(); |               let _root = reader.next_event(); | ||||||
|             }, |             } | ||||||
|             xml::reader::XmlEvent::Characters(characters_content) => { |             XmlEvent::Characters(ref text_content) => { | ||||||
|               let _root = reader.next_event(); |               let _root = reader.next_event(); | ||||||
|             }, |             } | ||||||
|             event => { |             event => { | ||||||
|               return Err(format!("unknown event {:?}", event)) |               return Err(format!("unknown event {:?}", event)) | ||||||
|             }, |             } | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         match simple_enum_value { |         match enum_value { | ||||||
|           Some(value) => Ok(value), |           Some(value) => Ok(value), | ||||||
|           None => { |           None => { | ||||||
|             Ok(#name::default()) |             Ok(#name::default()) | ||||||
| @ -315,3 +82,227 @@ pub fn parse( | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | fn parse_variant(variant: &syn::Variant, name: &Ident) -> Option<TokenStream> { | ||||||
|  |   let xml_element_name = YaSerdeAttribute::parse(&variant.attrs) | ||||||
|  |     .rename | ||||||
|  |     .unwrap_or_else(|| variant.ident.to_string()); | ||||||
|  | 
 | ||||||
|  |   let variant_name = { | ||||||
|  |     let label = &variant.ident; | ||||||
|  |     quote! { #name::#label } | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   match variant.fields { | ||||||
|  |     Fields::Unit => Some(quote! { | ||||||
|  |       #xml_element_name => { | ||||||
|  |         enum_value = Some(#variant_name); | ||||||
|  |       } | ||||||
|  |     }), | ||||||
|  |     Fields::Unnamed(ref fields) => { | ||||||
|  |       let field_visitors = build_unnamed_field_visitors(fields); | ||||||
|  |       let call_visitors = build_unnamed_visitor_calls(fields, &variant_name); | ||||||
|  | 
 | ||||||
|  |       if fields.unnamed.len() > 1 { | ||||||
|  |         unimplemented!("enum variant with multiple fields") | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       Some( | ||||||
|  |         fields | ||||||
|  |           .unnamed | ||||||
|  |           .iter() | ||||||
|  |           .take(1) | ||||||
|  |           .map(|_field| { | ||||||
|  |             quote! { | ||||||
|  |               #xml_element_name => { | ||||||
|  |                 #field_visitors | ||||||
|  |                 #call_visitors | ||||||
|  |               } | ||||||
|  |             } | ||||||
|  |           }) | ||||||
|  |           .collect(), | ||||||
|  |       ) | ||||||
|  |     } | ||||||
|  |     _ => None, | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn build_unnamed_field_visitors(fields: &syn::FieldsUnnamed) -> TokenStream { | ||||||
|  |   fields | ||||||
|  |     .unnamed | ||||||
|  |     .iter() | ||||||
|  |     .enumerate() | ||||||
|  |     .map(|(idx, field)| { | ||||||
|  |       let visitor_label = Ident::new(&format!("__Visitor_{}", idx), Span::call_site()); | ||||||
|  | 
 | ||||||
|  |       let make_visitor = | ||||||
|  |         |visitor: &TokenStream, field_type: &TokenStream, fn_body: &TokenStream| { | ||||||
|  |           Some(quote! { | ||||||
|  |             #[allow(non_snake_case, non_camel_case_types)] | ||||||
|  |             struct #visitor_label; | ||||||
|  |             impl<'de> Visitor<'de> for #visitor_label { | ||||||
|  |               type Value = #field_type; | ||||||
|  | 
 | ||||||
|  |               fn #visitor(self, v: &str) -> Result<Self::Value, String> { | ||||||
|  |                 #fn_body | ||||||
|  |               } | ||||||
|  |             } | ||||||
|  |           }) | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |       let simple_type_visitor = |simple_type| { | ||||||
|  |         let (field_type, visitor) = convert_simple_type(simple_type); | ||||||
|  | 
 | ||||||
|  |         make_visitor( | ||||||
|  |           &visitor, | ||||||
|  |           &field_type, | ||||||
|  |           "e! { Ok(#field_type::from_str(v).unwrap()) }, | ||||||
|  |         ) | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  |       get_field_type(field).and_then(|f| match f { | ||||||
|  |         FieldType::FieldTypeStruct { struct_name } => { | ||||||
|  |           let struct_id: String = struct_name | ||||||
|  |             .segments | ||||||
|  |             .iter() | ||||||
|  |             .map(|s| s.ident.to_string()) | ||||||
|  |             .collect(); | ||||||
|  | 
 | ||||||
|  |           make_visitor( | ||||||
|  |             "e! { visit_str }, | ||||||
|  |             "e! { #struct_name }, | ||||||
|  |             "e! { | ||||||
|  |               let content = "<".to_string() + #struct_id + ">" + v + "</" + #struct_id + ">"; | ||||||
|  |               let value : Result<#struct_name, String> = yaserde::de::from_str(&content); | ||||||
|  |               value | ||||||
|  |             }, | ||||||
|  |           ) | ||||||
|  |         } | ||||||
|  |         FieldType::FieldTypeOption { data_type } | FieldType::FieldTypeVec { data_type } => { | ||||||
|  |           match *data_type { | ||||||
|  |             FieldType::FieldTypeStruct { .. } => None, | ||||||
|  |             simple_type => simple_type_visitor(simple_type), | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |         simple_type => simple_type_visitor(simple_type), | ||||||
|  |       }) | ||||||
|  |     }) | ||||||
|  |     .filter_map(|f| f) | ||||||
|  |     .collect() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn build_unnamed_visitor_calls( | ||||||
|  |   fields: &syn::FieldsUnnamed, | ||||||
|  |   variant_name: &TokenStream, | ||||||
|  | ) -> TokenStream { | ||||||
|  |   fields | ||||||
|  |     .unnamed | ||||||
|  |     .iter() | ||||||
|  |     .enumerate() | ||||||
|  |     .map(|(idx, field)| { | ||||||
|  |       let visitor_label = Ident::new(&format!("__Visitor_{}", idx), Span::call_site()); | ||||||
|  | 
 | ||||||
|  |       let call_simple_type_visitor = |simple_type, action| { | ||||||
|  |         let (field_type, visitor) = convert_simple_type(simple_type); | ||||||
|  | 
 | ||||||
|  |         let label_name = format!("field_{}", idx); | ||||||
|  | 
 | ||||||
|  |         Some(quote! { | ||||||
|  |           let visitor = #visitor_label{}; | ||||||
|  | 
 | ||||||
|  |           if let XmlEvent::StartElement {name, ..} = reader.peek()?.clone() { | ||||||
|  |             if let Some(namespace) = name.namespace { | ||||||
|  |               match namespace.as_str() { | ||||||
|  |                 bad_ns => { | ||||||
|  |                   let msg = format!("bad field namespace for {}, found {}", | ||||||
|  |                     name.local_name.as_str(), | ||||||
|  |                     bad_ns); | ||||||
|  |                   return Err(msg); | ||||||
|  |                 } | ||||||
|  |               } | ||||||
|  |             } | ||||||
|  |             reader.set_map_value() | ||||||
|  |           } | ||||||
|  | 
 | ||||||
|  |           let result = reader.read_inner_value::<#field_type, _>(|reader| { | ||||||
|  |             if let XmlEvent::EndElement { .. } = *reader.peek()? { | ||||||
|  |               return visitor.#visitor(""); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if let Ok(XmlEvent::Characters(s)) = reader.next_event() { | ||||||
|  |               visitor.#visitor(&s) | ||||||
|  |             } else { | ||||||
|  |               Err(format!("unable to parse content for {}", #label_name)) | ||||||
|  |             } | ||||||
|  |           }); | ||||||
|  | 
 | ||||||
|  |           if let Ok(value) = result { | ||||||
|  |             #action | ||||||
|  |           } | ||||||
|  |         }) | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  |       let call_struct_visitor = |struct_name, action| { | ||||||
|  |         Some(quote! { | ||||||
|  |           reader.set_map_value(); | ||||||
|  |           match #struct_name::deserialize(reader) { | ||||||
|  |             Ok(value) => { | ||||||
|  |               #action; | ||||||
|  |               let _root = reader.next_event(); | ||||||
|  |             }, | ||||||
|  |             Err(msg) => { | ||||||
|  |               return Err(msg); | ||||||
|  |             }, | ||||||
|  |           } | ||||||
|  |         }) | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  |       let set_val = quote! { enum_value = Some(#variant_name(value)) }; | ||||||
|  |       let set_opt = quote! { enum_value = Some(#variant_name(Some(value))) }; | ||||||
|  |       let set_vec = quote! { | ||||||
|  |         match enum_value { | ||||||
|  |           Some(ref mut v) => match v { | ||||||
|  |             #variant_name(ref mut v) => v.push(value), | ||||||
|  |             _ => return Err(String::from("Got sequence of different types")) | ||||||
|  |           } | ||||||
|  |           None => { | ||||||
|  |             enum_value = Some(#variant_name(vec![value])); | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  |       get_field_type(field).and_then(|f| match f { | ||||||
|  |         FieldType::FieldTypeStruct { struct_name } => call_struct_visitor(struct_name, set_val), | ||||||
|  |         FieldType::FieldTypeOption { data_type } => match *data_type { | ||||||
|  |           FieldType::FieldTypeStruct { struct_name } => call_struct_visitor(struct_name, set_opt), | ||||||
|  |           simple_type => call_simple_type_visitor(simple_type, set_opt), | ||||||
|  |         }, | ||||||
|  |         FieldType::FieldTypeVec { data_type } => match *data_type { | ||||||
|  |           FieldType::FieldTypeStruct { struct_name } => call_struct_visitor(struct_name, set_vec), | ||||||
|  |           simple_type => call_simple_type_visitor(simple_type, set_vec), | ||||||
|  |         }, | ||||||
|  | 
 | ||||||
|  |         simple_type => call_simple_type_visitor(simple_type, set_val), | ||||||
|  |       }) | ||||||
|  |     }) | ||||||
|  |     .filter_map(|f| f) | ||||||
|  |     .collect() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn convert_simple_type(simple_type: FieldType) -> (TokenStream, TokenStream) { | ||||||
|  |   match simple_type { | ||||||
|  |     FieldType::FieldTypeString => (quote! {String}, quote! {visit_str}), | ||||||
|  |     FieldType::FieldTypeBool => (quote! {bool}, quote! {visit_bool}), | ||||||
|  |     FieldType::FieldTypeU8 => (quote! {u8}, quote! {visit_u8}), | ||||||
|  |     FieldType::FieldTypeI8 => (quote! {i8}, quote! {visit_i8}), | ||||||
|  |     FieldType::FieldTypeU16 => (quote! {u16}, quote! {visit_u16}), | ||||||
|  |     FieldType::FieldTypeI16 => (quote! {i16}, quote! {visit_i16}), | ||||||
|  |     FieldType::FieldTypeU32 => (quote! {u32}, quote! {visit_u32}), | ||||||
|  |     FieldType::FieldTypeI32 => (quote! {i32}, quote! {visit_i32}), | ||||||
|  |     FieldType::FieldTypeU64 => (quote! {u64}, quote! {visit_u64}), | ||||||
|  |     FieldType::FieldTypeI64 => (quote! {i64}, quote! {visit_i64}), | ||||||
|  |     FieldType::FieldTypeF32 => (quote! {f32}, quote! {visit_f32}), | ||||||
|  |     FieldType::FieldTypeF64 => (quote! {f64}, quote! {visit_f64}), | ||||||
|  |     _ => panic!("Not a simple type: {:?}", simple_type), | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | |||||||
| @ -203,11 +203,9 @@ pub fn parse( | |||||||
|     .iter() |     .iter() | ||||||
|     .map(|field| { |     .map(|field| { | ||||||
|       let field_attrs = YaSerdeAttribute::parse(&field.attrs); |       let field_attrs = YaSerdeAttribute::parse(&field.attrs); | ||||||
|       let label_name = if let Some(value) = field_attrs.rename { |       let label_name = field_attrs | ||||||
|         Ident::new(&value.to_string(), Span::call_site()).to_string() |         .rename | ||||||
|       } else { |         .unwrap_or_else(|| field.ident.as_ref().unwrap().to_string()); | ||||||
|         field.ident.clone().unwrap().to_string() |  | ||||||
|       }; |  | ||||||
| 
 | 
 | ||||||
|       let visitor_label = Ident::new(&format!("__Visitor{}", label_name), Span::call_site()); |       let visitor_label = Ident::new(&format!("__Visitor{}", label_name), Span::call_site()); | ||||||
| 
 | 
 | ||||||
| @ -896,11 +894,10 @@ pub fn parse( | |||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       let label = &get_value_label(&field.ident); |       let label = &get_value_label(&field.ident); | ||||||
|       let label_name = if let Some(value) = field_attrs.rename { | 
 | ||||||
|         Ident::new(&value.to_string(), Span::call_site()).to_string() |       let label_name = field_attrs | ||||||
|       } else { |         .rename | ||||||
|         field.ident.clone().unwrap().to_string() |         .unwrap_or_else(|| field.ident.as_ref().unwrap().to_string()); | ||||||
|       }; |  | ||||||
| 
 | 
 | ||||||
|       let visitor_label = Ident::new(&format!("__Visitor{}", label_name), Span::call_site()); |       let visitor_label = Ident::new(&format!("__Visitor{}", label_name), Span::call_site()); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -127,7 +127,104 @@ pub fn serialize( | |||||||
|             } |             } | ||||||
|           }) |           }) | ||||||
|         } |         } | ||||||
|         Fields::Unnamed(ref _fields) => unimplemented!(), |         Fields::Unnamed(ref fields) => { | ||||||
|  |           let enum_fields: TokenStream = fields | ||||||
|  |             .unnamed | ||||||
|  |             .iter() | ||||||
|  |             .map(|field| { | ||||||
|  |               let field_attrs = YaSerdeAttribute::parse(&field.attrs); | ||||||
|  |               if field_attrs.attribute { | ||||||
|  |                 return None; | ||||||
|  |               } | ||||||
|  | 
 | ||||||
|  |               let field_label_name = renamed_label.to_string(); | ||||||
|  | 
 | ||||||
|  |               let write_element = |action: &TokenStream| { | ||||||
|  |                 quote! { | ||||||
|  |                   let struct_start_event = XmlEvent::start_element(#field_label_name); | ||||||
|  |                   let _ret = writer.write(struct_start_event); | ||||||
|  | 
 | ||||||
|  |                   #action | ||||||
|  | 
 | ||||||
|  |                   let struct_end_event = XmlEvent::end_element(); | ||||||
|  |                   let _ret = writer.write(struct_end_event); | ||||||
|  |                 } | ||||||
|  |               }; | ||||||
|  | 
 | ||||||
|  |               let write_string_chars = quote! { | ||||||
|  |                 let data_event = XmlEvent::characters(item); | ||||||
|  |                 let _ret = writer.write(data_event); | ||||||
|  |               }; | ||||||
|  | 
 | ||||||
|  |               let write_simple_type = write_element("e! { | ||||||
|  |                 let s = item.to_string(); | ||||||
|  |                 let data_event = XmlEvent::characters(&s); | ||||||
|  |                 let _ret = writer.write(data_event); | ||||||
|  |               }); | ||||||
|  | 
 | ||||||
|  |               let serialize = quote! { | ||||||
|  |                 writer.set_skip_start_end(true); | ||||||
|  |                 if let Err(msg) = item.serialize(writer) { | ||||||
|  |                   return Err(msg); | ||||||
|  |                 }; | ||||||
|  |               }; | ||||||
|  | 
 | ||||||
|  |               let write_sub_type = |data_type| { | ||||||
|  |                 write_element(match data_type { | ||||||
|  |                   FieldType::FieldTypeString => &write_string_chars, | ||||||
|  |                   _ => &serialize, | ||||||
|  |                 }) | ||||||
|  |               }; | ||||||
|  | 
 | ||||||
|  |               let match_field = |write: &TokenStream| { | ||||||
|  |                 quote! { | ||||||
|  |                   match self { | ||||||
|  |                     &#name::#label(ref item) => { | ||||||
|  |                       #write | ||||||
|  |                     }, | ||||||
|  |                     _ => {}, | ||||||
|  |                   } | ||||||
|  |                 } | ||||||
|  |               }; | ||||||
|  | 
 | ||||||
|  |               match get_field_type(field) { | ||||||
|  |                 Some(FieldType::FieldTypeOption { data_type }) => { | ||||||
|  |                   let write = write_sub_type(*data_type); | ||||||
|  | 
 | ||||||
|  |                   Some(match_field("e! { | ||||||
|  |                     if let Some(item) = item { | ||||||
|  |                       #write | ||||||
|  |                     } | ||||||
|  |                   })) | ||||||
|  |                 } | ||||||
|  |                 Some(FieldType::FieldTypeVec { data_type }) => { | ||||||
|  |                   let write = write_sub_type(*data_type); | ||||||
|  | 
 | ||||||
|  |                   Some(match_field("e! { | ||||||
|  |                     for item in item { | ||||||
|  |                       #write | ||||||
|  |                     } | ||||||
|  |                   })) | ||||||
|  |                 } | ||||||
|  |                 Some(FieldType::FieldTypeStruct { .. }) => { | ||||||
|  |                   Some(write_element(&match_field(&serialize))) | ||||||
|  |                 } | ||||||
|  |                 Some(FieldType::FieldTypeString) => { | ||||||
|  |                   Some(match_field(&write_element(&write_string_chars))) | ||||||
|  |                 } | ||||||
|  |                 Some(_simple_type) => Some(match_field(&write_simple_type)), | ||||||
|  |                 _ => None, | ||||||
|  |               } | ||||||
|  |             }) | ||||||
|  |             .filter_map(|x| x) | ||||||
|  |             .collect(); | ||||||
|  | 
 | ||||||
|  |           Some(quote! { | ||||||
|  |             &#name::#label{..} => { | ||||||
|  |               #enum_fields | ||||||
|  |             } | ||||||
|  |           }) | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|     }) |     }) | ||||||
|     .filter(|x| x.is_some()) |     .filter(|x| x.is_some()) | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user