support type de/ser-rialization
This commit is contained in:
@@ -8,7 +8,7 @@ use syn::Ident;
|
||||
use syn::DataEnum;
|
||||
use proc_macro2::Span;
|
||||
|
||||
pub fn parse(data_enum: &DataEnum, name: &Ident, root: &String, namespaces: &BTreeMap<String, String>) -> Tokens {
|
||||
pub fn parse(data_enum: &DataEnum, name: &Ident, root: &String, _namespaces: &BTreeMap<String, String>) -> Tokens {
|
||||
let variables : Tokens = data_enum.variants.iter().map(|ref variant|
|
||||
{
|
||||
match variant.fields {
|
||||
@@ -18,12 +18,26 @@ pub fn parse(data_enum: &DataEnum, name: &Ident, root: &String, namespaces: &BTr
|
||||
let field_label = field.ident;
|
||||
|
||||
match get_field_type(field) {
|
||||
Some(FieldType::FieldTypeString) => {
|
||||
Some(quote!{
|
||||
#[allow(unused_mut)]
|
||||
let mut #field_label : String = "".to_string();
|
||||
})
|
||||
},
|
||||
Some(FieldType::FieldTypeString) =>
|
||||
build_default_value(&field_label, quote!{String}, quote!{"".to_string()}),
|
||||
Some(FieldType::FieldTypeBool) =>
|
||||
build_default_value(&field_label, quote!{bool}, quote!{false}),
|
||||
Some(FieldType::FieldTypeI8) =>
|
||||
build_default_value(&field_label, quote!{i8}, quote!{0}),
|
||||
Some(FieldType::FieldTypeU8) =>
|
||||
build_default_value(&field_label, quote!{u8}, quote!{0}),
|
||||
Some(FieldType::FieldTypeI16) =>
|
||||
build_default_value(&field_label, quote!{i16}, quote!{0}),
|
||||
Some(FieldType::FieldTypeU16) =>
|
||||
build_default_value(&field_label, quote!{u16}, quote!{0}),
|
||||
Some(FieldType::FieldTypeI32) =>
|
||||
build_default_value(&field_label, quote!{i32}, quote!{0}),
|
||||
Some(FieldType::FieldTypeU32) =>
|
||||
build_default_value(&field_label, quote!{u32}, quote!{0}),
|
||||
Some(FieldType::FieldTypeI64) =>
|
||||
build_default_value(&field_label, quote!{i64}, quote!{0}),
|
||||
Some(FieldType::FieldTypeU64) =>
|
||||
build_default_value(&field_label, quote!{u64}, quote!{0}),
|
||||
Some(FieldType::FieldTypeStruct{struct_name}) => {
|
||||
Some(quote!{
|
||||
#[allow(unused_mut)]
|
||||
@@ -33,12 +47,26 @@ pub fn parse(data_enum: &DataEnum, name: &Ident, root: &String, namespaces: &BTr
|
||||
Some(FieldType::FieldTypeVec{data_type}) => {
|
||||
let dt = Box::into_raw(data_type);
|
||||
match unsafe{dt.as_ref()} {
|
||||
Some(&FieldType::FieldTypeString) => {
|
||||
Some(quote!{
|
||||
#[allow(unused_mut)]
|
||||
let mut #field_label : Vec<String> = vec![];
|
||||
})
|
||||
},
|
||||
Some(&FieldType::FieldTypeString) =>
|
||||
build_default_value(&field_label, quote!{Vec<String>}, quote!{vec![]}),
|
||||
Some(&FieldType::FieldTypeBool) =>
|
||||
build_default_value(&field_label, quote!{Vec<bool>}, quote!{vec![]}),
|
||||
Some(&FieldType::FieldTypeI8) =>
|
||||
build_default_value(&field_label, quote!{Vec<i8>}, quote!{vec![]}),
|
||||
Some(&FieldType::FieldTypeU8) =>
|
||||
build_default_value(&field_label, quote!{Vec<u8>}, quote!{vec![]}),
|
||||
Some(&FieldType::FieldTypeI16) =>
|
||||
build_default_value(&field_label, quote!{Vec<i16>}, quote!{vec![]}),
|
||||
Some(&FieldType::FieldTypeU16) =>
|
||||
build_default_value(&field_label, quote!{Vec<u16>}, quote!{vec![]}),
|
||||
Some(&FieldType::FieldTypeI32) =>
|
||||
build_default_value(&field_label, quote!{Vec<i32>}, quote!{vec![]}),
|
||||
Some(&FieldType::FieldTypeU32) =>
|
||||
build_default_value(&field_label, quote!{Vec<u32>}, quote!{vec![]}),
|
||||
Some(&FieldType::FieldTypeI64) =>
|
||||
build_default_value(&field_label, quote!{Vec<i64>}, quote!{vec![]}),
|
||||
Some(&FieldType::FieldTypeU64) =>
|
||||
build_default_value(&field_label, quote!{Vec<u64>}, quote!{vec![]}),
|
||||
Some(&FieldType::FieldTypeStruct{struct_name}) => {
|
||||
Some(quote!{
|
||||
#[allow(unused_mut)]
|
||||
@@ -181,13 +209,6 @@ pub fn parse(data_enum: &DataEnum, name: &Ident, root: &String, namespaces: &BTr
|
||||
let _root = reader.next();
|
||||
},
|
||||
xml::reader::XmlEvent::Characters(characters_content) => {
|
||||
// println!("{:?} - {:?} -- {:?}", prev_level, current_level, characters_content.as_str());
|
||||
// if prev_level == current_level {
|
||||
// match characters_content.as_str() {
|
||||
// #match_to_enum
|
||||
// _ => {}
|
||||
// }
|
||||
// }
|
||||
let _root = reader.next();
|
||||
},
|
||||
event => {
|
||||
@@ -206,3 +227,10 @@ pub fn parse(data_enum: &DataEnum, name: &Ident, root: &String, namespaces: &BTr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn build_default_value(label: &Option<Ident>, field_type: Tokens, default: Tokens) -> Option<Tokens> {
|
||||
Some(quote!{
|
||||
#[allow(unused_mut)]
|
||||
let mut #label : #field_type = #default;
|
||||
})
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ use proc_macro2::Span;
|
||||
|
||||
pub fn parse(data_struct: &DataStruct, name: &Ident, root: &String, namespaces: &BTreeMap<String, String>) -> Tokens {
|
||||
|
||||
let validate_namespace : Tokens = namespaces.iter().map(|(ref prefix, ref namespace)| {
|
||||
let validate_namespace : Tokens = namespaces.iter().map(|(ref _prefix, ref namespace)| {
|
||||
Some(quote!(
|
||||
|
||||
let mut found = false;
|
||||
@@ -33,12 +33,26 @@ pub fn parse(data_struct: &DataStruct, name: &Ident, root: &String, namespaces:
|
||||
{
|
||||
let label = field.ident;
|
||||
match get_field_type(field) {
|
||||
Some(FieldType::FieldTypeString) => {
|
||||
Some(quote!{
|
||||
#[allow(unused_mut)]
|
||||
let mut #label : String = "".to_string();
|
||||
})
|
||||
},
|
||||
Some(FieldType::FieldTypeString) =>
|
||||
build_default_value(&label, quote!{String}, quote!{"".to_string()}),
|
||||
Some(FieldType::FieldTypeBool) =>
|
||||
build_default_value(&label, quote!{bool}, quote!{false}),
|
||||
Some(FieldType::FieldTypeI8) =>
|
||||
build_default_value(&label, quote!{i8}, quote!{0}),
|
||||
Some(FieldType::FieldTypeU8) =>
|
||||
build_default_value(&label, quote!{u8}, quote!{0}),
|
||||
Some(FieldType::FieldTypeI16) =>
|
||||
build_default_value(&label, quote!{i16}, quote!{0}),
|
||||
Some(FieldType::FieldTypeU16) =>
|
||||
build_default_value(&label, quote!{u16}, quote!{0}),
|
||||
Some(FieldType::FieldTypeI32) =>
|
||||
build_default_value(&label, quote!{i32}, quote!{0}),
|
||||
Some(FieldType::FieldTypeU32) =>
|
||||
build_default_value(&label, quote!{u32}, quote!{0}),
|
||||
Some(FieldType::FieldTypeI64) =>
|
||||
build_default_value(&label, quote!{i64}, quote!{0}),
|
||||
Some(FieldType::FieldTypeU64) =>
|
||||
build_default_value(&label, quote!{u64}, quote!{0}),
|
||||
Some(FieldType::FieldTypeStruct{struct_name}) => {
|
||||
Some(quote!{
|
||||
#[allow(unused_mut, non_snake_case, non_camel_case_types)]
|
||||
@@ -48,12 +62,26 @@ pub fn parse(data_struct: &DataStruct, name: &Ident, root: &String, namespaces:
|
||||
Some(FieldType::FieldTypeVec{data_type}) => {
|
||||
let dt = Box::into_raw(data_type);
|
||||
match unsafe{dt.as_ref()} {
|
||||
Some(&FieldType::FieldTypeString) => {
|
||||
Some(quote!{
|
||||
#[allow(unused_mut)]
|
||||
let mut #label : Vec<String> = vec![];
|
||||
})
|
||||
},
|
||||
Some(&FieldType::FieldTypeString) =>
|
||||
build_default_value(&label, quote!{Vec<String>}, quote!{vec![]}),
|
||||
Some(&FieldType::FieldTypeBool) =>
|
||||
build_default_value(&label, quote!{Vec<bool>}, quote!{vec![]}),
|
||||
Some(&FieldType::FieldTypeI8) =>
|
||||
build_default_value(&label, quote!{Vec<i8>}, quote!{vec![]}),
|
||||
Some(&FieldType::FieldTypeU8) =>
|
||||
build_default_value(&label, quote!{Vec<u8>}, quote!{vec![]}),
|
||||
Some(&FieldType::FieldTypeI16) =>
|
||||
build_default_value(&label, quote!{Vec<i16>}, quote!{vec![]}),
|
||||
Some(&FieldType::FieldTypeU16) =>
|
||||
build_default_value(&label, quote!{Vec<u16>}, quote!{vec![]}),
|
||||
Some(&FieldType::FieldTypeI32) =>
|
||||
build_default_value(&label, quote!{Vec<i32>}, quote!{vec![]}),
|
||||
Some(&FieldType::FieldTypeU32) =>
|
||||
build_default_value(&label, quote!{Vec<u32>}, quote!{vec![]}),
|
||||
Some(&FieldType::FieldTypeI64) =>
|
||||
build_default_value(&label, quote!{Vec<i64>}, quote!{vec![]}),
|
||||
Some(&FieldType::FieldTypeU64) =>
|
||||
build_default_value(&label, quote!{Vec<u64>}, quote!{vec![]}),
|
||||
Some(&FieldType::FieldTypeStruct{struct_name}) => {
|
||||
Some(quote!{
|
||||
#[allow(unused_mut)]
|
||||
@@ -73,23 +101,56 @@ pub fn parse(data_struct: &DataStruct, name: &Ident, root: &String, namespaces:
|
||||
|
||||
let field_visitors: Tokens = data_struct.fields.iter().map(|ref field|
|
||||
{
|
||||
let label = field.ident;
|
||||
let label_name = label.unwrap().to_string();
|
||||
let field_attrs = YaSerdeAttribute::parse(&field.attrs);
|
||||
let label_name =
|
||||
if let Some(value) = field_attrs.rename {
|
||||
Ident::new(&format!("{}", value), Span::call_site()).to_string()
|
||||
} else {
|
||||
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!{
|
||||
#[allow(non_snake_case, non_camel_case_types)]
|
||||
struct #visitor_label;
|
||||
impl<'de> Visitor<'de> for #visitor_label {
|
||||
type Value = String;
|
||||
|
||||
fn visit_str(self, v: &str) -> Result<Self::Value, String> {
|
||||
Ok(String::from(v))
|
||||
}
|
||||
}
|
||||
})
|
||||
let visitor = Ident::new("visit_str", Span::call_site());
|
||||
build_declare_visitor(quote!{String}, &visitor, &visitor_label)
|
||||
},
|
||||
Some(FieldType::FieldTypeBool) => {
|
||||
let visitor = Ident::new("visit_bool", Span::call_site());
|
||||
build_declare_visitor(quote!{bool}, &visitor, &visitor_label)
|
||||
},
|
||||
Some(FieldType::FieldTypeI8) => {
|
||||
let visitor = Ident::new("visit_i8", Span::call_site());
|
||||
build_declare_visitor(quote!{i8}, &visitor, &visitor_label)
|
||||
},
|
||||
Some(FieldType::FieldTypeU8) => {
|
||||
let visitor = Ident::new("visit_u8", Span::call_site());
|
||||
build_declare_visitor(quote!{u8}, &visitor, &visitor_label)
|
||||
},
|
||||
Some(FieldType::FieldTypeI16) => {
|
||||
let visitor = Ident::new("visit_i16", Span::call_site());
|
||||
build_declare_visitor(quote!{i16}, &visitor, &visitor_label)
|
||||
},
|
||||
Some(FieldType::FieldTypeU16) => {
|
||||
let visitor = Ident::new("visit_u16", Span::call_site());
|
||||
build_declare_visitor(quote!{u16}, &visitor, &visitor_label)
|
||||
},
|
||||
Some(FieldType::FieldTypeI32) => {
|
||||
let visitor = Ident::new("visit_i32", Span::call_site());
|
||||
build_declare_visitor(quote!{i32}, &visitor, &visitor_label)
|
||||
},
|
||||
Some(FieldType::FieldTypeU32) => {
|
||||
let visitor = Ident::new("visit_u32", Span::call_site());
|
||||
build_declare_visitor(quote!{u32}, &visitor, &visitor_label)
|
||||
},
|
||||
Some(FieldType::FieldTypeI64) => {
|
||||
let visitor = Ident::new("visit_i64", Span::call_site());
|
||||
build_declare_visitor(quote!{i64}, &visitor, &visitor_label)
|
||||
},
|
||||
Some(FieldType::FieldTypeU64) => {
|
||||
let visitor = Ident::new("visit_u64", Span::call_site());
|
||||
build_declare_visitor(quote!{u64}, &visitor, &visitor_label)
|
||||
},
|
||||
Some(FieldType::FieldTypeStruct{struct_name}) => {
|
||||
let struct_id = struct_name.to_string();
|
||||
@@ -113,17 +174,44 @@ pub fn parse(data_struct: &DataStruct, name: &Ident, root: &String, namespaces:
|
||||
let dt = Box::into_raw(data_type);
|
||||
match unsafe{dt.as_ref()} {
|
||||
Some(&FieldType::FieldTypeString) => {
|
||||
Some(quote!{
|
||||
#[allow(non_snake_case, non_camel_case_types)]
|
||||
struct #visitor_label;
|
||||
impl<'de> Visitor<'de> for #visitor_label {
|
||||
type Value = String;
|
||||
|
||||
fn visit_str(self, v: &str) -> Result<Self::Value, String> {
|
||||
Ok(String::from(v))
|
||||
}
|
||||
}
|
||||
})
|
||||
let visitor = Ident::new("visit_str", Span::call_site());
|
||||
build_declare_visitor(quote!{String}, &visitor, &visitor_label)
|
||||
}
|
||||
Some(&FieldType::FieldTypeBool) => {
|
||||
let visitor = Ident::new("visit_bool", Span::call_site());
|
||||
build_declare_visitor(quote!{bool}, &visitor, &visitor_label)
|
||||
}
|
||||
Some(&FieldType::FieldTypeI8) => {
|
||||
let visitor = Ident::new("visit_i8", Span::call_site());
|
||||
build_declare_visitor(quote!{i8}, &visitor, &visitor_label)
|
||||
}
|
||||
Some(&FieldType::FieldTypeU8) => {
|
||||
let visitor = Ident::new("visit_u8", Span::call_site());
|
||||
build_declare_visitor(quote!{u8}, &visitor, &visitor_label)
|
||||
}
|
||||
Some(&FieldType::FieldTypeI16) => {
|
||||
let visitor = Ident::new("visit_i16", Span::call_site());
|
||||
build_declare_visitor(quote!{i16}, &visitor, &visitor_label)
|
||||
}
|
||||
Some(&FieldType::FieldTypeU16) => {
|
||||
let visitor = Ident::new("visit_u16", Span::call_site());
|
||||
build_declare_visitor(quote!{u16}, &visitor, &visitor_label)
|
||||
}
|
||||
Some(&FieldType::FieldTypeI32) => {
|
||||
let visitor = Ident::new("visit_i32", Span::call_site());
|
||||
build_declare_visitor(quote!{i32}, &visitor, &visitor_label)
|
||||
}
|
||||
Some(&FieldType::FieldTypeU32) => {
|
||||
let visitor = Ident::new("visit_u32", Span::call_site());
|
||||
build_declare_visitor(quote!{u32}, &visitor, &visitor_label)
|
||||
}
|
||||
Some(&FieldType::FieldTypeI64) => {
|
||||
let visitor = Ident::new("visit_i64", Span::call_site());
|
||||
build_declare_visitor(quote!{i64}, &visitor, &visitor_label)
|
||||
}
|
||||
Some(&FieldType::FieldTypeU64) => {
|
||||
let visitor = Ident::new("visit_u64", Span::call_site());
|
||||
build_declare_visitor(quote!{u64}, &visitor, &visitor_label)
|
||||
}
|
||||
Some(&FieldType::FieldTypeStruct{struct_name}) => {
|
||||
let struct_ident = Ident::new(&format!("{}", struct_name), Span::def_site());
|
||||
@@ -167,31 +255,44 @@ pub fn parse(data_struct: &DataStruct, name: &Ident, root: &String, namespaces:
|
||||
|
||||
match get_field_type(field) {
|
||||
Some(FieldType::FieldTypeString) => {
|
||||
Some(quote!{
|
||||
#label_name => {
|
||||
let visitor = #visitor_label{};
|
||||
|
||||
if let XmlEvent::StartElement { .. } = *reader.peek()? {
|
||||
reader.set_map_value()
|
||||
}
|
||||
|
||||
let result = reader.read_inner_value::<String, _>(|reader| {
|
||||
if let XmlEvent::EndElement { .. } = *reader.peek()? {
|
||||
return visitor.visit_str("");
|
||||
}
|
||||
|
||||
if let Ok(XmlEvent::Characters(s)) = reader.next() {
|
||||
visitor.visit_str(&s)
|
||||
} else {
|
||||
Err(format!("unable to parse content for {}", #label_name))
|
||||
}
|
||||
});
|
||||
|
||||
if let Ok(value) = result {
|
||||
#label = value
|
||||
}
|
||||
}
|
||||
})
|
||||
let visitor = Ident::new("visit_str", Span::call_site());
|
||||
build_call_visitor(quote!{String}, &visitor, quote!{= value}, &visitor_label, &label, &label_name)
|
||||
},
|
||||
Some(FieldType::FieldTypeBool) => {
|
||||
let visitor = Ident::new("visit_bool", Span::call_site());
|
||||
build_call_visitor(quote!{bool}, &visitor, quote!{= value}, &visitor_label, &label, &label_name)
|
||||
},
|
||||
Some(FieldType::FieldTypeI8) => {
|
||||
let visitor = Ident::new("visit_i8", Span::call_site());
|
||||
build_call_visitor(quote!{i8}, &visitor, quote!{= value}, &visitor_label, &label, &label_name)
|
||||
},
|
||||
Some(FieldType::FieldTypeU8) => {
|
||||
let visitor = Ident::new("visit_u8", Span::call_site());
|
||||
build_call_visitor(quote!{u8}, &visitor, quote!{= value}, &visitor_label, &label, &label_name)
|
||||
},
|
||||
Some(FieldType::FieldTypeU16) => {
|
||||
let visitor = Ident::new("visit_u16", Span::call_site());
|
||||
build_call_visitor(quote!{u16}, &visitor, quote!{= value}, &visitor_label, &label, &label_name)
|
||||
},
|
||||
Some(FieldType::FieldTypeI16) => {
|
||||
let visitor = Ident::new("visit_i16", Span::call_site());
|
||||
build_call_visitor(quote!{i16}, &visitor, quote!{= value}, &visitor_label, &label, &label_name)
|
||||
},
|
||||
Some(FieldType::FieldTypeU32) => {
|
||||
let visitor = Ident::new("visit_u32", Span::call_site());
|
||||
build_call_visitor(quote!{u32}, &visitor, quote!{= value}, &visitor_label, &label, &label_name)
|
||||
},
|
||||
Some(FieldType::FieldTypeI32) => {
|
||||
let visitor = Ident::new("visit_i32", Span::call_site());
|
||||
build_call_visitor(quote!{i32}, &visitor, quote!{= value}, &visitor_label, &label, &label_name)
|
||||
},
|
||||
Some(FieldType::FieldTypeU64) => {
|
||||
let visitor = Ident::new("visit_u64", Span::call_site());
|
||||
build_call_visitor(quote!{u64}, &visitor, quote!{= value}, &visitor_label, &label, &label_name)
|
||||
},
|
||||
Some(FieldType::FieldTypeI64) => {
|
||||
let visitor = Ident::new("visit_i64", Span::call_site());
|
||||
build_call_visitor(quote!{i64}, &visitor, quote!{= value}, &visitor_label, &label, &label_name)
|
||||
},
|
||||
Some(FieldType::FieldTypeStruct{struct_name}) => {
|
||||
Some(quote!{
|
||||
@@ -213,30 +314,44 @@ pub fn parse(data_struct: &DataStruct, name: &Ident, root: &String, namespaces:
|
||||
let dt = Box::into_raw(data_type);
|
||||
match unsafe{dt.as_ref()} {
|
||||
Some(&FieldType::FieldTypeString) => {
|
||||
Some(quote!{
|
||||
#label_name => {
|
||||
let visitor = #visitor_label{};
|
||||
if let XmlEvent::StartElement { .. } = *reader.peek()? {
|
||||
reader.set_map_value()
|
||||
}
|
||||
|
||||
let result = reader.read_inner_value::<String, _>(|reader| {
|
||||
if let XmlEvent::EndElement { .. } = *reader.peek()? {
|
||||
return visitor.visit_str("");
|
||||
}
|
||||
|
||||
if let Ok(XmlEvent::Characters(s)) = reader.next() {
|
||||
visitor.visit_str(&s)
|
||||
} else {
|
||||
Err(format!("unable to parse content for {}", #label_name))
|
||||
}
|
||||
});
|
||||
|
||||
if let Ok(value) = result {
|
||||
#label.push(value)
|
||||
}
|
||||
}
|
||||
})
|
||||
let visitor = Ident::new("visit_str", Span::call_site());
|
||||
build_call_visitor(quote!{String}, &visitor, quote!{.push(value)}, &visitor_label, &label, &label_name)
|
||||
}
|
||||
Some(&FieldType::FieldTypeBool) => {
|
||||
let visitor = Ident::new("visit_bool", Span::call_site());
|
||||
build_call_visitor(quote!{bool}, &visitor, quote!{.push(value)}, &visitor_label, &label, &label_name)
|
||||
}
|
||||
Some(&FieldType::FieldTypeI8) => {
|
||||
let visitor = Ident::new("visit_i8", Span::call_site());
|
||||
build_call_visitor(quote!{i8}, &visitor, quote!{.push(value)}, &visitor_label, &label, &label_name)
|
||||
}
|
||||
Some(&FieldType::FieldTypeU8) => {
|
||||
let visitor = Ident::new("visit_u8", Span::call_site());
|
||||
build_call_visitor(quote!{u8}, &visitor, quote!{.push(value)}, &visitor_label, &label, &label_name)
|
||||
}
|
||||
Some(&FieldType::FieldTypeI16) => {
|
||||
let visitor = Ident::new("visit_i16", Span::call_site());
|
||||
build_call_visitor(quote!{i16}, &visitor, quote!{.push(value)}, &visitor_label, &label, &label_name)
|
||||
}
|
||||
Some(&FieldType::FieldTypeU16) => {
|
||||
let visitor = Ident::new("visit_u16", Span::call_site());
|
||||
build_call_visitor(quote!{u16}, &visitor, quote!{.push(value)}, &visitor_label, &label, &label_name)
|
||||
}
|
||||
Some(&FieldType::FieldTypeI32) => {
|
||||
let visitor = Ident::new("visit_i32", Span::call_site());
|
||||
build_call_visitor(quote!{i32}, &visitor, quote!{.push(value)}, &visitor_label, &label, &label_name)
|
||||
}
|
||||
Some(&FieldType::FieldTypeU32) => {
|
||||
let visitor = Ident::new("visit_u32", Span::call_site());
|
||||
build_call_visitor(quote!{u32}, &visitor, quote!{.push(value)}, &visitor_label, &label, &label_name)
|
||||
}
|
||||
Some(&FieldType::FieldTypeI64) => {
|
||||
let visitor = Ident::new("visit_i64", Span::call_site());
|
||||
build_call_visitor(quote!{i64}, &visitor, quote!{.push(value)}, &visitor_label, &label, &label_name)
|
||||
}
|
||||
Some(&FieldType::FieldTypeU64) => {
|
||||
let visitor = Ident::new("visit_u64", Span::call_site());
|
||||
build_call_visitor(quote!{u64}, &visitor, quote!{.push(value)}, &visitor_label, &label, &label_name)
|
||||
}
|
||||
Some(&FieldType::FieldTypeStruct{struct_name}) => {
|
||||
let struct_ident = Ident::new(&format!("{}", struct_name), Span::def_site());
|
||||
@@ -272,7 +387,6 @@ pub fn parse(data_struct: &DataStruct, name: &Ident, root: &String, namespaces:
|
||||
}
|
||||
|
||||
let label = field.ident;
|
||||
let field_ident = field.ident.unwrap().to_string();
|
||||
let label_name =
|
||||
if let Some(value) = field_attrs.rename {
|
||||
Ident::new(&format!("{}", value), Span::call_site()).to_string()
|
||||
@@ -291,7 +405,7 @@ pub fn parse(data_struct: &DataStruct, name: &Ident, root: &String, namespaces:
|
||||
})
|
||||
}
|
||||
Some(FieldType::FieldTypeStruct{struct_name}) => {
|
||||
let struct_ident = Ident::new(&format!("__Visitor_{}_{}", field_ident, struct_name), Span::call_site());
|
||||
let struct_ident = Ident::new(&format!("__Visitor_{}_{}", label_name, struct_name), Span::call_site());
|
||||
|
||||
Some(quote!{
|
||||
for attr in attributes {
|
||||
@@ -319,15 +433,27 @@ pub fn parse(data_struct: &DataStruct, name: &Ident, root: &String, namespaces:
|
||||
let field_attrs = YaSerdeAttribute::parse(&field.attrs);
|
||||
|
||||
match get_field_type(field) {
|
||||
Some(FieldType::FieldTypeString) => {
|
||||
if field_attrs.text {
|
||||
Some(quote!{
|
||||
#label = text_content.to_owned();
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
Some(FieldType::FieldTypeString) =>
|
||||
build_set_text_to_value(&field_attrs, &label, quote!{text_content.to_owned()}),
|
||||
Some(FieldType::FieldTypeBool) =>
|
||||
build_set_text_to_value(&field_attrs, &label, quote!{bool::from_str(text_content).unwrap()}),
|
||||
Some(FieldType::FieldTypeI8) =>
|
||||
build_set_text_to_value(&field_attrs, &label, quote!{i8::from_str(text_content).unwrap()}),
|
||||
Some(FieldType::FieldTypeU8) =>
|
||||
build_set_text_to_value(&field_attrs, &label, quote!{u8::from_str(text_content).unwrap()}),
|
||||
Some(FieldType::FieldTypeI16) =>
|
||||
build_set_text_to_value(&field_attrs, &label, quote!{i16::from_str(text_content).unwrap()}),
|
||||
Some(FieldType::FieldTypeU16) =>
|
||||
build_set_text_to_value(&field_attrs, &label, quote!{u16::from_str(text_content).unwrap()}),
|
||||
Some(FieldType::FieldTypeI32) =>
|
||||
build_set_text_to_value(&field_attrs, &label, quote!{i32::from_str(text_content).unwrap()}),
|
||||
Some(FieldType::FieldTypeU32) =>
|
||||
build_set_text_to_value(&field_attrs, &label, quote!{u32::from_str(text_content).unwrap()}),
|
||||
Some(FieldType::FieldTypeI64) =>
|
||||
build_set_text_to_value(&field_attrs, &label, quote!{i64::from_str(text_content).unwrap()}),
|
||||
Some(FieldType::FieldTypeU64) =>
|
||||
build_set_text_to_value(&field_attrs, &label, quote!{u64::from_str(text_content).unwrap()}),
|
||||
|
||||
Some(FieldType::FieldTypeStruct{..}) |
|
||||
Some(FieldType::FieldTypeVec{..})|
|
||||
None => None,
|
||||
@@ -341,14 +467,12 @@ pub fn parse(data_struct: &DataStruct, name: &Ident, root: &String, namespaces:
|
||||
{
|
||||
let label = field.ident;
|
||||
|
||||
match get_field_type(field) {
|
||||
Some(FieldType::FieldTypeString) |
|
||||
Some(FieldType::FieldTypeStruct{..}) |
|
||||
Some(FieldType::FieldTypeVec{..}) =>
|
||||
Some(quote!{
|
||||
#label: #label,
|
||||
}),
|
||||
None => None,
|
||||
if get_field_type(field).is_some() {
|
||||
Some(quote!{
|
||||
#label: #label,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.filter(|x| x.is_some())
|
||||
@@ -358,6 +482,8 @@ pub fn parse(data_struct: &DataStruct, name: &Ident, root: &String, namespaces:
|
||||
quote! {
|
||||
use xml::reader::XmlEvent;
|
||||
use yaserde::Visitor;
|
||||
#[allow(unknown_lints, unused_imports)]
|
||||
use std::str::FromStr;
|
||||
|
||||
impl YaDeserialize for #name {
|
||||
#[allow(unused_variables)]
|
||||
@@ -410,3 +536,64 @@ pub fn parse(data_struct: &DataStruct, name: &Ident, root: &String, namespaces:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn build_default_value(label: &Option<Ident>, field_type: Tokens, default: Tokens) -> Option<Tokens> {
|
||||
Some(quote!{
|
||||
#[allow(unused_mut)]
|
||||
let mut #label : #field_type = #default;
|
||||
})
|
||||
}
|
||||
|
||||
fn build_declare_visitor(field_type: Tokens, visitor: &Ident, visitor_label: &Ident) -> Option<Tokens> {
|
||||
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> {
|
||||
Ok(#field_type::from_str(v).unwrap())
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn build_call_visitor(field_type: Tokens, visitor: &Ident, action: Tokens, visitor_label: &Ident, label: &Option<Ident>, label_name: &String) -> Option<Tokens> {
|
||||
Some(quote!{
|
||||
#label_name => {
|
||||
let visitor = #visitor_label{};
|
||||
|
||||
if let XmlEvent::StartElement { .. } = *reader.peek()? {
|
||||
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() {
|
||||
visitor.#visitor(&s)
|
||||
} else {
|
||||
Err(format!("unable to parse content for {}", #label_name))
|
||||
}
|
||||
});
|
||||
|
||||
if let Ok(value) = result {
|
||||
// #label = value
|
||||
#label#action
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
fn build_set_text_to_value(field_attrs: &YaSerdeAttribute, label: &Option<Ident>, action: Tokens) -> Option<Tokens> {
|
||||
if field_attrs.text {
|
||||
Some(quote!{
|
||||
#label = #action;
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,15 @@ use syn::Type::Path;
|
||||
#[derive(Debug)]
|
||||
pub enum FieldType {
|
||||
FieldTypeString,
|
||||
FieldTypeBool,
|
||||
FieldTypeI8,
|
||||
FieldTypeU8,
|
||||
FieldTypeI16,
|
||||
FieldTypeU16,
|
||||
FieldTypeI32,
|
||||
FieldTypeU32,
|
||||
FieldTypeI64,
|
||||
FieldTypeU64,
|
||||
FieldTypeVec{data_type: Box<FieldType>},
|
||||
FieldTypeStruct{struct_name: syn::Ident},
|
||||
}
|
||||
@@ -14,6 +23,15 @@ impl FieldType {
|
||||
fn from_ident(t: &syn::PathSegment) -> Option<FieldType> {
|
||||
match t.ident.as_ref() {
|
||||
"String" => Some(FieldType::FieldTypeString),
|
||||
"bool" => Some(FieldType::FieldTypeBool),
|
||||
"i8" => Some(FieldType::FieldTypeI8),
|
||||
"u8" => Some(FieldType::FieldTypeU8),
|
||||
"i16" => Some(FieldType::FieldTypeI16),
|
||||
"u16" => Some(FieldType::FieldTypeU16),
|
||||
"i32" => Some(FieldType::FieldTypeI32),
|
||||
"u32" => Some(FieldType::FieldTypeU32),
|
||||
"i64" => Some(FieldType::FieldTypeI64),
|
||||
"u64" => Some(FieldType::FieldTypeU64),
|
||||
"Vec" => {
|
||||
get_vec_type(t).map(|data_type| {
|
||||
let p = syn::PathSegment{
|
||||
|
||||
@@ -30,11 +30,20 @@ pub fn serialize(data_struct: &DataStruct, name: &Ident, root: &String, namespac
|
||||
};
|
||||
|
||||
match get_field_type(field) {
|
||||
Some(FieldType::FieldTypeString) =>
|
||||
Some(FieldType::FieldTypeString) |
|
||||
Some(FieldType::FieldTypeBool) |
|
||||
Some(FieldType::FieldTypeI8) |
|
||||
Some(FieldType::FieldTypeU8) |
|
||||
Some(FieldType::FieldTypeI16) |
|
||||
Some(FieldType::FieldTypeU16) |
|
||||
Some(FieldType::FieldTypeI32) |
|
||||
Some(FieldType::FieldTypeU32) |
|
||||
Some(FieldType::FieldTypeI64) |
|
||||
Some(FieldType::FieldTypeU64) =>
|
||||
Some(quote!{
|
||||
.attr(#label_name, &self.#label)
|
||||
}),
|
||||
Some(FieldType::FieldTypeStruct{struct_name: _struct_name}) =>
|
||||
Some(FieldType::FieldTypeStruct{..}) =>
|
||||
Some(quote!{
|
||||
.attr(#label_name, &*{
|
||||
use std::mem;
|
||||
@@ -108,21 +117,35 @@ pub fn serialize(data_struct: &DataStruct, name: &Ident, root: &String, namespac
|
||||
let end_event = XmlEvent::end_element();
|
||||
let _ret = writer.write(end_event);
|
||||
}),
|
||||
Some(FieldType::FieldTypeStruct{..}) =>
|
||||
Some(FieldType::FieldTypeBool) |
|
||||
Some(FieldType::FieldTypeI8) |
|
||||
Some(FieldType::FieldTypeU8) |
|
||||
Some(FieldType::FieldTypeI16) |
|
||||
Some(FieldType::FieldTypeU16) |
|
||||
Some(FieldType::FieldTypeI32) |
|
||||
Some(FieldType::FieldTypeU32) |
|
||||
Some(FieldType::FieldTypeI64) |
|
||||
Some(FieldType::FieldTypeU64) =>
|
||||
Some(quote!{
|
||||
let start_event = XmlEvent::start_element(#label_name);
|
||||
let _ret = writer.write(start_event);
|
||||
|
||||
writer.set_skip_start_end(true);
|
||||
let content = format!("{}", &self.#label);
|
||||
let data_event = XmlEvent::characters(&content);
|
||||
let _ret = writer.write(data_event);
|
||||
|
||||
let end_event = XmlEvent::end_element();
|
||||
let _ret = writer.write(end_event);
|
||||
}),
|
||||
Some(FieldType::FieldTypeStruct{..}) =>
|
||||
Some(quote!{
|
||||
writer.set_skip_start_end(false);
|
||||
match self.#label.serialize(writer) {
|
||||
Ok(()) => {},
|
||||
Err(msg) => {
|
||||
return Err(msg);
|
||||
},
|
||||
};
|
||||
|
||||
let struct_end_event = XmlEvent::end_element();
|
||||
let _ret = writer.write(struct_end_event);
|
||||
}),
|
||||
Some(FieldType::FieldTypeVec{data_type}) => {
|
||||
let dt = Box::into_raw(data_type);
|
||||
@@ -141,12 +164,30 @@ pub fn serialize(data_struct: &DataStruct, name: &Ident, root: &String, namespac
|
||||
}
|
||||
})
|
||||
},
|
||||
Some(&FieldType::FieldTypeBool) |
|
||||
Some(&FieldType::FieldTypeI8) |
|
||||
Some(&FieldType::FieldTypeU8) |
|
||||
Some(&FieldType::FieldTypeI16) |
|
||||
Some(&FieldType::FieldTypeU16) |
|
||||
Some(&FieldType::FieldTypeI32) |
|
||||
Some(&FieldType::FieldTypeU32) |
|
||||
Some(&FieldType::FieldTypeI64) |
|
||||
Some(&FieldType::FieldTypeU64) => {
|
||||
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(format!("{}", item));
|
||||
let _ret = writer.write(data_event);
|
||||
|
||||
let end_event = XmlEvent::end_element();
|
||||
let _ret = writer.write(end_event);
|
||||
}
|
||||
})
|
||||
},
|
||||
Some(&FieldType::FieldTypeStruct{..}) => {
|
||||
Some(quote!{
|
||||
|
||||
let start_event = XmlEvent::start_element(#label_name);
|
||||
let _ret = writer.write(start_event);
|
||||
|
||||
for item in &self.#label {
|
||||
writer.set_skip_start_end(false);
|
||||
match item.serialize(writer) {
|
||||
@@ -156,8 +197,6 @@ pub fn serialize(data_struct: &DataStruct, name: &Ident, root: &String, namespac
|
||||
},
|
||||
};
|
||||
}
|
||||
let end_event = XmlEvent::end_element();
|
||||
let _ret = writer.write(end_event);
|
||||
})
|
||||
},
|
||||
Some(&FieldType::FieldTypeVec{..}) => {unimplemented!();},
|
||||
|
||||
Reference in New Issue
Block a user