support type de/ser-rialization
This commit is contained in:
parent
7a6ae6e6fe
commit
a88f6535f4
@ -25,6 +25,51 @@ pub trait Visitor<'de>: Sized {
|
||||
/// The value produced by this visitor.
|
||||
type Value;
|
||||
|
||||
fn visit_bool(self, v: &str) -> Result<Self::Value, String>
|
||||
{
|
||||
Err(format!("Unexpected bool {}", v))
|
||||
}
|
||||
|
||||
fn visit_i8(self, v: &str) -> Result<Self::Value, String>
|
||||
{
|
||||
Err(format!("Unexpected i8 {}", v))
|
||||
}
|
||||
|
||||
fn visit_u8(self, v: &str) -> Result<Self::Value, String>
|
||||
{
|
||||
Err(format!("Unexpected u8 {}", v))
|
||||
}
|
||||
|
||||
fn visit_i16(self, v: &str) -> Result<Self::Value, String>
|
||||
{
|
||||
Err(format!("Unexpected i16 {}", v))
|
||||
}
|
||||
|
||||
fn visit_u16(self, v: &str) -> Result<Self::Value, String>
|
||||
{
|
||||
Err(format!("Unexpected u16 {}", v))
|
||||
}
|
||||
|
||||
fn visit_i32(self, v: &str) -> Result<Self::Value, String>
|
||||
{
|
||||
Err(format!("Unexpected i32 {}", v))
|
||||
}
|
||||
|
||||
fn visit_u32(self, v: &str) -> Result<Self::Value, String>
|
||||
{
|
||||
Err(format!("Unexpected u32 {}", v))
|
||||
}
|
||||
|
||||
fn visit_i64(self, v: &str) -> Result<Self::Value, String>
|
||||
{
|
||||
Err(format!("Unexpected i64 {}", v))
|
||||
}
|
||||
|
||||
fn visit_u64(self, v: &str) -> Result<Self::Value, String>
|
||||
{
|
||||
Err(format!("Unexpected u64 {}", v))
|
||||
}
|
||||
|
||||
fn visit_str(self, v: &str) -> Result<Self::Value, String>
|
||||
{
|
||||
Err(format!("Unexpected str {}", v))
|
||||
@ -54,11 +99,13 @@ macro_rules! serialize_type {
|
||||
serialize_type!(bool);
|
||||
serialize_type!(char);
|
||||
|
||||
serialize_type!(usize);
|
||||
serialize_type!(u8);
|
||||
serialize_type!(u16);
|
||||
serialize_type!(u32);
|
||||
serialize_type!(u64);
|
||||
|
||||
serialize_type!(isize);
|
||||
serialize_type!(i8);
|
||||
serialize_type!(i16);
|
||||
serialize_type!(i32);
|
||||
@ -66,4 +113,3 @@ serialize_type!(i64);
|
||||
|
||||
serialize_type!(f32);
|
||||
serialize_type!(f64);
|
||||
|
||||
|
||||
48
yaserde/tests/der_type.rs
Normal file
48
yaserde/tests/der_type.rs
Normal file
@ -0,0 +1,48 @@
|
||||
|
||||
extern crate yaserde;
|
||||
#[macro_use]
|
||||
extern crate yaserde_derive;
|
||||
extern crate xml;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
use std::io::Read;
|
||||
use yaserde::YaDeserialize;
|
||||
use yaserde::de::from_str;
|
||||
|
||||
macro_rules! convert_and_validate {
|
||||
($type:ty, $value:expr, $content:expr) => ({
|
||||
|
||||
#[derive(YaDeserialize, PartialEq, Debug)]
|
||||
#[yaserde(root="data")]
|
||||
pub struct Data {
|
||||
item: $type
|
||||
}
|
||||
|
||||
let model = Data {
|
||||
item: $value
|
||||
};
|
||||
|
||||
let content = String::from("<?xml version=\"1.0\" encoding=\"utf-8\"?><data><item>") + $content + "</item></data>";
|
||||
|
||||
let loaded : Result<Data, String> = from_str(&content);
|
||||
assert_eq!(loaded, Ok(model));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn de_type() {
|
||||
convert_and_validate!(bool, true, "true");
|
||||
convert_and_validate!(u8, 12 as u8, "12");
|
||||
convert_and_validate!(i8, 12 as i8, "12");
|
||||
convert_and_validate!(i8, -12 as i8, "-12");
|
||||
convert_and_validate!(u16, 12 as u16, "12");
|
||||
convert_and_validate!(i16, 12 as i16, "12");
|
||||
convert_and_validate!(i16, -12 as i16, "-12");
|
||||
convert_and_validate!(u32, 12 as u32, "12");
|
||||
convert_and_validate!(i32, 12 as i32, "12");
|
||||
convert_and_validate!(i32, -12 as i32, "-12");
|
||||
convert_and_validate!(u64, 12 as u64, "12");
|
||||
convert_and_validate!(i64, 12 as i64, "12");
|
||||
convert_and_validate!(i64, -12 as i64, "-12");
|
||||
}
|
||||
46
yaserde/tests/se_type.rs
Normal file
46
yaserde/tests/se_type.rs
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
extern crate yaserde;
|
||||
#[macro_use]
|
||||
extern crate yaserde_derive;
|
||||
extern crate xml;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
use std::io::Write;
|
||||
use yaserde::YaSerialize;
|
||||
use yaserde::ser::to_string;
|
||||
|
||||
macro_rules! convert_and_validate {
|
||||
($type:ty, $value:expr, $content:expr) => ({
|
||||
|
||||
#[derive(YaSerialize, PartialEq, Debug)]
|
||||
#[yaserde(root="data")]
|
||||
pub struct Data {
|
||||
item: $type
|
||||
}
|
||||
let model = Data {
|
||||
item: $value
|
||||
};
|
||||
|
||||
let data : Result<String, String> = to_string(&model);
|
||||
let content = String::from("<?xml version=\"1.0\" encoding=\"utf-8\"?><data><item>") + $content + "</item></data>";
|
||||
assert_eq!(data, Ok(content));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ser_type() {
|
||||
convert_and_validate!(bool, true, "true");
|
||||
convert_and_validate!(u8, 12 as u8, "12");
|
||||
convert_and_validate!(i8, 12 as i8, "12");
|
||||
convert_and_validate!(i8, -12 as i8, "-12");
|
||||
convert_and_validate!(u16, 12 as u16, "12");
|
||||
convert_and_validate!(i16, 12 as i16, "12");
|
||||
convert_and_validate!(i16, -12 as i16, "-12");
|
||||
convert_and_validate!(u32, 12 as u32, "12");
|
||||
convert_and_validate!(i32, 12 as i32, "12");
|
||||
convert_and_validate!(i32, -12 as i32, "-12");
|
||||
convert_and_validate!(u64, 12 as u64, "12");
|
||||
convert_and_validate!(i64, 12 as i64, "12");
|
||||
convert_and_validate!(i64, -12 as i64, "-12");
|
||||
}
|
||||
@ -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!();},
|
||||
|
||||
Loading…
Reference in New Issue
Block a user