support Vec of structure

This commit is contained in:
Marc-Antoine Arnaud 2018-04-10 12:56:33 +02:00
parent cbfaa1e382
commit 26b6b21fd5
5 changed files with 143 additions and 46 deletions

View File

@ -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 = "<base><item>something</item></base>";
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 = "<base><items>something1</items><items>something2</items></base>";
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<SubStruct>
}
#[derive(YaDeserialize, PartialEq, Debug)]
#[yaserde(root="items")]
pub struct SubStruct {
field: String
}
let content = "<base><items><field>something1</field></items><items><field>something2</field></items></base>";
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 = "<base item=\"something\"><sub subitem=\"sub-something\"></sub></base>";
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 = "<base Item=\"something\"><sub sub_item=\"sub_something\"></sub></base>";
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 = "<base Item=\"something\"><sub sub_item=\"sub_something\">text_content</sub></base>";
convert_and_validate!(content, XmlStruct{
convert_and_validate!(content, XmlStruct, XmlStruct{
item: "something".to_string(),
sub_struct: SubStruct{
subitem: "sub_something".to_string(),

View File

@ -57,6 +57,34 @@ fn ser_list_of_items() {
let content = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base><items>something1</items><items>something2</items></base>".to_string();
convert_and_validate!(model, content);
#[derive(YaSerialize, PartialEq, Debug)]
#[yaserde(root="base")]
pub struct XmlStructOfStruct {
items: Vec<SubStruct>
}
#[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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><base><items><field>something1</field></items><items><field>something2</field></items></base>";
convert_and_validate!(model2, content);
}
#[test]

View File

@ -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<String> = 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

View File

@ -6,38 +6,47 @@ use syn::Type::Path;
#[derive(Debug)]
pub enum FieldType {
FieldTypeString,
FieldTypeVec{data_type: syn::Ident},
FieldTypeVec{data_type: Box<FieldType>},
FieldTypeStruct{struct_name: syn::Ident},
}
impl FieldType {
fn from_ident(t: &syn::PathSegment) -> Option<FieldType> {
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<FieldType> {
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,
}
}

View File

@ -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,
}
})