1#![warn(dead_code)]
2#![warn(unused_imports)]
3extern crate proc_macro;
4
5use proc_macro::TokenStream;
6use quote::quote;
7use syn::{parse_macro_input, ItemFn, ReturnType};
8
9#[proc_macro_attribute]
10pub fn backoff(_attr: TokenStream, item: TokenStream) -> TokenStream {
11
12 let input = parse_macro_input!(item as ItemFn);
13 let fn_attrs = &input.attrs;
14 let fn_vis = &input.vis;
15 let fn_sig = &input.sig;
16 let fn_block = &input.block;
17
18 let output_type = match &input.sig.output {
19 ReturnType::Type(_, ty) => ty,
20 ReturnType::Default => {
21 return syn::Error::new_spanned(&input.sig.output, "expected a return type")
22 .to_compile_error()
23 .into();
24 }
25 };
26
27 let expanded = quote! {
28 #(#fn_attrs)*
29 #fn_vis #fn_sig {
30
31 let result: #output_type = backoff::future::retry(backoff::ExponentialBackoff::default(), || async {
32 Ok(#fn_block?)
33 }).await;
34
35 result
36 }
37 };
38
39 TokenStream::from(expanded)
40}