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}