diff --git a/yaserde/tests/der_type.rs b/yaserde/tests/der_type.rs index 5f19323..fc03f6c 100644 --- a/yaserde/tests/der_type.rs +++ b/yaserde/tests/der_type.rs @@ -27,6 +27,25 @@ macro_rules! convert_and_validate { }}; } +macro_rules! convert_and_validate_for_attribute { + ($type: ty, $value: expr, $content: expr) => {{ + #[derive(YaDeserialize, PartialEq, Debug)] + #[yaserde(root = "data")] + pub struct Data { + #[yaserde(attribute)] + item: $type, + } + + let model = Data { item: $value }; + + let content = String::from(""; + + let loaded: Result = from_str(&content); + assert_eq!(loaded, Ok(model)); + }}; +} + #[test] fn de_type() { convert_and_validate!(bool, true, "true"); @@ -42,4 +61,18 @@ fn de_type() { convert_and_validate!(u64, 12 as u64, "12"); convert_and_validate!(i64, 12 as i64, "12"); convert_and_validate!(i64, -12 as i64, "-12"); + + convert_and_validate_for_attribute!(bool, true, "true"); + convert_and_validate_for_attribute!(u8, 12 as u8, "12"); + convert_and_validate_for_attribute!(i8, 12 as i8, "12"); + convert_and_validate_for_attribute!(i8, -12 as i8, "-12"); + convert_and_validate_for_attribute!(u16, 12 as u16, "12"); + convert_and_validate_for_attribute!(i16, 12 as i16, "12"); + convert_and_validate_for_attribute!(i16, -12 as i16, "-12"); + convert_and_validate_for_attribute!(u32, 12 as u32, "12"); + convert_and_validate_for_attribute!(i32, 12 as i32, "12"); + convert_and_validate_for_attribute!(i32, -12 as i32, "-12"); + convert_and_validate_for_attribute!(u64, 12 as u64, "12"); + convert_and_validate_for_attribute!(i64, 12 as i64, "12"); + convert_and_validate_for_attribute!(i64, -12 as i64, "-12"); } diff --git a/yaserde/tests/se_type.rs b/yaserde/tests/se_type.rs index 347a3a6..bd337c3 100644 --- a/yaserde/tests/se_type.rs +++ b/yaserde/tests/se_type.rs @@ -25,6 +25,23 @@ macro_rules! convert_and_validate { }}; } +macro_rules! convert_and_validate_as_attribute { + ($type: ty, $value: expr, $content: expr) => {{ + #[derive(YaSerialize, PartialEq, Debug)] + #[yaserde(root = "data")] + pub struct Data { + #[yaserde(attribute)] + item: $type, + } + let model = Data { item: $value }; + + let data: Result = to_string(&model); + let content = String::from(""; + assert_eq!(data, Ok(content)); + }}; +} + #[test] fn ser_type() { convert_and_validate!(bool, true, "true"); @@ -40,4 +57,18 @@ fn ser_type() { convert_and_validate!(u64, 12 as u64, "12"); convert_and_validate!(i64, 12 as i64, "12"); convert_and_validate!(i64, -12 as i64, "-12"); + + convert_and_validate_as_attribute!(bool, true, "true"); + convert_and_validate_as_attribute!(u8, 12 as u8, "12"); + convert_and_validate_as_attribute!(i8, 12 as i8, "12"); + convert_and_validate_as_attribute!(i8, -12 as i8, "-12"); + convert_and_validate_as_attribute!(u16, 12 as u16, "12"); + convert_and_validate_as_attribute!(i16, 12 as i16, "12"); + convert_and_validate_as_attribute!(i16, -12 as i16, "-12"); + convert_and_validate_as_attribute!(u32, 12 as u32, "12"); + convert_and_validate_as_attribute!(i32, 12 as i32, "12"); + convert_and_validate_as_attribute!(i32, -12 as i32, "-12"); + convert_and_validate_as_attribute!(u64, 12 as u64, "12"); + convert_and_validate_as_attribute!(i64, 12 as i64, "12"); + convert_and_validate_as_attribute!(i64, -12 as i64, "-12"); } diff --git a/yaserde_derive/src/de/expand_struct.rs b/yaserde_derive/src/de/expand_struct.rs index 9f876a7..7a87fcb 100644 --- a/yaserde_derive/src/de/expand_struct.rs +++ b/yaserde_derive/src/de/expand_struct.rs @@ -559,6 +559,8 @@ pub fn parse( field.ident.unwrap().to_string() }; + let visitor_label = Ident::new(&format!("__Visitor{}", label_name), Span::call_site()); + match get_field_type(field) { Some(FieldType::FieldTypeString) => Some(quote!{ for attr in attributes { @@ -567,6 +569,16 @@ pub fn parse( } } }), + Some(FieldType::FieldTypeBool) => build_call_visitor_for_attribute(&label, &label_name, "e!{visit_bool}, &visitor_label), + Some(FieldType::FieldTypeI8) => build_call_visitor_for_attribute(&label, &label_name, "e!{visit_i8}, &visitor_label), + Some(FieldType::FieldTypeU8) => build_call_visitor_for_attribute(&label, &label_name, "e!{visit_u8}, &visitor_label), + Some(FieldType::FieldTypeI16) => build_call_visitor_for_attribute(&label, &label_name, "e!{visit_i16}, &visitor_label), + Some(FieldType::FieldTypeU16) => build_call_visitor_for_attribute(&label, &label_name, "e!{visit_u16}, &visitor_label), + Some(FieldType::FieldTypeI32) => build_call_visitor_for_attribute(&label, &label_name, "e!{visit_i32}, &visitor_label), + Some(FieldType::FieldTypeU32) => build_call_visitor_for_attribute(&label, &label_name, "e!{visit_u32}, &visitor_label), + Some(FieldType::FieldTypeI64) => build_call_visitor_for_attribute(&label, &label_name, "e!{visit_i64}, &visitor_label), + Some(FieldType::FieldTypeU64) => build_call_visitor_for_attribute(&label, &label_name, "e!{visit_u64}, &visitor_label), + Some(FieldType::FieldTypeStruct { struct_name }) => { let struct_ident = Ident::new( &format!("__Visitor_{}_{}", label_name, struct_name), @@ -807,6 +819,25 @@ fn build_call_visitor( }) } +fn build_call_visitor_for_attribute( + label: &Option, + label_name: &str, + visitor: &Tokens, + visitor_label: &Ident, +) -> Option { + Some(quote!{ + for attr in attributes { + if attr.name.local_name == #label_name { + let visitor = #visitor_label{}; + match visitor.#visitor(&attr.value) { + Ok(value) => {#label = value;} + Err(msg) => {return Err(msg);} + } + } + } + }) +} + fn build_set_text_to_value( field_attrs: &YaSerdeAttribute, label: &Option, diff --git a/yaserde_derive/src/ser/expand_struct.rs b/yaserde_derive/src/ser/expand_struct.rs index 298a570..e6315c9 100644 --- a/yaserde_derive/src/ser/expand_struct.rs +++ b/yaserde_derive/src/ser/expand_struct.rs @@ -44,7 +44,16 @@ pub fn serialize( | Some(FieldType::FieldTypeU32) | Some(FieldType::FieldTypeI64) | Some(FieldType::FieldTypeU64) => Some(quote!{ - .attr(#label_name, &self.#label) + .attr(#label_name, &*{ + use std::mem; + unsafe { + let content = format!("{}", self.#label); + let ret : &'static str = mem::transmute(&content as &str); + mem::forget(content); + ret + } + + }) }), Some(FieldType::FieldTypeStruct { .. }) => Some(quote!{ .attr(#label_name, &*{