ora_client_macros/
lib.rs

1//! Macros for the ora-client crate.
2
3use proc_macro::TokenStream;
4
5use quote::{quote, ToTokens};
6use syn::{parse_macro_input, DeriveInput, Expr};
7
8use darling::FromDeriveInput;
9
10#[derive(FromDeriveInput)]
11#[darling(attributes(ora))]
12struct JobType {
13    #[darling(default = default_output)]
14    output: syn::Type,
15    #[darling(default)]
16    retries: Option<Expr>,
17    #[darling(default)]
18    timeout: Option<String>,
19
20    #[darling(default)]
21    default_labels: Option<syn::Expr>,
22
23    ident: syn::Ident,
24}
25
26fn default_output() -> syn::Type {
27    syn::parse_quote! { () }
28}
29
30impl ToTokens for JobType {
31    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
32        let output = &self.output;
33        let ident_str = self.ident.to_string();
34
35        let retry_policy = match &self.retries {
36            Some(retries) => quote! {
37                fn default_retry_policy() -> ora::job_definition::RetryPolicy {
38                    ora::job_definition::RetryPolicy {
39                        retries: #retries,
40                    }
41                }
42            },
43            None => quote! {},
44        };
45
46        let timeout_policy = match &self.timeout {
47            Some(timeout) => {
48                let timeout_seconds = humantime::parse_duration(timeout).unwrap().as_secs();
49
50                quote! {
51                    fn default_timeout_policy() -> ora::job_definition::TimeoutPolicy {
52                        ora::job_definition::TimeoutPolicy {
53                            timeout: Some(std::time::Duration::from_secs(#timeout_seconds as _)),
54                            base_time: ora::job_definition::TimeoutBaseTime::StartTime,
55                        }
56                    }
57                }
58            }
59            None => quote! {},
60        };
61
62        let default_labels = match &self.default_labels {
63            Some(default_labels) => quote! {
64                fn default_labels() -> std::collections::HashMap<String, String> {
65                    #default_labels
66                }
67            },
68            None => quote! {},
69        };
70
71        let ident = &self.ident;
72        tokens.extend(quote! {
73            impl ora::JobType for #ident {
74                type Output = #output;
75
76                fn id() -> &'static str {
77                    #ident_str
78                }
79
80                #retry_policy
81                #timeout_policy
82                #default_labels
83            }
84        });
85    }
86}
87
88/// Derive macro for the `JobType` trait.
89#[allow(clippy::missing_panics_doc)]
90#[proc_macro_derive(JobType, attributes(ora))]
91pub fn job_type_derive(input: TokenStream) -> TokenStream {
92    let input = parse_macro_input!(input as DeriveInput);
93
94    let job_type = JobType::from_derive_input(&input).unwrap();
95
96    quote! {#job_type}.into()
97}