xavier-derive 0.1.7

Derive module of Xavier. Xavier is a lightweight and versatile XML parsing library designed to streamline the process of handling XML data with ease and efficiency.
Documentation
use proc_macro2::TokenStream;
use quote::{quote};
use syn::{DeriveInput, LitBool};
use proc_macro2::Span;
use crate::common::meta::{MetaInfo, MetaName};
use crate::common::naming::names::XmlNames;
use crate::serialize::parser::element::XmlElementDef;
use crate::serialize::parser::declaration::XmlDeclaration;
use crate::serialize::parser::dtd::XmlDTD;
use crate::serialize::parser::instructions::XmlPI;

pub(crate) struct XmlMainTag;

impl XmlMainTag {
    pub fn parse(input: &DeriveInput) -> TokenStream {
        let obj_meta_info = MetaInfo::from_name(&input.attrs, MetaName::XML);
        let elements = XmlElementDef::parse(&input, obj_meta_info.as_ref());
        let tag = XmlNames::root(&input, obj_meta_info.as_ref());
        let dtd = XmlDTD::parse(&input, &tag);
        let pi = XmlPI::parse(&input);
        let declaration = XmlDeclaration::parse(&input, &tag);

        if let Some(elements) = elements {
            let attributes = elements.attributes;
            let children = elements.tags;
            let flatten = LitBool::new(obj_meta_info.unwrap_or(MetaInfo::empty()).contains("flatten"), Span::call_site());

            let namespace_tokens = if let Some(namespace) = elements.namespace {
                quote! { let namespace = &self.#namespace; }
            } else {
                quote! { let namespace = ""; }
            };

            quote! {
                #namespace_tokens

                let mut xml = String::new();
                let tag = if let Some(name) = xa_tag_name { name} else { #tag };

                xml.push_str(&#declaration);
                xml.push_str(&#pi);
                xml.push_str(&#dtd);

                let mut attributes = String::new();
                #(attributes.push_str(&#attributes);)*

                if !#flatten {
                    xml.push_str("<");
                    xml.push_str(&tag);
                    if !namespace.is_empty() {
                        xml.push_str(&namespace);
                    }
                    if !attributes.is_empty() {
                        xml.push_str(&attributes);
                    }
                    xml.push_str(">");
                }

                let mut children = String::new();
                #(children.push_str(&#children);)*
                xml.push_str(&children);

                if !#flatten {
                   xml.push_str(&format!("</{}>", tag));
                }
            }
        } else {
            quote! {
                let tag = #tag;
                let xml = format!("{}{}{}<{}></{}>", #declaration, #pi, #dtd, tag, tag).to_string();
            }
        }
    }
}