Add support for field types with multiple PathSegment's
This commit is contained in:
		
							parent
							
								
									bb36546d2e
								
							
						
					
					
						commit
						ab03d32cfb
					
				| @ -48,6 +48,52 @@ fn de_basic() { | ||||
|   ); | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn de_multiple_segments() { | ||||
|   mod other_mod { | ||||
|     use std::io::Read; | ||||
|     use yaserde::YaDeserialize; | ||||
| 
 | ||||
|     #[derive(YaDeserialize, PartialEq, Debug, Default)] | ||||
|     pub struct Page { | ||||
|       pub number: i32, | ||||
|       pub text: std::string::String, | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   #[derive(YaDeserialize, PartialEq, Debug)] | ||||
|   #[yaserde(root = "book")] | ||||
|   pub struct Book { | ||||
|     author: std::string::String, | ||||
|     title: std::string::String, | ||||
|     page: other_mod::Page, | ||||
|   } | ||||
| 
 | ||||
|   let content = r#" | ||||
|       <book> | ||||
|         <author>Antoine de Saint-Exupéry</author> | ||||
|         <title>Little prince</title> | ||||
|         <page> | ||||
|           <number>40</number> | ||||
|           <text>The Earth is not just an ordinary planet!</text> | ||||
|         </page> | ||||
|       </book> | ||||
|     "#;
 | ||||
| 
 | ||||
|   convert_and_validate!( | ||||
|     content, | ||||
|     Book, | ||||
|     Book { | ||||
|       author: String::from("Antoine de Saint-Exupéry"), | ||||
|       title: String::from("Little prince"), | ||||
|       page: other_mod::Page { | ||||
|         number: 40, | ||||
|         text: String::from("The Earth is not just an ordinary planet!"), | ||||
|       }, | ||||
|     } | ||||
|   ); | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn de_list_of_items() { | ||||
|   #[derive(YaDeserialize, PartialEq, Debug)] | ||||
|  | ||||
| @ -2,7 +2,7 @@ use attribute::*; | ||||
| use de::build_default_value::build_default_value; | ||||
| use field_type::*; | ||||
| use proc_macro2::{Span, TokenStream}; | ||||
| use quote::TokenStreamExt; | ||||
| use quote::{TokenStreamExt, ToTokens}; | ||||
| use std::collections::BTreeMap; | ||||
| use syn::DataStruct; | ||||
| use syn::Ident; | ||||
| @ -249,9 +249,9 @@ pub fn parse( | ||||
|           build_declare_visitor("e! {f64}, "e! {visit_f64}, &visitor_label) | ||||
|         } | ||||
|         Some(FieldType::FieldTypeStruct { struct_name }) => { | ||||
|           let struct_id = struct_name.to_string(); | ||||
|           let struct_id : String = struct_name.segments.iter().map(|s| s.ident.to_string()).collect(); | ||||
|           let struct_ident = Ident::new( | ||||
|             &format!("__Visitor_{}_{}", label_name, struct_name), | ||||
|             &format!("__Visitor_{}_{}", label_name, struct_id), | ||||
|             Span::call_site(), | ||||
|           ); | ||||
| 
 | ||||
| @ -309,7 +309,7 @@ pub fn parse( | ||||
|               build_declare_visitor("e! {f64}, "e! {visit_f64}, &visitor_label) | ||||
|             } | ||||
|             Some(&FieldType::FieldTypeStruct { ref struct_name }) => { | ||||
|               let struct_ident = Ident::new(&format!("{}", struct_name), Span::call_site()); | ||||
|               let struct_ident = Ident::new(&format!("{}", struct_name.into_token_stream()), Span::call_site()); | ||||
|               Some(quote! { | ||||
|                 #[allow(non_snake_case, non_camel_case_types)] | ||||
|                 struct #visitor_label; | ||||
| @ -363,7 +363,7 @@ pub fn parse( | ||||
|               build_declare_visitor("e! {f64}, "e! {visit_f64}, &visitor_label) | ||||
|             } | ||||
|             Some(&FieldType::FieldTypeStruct { ref struct_name }) => { | ||||
|               let struct_ident = Ident::new(&format!("{}", struct_name), Span::call_site()); | ||||
|               let struct_ident = Ident::new(&format!("{}", struct_name.into_token_stream()), Span::call_site()); | ||||
|               Some(quote! { | ||||
|                 #[allow(non_snake_case, non_camel_case_types)] | ||||
|                 struct #visitor_label; | ||||
| @ -685,7 +685,7 @@ pub fn parse( | ||||
|               ) | ||||
|             } | ||||
|             Some(&FieldType::FieldTypeStruct { ref struct_name }) => { | ||||
|               let struct_ident = Ident::new(&format!("{}", struct_name), Span::call_site()); | ||||
|               let struct_ident = Ident::new(&format!("{}", struct_name.into_token_stream()), Span::call_site()); | ||||
|               Some(quote! { | ||||
|                 #label_name => { | ||||
|                   reader.set_map_value(); | ||||
| @ -840,7 +840,7 @@ pub fn parse( | ||||
|               ) | ||||
|             } | ||||
|             Some(&FieldType::FieldTypeStruct { ref struct_name }) => { | ||||
|               let struct_ident = Ident::new(&format!("{}", struct_name), Span::call_site()); | ||||
|               let struct_ident = Ident::new(&format!("{}", struct_name.into_token_stream()), Span::call_site()); | ||||
|               Some(quote! { | ||||
|                 #label_name => { | ||||
|                   reader.set_map_value(); | ||||
| @ -1064,7 +1064,7 @@ pub fn parse( | ||||
|         } | ||||
|         Some(FieldType::FieldTypeStruct { struct_name }) => { | ||||
|           let struct_ident = Ident::new( | ||||
|             &format!("__Visitor_{}_{}", label_name, struct_name), | ||||
|             &format!("__Visitor_{}_{}", label_name, struct_name.into_token_stream()), | ||||
|             Span::call_site(), | ||||
|           ); | ||||
| 
 | ||||
|  | ||||
| @ -17,48 +17,45 @@ pub enum FieldType { | ||||
|   FieldTypeF64, | ||||
|   FieldTypeOption { data_type: Box<FieldType> }, | ||||
|   FieldTypeVec { data_type: Box<FieldType> }, | ||||
|   FieldTypeStruct { struct_name: syn::Ident }, | ||||
|   FieldTypeStruct { struct_name: syn::Path }, | ||||
| } | ||||
| 
 | ||||
| impl FieldType { | ||||
|   fn from_ident(t: &syn::PathSegment) -> Option<FieldType> { | ||||
|     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()), | ||||
|       }), | ||||
|       _struct_name => Some(FieldType::FieldTypeStruct { | ||||
|         struct_name: t.ident.clone(), | ||||
|       }), | ||||
|   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(&syn::Path::from(data_type)).unwrap()), | ||||
|           }), | ||||
|           "Vec" => get_sub_type(t).map(|data_type| FieldType::FieldTypeVec { | ||||
|             data_type: Box::new(FieldType::from_ident(&syn::Path::from(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) => { | ||||
|       if path.path.segments.len() != 1 { | ||||
|         return None; | ||||
|       } | ||||
|       match path.path.segments.first() { | ||||
|         Some(path_segment) => FieldType::from_ident(path_segment), | ||||
|         _ => None, | ||||
|       } | ||||
|     } | ||||
|     Path(ref path) => FieldType::from_ident(&path.path), | ||||
|     _ => None, | ||||
|   } | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user