Add deserialization for enums with values (#8)
This commit is contained in:
parent
a2bf70c5bd
commit
d277d5137b
@ -351,6 +351,178 @@ fn de_attribute_enum() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn de_complex_enum() {
|
||||
#[derive(YaDeserialize, PartialEq, Debug)]
|
||||
pub struct XmlStruct {
|
||||
background: Color,
|
||||
}
|
||||
|
||||
#[derive(YaDeserialize, PartialEq, Debug, Default)]
|
||||
pub struct OtherStruct {
|
||||
fi: i32,
|
||||
se: i32,
|
||||
}
|
||||
|
||||
#[derive(YaDeserialize, PartialEq, Debug)]
|
||||
pub enum Color {
|
||||
White,
|
||||
Black(String),
|
||||
Orange(std::string::String),
|
||||
Red(i32),
|
||||
Green(OtherStruct),
|
||||
Yellow(Option<String>),
|
||||
Brown(Option<OtherStruct>),
|
||||
Blue(Vec<String>),
|
||||
Purple(Vec<i32>),
|
||||
Magenta(Vec<OtherStruct>),
|
||||
#[yaserde(rename = "NotSoCyan")]
|
||||
Cyan(Vec<OtherStruct>),
|
||||
}
|
||||
|
||||
impl Default for Color {
|
||||
fn default() -> Color {
|
||||
Color::White
|
||||
}
|
||||
}
|
||||
|
||||
let content = r#"<?xml version="1.0" encoding="utf-8"?>
|
||||
<base>
|
||||
<background>
|
||||
<Black>text</Black>
|
||||
</background>
|
||||
</base>
|
||||
"#;
|
||||
convert_and_validate!(
|
||||
content,
|
||||
XmlStruct,
|
||||
XmlStruct {
|
||||
background: Color::Black(String::from("text")),
|
||||
}
|
||||
);
|
||||
|
||||
let content = r#"<?xml version="1.0" encoding="utf-8"?>
|
||||
<base>
|
||||
<background>
|
||||
<Orange>text</Orange>
|
||||
</background>
|
||||
</base>
|
||||
"#;
|
||||
convert_and_validate!(
|
||||
content,
|
||||
XmlStruct,
|
||||
XmlStruct {
|
||||
background: Color::Orange(String::from("text")),
|
||||
}
|
||||
);
|
||||
|
||||
let content = r#"<?xml version="1.0" encoding="utf-8"?>
|
||||
<base>
|
||||
<background>
|
||||
<Green>
|
||||
<fi>12</fi>
|
||||
<se>23</se>
|
||||
</Green>
|
||||
</background>
|
||||
</base>
|
||||
"#;
|
||||
convert_and_validate!(
|
||||
content,
|
||||
XmlStruct,
|
||||
XmlStruct {
|
||||
background: Color::Green(OtherStruct { fi: 12, se: 23 }),
|
||||
}
|
||||
);
|
||||
|
||||
let content = r#"<?xml version="1.0" encoding="utf-8"?>
|
||||
<base>
|
||||
<background>
|
||||
<Brown>
|
||||
<fi>12</fi>
|
||||
<se>23</se>
|
||||
</Brown>
|
||||
</background>
|
||||
</base>
|
||||
"#;
|
||||
convert_and_validate!(
|
||||
content,
|
||||
XmlStruct,
|
||||
XmlStruct {
|
||||
background: Color::Brown(Some(OtherStruct { fi: 12, se: 23 })),
|
||||
}
|
||||
);
|
||||
|
||||
let content = r#"<?xml version="1.0" encoding="utf-8"?>
|
||||
<base>
|
||||
<background>
|
||||
<Blue>abc</Blue>
|
||||
<Blue>def</Blue>
|
||||
</background>
|
||||
</base>
|
||||
"#;
|
||||
convert_and_validate!(
|
||||
content,
|
||||
XmlStruct,
|
||||
XmlStruct {
|
||||
background: Color::Blue(vec![String::from("abc"), String::from("def")]),
|
||||
}
|
||||
);
|
||||
|
||||
let content = r#"<?xml version="1.0" encoding="utf-8"?>
|
||||
<base>
|
||||
<background>
|
||||
<Purple>12</Purple>
|
||||
<Purple>43</Purple>
|
||||
</background>
|
||||
</base>
|
||||
"#;
|
||||
convert_and_validate!(
|
||||
content,
|
||||
XmlStruct,
|
||||
XmlStruct {
|
||||
background: Color::Purple(vec![12, 43]),
|
||||
}
|
||||
);
|
||||
|
||||
let content = r#"<?xml version="1.0" encoding="utf-8"?>
|
||||
<base>
|
||||
<background>
|
||||
<Magenta><fi>12</fi><se>23</se></Magenta>
|
||||
<Magenta><fi>63</fi><se>98</se></Magenta>
|
||||
</background>
|
||||
</base>
|
||||
"#;
|
||||
convert_and_validate!(
|
||||
content,
|
||||
XmlStruct,
|
||||
XmlStruct {
|
||||
background: Color::Magenta(vec![
|
||||
OtherStruct { fi: 12, se: 23 },
|
||||
OtherStruct { fi: 63, se: 98 }
|
||||
]),
|
||||
}
|
||||
);
|
||||
|
||||
let content = r#"<?xml version="1.0" encoding="utf-8"?>
|
||||
<base xmlns:ns="http://www.sample.com/ns/domain">
|
||||
<background>
|
||||
<NotSoCyan><fi>12</fi><se>23</se></NotSoCyan>
|
||||
<NotSoCyan><fi>63</fi><se>98</se></NotSoCyan>
|
||||
</background>
|
||||
</base>
|
||||
"#;
|
||||
convert_and_validate!(
|
||||
content,
|
||||
XmlStruct,
|
||||
XmlStruct {
|
||||
background: Color::Cyan(vec![
|
||||
OtherStruct { fi: 12, se: 23 },
|
||||
OtherStruct { fi: 63, se: 98 }
|
||||
])
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn de_name_issue_21() {
|
||||
#[derive(YaDeserialize, PartialEq, Debug)]
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
use attribute::*;
|
||||
use de::build_default_value::build_default_value;
|
||||
use field_type::*;
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::TokenStreamExt;
|
||||
use std::collections::BTreeMap;
|
||||
use syn::DataEnum;
|
||||
use syn::Fields;
|
||||
@ -14,250 +12,18 @@ pub fn parse(
|
||||
root: &str,
|
||||
_namespaces: &BTreeMap<String, String>,
|
||||
) -> TokenStream {
|
||||
let variables: TokenStream = data_enum
|
||||
.variants
|
||||
.iter()
|
||||
.map(|variant| match variant.fields {
|
||||
Fields::Unit => None,
|
||||
Fields::Named(ref fields) => {
|
||||
let enum_fields = fields
|
||||
.named
|
||||
.iter()
|
||||
.map(|field| {
|
||||
let field_label = &field.ident;
|
||||
let field_attrs = YaSerdeAttribute::parse(&field.attrs);
|
||||
|
||||
match get_field_type(field) {
|
||||
Some(FieldType::FieldTypeString) => build_default_value(
|
||||
field_label,
|
||||
"e! {String},
|
||||
"e! {"".to_string()},
|
||||
&field_attrs.default,
|
||||
),
|
||||
Some(FieldType::FieldTypeBool) => build_default_value(
|
||||
field_label,
|
||||
"e! {bool},
|
||||
"e! {false},
|
||||
&field_attrs.default,
|
||||
),
|
||||
Some(FieldType::FieldTypeI8) => {
|
||||
build_default_value(field_label, "e! {i8}, "e! {0}, &field_attrs.default)
|
||||
}
|
||||
Some(FieldType::FieldTypeU8) => {
|
||||
build_default_value(field_label, "e! {u8}, "e! {0}, &field_attrs.default)
|
||||
}
|
||||
Some(FieldType::FieldTypeI16) => build_default_value(
|
||||
field_label,
|
||||
"e! {i16},
|
||||
"e! {0},
|
||||
&field_attrs.default,
|
||||
),
|
||||
Some(FieldType::FieldTypeU16) => build_default_value(
|
||||
field_label,
|
||||
"e! {u16},
|
||||
"e! {0},
|
||||
&field_attrs.default,
|
||||
),
|
||||
Some(FieldType::FieldTypeI32) => build_default_value(
|
||||
field_label,
|
||||
"e! {i32},
|
||||
"e! {0},
|
||||
&field_attrs.default,
|
||||
),
|
||||
Some(FieldType::FieldTypeU32) => build_default_value(
|
||||
field_label,
|
||||
"e! {u32},
|
||||
"e! {0},
|
||||
&field_attrs.default,
|
||||
),
|
||||
Some(FieldType::FieldTypeI64) => build_default_value(
|
||||
field_label,
|
||||
"e! {i64},
|
||||
"e! {0},
|
||||
&field_attrs.default,
|
||||
),
|
||||
Some(FieldType::FieldTypeU64) => build_default_value(
|
||||
field_label,
|
||||
"e! {u64},
|
||||
"e! {0},
|
||||
&field_attrs.default,
|
||||
),
|
||||
Some(FieldType::FieldTypeF32) => build_default_value(
|
||||
field_label,
|
||||
"e! {f32},
|
||||
"e! {0},
|
||||
&field_attrs.default,
|
||||
),
|
||||
Some(FieldType::FieldTypeF64) => build_default_value(
|
||||
field_label,
|
||||
"e! {f64},
|
||||
"e! {0},
|
||||
&field_attrs.default,
|
||||
),
|
||||
Some(FieldType::FieldTypeStruct { struct_name }) => build_default_value(
|
||||
field_label,
|
||||
"e! {#struct_name},
|
||||
"e! {#struct_name::default()},
|
||||
&field_attrs.default,
|
||||
),
|
||||
Some(FieldType::FieldTypeOption { .. }) => {
|
||||
if let Some(d) = &field_attrs.default {
|
||||
let default_function = Ident::new(&d, Span::call_site());
|
||||
|
||||
Some(quote! {
|
||||
#[allow(unused_mut, non_snake_case, non_camel_case_types)]
|
||||
let mut #field_label = #default_function();
|
||||
})
|
||||
} else {
|
||||
Some(quote! {
|
||||
#[allow(unused_mut, non_snake_case, non_camel_case_types)]
|
||||
let mut #field_label = None;
|
||||
})
|
||||
}
|
||||
}
|
||||
Some(FieldType::FieldTypeVec { data_type }) => {
|
||||
let dt = Box::into_raw(data_type);
|
||||
match unsafe { dt.as_ref() } {
|
||||
Some(&FieldType::FieldTypeString) => build_default_value(
|
||||
field_label,
|
||||
"e! {Vec<String>},
|
||||
"e! {vec![]},
|
||||
&field_attrs.default,
|
||||
),
|
||||
Some(&FieldType::FieldTypeBool) => build_default_value(
|
||||
field_label,
|
||||
"e! {Vec<bool>},
|
||||
"e! {vec![]},
|
||||
&field_attrs.default,
|
||||
),
|
||||
Some(&FieldType::FieldTypeI8) => build_default_value(
|
||||
field_label,
|
||||
"e! {Vec<i8>},
|
||||
"e! {vec![]},
|
||||
&field_attrs.default,
|
||||
),
|
||||
Some(&FieldType::FieldTypeU8) => build_default_value(
|
||||
field_label,
|
||||
"e! {Vec<u8>},
|
||||
"e! {vec![]},
|
||||
&field_attrs.default,
|
||||
),
|
||||
Some(&FieldType::FieldTypeI16) => build_default_value(
|
||||
field_label,
|
||||
"e! {Vec<i16>},
|
||||
"e! {vec![]},
|
||||
&field_attrs.default,
|
||||
),
|
||||
Some(&FieldType::FieldTypeU16) => build_default_value(
|
||||
field_label,
|
||||
"e! {Vec<u16>},
|
||||
"e! {vec![]},
|
||||
&field_attrs.default,
|
||||
),
|
||||
Some(&FieldType::FieldTypeI32) => build_default_value(
|
||||
field_label,
|
||||
"e! {Vec<i32>},
|
||||
"e! {vec![]},
|
||||
&field_attrs.default,
|
||||
),
|
||||
Some(&FieldType::FieldTypeU32) => build_default_value(
|
||||
field_label,
|
||||
"e! {Vec<u32>},
|
||||
"e! {vec![]},
|
||||
&field_attrs.default,
|
||||
),
|
||||
Some(&FieldType::FieldTypeI64) => build_default_value(
|
||||
field_label,
|
||||
"e! {Vec<i64>},
|
||||
"e! {vec![]},
|
||||
&field_attrs.default,
|
||||
),
|
||||
Some(&FieldType::FieldTypeU64) => build_default_value(
|
||||
field_label,
|
||||
"e! {Vec<u64>},
|
||||
"e! {vec![]},
|
||||
&field_attrs.default,
|
||||
),
|
||||
Some(&FieldType::FieldTypeF32) => build_default_value(
|
||||
field_label,
|
||||
"e! {Vec<f32>},
|
||||
"e! {vec![]},
|
||||
&field_attrs.default,
|
||||
),
|
||||
Some(&FieldType::FieldTypeF64) => build_default_value(
|
||||
field_label,
|
||||
"e! {Vec<f64>},
|
||||
"e! {vec![]},
|
||||
&field_attrs.default,
|
||||
),
|
||||
Some(&FieldType::FieldTypeStruct { ref struct_name }) => build_default_value(
|
||||
field_label,
|
||||
"e! {Vec<#struct_name>},
|
||||
"e! {vec![]},
|
||||
&field_attrs.default,
|
||||
),
|
||||
Some(&FieldType::FieldTypeOption { .. })
|
||||
| Some(&FieldType::FieldTypeVec { .. }) => {
|
||||
unimplemented!();
|
||||
}
|
||||
None => {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
})
|
||||
.filter(|x| x.is_some())
|
||||
.map(|x| x.unwrap())
|
||||
.fold(TokenStream::new(), |mut sum, val| {
|
||||
sum.append_all(val);
|
||||
sum
|
||||
});
|
||||
|
||||
Some(enum_fields)
|
||||
}
|
||||
Fields::Unnamed(ref _fields) => {
|
||||
unimplemented!();
|
||||
}
|
||||
})
|
||||
.filter(|x| x.is_some())
|
||||
.map(|x| x.unwrap())
|
||||
.fold(TokenStream::new(), |mut sum, val| {
|
||||
sum.append_all(val);
|
||||
sum
|
||||
});
|
||||
|
||||
let match_to_enum: TokenStream = data_enum
|
||||
.variants
|
||||
.iter()
|
||||
.map(|variant| {
|
||||
let field_attrs = YaSerdeAttribute::parse(&variant.attrs);
|
||||
let renamed_label = match field_attrs.rename {
|
||||
Some(value) => Ident::new(&value.to_string(), Span::call_site()),
|
||||
None => variant.ident.clone(),
|
||||
};
|
||||
let label = &variant.ident;
|
||||
let label_name = renamed_label.to_string();
|
||||
|
||||
match variant.fields {
|
||||
Fields::Unit => Some(quote! {
|
||||
#label_name => {
|
||||
simple_enum_value = Some(#name::#label);
|
||||
}
|
||||
}),
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
.filter(|x| x.is_some())
|
||||
.map(|x| x.unwrap())
|
||||
.fold(TokenStream::new(), |mut tokens, token| {
|
||||
tokens.append_all(token);
|
||||
tokens
|
||||
});
|
||||
.map(|variant| parse_variant(variant, name))
|
||||
.filter_map(|f| f)
|
||||
.collect();
|
||||
|
||||
quote! {
|
||||
use xml::reader::XmlEvent;
|
||||
use yaserde::Visitor;
|
||||
#[allow(unknown_lints, unused_imports)]
|
||||
use std::str::FromStr;
|
||||
|
||||
impl YaDeserialize for #name {
|
||||
#[allow(unused_variables)]
|
||||
@ -271,41 +37,42 @@ pub fn parse(
|
||||
debug!("Enum: start to parse {:?}", named_element);
|
||||
|
||||
#[allow(unused_assignments, unused_mut)]
|
||||
let mut simple_enum_value = None;
|
||||
|
||||
#variables
|
||||
let mut enum_value = None;
|
||||
|
||||
loop {
|
||||
match reader.peek()?.to_owned() {
|
||||
XmlEvent::StartElement{name, attributes, namespace: _namespace} => {
|
||||
debug!("Enum: {}: {}", named_element, name.local_name.as_str());
|
||||
if name.local_name == named_element {
|
||||
let _next = reader.next_event();
|
||||
XmlEvent::StartElement{ref name, ref attributes, ..} => {
|
||||
|
||||
if let XmlEvent::Characters(content) = reader.peek()?.to_owned() {
|
||||
match content.as_str() {
|
||||
#match_to_enum
|
||||
_ => {}
|
||||
}
|
||||
match name.local_name.as_str() {
|
||||
#match_to_enum
|
||||
named_element => {
|
||||
let _root = reader.next_event();
|
||||
}
|
||||
}
|
||||
},
|
||||
XmlEvent::EndElement{name} => {
|
||||
if name.local_name.as_str() == named_element {
|
||||
|
||||
if let XmlEvent::Characters(content) = reader.peek()?.to_owned() {
|
||||
match content.as_str() {
|
||||
#match_to_enum
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
XmlEvent::EndElement{ref name} => {
|
||||
if name.local_name == named_element {
|
||||
break;
|
||||
}
|
||||
let _root = reader.next_event();
|
||||
},
|
||||
xml::reader::XmlEvent::Characters(characters_content) => {
|
||||
}
|
||||
XmlEvent::Characters(ref text_content) => {
|
||||
let _root = reader.next_event();
|
||||
},
|
||||
}
|
||||
event => {
|
||||
return Err(format!("unknown event {:?}", event))
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match simple_enum_value {
|
||||
match enum_value {
|
||||
Some(value) => Ok(value),
|
||||
None => {
|
||||
Ok(#name::default())
|
||||
@ -315,3 +82,227 @@ pub fn parse(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_variant(variant: &syn::Variant, name: &Ident) -> Option<TokenStream> {
|
||||
let xml_element_name = YaSerdeAttribute::parse(&variant.attrs)
|
||||
.rename
|
||||
.unwrap_or(variant.ident.to_string());
|
||||
|
||||
let variant_name = {
|
||||
let label = &variant.ident;
|
||||
quote! { #name::#label }
|
||||
};
|
||||
|
||||
match variant.fields {
|
||||
Fields::Unit => Some(quote! {
|
||||
#xml_element_name => {
|
||||
enum_value = Some(#variant_name);
|
||||
}
|
||||
}),
|
||||
Fields::Unnamed(ref fields) => {
|
||||
let field_visitors = build_unnamed_field_visitors(fields);
|
||||
let call_visitors = build_unnamed_visitor_calls(fields, &variant_name);
|
||||
|
||||
if fields.unnamed.len() > 1 {
|
||||
unimplemented!("enum variant with multiple fields")
|
||||
}
|
||||
|
||||
Some(
|
||||
fields
|
||||
.unnamed
|
||||
.iter()
|
||||
.take(1)
|
||||
.map(|_field| {
|
||||
quote! {
|
||||
#xml_element_name => {
|
||||
#field_visitors
|
||||
#call_visitors
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn build_unnamed_field_visitors(fields: &syn::FieldsUnnamed) -> TokenStream {
|
||||
fields
|
||||
.unnamed
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, field)| {
|
||||
let visitor_label = Ident::new(&format!("__Visitor_{}", idx), Span::call_site());
|
||||
|
||||
let make_visitor =
|
||||
|visitor: &TokenStream, field_type: &TokenStream, fn_body: &TokenStream| {
|
||||
Some(quote! {
|
||||
#[allow(non_snake_case, non_camel_case_types)]
|
||||
struct #visitor_label;
|
||||
impl<'de> Visitor<'de> for #visitor_label {
|
||||
type Value = #field_type;
|
||||
|
||||
fn #visitor(self, v: &str) -> Result<Self::Value, String> {
|
||||
#fn_body
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
let simple_type_visitor = |simple_type| {
|
||||
let (field_type, visitor) = convert_simple_type(simple_type);
|
||||
|
||||
make_visitor(
|
||||
&visitor,
|
||||
&field_type,
|
||||
"e! { Ok(#field_type::from_str(v).unwrap()) },
|
||||
)
|
||||
};
|
||||
|
||||
get_field_type(field).and_then(|f| match f {
|
||||
FieldType::FieldTypeStruct { struct_name } => {
|
||||
let struct_id: String = struct_name
|
||||
.segments
|
||||
.iter()
|
||||
.map(|s| s.ident.to_string())
|
||||
.collect();
|
||||
|
||||
make_visitor(
|
||||
"e! { visit_str },
|
||||
"e! { #struct_name },
|
||||
"e! {
|
||||
let content = "<".to_string() + #struct_id + ">" + v + "</" + #struct_id + ">";
|
||||
let value : Result<#struct_name, String> = yaserde::de::from_str(&content);
|
||||
value
|
||||
},
|
||||
)
|
||||
}
|
||||
FieldType::FieldTypeOption { data_type } | FieldType::FieldTypeVec { data_type } => {
|
||||
match *data_type {
|
||||
FieldType::FieldTypeStruct { .. } => None,
|
||||
simple_type => simple_type_visitor(simple_type),
|
||||
}
|
||||
}
|
||||
simple_type => simple_type_visitor(simple_type),
|
||||
})
|
||||
})
|
||||
.filter_map(|f| f)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn build_unnamed_visitor_calls(
|
||||
fields: &syn::FieldsUnnamed,
|
||||
variant_name: &TokenStream,
|
||||
) -> TokenStream {
|
||||
fields
|
||||
.unnamed
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, field)| {
|
||||
let visitor_label = Ident::new(&format!("__Visitor_{}", idx), Span::call_site());
|
||||
|
||||
let call_simple_type_visitor = |simple_type, action| {
|
||||
let (field_type, visitor) = convert_simple_type(simple_type);
|
||||
|
||||
let label_name = format!("field_{}", idx);
|
||||
|
||||
Some(quote! {
|
||||
let visitor = #visitor_label{};
|
||||
|
||||
if let XmlEvent::StartElement {name, ..} = reader.peek()?.clone() {
|
||||
if let Some(namespace) = name.namespace {
|
||||
match namespace.as_str() {
|
||||
bad_ns => {
|
||||
let msg = format!("bad field namespace for {}, found {}",
|
||||
name.local_name.as_str(),
|
||||
bad_ns);
|
||||
return Err(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
reader.set_map_value()
|
||||
}
|
||||
|
||||
let result = reader.read_inner_value::<#field_type, _>(|reader| {
|
||||
if let XmlEvent::EndElement { .. } = *reader.peek()? {
|
||||
return visitor.#visitor("");
|
||||
}
|
||||
|
||||
if let Ok(XmlEvent::Characters(s)) = reader.next_event() {
|
||||
visitor.#visitor(&s)
|
||||
} else {
|
||||
Err(format!("unable to parse content for {}", #label_name))
|
||||
}
|
||||
});
|
||||
|
||||
if let Ok(value) = result {
|
||||
#action
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
let call_struct_visitor = |struct_name, action| {
|
||||
Some(quote! {
|
||||
reader.set_map_value();
|
||||
match #struct_name::deserialize(reader) {
|
||||
Ok(value) => {
|
||||
#action;
|
||||
let _root = reader.next_event();
|
||||
},
|
||||
Err(msg) => {
|
||||
return Err(msg);
|
||||
},
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
let set_val = quote! { enum_value = Some(#variant_name(value)) };
|
||||
let set_opt = quote! { enum_value = Some(#variant_name(Some(value))) };
|
||||
let set_vec = quote! {
|
||||
match enum_value {
|
||||
Some(ref mut v) => match v {
|
||||
#variant_name(ref mut v) => v.push(value),
|
||||
_ => return Err(String::from("Got sequence of different types"))
|
||||
}
|
||||
None => {
|
||||
enum_value = Some(#variant_name(vec![value]));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
get_field_type(field).and_then(|f| match f {
|
||||
FieldType::FieldTypeStruct { struct_name } => call_struct_visitor(struct_name, set_val),
|
||||
FieldType::FieldTypeOption { data_type } => match *data_type {
|
||||
FieldType::FieldTypeStruct { struct_name } => call_struct_visitor(struct_name, set_opt),
|
||||
simple_type => call_simple_type_visitor(simple_type, set_opt),
|
||||
},
|
||||
FieldType::FieldTypeVec { data_type } => match *data_type {
|
||||
FieldType::FieldTypeStruct { struct_name } => call_struct_visitor(struct_name, set_vec),
|
||||
simple_type => call_simple_type_visitor(simple_type, set_vec),
|
||||
},
|
||||
|
||||
simple_type => call_simple_type_visitor(simple_type, set_val),
|
||||
})
|
||||
})
|
||||
.filter_map(|f| f)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn convert_simple_type(simple_type: FieldType) -> (TokenStream, TokenStream) {
|
||||
match simple_type {
|
||||
FieldType::FieldTypeString => (quote! {String}, quote! {visit_str}),
|
||||
FieldType::FieldTypeBool => (quote! {bool}, quote! {visit_bool}),
|
||||
FieldType::FieldTypeU8 => (quote! {u8}, quote! {visit_u8}),
|
||||
FieldType::FieldTypeI8 => (quote! {i8}, quote! {visit_i8}),
|
||||
FieldType::FieldTypeU16 => (quote! {u16}, quote! {visit_u16}),
|
||||
FieldType::FieldTypeI16 => (quote! {i16}, quote! {visit_i16}),
|
||||
FieldType::FieldTypeU32 => (quote! {u32}, quote! {visit_u32}),
|
||||
FieldType::FieldTypeI32 => (quote! {i32}, quote! {visit_i32}),
|
||||
FieldType::FieldTypeU64 => (quote! {u64}, quote! {visit_u64}),
|
||||
FieldType::FieldTypeI64 => (quote! {i64}, quote! {visit_i64}),
|
||||
FieldType::FieldTypeF32 => (quote! {f32}, quote! {visit_f32}),
|
||||
FieldType::FieldTypeF64 => (quote! {f64}, quote! {visit_f64}),
|
||||
_ => panic!("Not a simple type: {:?}", simple_type),
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user