axum-route 0.1.1

Minimalistic route macro for axum
Documentation
use proc_macro::{TokenStream, Span};
use syn::{parse_macro_input, ItemFn};
use syn::punctuated::Punctuated;
use syn::parse::{Parse, ParseStream};
use quote::quote;

struct Args {
    vars: Vec<syn::Expr>
}

impl Parse for Args {
    fn parse(input: ParseStream) -> syn::parse::Result<Self> {
        let vars = Punctuated::<syn::Expr, syn::Token![,]>::parse_terminated(input)?;
        
        Ok(Args {
            vars: vars.into_iter().collect(),
        })
    }
}

impl Args {
    pub fn get_method(&self) -> syn::Result<syn::Expr> {
        match self.vars.get(0) {
            Some(var) => Ok(var.clone()),
            None => return Err(syn::Error::new(
                Span::call_site().into(),
                "No HTTP Method was provided"
            ))
        }
    }
    
    pub fn get_route(&self) -> syn::Result<syn::Expr> {
        match self.vars.get(1) {
            Some(var) => Ok(var.clone()),
            None => return Err(syn::Error::new(
                Span::call_site().into(),
                "No Route was provided"
            ))
        }
    }
}

#[proc_macro_attribute]
pub fn route(args: TokenStream, input: TokenStream) -> TokenStream {
    let args = parse_macro_input!(args as Args);
    let func = parse_macro_input!(input as ItemFn);
    
    let vis = func.vis.clone();
    let ident = func.sig.ident.clone();
    
    let method = args.get_method().unwrap();
    let route = args.get_route().unwrap();
    
    let expanded = quote! {
        #[allow(non_camel_case_types)]
        #vis struct #ident;
        
        impl #ident {
            #vis fn route() -> axum::Router {
                #func
                
                axum::Router::new().route(#route, #method (#ident))
            }
        }
    };
    
    expanded.into()
}