tokio_timeout/
lib.rs

1#![warn(clippy::pedantic)]
2use proc_macro::TokenStream;
3
4/// # Timeout macro
5///
6/// A proc macro attribute that can be put on an async function, running within a
7/// tokio runtime, with the feature `time` enabled, which wraps the function in `tokio::time::timeout`
8///
9/// ```
10/// #[tokio_timeout::timeout(duration = "1s", on_error = "panic")]
11/// async fn my_fn() {
12///     println!("hello!");
13/// }
14/// ```
15///
16/// It takes two mandatory arguments 'duration' and `on_error`.
17///
18/// ## Duration
19///
20/// 'Duration' can be either a string-literal that specifies a duration,
21/// valid values are `<n>h` for hours, `<n>m` for minutes, `<n>s` for seconds, and `<n>ms`
22/// for milliseconds. They can be chained together.
23///
24/// ```
25/// #[tokio_timeout::timeout(duration = "5h4m3s2ms", on_error = "panic")]
26/// async fn my_fn() {
27///     println!("hello!");
28/// }
29/// ```
30///
31/// Duration can also be specified to be some constant
32///
33/// ```
34/// use std::time::Duration;
35///
36/// const MY_DUR: Duration = Duration::from_millis(55);
37///
38/// #[tokio_timeout::timeout(duration = MY_DUR, on_error = "panic")]
39/// async fn my_fn() {
40///     println!("hello!");
41/// }
42/// ```
43///
44/// ## On error
45///
46/// On error can either be the string literal "panic", as seen in examples above,
47/// or something that can be invoked with a `&'static str` to produce an error.
48///
49/// ```
50///
51/// fn to_error_result(s: &str) -> Result<(), String>{
52///    Err(s.to_string())
53/// }
54///
55/// #[tokio_timeout::timeout(duration = "5h4m3s2ms", on_error = to_error_result)]
56/// async fn my_fn_string_err() -> Result<(), String>{
57///     println!("hello!");
58///     Ok(())
59/// }
60///
61/// pub enum MyErr {
62///     Timeout(&'static str)
63/// }
64///
65/// const fn to_error_enum(s: &'static str) -> Result<(), MyErr> {
66///     Err(MyErr::Timeout(s))
67/// }
68///
69/// #[tokio_timeout::timeout(duration = "5h4m3s2ms", on_error = to_error_enum)]
70/// async fn my_fn_enum_err() -> Result<(), MyErr>{
71///     println!("hello!");
72///     Ok(())
73/// }
74///
75/// fn print_err(s: &'static str) {
76///     eprintln!("oh no: {s}")
77/// }
78///
79/// #[tokio_timeout::timeout(duration = "5h4m3s2ms", on_error = print_err)]
80/// async fn my_print_timeout_fn() {
81///     println!("hello!");
82/// }
83///
84/// #[tokio_timeout::timeout(duration = "5h4m3s2ms", on_error = anyhow::bail!)]
85/// async fn anyhow_err_fn() -> anyhow::Result<()> {
86///     println!("hello!");
87///     Ok(())
88/// }
89///
90/// ```
91///
92/// ```compile_fail
93/// #[tokio_timeout::timeout]
94/// async fn both_attrs_needed() {}
95/// ```
96///
97/// ```compile_fail
98/// #[tokio_timeout::timeout]
99/// fn only_async_functions() {}
100/// ```
101///
102/// ```compile_fail
103/// #[tokio_timeout::timeout(duration = "1z", on_error = "panic")]
104/// async fn unrecognized_duration() {}
105/// ```
106///
107/// ```compile_fail
108/// #[tokio_timeout::timeout(duration = "1s", on_error = "panico")]
109/// async fn unrecognized_on_error() {}
110/// ```
111///
112#[proc_macro_attribute]
113pub fn timeout(attr: TokenStream, item: TokenStream) -> TokenStream {
114    timeout_macro_parse::tokio_timeout(attr, item)
115}