1#![warn(missing_docs)]
6#![doc(
7 html_logo_url = "https://raw.githubusercontent.com/getsentry/relay/master/artwork/relay-icon.png",
8 html_favicon_url = "https://raw.githubusercontent.com/getsentry/relay/master/artwork/relay-icon.png"
9)]
10#![allow(clippy::derive_partial_eq_without_eq)]
11
12use proc_macro::TokenStream;
13use quote::ToTokens;
14use syn::fold::Fold;
15
16struct CatchUnwind;
17
18impl CatchUnwind {
19 fn fold(&mut self, input: TokenStream) -> TokenStream {
20 let f = syn::parse(input).expect("#[catch_unwind] can only be applied to functions");
21 self.fold_item_fn(f).to_token_stream().into()
22 }
23}
24
25impl Fold for CatchUnwind {
26 fn fold_item_fn(&mut self, i: syn::ItemFn) -> syn::ItemFn {
27 if i.sig.unsafety.is_none() {
28 panic!("#[catch_unwind] requires `unsafe fn`");
29 }
30
31 let inner = i.block;
32 let folded = quote::quote! {{
33 ::relay_ffi::__internal::catch_errors(|| {
34 let __ret = #inner;
35
36 #[allow(unreachable_code)]
37 Ok(__ret)
38 })
39 }};
40
41 let block = Box::new(syn::parse2(folded).unwrap());
42 syn::ItemFn { block, ..i }
43 }
44}
45
46#[proc_macro_attribute]
64pub fn catch_unwind(_attr: TokenStream, item: TokenStream) -> TokenStream {
65 CatchUnwind.fold(item)
66}