Skip to main content

wstd_axum_macro/
lib.rs

1use proc_macro::TokenStream;
2use quote::{quote, quote_spanned};
3use syn::{ItemFn, parse_macro_input, spanned::Spanned};
4
5#[proc_macro_attribute]
6pub fn attr_macro_http_server(_attr: TokenStream, item: TokenStream) -> TokenStream {
7    let input = parse_macro_input!(item as ItemFn);
8
9    if input.sig.ident != "main" {
10        return quote_spanned! { input.sig.ident.span()=>
11            compile_error!("only `fn main` can be used for #[wstd_axum::http_server]");
12        }
13        .into();
14    }
15
16    if !input.sig.inputs.is_empty() {
17        return quote_spanned! { input.sig.inputs.span()=>
18            compile_error!("arguments to main are not supported");
19        }
20        .into();
21    }
22    let (async_, call) = if input.sig.asyncness.is_some() {
23        (quote!(async), quote!(__make_service().await))
24    } else {
25        (quote!(), quote!(__make_service()))
26    };
27    let attrs = input.attrs;
28    let output = input.sig.output;
29    let block = input.block;
30    quote! {
31        #[::wstd::http_server]
32        pub async fn main(
33            __request: ::wstd::http::Request<::wstd::http::Body>
34        ) -> ::wstd::http::error::Result<::wstd::http::Response<::wstd::http::Body>> {
35
36            #(#attrs)*
37            #async_ fn __make_service() #output {
38                #block
39            }
40
41            let __service = #call;
42
43            ::wstd_axum::serve(__request, __service).await
44        }
45    }
46    .into()
47}