Merge pull request #168 from jondo2010/support_xst_lists

Support deserializing xst xs:list attributes as `Vec` types.
This commit is contained in:
Marc-Antoine ARNAUD 2023-12-31 13:40:14 +01:00 committed by GitHub
commit 2426700211
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 66 additions and 3 deletions

View File

@ -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<i32>,
#[yaserde(child, attribute, rename = "seq2")]
seq2: Vec<Inner>,
#[yaserde(attribute, rename = "seq3")]
seq3: Vec<String>,
}
let content = r#"<Outer seq1="1 2 3 4" seq2="foo foo bar" seq3="one two" />"#;
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);
}

View File

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

View File

@ -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(
&quote! { .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(
&quote! { .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 }),
}