From afdbf2dc45b09ad4fbc0bc6bf9a0dcb75b9f7b7b Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Mon, 5 Sep 2022 13:14:31 +0200 Subject: [PATCH] Move serialization macro into module --- instant-xml-macros/src/lib.rs | 66 +----------------------------- instant-xml-macros/src/ser.rs | 76 +++++++++++++++++++++++++++++++---- 2 files changed, 71 insertions(+), 71 deletions(-) diff --git a/instant-xml-macros/src/lib.rs b/instant-xml-macros/src/lib.rs index 3fa3c68..30a136c 100644 --- a/instant-xml-macros/src/lib.rs +++ b/instant-xml-macros/src/lib.rs @@ -5,76 +5,14 @@ mod ser; use std::collections::HashMap; -use proc_macro2::TokenStream; -use quote::{quote, ToTokens}; +use quote::quote; use syn::punctuated::Punctuated; use syn::{parse_macro_input, Meta, NestedMeta}; -use crate::ser::Serializer; - #[proc_macro_derive(ToXml, attributes(xml))] pub fn to_xml(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let ast = parse_macro_input!(input as syn::DeriveInput); - - let ident = &ast.ident; - let generics = (&ast.generics).into_token_stream(); - - let root_name = ident.to_string(); - let mut serializer = Serializer::new(&ast); - - let mut header = TokenStream::new(); - serializer.add_header(&mut header); - - let mut body = TokenStream::new(); - let mut attributes = TokenStream::new(); - match &ast.data { - syn::Data::Struct(ref data) => { - match data.fields { - syn::Fields::Named(ref fields) => { - fields.named.iter().for_each(|field| { - serializer.process_named_field(field, &mut body, &mut attributes); - }); - } - syn::Fields::Unnamed(_) => todo!(), - syn::Fields::Unit => {} - }; - } - _ => todo!(), - }; - - let mut footer = TokenStream::new(); - serializer.add_footer(&root_name, &mut footer); - - let current_namespaces = serializer.namespaces_token(); - - proc_macro::TokenStream::from(quote!( - impl #generics ToXml for #ident #generics { - fn serialize( - &self, - serializer: &mut instant_xml::Serializer, - ) -> Result<(), instant_xml::Error> { - let _ = serializer.consume_field_context(); - let mut field_context = instant_xml::ser::FieldContext { - name: #root_name, - attribute: None, - }; - - #attributes - - #header - #current_namespaces - #body - #footer - - // Removing current namespaces - for it in to_remove { - serializer.parent_namespaces.remove(it); - } - - Ok(()) - } - }; - )) + ser::to_xml(&ast).into() } #[proc_macro_derive(FromXml, attributes(xml))] diff --git a/instant-xml-macros/src/ser.rs b/instant-xml-macros/src/ser.rs index f213c8f..f771b61 100644 --- a/instant-xml-macros/src/ser.rs +++ b/instant-xml-macros/src/ser.rs @@ -1,20 +1,82 @@ use proc_macro2::TokenStream; -use quote::quote; +use quote::{quote, ToTokens}; use crate::{ContainerMeta, FieldMeta, Namespace}; -pub struct Serializer { +pub fn to_xml(input: &syn::DeriveInput) -> proc_macro2::TokenStream { + let ident = &input.ident; + let generics = (&input.generics).into_token_stream(); + + let root_name = ident.to_string(); + let mut serializer = Serializer::new(input); + + let mut header = TokenStream::new(); + serializer.add_header(&mut header); + + let mut body = TokenStream::new(); + let mut attributes = TokenStream::new(); + match &input.data { + syn::Data::Struct(ref data) => { + match data.fields { + syn::Fields::Named(ref fields) => { + fields.named.iter().for_each(|field| { + serializer.process_named_field(field, &mut body, &mut attributes); + }); + } + syn::Fields::Unnamed(_) => todo!(), + syn::Fields::Unit => {} + }; + } + _ => todo!(), + }; + + let mut footer = TokenStream::new(); + serializer.add_footer(&root_name, &mut footer); + + let current_namespaces = serializer.namespaces_token(); + + quote!( + impl #generics ToXml for #ident #generics { + fn serialize( + &self, + serializer: &mut instant_xml::Serializer, + ) -> Result<(), instant_xml::Error> { + let _ = serializer.consume_field_context(); + let mut field_context = instant_xml::ser::FieldContext { + name: #root_name, + attribute: None, + }; + + #attributes + + #header + #current_namespaces + #body + #footer + + // Removing current namespaces + for it in to_remove { + serializer.parent_namespaces.remove(it); + } + + Ok(()) + } + }; + ) +} + +struct Serializer { meta: ContainerMeta, } impl<'a> Serializer { - pub fn new(input: &syn::DeriveInput) -> Self { + fn new(input: &syn::DeriveInput) -> Self { Self { meta: ContainerMeta::from_derive(input), } } - pub fn add_header(&mut self, output: &'a mut TokenStream) { + fn add_header(&mut self, output: &'a mut TokenStream) { output.extend(quote!( serializer.output.write_char('<')?; serializer.output.write_str(field_context.name)?; @@ -60,7 +122,7 @@ impl<'a> Serializer { )); } - pub fn add_footer(&mut self, root_name: &str, output: &'a mut TokenStream) { + fn add_footer(&mut self, root_name: &str, output: &'a mut TokenStream) { output.extend(quote!( serializer.output.write_str(" Serializer { )); } - pub fn process_named_field( + fn process_named_field( &mut self, field: &syn::Field, body: &mut TokenStream, @@ -134,7 +196,7 @@ impl<'a> Serializer { )); } - pub fn namespaces_token(&self) -> TokenStream { + fn namespaces_token(&self) -> TokenStream { let mut namespaces = quote!( let mut to_remove: Vec<&str> = Vec::new(); );