fastedge_derive/
lib.rs

1/*
2* Copyright 2024 G-Core Innovations SARL
3*/
4use proc_macro::TokenStream;
5
6use quote::quote;
7use syn::{parse_macro_input, ItemFn};
8
9/// Main function attribute for a FastEdge application.
10///
11/// ## Usage
12///
13/// The `main` function takes a request and returns a response or an error. For example:
14///
15/// ```rust,no_run
16/// use anyhow::Result;
17/// use fastedge::http::{Request, Response, StatusCode};
18/// use fastedge::body::Body;
19///
20/// #[fastedge::http]
21/// fn main(req: Request<Body>) -> Result<Response<Body>> {
22///     Response::builder().status(StatusCode::OK).body(Body::empty())
23/// }
24#[proc_macro_attribute]
25pub fn http(_attr: TokenStream, item: TokenStream) -> TokenStream {
26    let func = parse_macro_input!(item as ItemFn);
27    let func_name = &func.sig.ident;
28
29    quote!(
30        use fastedge::http_handler::Guest;
31        struct Component;
32
33        #[inline(always)]
34        fn internal_error(body: &str) -> ::fastedge::http_handler::Response {
35            ::fastedge::http_handler::Response {
36                status: ::fastedge::http::StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
37                headers: Some(vec![]),
38                body: Some(body.as_bytes().to_vec()),
39            }
40        }
41
42        #[inline(always)]
43        #[no_mangle]
44        #func
45
46        impl Guest for Component {
47            #[no_mangle]
48            fn process(req: ::fastedge::http_handler::Request) -> ::fastedge::http_handler::Response {
49
50                let Ok(request) = req.try_into() else {
51                    return internal_error("http request decode error")
52                };
53
54                let res = match #func_name(request) {
55                    Ok(res) => res,
56                    Err(error) => {
57                        return internal_error(error.to_string().as_str());
58                    }
59                };
60
61                let Ok(response) = ::fastedge::http_handler::Response::try_from(res) else {
62                    return internal_error("http response encode error")
63                };
64                response
65            }
66        }
67
68        fastedge::export!(Component with_types_in fastedge);
69
70
71    ).into()
72}