diff --git a/yaserde_derive/src/attribute.rs b/yaserde_derive/src/common/attribute.rs similarity index 100% rename from yaserde_derive/src/attribute.rs rename to yaserde_derive/src/common/attribute.rs diff --git a/yaserde_derive/src/common/field.rs b/yaserde_derive/src/common/field.rs new file mode 100644 index 0000000..6e01569 --- /dev/null +++ b/yaserde_derive/src/common/field.rs @@ -0,0 +1,168 @@ +use crate::common::attribute::YaSerdeAttribute; +use proc_macro2::{Ident, TokenStream}; +use std::fmt; +use syn; +use syn::Type::Path; + +#[derive(Debug)] +pub enum Field { + FieldString, + FieldBool, + FieldI8, + FieldU8, + FieldI16, + FieldU16, + FieldI32, + FieldU32, + FieldI64, + FieldU64, + FieldF32, + FieldF64, + FieldOption { data_type: Box }, + FieldVec { data_type: Box }, + FieldStruct { struct_name: syn::Path }, +} + +impl Field { + pub fn is_attribute(token_field: &syn::Field) -> bool { + YaSerdeAttribute::parse(&token_field.attrs).attribute + } + + pub fn is_text_content(token_field: &syn::Field) -> bool { + YaSerdeAttribute::parse(&token_field.attrs).text + } + + pub fn label(token_field: &syn::Field) -> Option { + token_field.ident.clone() + } + + pub fn renamed_label(token_field: &syn::Field, root_attributes: &YaSerdeAttribute) -> String { + let attributes = YaSerdeAttribute::parse(&token_field.attrs); + + let prefix = if root_attributes.default_namespace == attributes.prefix { + "".to_string() + } else { + attributes + .prefix + .clone() + .map_or("".to_string(), |prefix| prefix + ":") + }; + + let label = attributes + .rename + .clone() + .unwrap_or_else(|| token_field.ident.as_ref().unwrap().to_string()); + + format!("{}{}", prefix, label) + } + + pub fn get_simple_type_visitor(&self) -> TokenStream { + let ident = format_ident!("visit_{}", self.to_string()); + quote! {#ident} + } +} + +impl From<&syn::Path> for Field { + fn from(path: &syn::Path) -> Self { + let result = if let Some(segment) = path.segments.last() { + match segment.ident.to_string().as_str() { + "String" => Some(Field::FieldString), + "bool" => Some(Field::FieldBool), + "i8" => Some(Field::FieldI8), + "u8" => Some(Field::FieldU8), + "i16" => Some(Field::FieldI16), + "u16" => Some(Field::FieldU16), + "i32" => Some(Field::FieldI32), + "u32" => Some(Field::FieldU32), + "i64" => Some(Field::FieldI64), + "u64" => Some(Field::FieldU64), + "f32" => Some(Field::FieldF32), + "f64" => Some(Field::FieldF64), + "Option" => Some(Field::FieldOption { + data_type: Box::new(Field::from(segment)), + }), + "Vec" => Some(Field::FieldVec { + data_type: Box::new(Field::from(segment)), + }), + _ => None, + } + } else { + None + }; + + result.unwrap_or_else(|| Field::FieldStruct { + struct_name: path.clone(), + }) + } +} + +impl From<&syn::Field> for Field { + fn from(field: &syn::Field) -> Self { + match field.ty { + Path(ref path) => Field::from(&path.path), + _ => panic!("unable to match {:?}", field.ty), + } + } +} + +impl From<&syn::PathSegment> for Field { + fn from(path_segment: &syn::PathSegment) -> Self { + if let syn::PathArguments::AngleBracketed(ref args) = path_segment.arguments { + if let Some(tt) = args.args.first() { + if let syn::GenericArgument::Type(ref argument) = *tt { + if let Path(ref path) = *argument { + return Field::from(&path.path); + } + } + } + } + unimplemented!() + } +} + +impl Into for Field { + fn into(self) -> proc_macro2::TokenStream { + match self { + Field::FieldString => quote! {String}, + Field::FieldBool => quote! {bool}, + Field::FieldI8 => quote! {i8}, + Field::FieldU8 => quote! {u8}, + Field::FieldI16 => quote! {i16}, + Field::FieldU16 => quote! {u16}, + Field::FieldI32 => quote! {i32}, + Field::FieldU32 => quote! {u32}, + Field::FieldI64 => quote! {i64}, + Field::FieldU64 => quote! {u64}, + Field::FieldF32 => quote! {f32}, + Field::FieldF64 => quote! {f64}, + _ => panic!("Not a simple type: {:?}", self), + } + } +} + +impl Into for &Field { + fn into(self) -> String { + match self { + Field::FieldString => "str".to_string(), + Field::FieldBool => "bool".to_string(), + Field::FieldI8 => "i8".to_string(), + Field::FieldU8 => "u8".to_string(), + Field::FieldI16 => "i16".to_string(), + Field::FieldU16 => "u16".to_string(), + Field::FieldI32 => "i32".to_string(), + Field::FieldU32 => "u32".to_string(), + Field::FieldI64 => "i64".to_string(), + Field::FieldU64 => "u64".to_string(), + Field::FieldF32 => "f32".to_string(), + Field::FieldF64 => "f64".to_string(), + _ => panic!("Not a simple type: {:?}", self), + } + } +} + +impl fmt::Display for Field { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let string_representation: String = self.into(); + write!(f, "{}", string_representation) + } +} diff --git a/yaserde_derive/src/common/mod.rs b/yaserde_derive/src/common/mod.rs new file mode 100644 index 0000000..2dc2de9 --- /dev/null +++ b/yaserde_derive/src/common/mod.rs @@ -0,0 +1,5 @@ +mod attribute; +mod field; + +pub use attribute::YaSerdeAttribute; +pub use field::Field; diff --git a/yaserde_derive/src/de/expand_enum.rs b/yaserde_derive/src/de/expand_enum.rs index c43d246..c1efe82 100644 --- a/yaserde_derive/src/de/expand_enum.rs +++ b/yaserde_derive/src/de/expand_enum.rs @@ -1,10 +1,11 @@ -use crate::attribute::*; -use crate::field_type::*; +use crate::common::{Field, YaSerdeAttribute}; use proc_macro2::TokenStream; -use syn::spanned::Spanned; -use syn::DataEnum; -use syn::Fields; -use syn::Ident; +use syn::{ + spanned::Spanned, + DataEnum, + Fields, + Ident, +}; pub fn parse( data_enum: &DataEnum, @@ -160,9 +161,9 @@ fn build_unnamed_field_visitors(fields: &syn::FieldsUnnamed) -> TokenStream { }) }; - let simple_type_visitor = |simple_type| { - let field_type = get_simple_type_token(&simple_type); - let visitor = get_simple_type_visitor(&simple_type); + let simple_type_visitor = |simple_type: Field| { + let visitor = simple_type.get_simple_type_visitor(); + let field_type = simple_type.into(); make_visitor( &visitor, @@ -171,8 +172,8 @@ fn build_unnamed_field_visitors(fields: &syn::FieldsUnnamed) -> TokenStream { ) }; - get_field_type(field).and_then(|f| match f { - FieldType::FieldTypeStruct { struct_name } => { + match Field::from(field) { + Field::FieldStruct { struct_name } => { let struct_id: String = struct_name .segments .iter() @@ -189,14 +190,12 @@ fn build_unnamed_field_visitors(fields: &syn::FieldsUnnamed) -> TokenStream { }, ) } - FieldType::FieldTypeOption { data_type } | FieldType::FieldTypeVec { data_type } => { - match *data_type { - FieldType::FieldTypeStruct { .. } => None, - simple_type => simple_type_visitor(simple_type), - } - } + Field::FieldOption { data_type } | Field::FieldVec { data_type } => match *data_type { + Field::FieldStruct { .. } => None, + simple_type => simple_type_visitor(simple_type), + }, simple_type => simple_type_visitor(simple_type), - }) + } }) .filter_map(|f| f) .collect() @@ -213,9 +212,9 @@ fn build_unnamed_visitor_calls( .map(|(idx, field)| { let visitor_label = Ident::new(&format!("__Visitor_{}", idx), field.span()); - let call_simple_type_visitor = |simple_type, action| { - let field_type = get_simple_type_token(&simple_type); - let visitor = get_simple_type_visitor(&simple_type); + let call_simple_type_visitor = |simple_type: Field, action| { + let visitor = simple_type.get_simple_type_visitor(); + let field_type: TokenStream = simple_type.into(); let label_name = format!("field_{}", idx); @@ -279,19 +278,19 @@ fn build_unnamed_visitor_calls( } }; - get_field_type(field).and_then(|f| match f { - FieldType::FieldTypeStruct { struct_name } => call_struct_visitor(struct_name, set_val), - FieldType::FieldTypeOption { data_type } => match *data_type { - FieldType::FieldTypeStruct { struct_name } => call_struct_visitor(struct_name, set_opt), + match Field::from(field) { + Field::FieldStruct { struct_name } => call_struct_visitor(struct_name, set_val), + Field::FieldOption { data_type } => match *data_type { + Field::FieldStruct { struct_name } => call_struct_visitor(struct_name, set_opt), simple_type => call_simple_type_visitor(simple_type, set_opt), }, - FieldType::FieldTypeVec { data_type } => match *data_type { - FieldType::FieldTypeStruct { struct_name } => call_struct_visitor(struct_name, set_vec), + Field::FieldVec { data_type } => match *data_type { + Field::FieldStruct { struct_name } => call_struct_visitor(struct_name, set_vec), simple_type => call_simple_type_visitor(simple_type, set_vec), }, simple_type => call_simple_type_visitor(simple_type, set_val), - }) + } }) .filter_map(|f| f) .collect() diff --git a/yaserde_derive/src/de/expand_struct.rs b/yaserde_derive/src/de/expand_struct.rs index 3c48215..4066e62 100644 --- a/yaserde_derive/src/de/expand_struct.rs +++ b/yaserde_derive/src/de/expand_struct.rs @@ -1,11 +1,12 @@ -use crate::attribute::*; +use crate::common::{Field, YaSerdeAttribute}; use crate::de::build_default_value::build_default_value; -use crate::field_type::*; use proc_macro2::{Span, TokenStream}; use std::collections::BTreeMap; -use syn::spanned::Spanned; -use syn::DataStruct; -use syn::Ident; +use syn::{ + spanned::Spanned, + DataStruct, + Ident, +}; pub fn parse( data_struct: &DataStruct, @@ -33,14 +34,14 @@ pub fn parse( let label = &get_value_label(&field.ident); let field_attrs = YaSerdeAttribute::parse(&field.attrs); - get_field_type(field).and_then(|f| match f { - FieldType::FieldTypeStruct { struct_name } => build_default_value( + match Field::from(field) { + Field::FieldStruct { struct_name } => build_default_value( label, "e! {#struct_name}, "e! {#struct_name::default()}, &field_attrs.default, ), - FieldType::FieldTypeOption { .. } => { + Field::FieldOption { .. } => { if let Some(d) = &field_attrs.default { let default_function = Ident::new(&d, field.span()); @@ -55,18 +56,18 @@ pub fn parse( }) } } - FieldType::FieldTypeVec { data_type } => match *data_type { - FieldType::FieldTypeStruct { ref struct_name } => build_default_value( + Field::FieldVec { data_type } => match *data_type { + Field::FieldStruct { ref struct_name } => build_default_value( label, "e! {Vec<#struct_name>}, "e! {vec![]}, &field_attrs.default, ), - FieldType::FieldTypeOption { .. } | FieldType::FieldTypeVec { .. } => { + Field::FieldOption { .. } | Field::FieldVec { .. } => { unimplemented!(); } simple_type => { - let type_token = get_simple_type_token(&simple_type); + let type_token: TokenStream = simple_type.into(); build_default_value( label, @@ -77,7 +78,8 @@ pub fn parse( } }, simple_type => { - let type_token = get_simple_type_token(&simple_type); + let type_token: TokenStream = simple_type.into(); + build_default_value( label, &type_token, @@ -85,7 +87,7 @@ pub fn parse( &field_attrs.default, ) } - }) + } }) .filter_map(|x| x) .collect(); @@ -123,10 +125,10 @@ pub fn parse( }) }; - let simple_type_visitor = |simple_type: FieldType| { - let field_type = get_simple_type_token(&simple_type); - let visitor = get_simple_type_visitor(&simple_type); + let simple_type_visitor = |simple_type: Field| { + let visitor = simple_type.get_simple_type_visitor(); let visitor_label = build_visitor_ident(&label_name, field.span(), None); + let field_type: TokenStream = simple_type.into(); Some(quote! { #[allow(non_snake_case, non_camel_case_types)] @@ -141,20 +143,20 @@ pub fn parse( }) }; - get_field_type(field).and_then(|f| match f { - FieldType::FieldTypeStruct { struct_name } => struct_visitor(struct_name), - FieldType::FieldTypeOption { data_type } => match *data_type { - FieldType::FieldTypeStruct { struct_name } => struct_visitor(struct_name), - FieldType::FieldTypeOption { .. } | FieldType::FieldTypeVec { .. } => None, + match Field::from(field) { + Field::FieldStruct { struct_name } => struct_visitor(struct_name), + Field::FieldOption { data_type } => match *data_type { + Field::FieldStruct { struct_name } => struct_visitor(struct_name), + Field::FieldOption { .. } | Field::FieldVec { .. } => None, simple_type => simple_type_visitor(simple_type), }, - FieldType::FieldTypeVec { data_type } => match *data_type { - FieldType::FieldTypeStruct { struct_name } => struct_visitor(struct_name), - FieldType::FieldTypeOption { .. } | FieldType::FieldTypeVec { .. } => None, + Field::FieldVec { data_type } => match *data_type { + Field::FieldStruct { struct_name } => struct_visitor(struct_name), + Field::FieldOption { .. } | Field::FieldVec { .. } => None, simple_type => simple_type_visitor(simple_type), }, simple_type => simple_type_visitor(simple_type), - }) + } }) .filter_map(|x| x) .collect(); @@ -192,10 +194,12 @@ pub fn parse( }) }; - let visit_simple = |simple_type: FieldType, action: TokenStream| { + let visit_simple = |simple_type: Field, action: TokenStream| { + let field_visitor = simple_type.get_simple_type_visitor(); + let field_type: TokenStream = simple_type.into(); build_call_visitor( - &get_simple_type_token(&simple_type), - &get_simple_type_visitor(&simple_type), + &field_type, + &field_visitor, &action, &field_attrs, label, @@ -204,18 +208,18 @@ pub fn parse( ) }; - let visit_sub = |sub_type: Box, action: TokenStream| match *sub_type { - FieldType::FieldTypeOption { .. } | FieldType::FieldTypeVec { .. } => unimplemented!(), - FieldType::FieldTypeStruct { struct_name } => visit_struct(struct_name, action), + let visit_sub = |sub_type: Box, action: TokenStream| match *sub_type { + Field::FieldOption { .. } | Field::FieldVec { .. } => unimplemented!(), + Field::FieldStruct { struct_name } => visit_struct(struct_name, action), simple_type => visit_simple(simple_type, action), }; - get_field_type(field).and_then(|f| match f { - FieldType::FieldTypeStruct { struct_name } => visit_struct(struct_name, quote! {= value}), - FieldType::FieldTypeOption { data_type } => visit_sub(data_type, quote! {= Some(value)}), - FieldType::FieldTypeVec { data_type } => visit_sub(data_type, quote! {.push(value)}), + match Field::from(field) { + Field::FieldStruct { struct_name } => visit_struct(struct_name, quote! {= value}), + Field::FieldOption { data_type } => visit_sub(data_type, quote! {= Some(value)}), + Field::FieldVec { data_type } => visit_sub(data_type, quote! {.push(value)}), simple_type => visit_simple(simple_type, quote! {= value}), - }) + } }) .filter_map(|x| x) .collect(); @@ -231,18 +235,18 @@ pub fn parse( return None; } - get_field_type(field).and_then(|f| match f { - FieldType::FieldTypeStruct { .. } => Some(quote! { + match Field::from(field) { + Field::FieldStruct { .. } => Some(quote! { #value_label = yaserde::de::from_str(&unused_xml_elements)?; }), - FieldType::FieldTypeOption { data_type } => match *data_type { - FieldType::FieldTypeStruct { .. } => Some(quote! { + Field::FieldOption { data_type } => match *data_type { + Field::FieldStruct { .. } => Some(quote! { #value_label = yaserde::de::from_str(&unused_xml_elements).ok(); }), field_type => unimplemented!("\"flatten\" is not implemented for {:?}", field_type), }, field_type => unimplemented!("\"flatten\" is not implemented for {:?}", field_type), - }) + } }) .filter_map(|x| x) .collect(); @@ -294,27 +298,27 @@ pub fn parse( ) }; - let visit_simple = |simple_type: FieldType, action: TokenStream| { + let visit_simple = |simple_type: Field, action: TokenStream| { visit( &action, - &get_simple_type_visitor(&simple_type), + &simple_type.get_simple_type_visitor(), &visitor_label, ) }; - let visit_sub = |sub_type: Box, action: TokenStream| match *sub_type { - FieldType::FieldTypeOption { .. } | FieldType::FieldTypeVec { .. } => unimplemented!(), - FieldType::FieldTypeStruct { struct_name } => visit_struct(struct_name, action), + let visit_sub = |sub_type: Box, action: TokenStream| match *sub_type { + Field::FieldOption { .. } | Field::FieldVec { .. } => unimplemented!(), + Field::FieldStruct { struct_name } => visit_struct(struct_name, action), simple_type => visit_simple(simple_type, action), }; - get_field_type(field).and_then(|f| match f { - FieldType::FieldTypeString => visit_string(), - FieldType::FieldTypeOption { data_type } => visit_sub(data_type, quote! {= Some(value)}), - FieldType::FieldTypeVec { .. } => unimplemented!(), - FieldType::FieldTypeStruct { struct_name } => visit_struct(struct_name, quote! {= value}), + match Field::from(field) { + Field::FieldString => visit_string(), + Field::FieldOption { data_type } => visit_sub(data_type, quote! {= Some(value)}), + Field::FieldVec { .. } => unimplemented!(), + Field::FieldStruct { struct_name } => visit_struct(struct_name, quote! {= value}), simple_type => visit_simple(simple_type, quote! {= value}), - }) + } }) .filter_map(|x| x) .collect(); @@ -334,16 +338,14 @@ pub fn parse( } }; - get_field_type(field).and_then(|f| match f { - FieldType::FieldTypeString => set_text("e! {text_content.to_owned()}), - FieldType::FieldTypeStruct { .. } - | FieldType::FieldTypeOption { .. } - | FieldType::FieldTypeVec { .. } => None, + match Field::from(field) { + Field::FieldString => set_text("e! {text_content.to_owned()}), + Field::FieldStruct { .. } | Field::FieldOption { .. } | Field::FieldVec { .. } => None, simple_type => { - let type_token = get_simple_type_token(&simple_type); + let type_token: TokenStream = simple_type.into(); set_text("e! {#type_token::from_str(text_content).unwrap()}) } - }) + } }) .filter_map(|x| x) .collect(); @@ -355,11 +357,8 @@ pub fn parse( let label = &field.ident; let value_label = &get_value_label(&field.ident); - get_field_type(field).map(|_| { - quote! { #label: #value_label, } - }) + quote! { #label: #value_label, } }) - .filter_map(|x| x) .collect(); let (init_unused, write_unused, visit_unused) = if call_flatten_visitors.is_empty() { diff --git a/yaserde_derive/src/de/mod.rs b/yaserde_derive/src/de/mod.rs index 84f1f17..ec9ff56 100644 --- a/yaserde_derive/src/de/mod.rs +++ b/yaserde_derive/src/de/mod.rs @@ -2,7 +2,7 @@ pub mod build_default_value; pub mod expand_enum; pub mod expand_struct; -use crate::attribute; +use crate::common::YaSerdeAttribute; use proc_macro2::TokenStream; use syn; use syn::Ident; @@ -12,7 +12,7 @@ pub fn expand_derive_deserialize(ast: &syn::DeriveInput) -> Result }, - FieldTypeVec { data_type: Box }, - FieldTypeStruct { struct_name: syn::Path }, -} - -impl FieldType { - fn from_ident(path: &syn::Path) -> Option { - match path.segments.last() { - Some(t) => match t.ident.to_string().as_str() { - "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), - "f32" => Some(FieldType::FieldTypeF32), - "f64" => Some(FieldType::FieldTypeF64), - "Option" => get_sub_type(t).map(|data_type| FieldType::FieldTypeOption { - data_type: Box::new(FieldType::from_ident(&data_type).unwrap()), - }), - "Vec" => get_sub_type(t).map(|data_type| FieldType::FieldTypeVec { - data_type: Box::new(FieldType::from_ident(&data_type).unwrap()), - }), - _ => Some(FieldType::FieldTypeStruct { - struct_name: path.clone(), - }), - }, - _ => None, - } - } -} - -pub fn get_field_type(field: &syn::Field) -> Option { - match field.ty { - Path(ref path) => FieldType::from_ident(&path.path), - _ => None, - } -} - -fn get_sub_type(t: &syn::PathSegment) -> Option { - if let syn::PathArguments::AngleBracketed(ref args) = t.arguments { - if let Some(tt) = args.args.first() { - if let syn::GenericArgument::Type(ref argument) = *tt { - if let Path(ref path) = *argument { - return Some(path.path.clone()); - } - } - } - } - - None -} - -pub fn get_simple_type_token(field_type: &FieldType) -> proc_macro2::TokenStream { - match field_type { - FieldType::FieldTypeString => quote! {String}, - FieldType::FieldTypeBool => quote! {bool}, - FieldType::FieldTypeI8 => quote! {i8}, - FieldType::FieldTypeU8 => quote! {u8}, - FieldType::FieldTypeI16 => quote! {i16}, - FieldType::FieldTypeU16 => quote! {u16}, - FieldType::FieldTypeI32 => quote! {i32}, - FieldType::FieldTypeU32 => quote! {u32}, - FieldType::FieldTypeI64 => quote! {i64}, - FieldType::FieldTypeU64 => quote! {u64}, - FieldType::FieldTypeF32 => quote! {f32}, - FieldType::FieldTypeF64 => quote! {f64}, - _ => panic!("Not a simple type: {:?}", field_type), - } -} - -pub fn get_simple_type_visitor(field_type: &FieldType) -> proc_macro2::TokenStream { - let ident = format_ident!( - "visit_{}", - get_simple_type_token(field_type) - .to_string() - .replace("String", "str") - ); - - quote! {#ident} -} diff --git a/yaserde_derive/src/lib.rs b/yaserde_derive/src/lib.rs index 527a439..7fd17fa 100644 --- a/yaserde_derive/src/lib.rs +++ b/yaserde_derive/src/lib.rs @@ -6,9 +6,8 @@ extern crate proc_macro2; extern crate quote; extern crate syn; -mod attribute; +mod common; mod de; -mod field_type; mod ser; use proc_macro::TokenStream; diff --git a/yaserde_derive/src/ser/element.rs b/yaserde_derive/src/ser/element.rs index 313be33..65e5c44 100644 --- a/yaserde_derive/src/ser/element.rs +++ b/yaserde_derive/src/ser/element.rs @@ -1,4 +1,4 @@ -use crate::attribute::*; +use crate::common::YaSerdeAttribute; use proc_macro2::{Ident, Span, TokenStream}; pub fn enclose_formatted_characters(label: &Ident, label_name: String) -> TokenStream { diff --git a/yaserde_derive/src/ser/expand_enum.rs b/yaserde_derive/src/ser/expand_enum.rs index fb42821..cb85a93 100644 --- a/yaserde_derive/src/ser/expand_enum.rs +++ b/yaserde_derive/src/ser/expand_enum.rs @@ -1,8 +1,6 @@ -use crate::attribute::*; -use crate::field_type::*; +use crate::common::{Field, YaSerdeAttribute}; use crate::ser::{implement_deserializer::implement_deserializer, label::build_label_name}; use proc_macro2::TokenStream; -use syn::spanned::Spanned; use syn::DataEnum; use syn::Fields; use syn::Ident; @@ -52,38 +50,34 @@ fn inner_enum_inspector( .named .iter() .map(|field| { - let field_attrs = YaSerdeAttribute::parse(&field.attrs); - if field_attrs.attribute { + if Field::is_attribute(field) { return None; } - let field_label = &field.ident; - if field_attrs.text { + let field_label = Field::label(field); + + if Field::is_text_content(field) { return Some(quote!( let data_event = XmlEvent::characters(&self.#field_label); writer.write(data_event).map_err(|e| e.to_string())?; )); } - let renamed_field_label = match field_attrs.rename { - Some(value) => Some(Ident::new(&value.replace("\"", ""), field.span())), - None => field.ident.clone(), - }; - let field_label_name = renamed_field_label.unwrap().to_string(); + let field_label_name = Field::renamed_label(field, root_attributes); - match get_field_type(field) { - Some(FieldType::FieldTypeString) - | Some(FieldType::FieldTypeBool) - | Some(FieldType::FieldTypeU8) - | Some(FieldType::FieldTypeI8) - | Some(FieldType::FieldTypeU16) - | Some(FieldType::FieldTypeI16) - | Some(FieldType::FieldTypeU32) - | Some(FieldType::FieldTypeI32) - | Some(FieldType::FieldTypeF32) - | Some(FieldType::FieldTypeU64) - | Some(FieldType::FieldTypeI64) - | Some(FieldType::FieldTypeF64) => Some({ + match Field::from(field) { + Field::FieldString + | Field::FieldBool + | Field::FieldU8 + | Field::FieldI8 + | Field::FieldU16 + | Field::FieldI16 + | Field::FieldU32 + | Field::FieldI32 + | Field::FieldF32 + | Field::FieldU64 + | Field::FieldI64 + | Field::FieldF64 => Some({ quote! { match self { &#name::#label{ref #field_label, ..} => { @@ -101,7 +95,7 @@ fn inner_enum_inspector( } } }), - Some(FieldType::FieldTypeStruct { .. }) => Some(quote! { + Field::FieldStruct { .. } => Some(quote! { match self { &#name::#label{ref #field_label, ..} => { writer.set_start_event_name(Some(#field_label_name.to_string())); @@ -111,7 +105,7 @@ fn inner_enum_inspector( _ => {} } }), - Some(FieldType::FieldTypeVec { .. }) => Some(quote! { + Field::FieldVec { .. } => Some(quote! { match self { &#name::#label{ref #field_label, ..} => { for item in #field_label { @@ -123,7 +117,7 @@ fn inner_enum_inspector( _ => {} } }), - _ => None, + Field::FieldOption { .. } => None, } }) .filter_map(|x| x) @@ -139,9 +133,8 @@ fn inner_enum_inspector( let enum_fields: TokenStream = fields .unnamed .iter() - .map(|field| { - let field_attrs = YaSerdeAttribute::parse(&field.attrs); - if field_attrs.attribute { + .map(|token_field| { + if Field::is_attribute(token_field) { return None; } @@ -176,7 +169,7 @@ fn inner_enum_inspector( let write_sub_type = |data_type| { write_element(match data_type { - FieldType::FieldTypeString => &write_string_chars, + Field::FieldString => &write_string_chars, _ => &serialize, }) }; @@ -192,8 +185,8 @@ fn inner_enum_inspector( } }; - match get_field_type(field) { - Some(FieldType::FieldTypeOption { data_type }) => { + match Field::from(token_field) { + Field::FieldOption { data_type } => { let write = write_sub_type(*data_type); Some(match_field("e! { @@ -202,7 +195,7 @@ fn inner_enum_inspector( } })) } - Some(FieldType::FieldTypeVec { data_type }) => { + Field::FieldVec { data_type } => { let write = write_sub_type(*data_type); Some(match_field("e! { @@ -211,14 +204,9 @@ fn inner_enum_inspector( } })) } - Some(FieldType::FieldTypeStruct { .. }) => { - Some(write_element(&match_field(&serialize))) - } - Some(FieldType::FieldTypeString) => { - Some(match_field(&write_element(&write_string_chars))) - } - Some(_simple_type) => Some(match_field(&write_simple_type)), - _ => None, + Field::FieldStruct { .. } => Some(write_element(&match_field(&serialize))), + Field::FieldString => Some(match_field(&write_element(&write_string_chars))), + _simple_type => Some(match_field(&write_simple_type)), } }) .filter_map(|x| x) diff --git a/yaserde_derive/src/ser/expand_struct.rs b/yaserde_derive/src/ser/expand_struct.rs index 16bfed5..32567f9 100644 --- a/yaserde_derive/src/ser/expand_struct.rs +++ b/yaserde_derive/src/ser/expand_struct.rs @@ -1,8 +1,6 @@ -use crate::attribute::*; -use crate::field_type::*; -use crate::ser::{ - element::*, implement_deserializer::implement_deserializer, label::build_label_name, -}; +use crate::common::{Field, YaSerdeAttribute}; + +use crate::ser::{element::*, implement_deserializer::implement_deserializer}; use proc_macro2::TokenStream; use syn::spanned::Spanned; use syn::DataStruct; @@ -19,31 +17,26 @@ pub fn serialize( .iter() .map(|field| { let field_attrs = YaSerdeAttribute::parse(&field.attrs); - if !field_attrs.attribute { + if !Field::is_attribute(field) { return None; } - let label = &field.ident; + let label = Field::label(field); + let label_name = Field::renamed_label(field, root_attributes); - let label_name = build_label_name( - &label.as_ref().unwrap(), - &field_attrs, - &root_attributes.default_namespace, - ); - - get_field_type(field).and_then(|f| match f { - FieldType::FieldTypeString - | FieldType::FieldTypeBool - | FieldType::FieldTypeI8 - | FieldType::FieldTypeU8 - | FieldType::FieldTypeI16 - | FieldType::FieldTypeU16 - | FieldType::FieldTypeI32 - | FieldType::FieldTypeU32 - | FieldType::FieldTypeI64 - | FieldType::FieldTypeU64 - | FieldType::FieldTypeF32 - | FieldType::FieldTypeF64 => { + match Field::from(field) { + Field::FieldString + | Field::FieldBool + | Field::FieldI8 + | Field::FieldU8 + | Field::FieldI16 + | Field::FieldU16 + | Field::FieldI32 + | Field::FieldU32 + | Field::FieldI64 + | Field::FieldU64 + | Field::FieldF32 + | Field::FieldF64 => { if let Some(ref d) = field_attrs.default { let default_function = Ident::new(&d, field.span()); Some(quote! { @@ -62,8 +55,8 @@ pub fn serialize( }) } } - FieldType::FieldTypeOption { data_type } => match *data_type { - FieldType::FieldTypeString => { + Field::FieldOption { data_type } => match *data_type { + Field::FieldString => { if let Some(ref d) = field_attrs.default { let default_function = Ident::new(&d, field.span()); Some(quote! { @@ -89,17 +82,17 @@ pub fn serialize( }) } } - FieldType::FieldTypeBool - | FieldType::FieldTypeI8 - | FieldType::FieldTypeU8 - | FieldType::FieldTypeI16 - | FieldType::FieldTypeU16 - | FieldType::FieldTypeI32 - | FieldType::FieldTypeU32 - | FieldType::FieldTypeI64 - | FieldType::FieldTypeU64 - | FieldType::FieldTypeF32 - | FieldType::FieldTypeF64 => { + Field::FieldBool + | Field::FieldI8 + | Field::FieldU8 + | Field::FieldI16 + | Field::FieldU16 + | Field::FieldI32 + | Field::FieldU32 + | Field::FieldI64 + | Field::FieldU64 + | Field::FieldF32 + | Field::FieldF64 => { if let Some(ref d) = field_attrs.default { let default_function = Ident::new(&d, field.span()); Some(quote! { @@ -127,7 +120,7 @@ pub fn serialize( }) } } - FieldType::FieldTypeVec { .. } => { + Field::FieldVec { .. } => { let item_ident = Ident::new("yaserde_item", field.span()); let inner = enclose_formatted_characters(&item_ident, label_name); @@ -151,7 +144,7 @@ pub fn serialize( }) } } - FieldType::FieldTypeStruct { .. } => { + Field::FieldStruct { .. } => { if let Some(ref d) = field_attrs.default { let default_function = Ident::new(&d, field.span()); Some(quote! { @@ -183,7 +176,7 @@ pub fn serialize( } _ => unimplemented!(), }, - FieldType::FieldTypeStruct { .. } => { + Field::FieldStruct { .. } => { if let Some(ref d) = field_attrs.default { let default_function = Ident::new(&d, field.span()); Some(quote! { @@ -203,7 +196,7 @@ pub fn serialize( } } _ => None, - }) + } }) .filter_map(|x| x) .collect(); @@ -213,51 +206,49 @@ pub fn serialize( .iter() .map(|field| { let field_attrs = YaSerdeAttribute::parse(&field.attrs); - if field_attrs.attribute { + if Field::is_attribute(field) { return None; } - let label = &field.ident; - if field_attrs.text { + let label = Field::label(field); + if Field::is_text_content(field) { return Some(quote!( let data_event = XmlEvent::characters(&self.#label); writer.write(data_event).map_err(|e| e.to_string())?; )); } - let label_name = build_label_name( - &label.as_ref().unwrap(), - &field_attrs, - &root_attributes.default_namespace, - ); - let conditions = condition_generator(label, &field_attrs); + let label_name = Field::renamed_label(field, root_attributes); - get_field_type(field).and_then(|f| match f { - FieldType::FieldTypeString - | FieldType::FieldTypeBool - | FieldType::FieldTypeI8 - | FieldType::FieldTypeU8 - | FieldType::FieldTypeI16 - | FieldType::FieldTypeU16 - | FieldType::FieldTypeI32 - | FieldType::FieldTypeU32 - | FieldType::FieldTypeI64 - | FieldType::FieldTypeU64 - | FieldType::FieldTypeF32 - | FieldType::FieldTypeF64 => serialize_element(label, label_name, &conditions), - FieldType::FieldTypeOption { data_type } => match *data_type { - FieldType::FieldTypeString - | FieldType::FieldTypeBool - | FieldType::FieldTypeI8 - | FieldType::FieldTypeU8 - | FieldType::FieldTypeI16 - | FieldType::FieldTypeU16 - | FieldType::FieldTypeI32 - | FieldType::FieldTypeU32 - | FieldType::FieldTypeI64 - | FieldType::FieldTypeU64 - | FieldType::FieldTypeF32 - | FieldType::FieldTypeF64 => { + let conditions = condition_generator(&label, &field_attrs); + + match Field::from(field) { + Field::FieldString + | Field::FieldBool + | Field::FieldI8 + | Field::FieldU8 + | Field::FieldI16 + | Field::FieldU16 + | Field::FieldI32 + | Field::FieldU32 + | Field::FieldI64 + | Field::FieldU64 + | Field::FieldF32 + | Field::FieldF64 => serialize_element(&label, label_name, &conditions), + + Field::FieldOption { data_type } => match *data_type { + Field::FieldString + | Field::FieldBool + | Field::FieldI8 + | Field::FieldU8 + | Field::FieldI16 + | Field::FieldU16 + | Field::FieldI32 + | Field::FieldU32 + | Field::FieldI64 + | Field::FieldU64 + | Field::FieldF32 + | Field::FieldF64 => { let item_ident = Ident::new("yaserde_item", field.span()); let inner = enclose_formatted_characters_for_value(&item_ident, label_name); @@ -269,7 +260,7 @@ pub fn serialize( } }) } - FieldType::FieldTypeVec { .. } => { + Field::FieldVec { .. } => { let item_ident = Ident::new("yaserde_item", field.span()); let inner = enclose_formatted_characters_for_value(&item_ident, label_name); @@ -283,7 +274,7 @@ pub fn serialize( } }) } - FieldType::FieldTypeStruct { .. } => Some(if field_attrs.flatten { + Field::FieldStruct { .. } => Some(if field_attrs.flatten { quote! { if let Some(ref item) = &self.#label { writer.set_start_event_name(None); @@ -302,7 +293,7 @@ pub fn serialize( }), _ => unimplemented!(), }, - FieldType::FieldTypeStruct { .. } => { + Field::FieldStruct { .. } => { let (start_event, skip_start) = if field_attrs.flatten { (quote!(None), true) } else { @@ -315,8 +306,8 @@ pub fn serialize( self.#label.serialize(writer)?; }) } - FieldType::FieldTypeVec { data_type } => match *data_type { - FieldType::FieldTypeString => { + Field::FieldVec { data_type } => match *data_type { + Field::FieldString => { let item_ident = Ident::new("yaserde_item", field.span()); let inner = enclose_formatted_characters_for_value(&item_ident, label_name); @@ -326,17 +317,17 @@ pub fn serialize( } }) } - FieldType::FieldTypeBool - | FieldType::FieldTypeI8 - | FieldType::FieldTypeU8 - | FieldType::FieldTypeI16 - | FieldType::FieldTypeU16 - | FieldType::FieldTypeI32 - | FieldType::FieldTypeU32 - | FieldType::FieldTypeI64 - | FieldType::FieldTypeU64 - | FieldType::FieldTypeF32 - | FieldType::FieldTypeF64 => { + Field::FieldBool + | Field::FieldI8 + | Field::FieldU8 + | Field::FieldI16 + | Field::FieldU16 + | Field::FieldI32 + | Field::FieldU32 + | Field::FieldI64 + | Field::FieldU64 + | Field::FieldF32 + | Field::FieldF64 => { let item_ident = Ident::new("yaserde_item", field.span()); let inner = enclose_formatted_characters_for_value(&item_ident, label_name); @@ -346,7 +337,7 @@ pub fn serialize( } }) } - FieldType::FieldTypeOption { .. } => Some(quote! { + Field::FieldOption { .. } => Some(quote! { for item in &self.#label { if let Some(value) = item { writer.set_start_event_name(None); @@ -355,18 +346,18 @@ pub fn serialize( } } }), - FieldType::FieldTypeStruct { .. } => Some(quote! { + Field::FieldStruct { .. } => Some(quote! { for item in &self.#label { writer.set_start_event_name(None); writer.set_skip_start_end(false); item.serialize(writer)?; } }), - FieldType::FieldTypeVec { .. } => { + Field::FieldVec { .. } => { unimplemented!(); } }, - }) + } }) .filter_map(|x| x) .collect(); diff --git a/yaserde_derive/src/ser/implement_deserializer.rs b/yaserde_derive/src/ser/implement_deserializer.rs index b128d7b..645b4ed 100644 --- a/yaserde_derive/src/ser/implement_deserializer.rs +++ b/yaserde_derive/src/ser/implement_deserializer.rs @@ -1,4 +1,4 @@ -use crate::attribute::YaSerdeAttribute; +use crate::common::YaSerdeAttribute; use crate::ser::namespace::generate_namespaces_definition; use proc_macro2::Ident; use proc_macro2::TokenStream; diff --git a/yaserde_derive/src/ser/label.rs b/yaserde_derive/src/ser/label.rs index b77ee2e..89998a5 100644 --- a/yaserde_derive/src/ser/label.rs +++ b/yaserde_derive/src/ser/label.rs @@ -1,4 +1,4 @@ -use crate::attribute::YaSerdeAttribute; +use crate::common::YaSerdeAttribute; use proc_macro2::Ident; pub fn build_label_name( diff --git a/yaserde_derive/src/ser/mod.rs b/yaserde_derive/src/ser/mod.rs index 6e5e8c1..c294514 100644 --- a/yaserde_derive/src/ser/mod.rs +++ b/yaserde_derive/src/ser/mod.rs @@ -5,7 +5,7 @@ pub mod implement_deserializer; pub mod label; pub mod namespace; -use crate::attribute::YaSerdeAttribute; +use crate::common::YaSerdeAttribute; use proc_macro2::TokenStream; use syn; use syn::Ident; diff --git a/yaserde_derive/src/ser/namespace.rs b/yaserde_derive/src/ser/namespace.rs index 6a7bf5a..3127531 100644 --- a/yaserde_derive/src/ser/namespace.rs +++ b/yaserde_derive/src/ser/namespace.rs @@ -1,4 +1,4 @@ -use crate::attribute::YaSerdeAttribute; +use crate::common::YaSerdeAttribute; use proc_macro2::TokenStream; pub fn generate_namespaces_definition(attributes: &YaSerdeAttribute) -> TokenStream {