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#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
28#[builder(derive(Debug))]
29#[cfg_attr(feature = "clap", derive(clap::Args))]
30#[cfg_attr(feature = "clap", command(about = None, long_about = None))]
31pub struct TimingOptions {
32    /// Allow at most this duration for the command (for example, 30s).
33    #[cfg_attr(
34        feature = "clap",
35        clap(
36            long,
37            value_name = "DURATION",
38            value_parser = humantime::parse_duration,
39            help = "Allow at most this duration for the command",
40            long_help = HELP_DEADLINE
41        )
42    )]
43    #[cfg_attr(
44        feature = "serde",
45        serde(
46            default,
47            skip_serializing_if = "Option::is_none",
48            with = "crate::serialization::optional_duration"
49        )
50    )]
51    pub deadline: Option<Duration>,
52}
53
54#[cfg(any(feature = "std", feature = "clap"))]
55impl TimingOptions {
56    /// Formats an explicit deadline as one `--deadline=DURATION` argument.
57    ///
58    /// Returns `None` when unset; a zero duration is forwarded as `0s`.
59    pub fn deadline_option(&self) -> Option<String> {
60        self.deadline
61            .map(|value| format!("--deadline={}", humantime::format_duration(value)))
62    }
63}