1
0
Fork 0
mirror of https://gitlab.com/msrd0/gotham-restful.git synced 2025-02-23 21:12:28 +00:00
deprecated-gotham-restful/gotham_restful_derive/src/method.rs

97 lines
2 KiB
Rust
Raw Normal View History

use proc_macro::TokenStream;
use proc_macro2::{Ident, TokenStream as TokenStream2};
use quote::{format_ident, quote};
use syn::{
FnArg,
ItemFn,
ReturnType,
parse_macro_input
};
pub enum Method
{
ReadAll,
Read,
Create,
UpdateAll,
Update,
DeleteAll,
Delete
}
impl Method
{
fn trait_ident(&self) -> Ident
{
use Method::*;
let name = match self {
ReadAll => "ReadAll",
Read => "Read",
Create => "Create",
UpdateAll => "UpdateAll",
Update => "Update",
DeleteAll => "DeleteAll",
Delete => "Delete"
};
format_ident!("Resource{}", name)
}
fn fn_ident(&self) -> Ident
{
use Method::*;
let name = match self {
ReadAll => "read_all",
Read => "read",
Create => "create",
UpdateAll => "update_all",
Update => "update",
DeleteAll => "delete_all",
Delete => "delete"
};
format_ident!("{}", name)
}
}
pub fn expand_method(method : Method, attrs : TokenStream, item : TokenStream) -> TokenStream
{
let ident = parse_macro_input!(attrs as Ident);
let fun = parse_macro_input!(item as ItemFn);
let ret = match fun.sig.output {
ReturnType::Default => quote!(()),
ReturnType::Type(_, ty) => quote!(#ty)
};
let args : Vec<(TokenStream2, TokenStream2)> = fun.sig.inputs.iter().map(|arg| match arg {
FnArg::Typed(arg) => {
let pat = &arg.pat;
let ty = &arg.ty;
(quote!(#pat), quote!(#ty))
},
FnArg::Receiver(_) => panic!("didn't expect self parameter")
}).collect();
let mut generics : Vec<TokenStream2> = Vec::new();
for i in 1..args.len()
{
let (_, ty) = &args[i];
generics.push(quote!(#ty));
}
generics.push(quote!(#ret));
let args : Vec<TokenStream2> = args.into_iter().map(|(pat, ty)| quote!(#pat : #ty)).collect();
let block = fun.block;
let trait_ident = method.trait_ident();
let fn_ident = method.fn_ident();
let output = quote! {
impl ::gotham_restful::#trait_ident<#(#generics),*> for #ident
where #ident : ::gotham_restful::Resource
{
fn #fn_ident(#(#args),*) -> #ret
#block
}
};
output.into()
}