diff --git a/yaserde/tests/deserializer.rs b/yaserde/tests/deserializer.rs
index 2b94548..a30607e 100644
--- a/yaserde/tests/deserializer.rs
+++ b/yaserde/tests/deserializer.rs
@@ -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#"
+
+ Antoine de Saint-Exupéry
+ Little prince
+
+ 40
+ The Earth is not just an ordinary planet!
+
+
+ "#;
+
+ 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)]
diff --git a/yaserde_derive/src/de/expand_struct.rs b/yaserde_derive/src/de/expand_struct.rs
index 22debe1..0864af9 100644
--- a/yaserde_derive/src/de/expand_struct.rs
+++ b/yaserde_derive/src/de/expand_struct.rs
@@ -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::{ToTokens, TokenStreamExt};
use std::collections::BTreeMap;
use syn::DataStruct;
use syn::Ident;
@@ -249,9 +249,13 @@ 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 +313,10 @@ 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 +370,10 @@ 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 +695,10 @@ 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 +853,10 @@ 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 +1080,11 @@ 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(),
);
diff --git a/yaserde_derive/src/field_type.rs b/yaserde_derive/src/field_type.rs
index f567a98..8975f98 100644
--- a/yaserde_derive/src/field_type.rs
+++ b/yaserde_derive/src/field_type.rs
@@ -17,48 +17,43 @@ pub enum FieldType {
FieldTypeF64,
FieldTypeOption { data_type: Box },
FieldTypeVec { data_type: Box },
- FieldTypeStruct { struct_name: syn::Ident },
+ FieldTypeStruct { struct_name: syn::Path },
}
impl FieldType {
- fn from_ident(t: &syn::PathSegment) -> Option {
- 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 {
+ 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 {
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,
}
}