refactoring code to better support
This commit is contained in:
@@ -19,11 +19,13 @@ pub fn parse(data_enum: &DataEnum, name: &Ident, root: &String) -> Tokens {
|
||||
match get_field_type(field) {
|
||||
Some(FieldType::FieldTypeString) => {
|
||||
Some(quote!{
|
||||
#[allow(unused_mut)]
|
||||
let mut #field_label : String = "".to_string();
|
||||
})
|
||||
},
|
||||
Some(FieldType::FieldTypeStruct{struct_name}) => {
|
||||
Some(quote!{
|
||||
#[allow(unused_mut)]
|
||||
let mut #field_label : #struct_name = #struct_name::default();
|
||||
})
|
||||
},
|
||||
@@ -32,11 +34,13 @@ pub fn parse(data_enum: &DataEnum, name: &Ident, root: &String) -> Tokens {
|
||||
match unsafe{dt.as_ref()} {
|
||||
Some(&FieldType::FieldTypeString) => {
|
||||
Some(quote!{
|
||||
#[allow(unused_mut)]
|
||||
let mut #field_label : Vec<String> = vec![];
|
||||
})
|
||||
},
|
||||
Some(&FieldType::FieldTypeStruct{struct_name}) => {
|
||||
Some(quote!{
|
||||
#[allow(unused_mut)]
|
||||
let mut #field_label : Vec<#struct_name> = vec![];
|
||||
})
|
||||
},
|
||||
@@ -63,113 +67,43 @@ pub fn parse(data_enum: &DataEnum, name: &Ident, root: &String) -> Tokens {
|
||||
.map(|x| x.unwrap())
|
||||
.fold(Tokens::new(), |mut sum, val| {sum.append_all(val); sum});
|
||||
|
||||
let fields : Tokens = data_enum.variants.iter().map(|ref variant|
|
||||
{
|
||||
let variant_attrs = YaSerdeAttribute::parse(&variant.attrs);
|
||||
let renamed_variant_label =
|
||||
match variant_attrs.rename {
|
||||
Some(value) => Ident::new(&format!("{}", value), Span::call_site()),
|
||||
None => variant.ident
|
||||
};
|
||||
let variant_label_name = renamed_variant_label.to_string();
|
||||
|
||||
let enum_visitors: Tokens = data_enum.variants.iter().map(|ref variant| {
|
||||
match variant.fields {
|
||||
Fields::Unit => None,
|
||||
Fields::Named(ref fields) => {
|
||||
let enum_fields = fields.named.iter().map(|ref field| {
|
||||
let field_attrs = YaSerdeAttribute::parse(&field.attrs);
|
||||
let field_label = field.ident;
|
||||
let renamed_field_label =
|
||||
match field_attrs.rename {
|
||||
Some(value) => Some(Ident::new(&format!("{}", value), Span::call_site())),
|
||||
None => field.ident
|
||||
};
|
||||
// let label = field.ident;
|
||||
// let label_name = label.unwrap().to_string();
|
||||
// let visitor_label = Ident::new(&format!("__Visitor{}", label_name), Span::call_site());
|
||||
|
||||
let field_label_name = renamed_field_label.unwrap().to_string();
|
||||
match get_field_type(field) {
|
||||
Some(FieldType::FieldTypeString) => {
|
||||
Some(quote!{
|
||||
#variant_label_name => {
|
||||
#[warn(unused_assignments)]
|
||||
let mut local_level = 0;
|
||||
let mut search_local_level = 0;
|
||||
loop{
|
||||
match read.next() {
|
||||
Ok(XmlEvent::StartElement{name, attributes, namespace: _namespace}) => {
|
||||
if name.local_name == #field_label_name {
|
||||
search_local_level += 1
|
||||
}
|
||||
local_level += 1;
|
||||
},
|
||||
Ok(XmlEvent::EndElement{name}) => {
|
||||
local_level -= 1;
|
||||
if name.local_name == #field_label_name {
|
||||
break;
|
||||
}
|
||||
},
|
||||
Ok(xml::reader::XmlEvent::Characters(characters_content)) => {
|
||||
if local_level == 1 && search_local_level == 1 {
|
||||
#field_label = characters_content.trim().to_string();
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
},
|
||||
Some(FieldType::FieldTypeStruct{struct_name: _struct_name}) => {
|
||||
println!("{:?}", field);
|
||||
Some(quote!{
|
||||
#field_label_name => {
|
||||
println!("Start to parse {:?}", #field_label_name);
|
||||
#[warn(unused_assignments)]
|
||||
let mut local_level = 0;
|
||||
let mut search_local_level = 0;
|
||||
// struct #visitor_label;
|
||||
// impl<'de> Visitor<'de> for #visitor_label {
|
||||
// type Value = String;
|
||||
|
||||
loop{
|
||||
match read.next() {
|
||||
Ok(XmlEvent::StartElement{name, attributes, namespace: _namespace}) => {
|
||||
println!("Enum: start element = {:?}", name.local_name.as_str());
|
||||
if name.local_name == #field_label_name {
|
||||
search_local_level += 1
|
||||
}
|
||||
local_level += 1;
|
||||
prev_level += 1;
|
||||
},
|
||||
Ok(XmlEvent::EndElement{name}) => {
|
||||
println!("Enum: end element = {:?}", name.local_name.as_str());
|
||||
local_level -= 1;
|
||||
if name.local_name == #field_label_name {
|
||||
break;
|
||||
}
|
||||
},
|
||||
Ok(xml::reader::XmlEvent::Characters(characters_content)) => {
|
||||
println!("Enum: found value = {:?}", characters_content);
|
||||
if local_level == 1 && search_local_level == 1 {
|
||||
println!("found value = {:?}", characters_content);
|
||||
#field_label = characters_content.trim().to_string();
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
},
|
||||
// fn visit_str(self, v: &str) -> Result<Self::Value, String> {
|
||||
// match v {
|
||||
// _ => Err("unable to match \"{}\" with enum {}", v, #label_name)
|
||||
// }
|
||||
// Ok(String::from(v))
|
||||
// }
|
||||
// }
|
||||
})
|
||||
},
|
||||
data => {
|
||||
println!("{:?}", data);
|
||||
None}
|
||||
_ => None
|
||||
}
|
||||
|
||||
})
|
||||
.filter(|x| x.is_some())
|
||||
.map(|x| x.unwrap())
|
||||
.fold(Tokens::new(), |mut sum, val| {sum.append_all(val); sum});
|
||||
|
||||
Some(enum_fields)
|
||||
},
|
||||
Fields::Unnamed(ref _fields) => {unimplemented!();}
|
||||
}
|
||||
Fields::Unnamed(ref _fields) => {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
})
|
||||
.filter(|x| x.is_some())
|
||||
@@ -195,10 +129,7 @@ pub fn parse(data_enum: &DataEnum, name: &Ident, root: &String) -> Tokens {
|
||||
}
|
||||
})
|
||||
},
|
||||
Fields::Named(ref _fields) => {
|
||||
None
|
||||
}
|
||||
Fields::Unnamed(ref _fields) => {
|
||||
_ => {
|
||||
None
|
||||
}
|
||||
}
|
||||
@@ -212,67 +143,54 @@ pub fn parse(data_enum: &DataEnum, name: &Ident, root: &String) -> Tokens {
|
||||
|
||||
impl YaDeserialize for #name {
|
||||
#[allow(unused_variables)]
|
||||
fn derive_deserialize<R: Read>(read: &mut xml::EventReader<R>, parent_attributes: Option<&Vec<xml::attribute::OwnedAttribute>>) -> Result<Self, String> {
|
||||
let mut prev_level = 0;
|
||||
let mut current_level = 0;
|
||||
#[warn(unused_assignments, unused_mut)]
|
||||
fn deserialize<R: Read>(reader: &mut yaserde::de::Deserializer<R>) -> Result<Self, String> {
|
||||
let named_element =
|
||||
if let XmlEvent::StartElement{name, ..} = reader.peek()?.to_owned() {
|
||||
name.local_name.to_owned()
|
||||
} else {
|
||||
String::from(#root)
|
||||
};
|
||||
debug!("Enum: start to parse {:?}", named_element);
|
||||
|
||||
#[allow(unused_assignments, unused_mut)]
|
||||
let mut simple_enum_value = None;
|
||||
|
||||
println!("Enum: start to parse {}", #root);
|
||||
#variables
|
||||
#enum_visitors
|
||||
|
||||
loop {
|
||||
match read.next() {
|
||||
Ok(XmlEvent::StartDocument{..}) => {
|
||||
},
|
||||
Ok(XmlEvent::EndDocument) => {
|
||||
break;
|
||||
},
|
||||
Ok(XmlEvent::StartElement{name, attributes, namespace: _namespace}) => {
|
||||
println!("Enum: {} | {} - {}: {}", #root, prev_level, current_level, name.local_name.as_str());
|
||||
if prev_level == current_level {
|
||||
match name.local_name.as_str() {
|
||||
#root => {
|
||||
let root_attributes = attributes.clone();
|
||||
let current_attributes = Some(&root_attributes);
|
||||
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();
|
||||
|
||||
current_level += 1;
|
||||
},
|
||||
#fields
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
||||
prev_level += 1;
|
||||
},
|
||||
Ok(XmlEvent::EndElement{name}) => {
|
||||
println!("CLOSE {} | {} - {}: {}", #root, prev_level, current_level, name.local_name.as_str());
|
||||
|
||||
if prev_level == current_level {
|
||||
println!("LEVEL BREAK {}", #root);
|
||||
match simple_enum_value {
|
||||
Some(value) => return Ok(value),
|
||||
None => {
|
||||
return Ok(#name::default());
|
||||
},
|
||||
}
|
||||
}
|
||||
prev_level -= 1;
|
||||
},
|
||||
Ok(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
|
||||
_ => {}
|
||||
if let XmlEvent::Characters(content) = reader.peek()?.to_owned() {
|
||||
match content.as_str() {
|
||||
#match_to_enum
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Ok(event) => {
|
||||
println!("{:?}", event);
|
||||
XmlEvent::EndElement{name} => {
|
||||
if name.local_name.as_str() == named_element {
|
||||
break;
|
||||
}
|
||||
let _root = reader.next();
|
||||
},
|
||||
Err(_msg) => {
|
||||
break;
|
||||
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 => {
|
||||
return Err(format!("unknown event {:?}", event))
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -281,7 +199,6 @@ pub fn parse(data_enum: &DataEnum, name: &Ident, root: &String) -> Tokens {
|
||||
Some(value) => Ok(value),
|
||||
None => {
|
||||
Ok(#name::default())
|
||||
// Err("unable to load Enum value".to_string())
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,17 +7,19 @@ use syn::DataStruct;
|
||||
use proc_macro2::Span;
|
||||
|
||||
pub fn parse(data_struct: &DataStruct, name: &Ident, root: &String) -> Tokens {
|
||||
let variables : Tokens = data_struct.fields.iter().map(|ref field|
|
||||
let variables: Tokens = data_struct.fields.iter().map(|ref field|
|
||||
{
|
||||
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::FieldTypeStruct{struct_name}) => {
|
||||
Some(quote!{
|
||||
#[allow(unused_mut, non_snake_case, non_camel_case_types)]
|
||||
let mut #label : #struct_name = #struct_name::default();
|
||||
})
|
||||
},
|
||||
@@ -26,11 +28,13 @@ pub fn parse(data_struct: &DataStruct, name: &Ident, root: &String) -> Tokens {
|
||||
match unsafe{dt.as_ref()} {
|
||||
Some(&FieldType::FieldTypeString) => {
|
||||
Some(quote!{
|
||||
#[allow(unused_mut)]
|
||||
let mut #label : Vec<String> = vec![];
|
||||
})
|
||||
},
|
||||
Some(&FieldType::FieldTypeStruct{struct_name}) => {
|
||||
Some(quote!{
|
||||
#[allow(unused_mut)]
|
||||
let mut #label : Vec<#struct_name> = vec![];
|
||||
})
|
||||
},
|
||||
@@ -45,114 +49,42 @@ pub fn parse(data_struct: &DataStruct, name: &Ident, root: &String) -> Tokens {
|
||||
.map(|x| x.unwrap())
|
||||
.fold(Tokens::new(), |mut sum, val| {sum.append_all(val); sum});
|
||||
|
||||
let attributes_loading: Tokens = data_struct.fields.iter().map(|ref field|
|
||||
match get_field_type(field) {
|
||||
Some(FieldType::FieldTypeString) => {
|
||||
let label = field.ident;
|
||||
let field_attrs = YaSerdeAttribute::parse(&field.attrs);
|
||||
|
||||
match (field_attrs.attribute, field_attrs.rename) {
|
||||
(true, Some(value)) => {
|
||||
let label_name = Ident::new(&format!("{}", value), Span::call_site()).to_string();
|
||||
Some(quote!{
|
||||
match current_attributes {
|
||||
Some(attributes) =>
|
||||
for attr in attributes {
|
||||
if attr.name.local_name == #label_name {
|
||||
#label = attr.value.to_owned();
|
||||
}
|
||||
},
|
||||
None => {},
|
||||
}
|
||||
})
|
||||
},
|
||||
(true, None) => {
|
||||
let label_name = field.ident.unwrap().to_string();
|
||||
Some(quote!{
|
||||
match current_attributes {
|
||||
Some(attributes) =>
|
||||
for attr in attributes {
|
||||
if attr.name.local_name == #label_name {
|
||||
#label = attr.value.to_owned();
|
||||
}
|
||||
},
|
||||
None => {},
|
||||
}
|
||||
})
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
None
|
||||
}
|
||||
})
|
||||
.filter(|x| x.is_some())
|
||||
.map(|x| x.unwrap())
|
||||
.fold(Tokens::new(), |mut sum, val| {sum.append_all(val); sum});
|
||||
|
||||
let assign_text_field: Tokens = data_struct.fields.iter().map(|ref field|
|
||||
match get_field_type(field) {
|
||||
Some(FieldType::FieldTypeString) => {
|
||||
let label = field.ident;
|
||||
let field_attrs = YaSerdeAttribute::parse(&field.attrs);
|
||||
|
||||
match field_attrs.text {
|
||||
true => {
|
||||
Some(quote!{
|
||||
#label = characters_content.to_owned();
|
||||
})
|
||||
},
|
||||
false => None
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
None
|
||||
}
|
||||
})
|
||||
.filter(|x| x.is_some())
|
||||
.map(|x| x.unwrap())
|
||||
.fold(Tokens::new(), |mut sum, val| {sum.append_all(val); sum});
|
||||
|
||||
let fields : Tokens = data_struct.fields.iter().map(|ref field|
|
||||
let field_visitors: Tokens = data_struct.fields.iter().map(|ref field|
|
||||
{
|
||||
let field_attrs = YaSerdeAttribute::parse(&field.attrs);
|
||||
let label = field.ident;
|
||||
let renamed_label =
|
||||
match field_attrs.rename {
|
||||
Some(value) => Some(Ident::new(&format!("{}", value), Span::call_site())),
|
||||
None => field.ident
|
||||
};
|
||||
let label_name = label.unwrap().to_string();
|
||||
let visitor_label = Ident::new(&format!("__Visitor{}", label_name), Span::call_site());
|
||||
|
||||
let label_name = renamed_label.unwrap().to_string();
|
||||
match get_field_type(field) {
|
||||
Some(FieldType::FieldTypeString) => {
|
||||
Some(quote!{
|
||||
#label_name => {
|
||||
match read.next() {
|
||||
Ok(xml::reader::XmlEvent::Characters(characters_content)) => {
|
||||
#label = characters_content.trim().to_string();
|
||||
},
|
||||
_ => {},
|
||||
#[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))
|
||||
}
|
||||
},
|
||||
}
|
||||
})
|
||||
},
|
||||
Some(FieldType::FieldTypeStruct{struct_name}) => {
|
||||
let struct_ident = Ident::new(&format!("{}", struct_name), Span::def_site());
|
||||
let struct_id = struct_name.to_string();
|
||||
let struct_ident = Ident::new(&format!("__Visitor_{}_{}", label_name, struct_name), Span::call_site());
|
||||
|
||||
Some(quote!{
|
||||
#label_name => {
|
||||
match #struct_ident::derive_deserialize(read, Some(&attributes)) {
|
||||
Ok(parsed_structure) => {
|
||||
prev_level -= 1;
|
||||
#label = parsed_structure;
|
||||
},
|
||||
Err(msg) => {
|
||||
return Err(msg);
|
||||
},
|
||||
#[allow(non_snake_case, non_camel_case_types)]
|
||||
struct #struct_ident;
|
||||
impl<'de> Visitor<'de> for #struct_ident {
|
||||
type Value = #struct_name;
|
||||
|
||||
fn visit_str(self, v: &str) -> Result<Self::Value, String> {
|
||||
let content = "<".to_string() + #struct_id + ">" + v + "</" + #struct_id + ">";
|
||||
let value : Result<#struct_name, String> = yaserde::de::from_str(&content);
|
||||
value
|
||||
}
|
||||
},
|
||||
}
|
||||
})
|
||||
},
|
||||
Some(FieldType::FieldTypeVec{data_type}) => {
|
||||
@@ -160,34 +92,30 @@ pub fn parse(data_struct: &DataStruct, name: &Ident, root: &String) -> Tokens {
|
||||
match unsafe{dt.as_ref()} {
|
||||
Some(&FieldType::FieldTypeString) => {
|
||||
Some(quote!{
|
||||
#label_name => {
|
||||
match read.next() {
|
||||
Ok(xml::reader::XmlEvent::Characters(characters_content)) => {
|
||||
#label.push(characters_content.trim().to_string());
|
||||
},
|
||||
_ => {},
|
||||
#[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))
|
||||
}
|
||||
},
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
Some(&FieldType::FieldTypeStruct{struct_name}) => {
|
||||
let struct_ident = Ident::new(&format!("{}", struct_name), Span::def_site());
|
||||
Some(quote!{
|
||||
#label_name => {
|
||||
match #struct_ident::derive_deserialize(read, Some(&attributes)) {
|
||||
Ok(parsed_item) => {
|
||||
prev_level -= 1;
|
||||
#label.push(parsed_item);
|
||||
},
|
||||
Err(msg) => {
|
||||
return Err(msg);
|
||||
},
|
||||
}
|
||||
},
|
||||
#[allow(non_snake_case, non_camel_case_types)]
|
||||
struct #visitor_label;
|
||||
impl<'de> Visitor<'de> for #visitor_label {
|
||||
type Value = #struct_ident;
|
||||
}
|
||||
})
|
||||
},
|
||||
Some(&FieldType::FieldTypeVec{..}) => {unimplemented!();},
|
||||
None => {unimplemented!();},
|
||||
}
|
||||
_ => {
|
||||
None
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => None
|
||||
@@ -197,7 +125,197 @@ pub fn parse(data_struct: &DataStruct, name: &Ident, root: &String) -> Tokens {
|
||||
.map(|x| x.unwrap())
|
||||
.fold(Tokens::new(), |mut sum, val| {sum.append_all(val); sum});
|
||||
|
||||
let struct_builder : Tokens = data_struct.fields.iter().map(|ref field|
|
||||
let call_visitors: Tokens = data_struct.fields.iter().map(|ref field|
|
||||
{
|
||||
let field_attrs = YaSerdeAttribute::parse(&field.attrs);
|
||||
let label = field.ident;
|
||||
|
||||
if field_attrs.attribute {
|
||||
return None;
|
||||
}
|
||||
|
||||
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!{
|
||||
#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
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
Some(FieldType::FieldTypeStruct{struct_name}) => {
|
||||
Some(quote!{
|
||||
#label_name => {
|
||||
reader.set_map_value();
|
||||
match #struct_name::deserialize(reader) {
|
||||
Ok(parsed_item) => {
|
||||
#label = parsed_item;
|
||||
let _root = reader.next();
|
||||
},
|
||||
Err(msg) => {
|
||||
return Err(msg);
|
||||
},
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
Some(FieldType::FieldTypeVec{data_type}) => {
|
||||
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)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
Some(&FieldType::FieldTypeStruct{struct_name}) => {
|
||||
let struct_ident = Ident::new(&format!("{}", struct_name), Span::def_site());
|
||||
Some(quote!{
|
||||
#label_name => {
|
||||
reader.set_map_value();
|
||||
match #struct_ident::deserialize(reader) {
|
||||
Ok(parsed_item) => {
|
||||
#label.push(parsed_item);
|
||||
let _root = reader.next();
|
||||
},
|
||||
Err(msg) => {
|
||||
return Err(msg);
|
||||
},
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
_ => unimplemented!()
|
||||
}
|
||||
},
|
||||
_ => None
|
||||
}
|
||||
})
|
||||
.filter(|x| x.is_some())
|
||||
.map(|x| x.unwrap())
|
||||
.fold(Tokens::new(), |mut sum, val| {sum.append_all(val); sum});
|
||||
|
||||
let attributes_loading: Tokens = data_struct.fields.iter().map(|ref field| {
|
||||
let field_attrs = YaSerdeAttribute::parse(&field.attrs);
|
||||
if !field_attrs.attribute {
|
||||
return None;
|
||||
}
|
||||
|
||||
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()
|
||||
} else {
|
||||
field.ident.unwrap().to_string()
|
||||
};
|
||||
|
||||
match get_field_type(field) {
|
||||
Some(FieldType::FieldTypeString) => {
|
||||
Some(quote!{
|
||||
for attr in attributes {
|
||||
if attr.name.local_name == #label_name {
|
||||
#label = attr.value.to_owned();
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
Some(FieldType::FieldTypeStruct{struct_name}) => {
|
||||
let struct_ident = Ident::new(&format!("__Visitor_{}_{}", field_ident, struct_name), Span::call_site());
|
||||
|
||||
Some(quote!{
|
||||
for attr in attributes {
|
||||
if attr.name.local_name == #label_name {
|
||||
let visitor = #struct_ident{};
|
||||
match visitor.visit_str(&attr.value) {
|
||||
Ok(value) => {#label = value;}
|
||||
Err(msg) => {return Err(msg);}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
_ => {
|
||||
None
|
||||
}
|
||||
}})
|
||||
.filter(|x| x.is_some())
|
||||
.map(|x| x.unwrap())
|
||||
.fold(Tokens::new(), |mut sum, val| {sum.append_all(val); sum});
|
||||
|
||||
let set_text: Tokens = data_struct.fields.iter().map(|ref field|
|
||||
{
|
||||
let label = field.ident;
|
||||
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::FieldTypeStruct{..}) |
|
||||
Some(FieldType::FieldTypeVec{..})|
|
||||
None => None,
|
||||
}
|
||||
})
|
||||
.filter(|x| x.is_some())
|
||||
.map(|x| x.unwrap())
|
||||
.fold(Tokens::new(), |mut tokens, token| {tokens.append_all(token); tokens});
|
||||
|
||||
let struct_builder: Tokens = data_struct.fields.iter().map(|ref field|
|
||||
{
|
||||
let label = field.ident;
|
||||
|
||||
@@ -217,64 +335,52 @@ pub fn parse(data_struct: &DataStruct, name: &Ident, root: &String) -> Tokens {
|
||||
|
||||
quote! {
|
||||
use xml::reader::XmlEvent;
|
||||
use yaserde::Visitor;
|
||||
|
||||
impl YaDeserialize for #name {
|
||||
#[allow(unused_variables)]
|
||||
fn derive_deserialize<R: Read>(read: &mut xml::EventReader<R>, parent_attributes: Option<&Vec<xml::attribute::OwnedAttribute>>) -> Result<Self, String> {
|
||||
let mut prev_level = 0;
|
||||
let mut current_level = 0;
|
||||
|
||||
println!("Struct: start to parse {}", #root);
|
||||
fn deserialize<R: Read>(reader: &mut yaserde::de::Deserializer<R>) -> Result<Self, String> {
|
||||
let named_element =
|
||||
if let XmlEvent::StartElement{name, ..} = reader.peek()?.to_owned() {
|
||||
name.local_name.to_owned()
|
||||
} else {
|
||||
String::from(#root)
|
||||
};
|
||||
debug!("Struct: start to parse {:?}", named_element);
|
||||
|
||||
#variables
|
||||
let current_attributes = parent_attributes;
|
||||
#attributes_loading
|
||||
#field_visitors
|
||||
|
||||
loop {
|
||||
match read.next() {
|
||||
Ok(XmlEvent::StartDocument{..}) => {
|
||||
},
|
||||
Ok(XmlEvent::EndDocument) => {
|
||||
break;
|
||||
},
|
||||
Ok(XmlEvent::StartElement{name, attributes, namespace: _namespace}) => {
|
||||
println!("Struct: {} | {} - {}: {}", #root, prev_level, current_level, name.local_name.as_str());
|
||||
if prev_level == current_level {
|
||||
match name.local_name.as_str() {
|
||||
#root => {
|
||||
let root_attributes = attributes.clone();
|
||||
let current_attributes = Some(&root_attributes);
|
||||
#attributes_loading
|
||||
|
||||
current_level += 1;
|
||||
},
|
||||
#fields
|
||||
_ => {}
|
||||
};
|
||||
match reader.peek()?.to_owned() {
|
||||
XmlEvent::StartElement{ref name, ref attributes, ..} => {
|
||||
match name.local_name.as_str() {
|
||||
#call_visitors
|
||||
named_element => {
|
||||
let _root = reader.next();
|
||||
}
|
||||
// name => {
|
||||
// return Err(format!("unknown key {}", name))
|
||||
// }
|
||||
}
|
||||
|
||||
prev_level += 1;
|
||||
},
|
||||
Ok(XmlEvent::EndElement{name}) => {
|
||||
println!("Struct: end element {}", name);
|
||||
if #root == name.local_name.as_str() {
|
||||
println!("Struct: break for {}", #root);
|
||||
#attributes_loading
|
||||
}
|
||||
XmlEvent::EndElement{ref name} => {
|
||||
if name.local_name == named_element {
|
||||
break;
|
||||
}
|
||||
prev_level -= 1;
|
||||
let _root = reader.next();
|
||||
}
|
||||
XmlEvent::Characters(ref text_content) => {
|
||||
#set_text
|
||||
let _root = reader.next();
|
||||
}
|
||||
event => {
|
||||
return Err(format!("unknown event {:?}", event))
|
||||
}
|
||||
Ok(xml::reader::XmlEvent::Characters(characters_content)) => {
|
||||
if prev_level == current_level {
|
||||
#assign_text_field
|
||||
}
|
||||
},
|
||||
Ok(_event) => {
|
||||
},
|
||||
Err(_msg) => {
|
||||
break;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Ok(#name{#struct_builder})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,30 +51,17 @@ pub fn get_field_type(field: &syn::Field) -> Option<FieldType> {
|
||||
}
|
||||
|
||||
fn get_vec_type(t: &syn::PathSegment) -> Option<syn::Ident> {
|
||||
match t.arguments {
|
||||
syn::PathArguments::AngleBracketed(ref args) => {
|
||||
match args.args.first() {
|
||||
Some(Pair::End(tt)) => {
|
||||
match tt {
|
||||
&syn::GenericArgument::Type(ref argument) => {
|
||||
match argument {
|
||||
&Path(ref path2) => {
|
||||
match path2.path.segments.first() {
|
||||
Some(Pair::End(ttt)) => {
|
||||
Some(ttt.ident)
|
||||
},
|
||||
_ => None
|
||||
}
|
||||
},
|
||||
_ => None
|
||||
}
|
||||
},
|
||||
_ => None
|
||||
if let syn::PathArguments::AngleBracketed(ref args) = t.arguments {
|
||||
if let Some(Pair::End(tt)) = args.args.first() {
|
||||
if let &syn::GenericArgument::Type(ref argument) = tt {
|
||||
if let &Path(ref path2) = argument {
|
||||
if let Some(Pair::End(ttt)) = path2.path.segments.first() {
|
||||
return Some(ttt.ident)
|
||||
}
|
||||
},
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
@@ -75,11 +75,9 @@ pub fn serialize(data_enum: &DataEnum, name: &Ident, root: &String) -> Tokens {
|
||||
|
||||
match self {
|
||||
&#name::#label{ref #field_label, ..} => {
|
||||
match #field_label.derive_serialize(writer, true) {
|
||||
Ok(()) => {},
|
||||
Err(msg) => {
|
||||
return Err(msg);
|
||||
},
|
||||
writer.set_skip_start_end(true);
|
||||
if let Err(msg) = #field_label.serialize(writer) {
|
||||
return Err(msg);
|
||||
};
|
||||
},
|
||||
_ => {}
|
||||
@@ -96,11 +94,9 @@ pub fn serialize(data_enum: &DataEnum, name: &Ident, root: &String) -> Tokens {
|
||||
let struct_start_event = XmlEvent::start_element(#field_label_name);
|
||||
let _ret = writer.write(struct_start_event);
|
||||
|
||||
match item.derive_serialize(writer, true) {
|
||||
Ok(()) => {},
|
||||
Err(msg) => {
|
||||
return Err(msg);
|
||||
},
|
||||
writer.set_skip_start_end(true);
|
||||
if let Err(msg) = item.serialize(writer) {
|
||||
return Err(msg);
|
||||
};
|
||||
let struct_end_event = XmlEvent::end_element();
|
||||
let _ret = writer.write(struct_end_event);
|
||||
@@ -142,8 +138,10 @@ pub fn serialize(data_enum: &DataEnum, name: &Ident, root: &String) -> Tokens {
|
||||
|
||||
impl YaSerialize for #name {
|
||||
#[allow(unused_variables)]
|
||||
fn derive_serialize<W: Write>(&self, writer: &mut xml::EventWriter<W>, skip_start_end: bool) -> Result<(), String> {
|
||||
if !skip_start_end {
|
||||
fn serialize<W: Write>(&self, writer: &mut yaserde::ser::Serializer<W>) -> Result<(), String> {
|
||||
error!("Enum: start to expand {:?}", #root);
|
||||
|
||||
if !writer.skip_start_end() {
|
||||
let struct_start_event = XmlEvent::start_element(#root);
|
||||
let _ret = writer.write(struct_start_event);
|
||||
}
|
||||
@@ -152,10 +150,11 @@ pub fn serialize(data_enum: &DataEnum, name: &Ident, root: &String) -> Tokens {
|
||||
#write_enum_content
|
||||
}
|
||||
|
||||
if !skip_start_end {
|
||||
if !writer.skip_start_end() {
|
||||
let struct_end_event = XmlEvent::end_element();
|
||||
let _ret = writer.write(struct_end_event);
|
||||
}
|
||||
writer.set_skip_start_end(false);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ use quote::Tokens;
|
||||
use syn::Ident;
|
||||
use syn::DataStruct;
|
||||
use proc_macro2::Span;
|
||||
use std::string::ToString;
|
||||
|
||||
pub fn serialize(data_struct: &DataStruct, name: &Ident, root: &String) -> Tokens {
|
||||
let build_attributes : Tokens = data_struct.fields.iter().map(|ref field|
|
||||
@@ -27,7 +28,25 @@ pub fn serialize(data_struct: &DataStruct, name: &Ident, root: &String) -> Token
|
||||
Some(quote!{
|
||||
.attr(#label_name, &self.#label)
|
||||
}),
|
||||
_ => None
|
||||
Some(FieldType::FieldTypeStruct{struct_name: _struct_name}) =>
|
||||
Some(quote!{
|
||||
.attr(#label_name, &*{
|
||||
use std::mem;
|
||||
match yaserde::ser::to_string_content(&self.#label) {
|
||||
Ok(value) => {
|
||||
unsafe {
|
||||
let ret : &'static str = mem::transmute(&value as &str);
|
||||
mem::forget(value);
|
||||
ret
|
||||
}
|
||||
},
|
||||
Err(msg) => return Err("Unable to serialize content".to_owned()),
|
||||
}
|
||||
})
|
||||
}),
|
||||
_ => {
|
||||
None
|
||||
}
|
||||
}
|
||||
})
|
||||
.filter(|x| x.is_some())
|
||||
@@ -68,7 +87,8 @@ pub fn serialize(data_struct: &DataStruct, name: &Ident, root: &String) -> Token
|
||||
}),
|
||||
Some(FieldType::FieldTypeStruct{..}) =>
|
||||
Some(quote!{
|
||||
match self.#label.derive_serialize(writer, false) {
|
||||
writer.set_skip_start_end(false);
|
||||
match self.#label.serialize(writer) {
|
||||
Ok(()) => {},
|
||||
Err(msg) => {
|
||||
return Err(msg);
|
||||
@@ -95,7 +115,8 @@ pub fn serialize(data_struct: &DataStruct, name: &Ident, root: &String) -> Token
|
||||
Some(&FieldType::FieldTypeStruct{..}) => {
|
||||
Some(quote!{
|
||||
for item in &self.#label {
|
||||
match item.derive_serialize(writer, false) {
|
||||
writer.set_skip_start_end(false);
|
||||
match item.serialize(writer) {
|
||||
Ok(()) => {},
|
||||
Err(msg) => {
|
||||
return Err(msg);
|
||||
@@ -122,15 +143,17 @@ pub fn serialize(data_struct: &DataStruct, name: &Ident, root: &String) -> Token
|
||||
|
||||
impl YaSerialize for #name {
|
||||
#[allow(unused_variables)]
|
||||
fn derive_serialize<W: Write>(&self, writer: &mut xml::EventWriter<W>, skip_start_end: bool) -> Result<(), String> {
|
||||
if !skip_start_end {
|
||||
fn serialize<W: Write>(&self, writer: &mut yaserde::ser::Serializer<W>) -> Result<(), String> {
|
||||
error!("Struct: start to expand {:?}", #root);
|
||||
|
||||
if !writer.skip_start_end() {
|
||||
let struct_start_event = XmlEvent::start_element(#root)#build_attributes;
|
||||
let _ret = writer.write(struct_start_event);
|
||||
}
|
||||
|
||||
#struct_inspector
|
||||
|
||||
if !skip_start_end {
|
||||
if !writer.skip_start_end() {
|
||||
let struct_end_event = XmlEvent::end_element();
|
||||
let _ret = writer.write(struct_end_event);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ pub mod expand_enum;
|
||||
pub mod expand_struct;
|
||||
|
||||
use attribute;
|
||||
|
||||
use proc_macro2::Span;
|
||||
use quote;
|
||||
use syn;
|
||||
|
||||
Reference in New Issue
Block a user