serialize Vec and Option<Vec>

fix #5
This commit is contained in:
Marc-Antoine Arnaud 2018-11-05 17:02:37 +01:00
parent 9cab498963
commit 96bac71db5
4 changed files with 79 additions and 39 deletions

View File

@ -85,6 +85,11 @@ fn ser_option() {
convert_and_validate!(f64, Some(-12.5 as f64), Some("-12.5"));
convert_and_validate!(f64, None, None);
convert_and_validate!(Vec<u8>, None, None);
convert_and_validate!(Vec<u8>, Some(vec![0]), Some("0"));
convert_and_validate!(Vec<String>, None, None);
convert_and_validate!(Vec<String>, Some(vec!["test".to_string()]), Some("test"));
convert_and_validate_as_attribute!(String, Some("test".to_string()), Some("test"));
convert_and_validate_as_attribute!(String, None, None);
convert_and_validate_as_attribute!(bool, Some(true), Some("true"));

View File

@ -19,8 +19,12 @@ macro_rules! convert_and_validate {
let model = Data { item: $value };
let data: Result<String, String> = to_string(&model);
let content = String::from("<?xml version=\"1.0\" encoding=\"utf-8\"?><data><item>") + $content
+ "</item></data>";
let content = if $content == "" {
String::from("<?xml version=\"1.0\" encoding=\"utf-8\"?><data />")
} else {
String::from("<?xml version=\"1.0\" encoding=\"utf-8\"?><data><item>") + $content
+ "</item></data>"
};
assert_eq!(data, Ok(content));
}};
}
@ -60,6 +64,8 @@ fn ser_type() {
convert_and_validate!(i64, -12 as i64, "-12");
convert_and_validate!(f32, -12.5 as f32, "-12.5");
convert_and_validate!(f64, -12.5 as f64, "-12.5");
convert_and_validate!(Vec<String>, vec![], "");
convert_and_validate!(Vec<String>, vec!["test".to_string()], "test");
convert_and_validate_as_attribute!(String, "test".to_string(), "test");
convert_and_validate_as_attribute!(bool, true, "true");

View File

@ -37,49 +37,47 @@ impl FieldType {
"f32" => Some(FieldType::FieldTypeF32),
"f64" => Some(FieldType::FieldTypeF64),
"Option" => get_sub_type(t).map(|data_type| {
let p = syn::PathSegment {
ident: data_type,
arguments: syn::PathArguments::None,
};
FieldType::FieldTypeOption {
data_type: Box::new(FieldType::from_ident(&p).unwrap()),
data_type: Box::new(FieldType::from_ident(&data_type).unwrap()),
}
}),
"Vec" => get_sub_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()),
data_type: Box::new(FieldType::from_ident(&data_type).unwrap()),
}
}),
_struct_name => Some(FieldType::FieldTypeStruct {
_struct_name => {
Some(FieldType::FieldTypeStruct {
struct_name: t.ident.clone(),
}),
})},
}
}
}
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)) => FieldType::from_ident(t),
_ => None,
Path(ref path) => {
if path.path.segments.len() != 1 {
return None;
}
match path.path.segments.first() {
Some(Pair::End(t)) => FieldType::from_ident(t),
_ => {
None
},
}
},
_ => None,
}
}
fn get_sub_type(t: &syn::PathSegment) -> Option<syn::Ident> {
fn get_sub_type(t: &syn::PathSegment) -> Option<syn::PathSegment> {
if let syn::PathArguments::AngleBracketed(ref args) = t.arguments {
if let Some(Pair::End(tt)) = args.args.first() {
if let syn::GenericArgument::Type(ref argument) = *tt {
if let Path(ref path2) = *argument {
if let Some(Pair::End(ttt)) = path2.path.segments.first() {
return Some(ttt.ident.clone());
return Some(ttt.clone());
}
}
}

View File

@ -23,14 +23,14 @@ pub fn serialize(
}
let renamed_label = match field_attrs.rename {
Some(value) => Some(Ident::new(&format!("{}", value), Span::call_site())),
None => field.ident.clone(),
Some(value) => Ident::new(&format!("{}", value), Span::call_site()),
None => field.ident.clone().unwrap(),
};
let label = &field.ident;
let label_name = if let Some(prefix) = field_attrs.prefix {
prefix + ":" + renamed_label.unwrap().to_string().as_ref()
prefix + ":" + renamed_label.to_string().as_ref()
} else {
renamed_label.unwrap().to_string()
renamed_label.to_string()
};
match get_field_type(field) {
@ -93,6 +93,20 @@ pub fn serialize(
struct_start_event
};
}),
Some(&FieldType::FieldTypeVec{..}) => {
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 end_event = XmlEvent::end_element();
let _ret = writer.write(end_event);
}
})
}
_ => None,
}
}
@ -153,14 +167,14 @@ pub fn serialize(
}
let renamed_label = match field_attrs.rename {
Some(value) => Some(Ident::new(&format!("{}", value), Span::call_site())),
None => field.ident.clone(),
Some(value) => Ident::new(&format!("{}", value), Span::call_site()),
None => field.ident.clone().unwrap(),
};
let label_name = if let Some(prefix) = field_attrs.prefix {
prefix + ":" + renamed_label.unwrap().to_string().as_ref()
prefix + ":" + renamed_label.to_string().as_ref()
} else {
renamed_label.unwrap().to_string()
renamed_label.to_string()
};
match get_field_type(field) {
@ -233,18 +247,35 @@ pub fn serialize(
let _ret = writer.write(end_event);
}
}),
Some(&FieldType::FieldTypeVec{ .. }) => Some(quote!{
if let Some(ref items) = &self.#label {
for item in items.iter() {
let start_event = XmlEvent::start_element(#label_name);
let _ret = writer.write(start_event);
let value = format!("{}", item);
let data_event = XmlEvent::characters(&value);
let _ret = writer.write(data_event);
let end_event = XmlEvent::end_element();
let _ret = writer.write(end_event);
}
}
}),
_ => None,
}
}
Some(FieldType::FieldTypeStruct { .. }) => Some(quote!{
writer.set_skip_start_end(false);
match self.#label.serialize(writer) {
Ok(()) => {},
Err(msg) => {
return Err(msg);
},
};
}),
Some(FieldType::FieldTypeStruct { .. }) => {
Some(quote!{
writer.set_skip_start_end(false);
match self.#label.serialize(writer) {
Ok(()) => {},
Err(msg) => {
return Err(msg);
},
};
})
},
Some(FieldType::FieldTypeVec { data_type }) => {
let dt = Box::into_raw(data_type);
match unsafe { dt.as_ref() } {
@ -313,7 +344,7 @@ pub fn serialize(
unimplemented!();
}
}
}
},
None => None,
}
})