1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
use proc_macro::TokenStream;
use quote::{quote, ToTokens};

#[proc_macro_attribute]
pub fn request_handler(_: TokenStream, item: TokenStream) -> TokenStream {
    let ast: syn::ItemFn = syn::parse(item).unwrap();
    let func_ident = ast.sig.ident.clone();

    let gen = quote! {
        mod webhook_flows_macros {
            extern "C" {
                pub fn get_event_headers_length() -> i32;
                pub fn get_event_headers(p: *mut u8) -> i32;
                pub fn get_event_query_length() -> i32;
                pub fn get_event_query(p: *mut u8) -> i32;
                pub fn get_event_subpath_length() -> i32;
                pub fn get_event_subpath(p: *mut u8) -> i32;
                pub fn get_event_body_length() -> i32;
                pub fn get_event_body(p: *mut u8) -> i32;
            }
        }

        fn __request() -> Option<(Vec<(String, String)>, String, HashMap<String, Value>, Vec<u8>)> {
            unsafe {
                let l = webhook_flows_macros::get_event_headers_length();
                let mut event_headers = Vec::<u8>::with_capacity(l as usize);
                let c = webhook_flows_macros::get_event_headers(event_headers.as_mut_ptr());
                assert!(c == l);
                event_headers.set_len(c as usize);
                let event_headers = serde_json::from_slice(&event_headers).unwrap();

                let l = webhook_flows_macros::get_event_query_length();
                let mut event_query = Vec::<u8>::with_capacity(l as usize);
                let c = webhook_flows_macros::get_event_query(event_query.as_mut_ptr());
                assert!(c == l);
                event_query.set_len(c as usize);
                let event_query = serde_json::from_slice(&event_query).unwrap();

                let l = webhook_flows_macros::get_event_subpath_length();
                let mut event_subpath = Vec::<u8>::with_capacity(l as usize);
                let c = webhook_flows_macros::get_event_subpath(event_subpath.as_mut_ptr());
                assert!(c == l);
                event_subpath.set_len(c as usize);
                let event_subpath = String::from_utf8_lossy(&event_subpath).into_owned();

                let l = webhook_flows_macros::get_event_body_length();
                let mut event_body = Vec::<u8>::with_capacity(l as usize);
                let c = webhook_flows_macros::get_event_body(event_body.as_mut_ptr());
                assert!(c == l);
                event_body.set_len(c as usize);

                Some((event_headers, event_subpath, event_query, event_body))
            }
        }

        #[no_mangle]
        #[tokio::main(flavor = "current_thread")]
        pub async fn __webhook__on_request_received() {
            if let Some((headers, subpath, qry, body)) = __request() {
                #func_ident(headers, subpath, qry, body).await;
            }
        }
    };

    let ori_run_str = ast.to_token_stream().to_string();
    let x = gen.to_string() + &ori_run_str;
    x.parse().unwrap()
}