diff --git a/yaserde/tests/deserializer.rs b/yaserde/tests/deserializer.rs index 53489f2..fcf7cb8 100644 --- a/yaserde/tests/deserializer.rs +++ b/yaserde/tests/deserializer.rs @@ -9,10 +9,10 @@ use xml::reader::EventReader; use yaserde::YaDeserialize; macro_rules! convert_and_validate { - ($content:expr, $model:expr) => { + ($content:expr, $struct:tt, $model:expr) => { let mut parser = EventReader::from_str($content); - let loaded = XmlStruct::derive_deserialize(&mut parser, None); + let loaded = $struct::derive_deserialize(&mut parser, None); assert_eq!(loaded, Ok($model)); } } @@ -26,7 +26,7 @@ fn de_basic() { } let content = "something"; - convert_and_validate!(content, XmlStruct{ + convert_and_validate!(content, XmlStruct, XmlStruct{ item: "something".to_string() }); } @@ -40,12 +40,37 @@ fn de_list_of_items() { } let content = "something1something2"; - convert_and_validate!(content, XmlStruct{ + convert_and_validate!(content, XmlStruct, XmlStruct{ items: vec![ "something1".to_string(), "something2".to_string() ] }); + + #[derive(YaDeserialize, PartialEq, Debug)] + #[yaserde(root="base")] + pub struct XmlStructOfStruct { + items: Vec + } + + + #[derive(YaDeserialize, PartialEq, Debug)] + #[yaserde(root="items")] + pub struct SubStruct { + field: String + } + + let content = "something1something2"; + convert_and_validate!(content, XmlStructOfStruct, XmlStructOfStruct{ + items: vec![ + SubStruct{ + field: "something1".to_string() + }, + SubStruct{ + field: "something2".to_string() + } + ] + }); } #[test] @@ -74,7 +99,7 @@ fn de_attributes() { } let content = ""; - convert_and_validate!(content, XmlStruct{ + convert_and_validate!(content, XmlStruct, XmlStruct{ item: "something".to_string(), sub: SubStruct{ subitem: "sub-something".to_string() @@ -109,7 +134,7 @@ fn de_rename() { } let content = ""; - convert_and_validate!(content, XmlStruct{ + convert_and_validate!(content, XmlStruct, XmlStruct{ item: "something".to_string(), sub_struct: SubStruct{ subitem: "sub_something".to_string() @@ -147,7 +172,7 @@ fn de_text_content_with_attributes() { } let content = "text_content"; - convert_and_validate!(content, XmlStruct{ + convert_and_validate!(content, XmlStruct, XmlStruct{ item: "something".to_string(), sub_struct: SubStruct{ subitem: "sub_something".to_string(), diff --git a/yaserde/tests/serializer.rs b/yaserde/tests/serializer.rs index 8424f8c..e1f9090 100644 --- a/yaserde/tests/serializer.rs +++ b/yaserde/tests/serializer.rs @@ -57,6 +57,34 @@ fn ser_list_of_items() { let content = "something1something2".to_string(); convert_and_validate!(model, content); + + + #[derive(YaSerialize, PartialEq, Debug)] + #[yaserde(root="base")] + pub struct XmlStructOfStruct { + items: Vec + } + + + #[derive(YaSerialize, PartialEq, Debug)] + #[yaserde(root="items")] + pub struct SubStruct { + field: String + } + + let model2 = XmlStructOfStruct{ + items: vec![ + SubStruct{ + field: "something1".to_string() + }, + SubStruct{ + field: "something2".to_string() + } + ] + }; + + let content = "something1something2"; + convert_and_validate!(model2, content); } #[test] diff --git a/yaserde_derive/src/de/expand_struct.rs b/yaserde_derive/src/de/expand_struct.rs index fbe6593..93b103a 100644 --- a/yaserde_derive/src/de/expand_struct.rs +++ b/yaserde_derive/src/de/expand_struct.rs @@ -16,16 +16,28 @@ pub fn parse(data_struct: &DataStruct, name: &Ident, root: &String) -> Tokens { let mut #label : String = "".to_string(); }) }, - Some(FieldType::FieldTypeVec{data_type}) => { - Some(quote!{ - let mut #label : Vec<#data_type> = vec![]; - }) - }, Some(FieldType::FieldTypeStruct{struct_name}) => { Some(quote!{ let mut #label : #struct_name = #struct_name::default(); }) - } + }, + Some(FieldType::FieldTypeVec{data_type}) => { + let dt = Box::into_raw(data_type); + match unsafe{dt.as_ref()} { + Some(&FieldType::FieldTypeString) => { + Some(quote!{ + let mut #label : Vec = vec![]; + }) + }, + Some(&FieldType::FieldTypeStruct{struct_name}) => { + Some(quote!{ + let mut #label : Vec<#struct_name> = vec![]; + }) + }, + Some(&FieldType::FieldTypeVec{..}) => {unimplemented!();}, + None => {unimplemented!();}, + } + }, _ => None } }) @@ -144,8 +156,9 @@ pub fn parse(data_struct: &DataStruct, name: &Ident, root: &String) -> Tokens { }) }, Some(FieldType::FieldTypeVec{data_type}) => { - match data_type.to_string().as_str() { - "String" => { + let dt = Box::into_raw(data_type); + match unsafe{dt.as_ref()} { + Some(&FieldType::FieldTypeString) => { Some(quote!{ #label_name => { match read.next() { @@ -157,7 +170,7 @@ pub fn parse(data_struct: &DataStruct, name: &Ident, root: &String) -> Tokens { }, }) }, - struct_name => { + Some(&FieldType::FieldTypeStruct{struct_name}) => { let struct_ident = Ident::new(&format!("{}", struct_name), Span::def_site()); Some(quote!{ #label_name => { @@ -172,7 +185,9 @@ pub fn parse(data_struct: &DataStruct, name: &Ident, root: &String) -> Tokens { } }, }) - } + }, + Some(&FieldType::FieldTypeVec{..}) => {unimplemented!();}, + None => {unimplemented!();}, } }, _ => None diff --git a/yaserde_derive/src/field_type.rs b/yaserde_derive/src/field_type.rs index 4c694a6..5b9601c 100644 --- a/yaserde_derive/src/field_type.rs +++ b/yaserde_derive/src/field_type.rs @@ -6,38 +6,47 @@ use syn::Type::Path; #[derive(Debug)] pub enum FieldType { FieldTypeString, - FieldTypeVec{data_type: syn::Ident}, + FieldTypeVec{data_type: Box}, FieldTypeStruct{struct_name: syn::Ident}, } +impl FieldType { + fn from_ident(t: &syn::PathSegment) -> Option { + match t.ident.as_ref() { + "String" => Some(FieldType::FieldTypeString), + "Vec" => { + get_vec_type(t).map(|data_type| { + let p = syn::PathSegment{ + ident: data_type, + arguments: syn::PathArguments::None + }; + + FieldType::FieldTypeVec{ + data_type: Box::new(FieldType::from_ident(&p).unwrap()) + } + }) + }, + _struct_name => + Some(FieldType::FieldTypeStruct{ + struct_name: t.ident + }), + } + } +} + pub fn get_field_type(field: &syn::Field) -> Option { match field.ty { Path(ref path) => { match path.path.segments.first() { Some(Pair::End(t)) => { - match t.ident.to_string().as_str() { - "String" => Some(FieldType::FieldTypeString), - "Vec" => { - match get_vec_type(t) { - Some(data_type) => - Some(FieldType::FieldTypeVec{ - data_type: data_type - }), - None => None, - } - }, - _struct_name => - Some(FieldType::FieldTypeStruct{ - struct_name: t.ident - }), - } + FieldType::from_ident(t) }, _ => { None }, } }, - _ => {None}, + _ => None, } } diff --git a/yaserde_derive/src/ser/expand_struct.rs b/yaserde_derive/src/ser/expand_struct.rs index 7d913aa..bb50aa5 100644 --- a/yaserde_derive/src/ser/expand_struct.rs +++ b/yaserde_derive/src/ser/expand_struct.rs @@ -75,19 +75,39 @@ pub fn serialize(data_struct: &DataStruct, name: &Ident, root: &String) -> Token }, }; }), - Some(FieldType::FieldTypeVec{..}) => - Some(quote!{ - for item in &self.#label { - let start_event = XmlEvent::start_element(#label_name); - let _ret = writer.write(start_event); + Some(FieldType::FieldTypeVec{data_type}) => { + let dt = Box::into_raw(data_type); + match unsafe{dt.as_ref()} { + Some(&FieldType::FieldTypeString) => { + Some(quote!{ + for item in &self.#label { + let start_event = XmlEvent::start_element(#label_name); + let _ret = writer.write(start_event); - let data_event = XmlEvent::characters(item); - let _ret = writer.write(data_event); + let data_event = XmlEvent::characters(item); + let _ret = writer.write(data_event); - let end_event = XmlEvent::end_element(); - let _ret = writer.write(end_event); - } - }), + let end_event = XmlEvent::end_element(); + let _ret = writer.write(end_event); + } + }) + }, + Some(&FieldType::FieldTypeStruct{..}) => { + Some(quote!{ + for item in &self.#label { + match item.derive_serialize(writer) { + Ok(()) => {}, + Err(msg) => { + return Err(msg); + }, + }; + } + }) + }, + Some(&FieldType::FieldTypeVec{..}) => {unimplemented!();}, + None => {unimplemented!();}, + } + }, None => None, } })