PluralKit/crates/macros/src/api.rs
2025-09-06 18:28:24 +00:00

52 lines
1.6 KiB
Rust

use quote::quote;
use syn::{FnArg, ItemFn, Pat, parse_macro_input};
fn _pretty_print(ts: &proc_macro2::TokenStream) -> String {
let file = syn::parse_file(&ts.to_string()).unwrap();
prettyplease::unparse(&file)
}
pub fn macro_impl(
_args: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let input = parse_macro_input!(input as ItemFn);
let fn_name = &input.sig.ident;
let fn_params = &input.sig.inputs;
let fn_body = &input.block;
let syn::ReturnType::Type(_, fn_return_type) = &input.sig.output else {
panic!("handler return type must not be nothing");
};
let pms: Vec<proc_macro2::TokenStream> = fn_params
.iter()
.map(|v| {
let FnArg::Typed(pat) = v else {
panic!("must not have self param in handler");
};
let mut pat = pat.pat.clone();
if let Pat::Ident(ident) = *pat {
let mut ident = ident.clone();
ident.mutability = None;
pat = Box::new(Pat::Ident(ident));
}
quote! { #pat }
})
.collect();
let res = quote! {
#[allow(unused_mut)]
pub async fn #fn_name(#fn_params) -> axum::response::Response {
async fn inner(#fn_params) -> Result<#fn_return_type, crate::error::PKError> {
#fn_body
}
match inner(#(#pms),*).await {
Ok(res) => res.into_response(),
Err(err) => err.into_response(),
}
}
};
res.into()
}