actix-web-cute-codegen 0.1.0

My codegen macros
Documentation
use quote::quote;
use proc_macro::TokenStream;

use std::fmt;

pub struct Args {
    path: String,
    service: Vec<String>,
    guards: Vec<String>,
    ast: syn::DeriveInput,
}

impl Args {
    pub fn new(ast: syn::DeriveInput) -> Self {
        let struct_data = match ast.data {
            syn::Data::Struct(ref data) => data,
            _ => panic!("derive(Scope) is available for structs only"),
        };

        let mut path = "/".to_owned();
        for attr in ast.attrs.iter().flat_map(|attr| attr.parse_meta().ok()) {
            if attr.name() == "path" {
                match attr {
                    syn::Meta::NameValue(meta) => match meta.lit {
                        syn::Lit::Str(text) => {
                            path = text.value()
                        },
                        _ => panic!("'path' attribute is invalid, should string value"),
                    },
                    _ => panic!("'path' attribute is invalid, should contain value"),
                }
            }
        }

        let mut service = Vec::new();
        let mut guards = Vec::new();
        for field in struct_data.fields.iter() {
            for meta in field.attrs.iter().filter_map(|attr| attr.interpret_meta()) {
                let variable_name = field.ident.as_ref().expect("Named field is needed");

                if meta.name() == "service" {
                    match meta {
                        syn::Meta::Word(_) => {
                            service.push(variable_name.to_string())
                        },
                        _ => panic!("'service' attribute for field '{}' is invalid. Should have no value", variable_name)
                    }
                } else if meta.name() == "guard" {
                    match meta {
                        syn::Meta::Word(_) => {
                            guards.push(variable_name.to_string())
                        },
                        _ => panic!("'guard' attribute for field '{}' is invalid. Should have no value", variable_name)
                    }
                }
            }
        }

        Self {
            path,
            service,
            guards,
            ast
        }
    }

    pub fn generate(&self) -> TokenStream {
        let text = self.to_string();

        match text.parse() {
            Ok(res) => res,
            Err(error) => panic!("Error: {:?}\nGenerated code: {}", error, text)
        }
    }
}

impl fmt::Display for Args {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let (impl_gen, type_gen, where_clause) = self.ast.generics.split_for_impl();

        writeln!(f, "{} {}{} {{", quote!(impl#impl_gen), self.ast.ident, quote!(#type_gen #where_clause))?;

        writeln!(f, "    pub fn actix_scope<P: 'static>(self) -> actix_web::Scope<P> {{")?;

        write!(f, "        actix_web::Scope::new(\"{}\")", self.path)?;

        for service in self.service.iter() {
            write!(f, ".service(self.{})", service)?;
        }
        for guard in self.guards.iter() {
            write!(f, ".guard(self.{})", guard)?;
        }

        writeln!(f, "\n    }}")?;
        writeln!(f, "}}")
    }
}