diff --git a/yaserde/tests/deserializer.rs b/yaserde/tests/deserializer.rs index 24e26c2..71337a3 100644 --- a/yaserde/tests/deserializer.rs +++ b/yaserde/tests/deserializer.rs @@ -4,8 +4,10 @@ extern crate yaserde; extern crate yaserde_derive; use log::debug; +use std::default; use std::io::Read; -use yaserde::de::from_str; +use std::str::FromStr; +use yaserde::de::{self, from_str}; use yaserde::YaDeserialize; fn init() { @@ -1050,3 +1052,37 @@ fn de_same_field_name_but_some_other_fields_or_something() { serialize_and_validate!(model, content); deserialize_and_validate!(content, model, FooOuter); } + +#[test] +fn de_attribute_sequence() { + init(); + + #[derive(Default, Debug, YaDeserialize, PartialEq)] + pub enum Inner { + #[default] + #[yaserde(rename = "foo")] + Foo, + #[yaserde(rename = "bar")] + Bar, + } + + #[derive(Default, Debug, PartialEq, YaDeserialize)] + pub struct Outer { + #[yaserde(attribute, rename = "seq1")] + seq1: Vec, + #[yaserde(child, attribute, rename = "seq2")] + seq2: Vec, + #[yaserde(attribute, rename = "seq3")] + seq3: Vec, + } + + let content = r#""#; + let model = Outer { + seq1: vec![1, 2, 3, 4], + seq2: vec![Inner::Foo, Inner::Foo, Inner::Bar], + seq3: vec!["one".to_string(), "two".to_string()], + }; + + //serialize_and_validate!(model, content); + deserialize_and_validate!(content, model, Outer); +} diff --git a/yaserde_derive/src/common/field.rs b/yaserde_derive/src/common/field.rs index 4aaa4b6..594a178 100644 --- a/yaserde_derive/src/common/field.rs +++ b/yaserde_derive/src/common/field.rs @@ -293,6 +293,7 @@ impl From<&Field> for String { Field::FieldU64 => "u64".to_string(), Field::FieldF32 => "f32".to_string(), Field::FieldF64 => "f64".to_string(), + Field::FieldStruct { struct_name } => quote!{#struct_name}.to_string(), _ => panic!("Not a simple type: {:?}", field), } } diff --git a/yaserde_derive/src/de/expand_struct.rs b/yaserde_derive/src/de/expand_struct.rs index 3539c7d..28661c1 100644 --- a/yaserde_derive/src/de/expand_struct.rs +++ b/yaserde_derive/src/de/expand_struct.rs @@ -38,7 +38,7 @@ pub fn parse( quote!(::std::vec![]), ), Field::FieldOption { .. } | Field::FieldVec { .. } => { - unimplemented!(); + unimplemented!("Option or Vec nested in Vec<>"); } simple_type => { let type_token: TokenStream = simple_type.into(); @@ -239,6 +239,20 @@ pub fn parse( }) }; + let visit_vec = |action: &TokenStream, visitor: &Ident, visitor_label: &Ident| { + Some(quote! { + for attr in attributes { + if attr.name.local_name == #label_name { + for value in attr.value.split_whitespace() { + let visitor = #visitor_label{}; + let value = visitor.#visitor(value)?; + #label #action; + } + } + } + }) + }; + let visit_string = || { Some(quote! { for attr in attributes { @@ -276,7 +290,19 @@ pub fn parse( Field::FieldOption { data_type } => { visit_sub(data_type, quote! { = ::std::option::Option::Some(value) }) } - Field::FieldVec { .. } => unimplemented!(), + Field::FieldVec { data_type } => match data_type.as_ref() { + Field::FieldStruct { struct_name } => visit_vec( + "e! { .push(value) }, + &Ident::new("visit_str", field.get_span()), + &build_visitor_ident(&label_name, field.get_span(), Some(&struct_name)), + ), + Field::FieldOption { .. } | Field::FieldVec { .. } => unimplemented!("Not supported"), + simple_type => visit_vec( + "e! { .push(value) }, + &simple_type.get_simple_type_visitor(), + &visitor_label, + ), + }, Field::FieldStruct { struct_name } => visit_struct(struct_name, quote! { = value }), simple_type => visit_simple(simple_type, quote! { = value }), }