github_flows_macros/
lib.rs

1use proc_macro::TokenStream;
2use quote::{quote, ToTokens};
3
4#[proc_macro_attribute]
5pub fn event_handler(_: TokenStream, item: TokenStream) -> TokenStream {
6    let ast: syn::ItemFn = syn::parse(item).unwrap();
7    let func_ident = ast.sig.ident.clone();
8
9    let gen = quote! {
10        mod github_flows_macros {
11            extern "C" {
12                pub fn get_event_body_length() -> i32;
13                pub fn get_event_body(p: *mut u8) -> i32;
14                pub fn get_event_headers_length() -> i32;
15                pub fn get_event_headers(p: *mut u8) -> i32;
16            }
17
18        }
19
20        fn __github_event_headers() -> Option<Vec<(String, String)>> {
21            unsafe {
22                let l = github_flows_macros::get_event_headers_length();
23                let mut event_body = Vec::<u8>::with_capacity(l as usize);
24                let c = github_flows_macros::get_event_headers(event_body.as_mut_ptr());
25                assert!(c == l);
26                event_body.set_len(c as usize);
27
28                match serde_json::from_slice(&event_body) {
29                    Ok(e) => Some(e),
30                    Err(_) => None,
31                }
32            }
33        }
34
35
36        fn __github_event_received() -> Result<github_flows::octocrab::models::webhook_events::WebhookEvent, serde_json::Error> {
37            unsafe {
38                let headers = __github_event_headers();
39                let event_name = headers
40                    .unwrap_or_default()
41                    .into_iter()
42                    .find(|header| header.0.to_ascii_lowercase() == "x-github-event") // X-GitHub-Event
43                    .unwrap_or((String::new(), String::new()))
44                    .1;
45
46                let l = github_flows_macros::get_event_body_length();
47                let mut event_body = Vec::<u8>::with_capacity(l as usize);
48                let c = github_flows_macros::get_event_body(event_body.as_mut_ptr());
49                assert!(c == l);
50                event_body.set_len(c as usize);
51
52                github_flows::octocrab::models::webhook_events::WebhookEvent::try_from_header_and_body(&event_name, &event_body)
53            }
54        }
55
56        #[no_mangle]
57        #[tokio::main(flavor = "current_thread")]
58        pub async fn __github__on_event_received() {
59            let webhook_event = __github_event_received();
60            #func_ident(webhook_event).await;
61        }
62    };
63
64    let ori_run_str = ast.to_token_stream().to_string();
65    let x = gen.to_string() + &ori_run_str;
66    x.parse().unwrap()
67}