use darling::FromMeta;
use proc_macro::TokenStream;
use quote::quote;
use crate::bundlepart::{self, FnSpec};
#[derive(Debug, FromMeta, Default)]
struct PeriodicConfMeta {
#[darling(default)]
secs: Option<u64>,
#[darling(default)]
millis: Option<u64>,
#[darling(default)]
target: Option<String>,
}
pub(crate) fn parse_periodic(attr: TokenStream, item: TokenStream) -> TokenStream {
bundlepart::generate_bundle_part::<PeriodicConfMeta>(
attr,
item,
"periodic",
build_periodic_conf,
)
}
fn build_periodic_conf(
conf: &PeriodicConfMeta,
_spec: &FnSpec,
) -> Result<proc_macro2::TokenStream, syn::Error> {
let interval = match (conf.secs, conf.millis) {
(Some(s), None) => quote! { ::tokio::time::Duration::from_secs(#s) },
(None, Some(m)) => quote! { ::tokio::time::Duration::from_millis(#m) },
(Some(s), Some(m)) => {
quote! { ::tokio::time::Duration::from_secs(#s) + ::tokio::time::Duration::from_millis(#m) }
}
(None, None) => {
return Err(syn::Error::new(
proc_macro2::Span::call_site(),
"Periodic requires at least one of: secs, millis. Use: #[periodic(secs = 60)] or #[periodic(millis = 1000)]"
));
}
};
let target = if let Some(target_str) = &conf.target {
quote! { ::uxar::emitters::EmitTarget::from_str(#target_str).unwrap_or_default() }
} else {
quote! { ::uxar::emitters::EmitTarget::default() }
};
Ok(quote! {
::uxar::emitters::PeriodicConf {
interval: #interval,
target: #target,
}
})
}