Skip to main content

asimov_patterns/options/
timing.rs

1// This is free and unencumbered software released into the public domain.
2
3//! Shared execution timing options.
4
5#[cfg(any(feature = "std", feature = "clap"))]
6use alloc::{format, string::String};
7use bon::Builder;
8use core::time::Duration;
9
10#[cfg(feature = "clap")]
11const HELP_DEADLINE: &str = r#"Allow at most this duration for the command.
12
13Use a relative duration such as 30s or "1m 30s", not an absolute timestamp.
14Zero is accepted. If omitted, timing policy is command-specific."#;
15
16/// Execution timing requests shared by program commands.
17///
18/// Flatten this alongside a program's options in a host's Clap arguments.
19/// The deadline is a relative duration, not an absolute timestamp. It defaults
20/// to `None`, leaving timing policy to the implementation. Clap accepts
21/// human-readable durations such as `30s` or `1m 30s`, including zero.
22///
23/// These options do not enforce timeouts. Hosts can forward an explicit value
24/// using `deadline_option()` (available with `std` or `clap`). Cache freshness
25/// is configured separately by [`crate::CachingOptions`].
26#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, Builder)]
27#[builder(derive(Debug))]
28#[cfg_attr(feature = "clap", derive(clap::Args))]
29#[cfg_attr(feature = "clap", command(about = None, long_about = None))]
30pub struct TimingOptions {
31    /// Allow at most this duration for the command (for example, 30s).
32    #[cfg_attr(
33        feature = "clap",
34        clap(
35            long,
36            value_name = "DURATION",
37            value_parser = humantime::parse_duration,
38            help = "Allow at most this duration for the command",
39            long_help = HELP_DEADLINE
40        )
41    )]
42    pub deadline: Option<Duration>,
43}
44
45#[cfg(any(feature = "std", feature = "clap"))]
46impl TimingOptions {
47    /// Formats an explicit deadline as one `--deadline=DURATION` argument.
48    ///
49    /// Returns `None` when unset; a zero duration is forwarded as `0s`.
50    pub fn deadline_option(&self) -> Option<String> {
51        self.deadline
52            .map(|value| format!("--deadline={}", humantime::format_duration(value)))
53    }
54}