axum_err_handler_macro/
lib.rs1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{DeriveInput, parse::ParseStream, parse_macro_input};
4
5use crate::context::parse_final_response_context_block;
6
7pub(crate) mod context;
8mod custom_fn;
9
10#[proc_macro_derive(AxumErrorResponse, attributes(status_code, code, response))]
11pub fn derive_axum_error_response(input: TokenStream) -> TokenStream {
12 let input = parse_macro_input!(input as DeriveInput);
14 let custom_fn = custom_fn::parse_custom_fn(&input);
15 let name = input.ident.clone();
16
17 let response_block = parse_final_response_context_block(&name, &input);
18
19 let mut expand = quote! {
20 #response_block
21 };
22
23 if custom_fn.is_some() {
24 let custom_fn_name = custom_fn.unwrap();
25
26 let fn_name = custom_fn_name.value();
27 let fn_ident = syn::Ident::new(&fn_name, custom_fn_name.span());
28
29 expand.extend(quote! {
30 impl axum::response::IntoResponse for #name {
31 fn into_response(self) -> axum::response::Response {
32 use axum_error_handler::IntoErrorResponseContext;
33
34 #fn_ident(self.into_response_context())
35 }
36 }
37 });
38
39 TokenStream::from(expand)
40 } else {
41 expand.extend(quote! {
42 impl axum::response::IntoResponse for #name {
43 fn into_response(self) -> axum::response::Response {
44 use axum_error_handler::IntoErrorResponseContext;
45
46 self.into_response_context().into_response()
47 }
48 }
49 });
50
51 TokenStream::from(expand)
52 }
53}