Skip to main content

minion_engine/config/
mod.rs

1pub mod defaults;
2pub mod manager;
3pub mod merge;
4
5pub use defaults::apply_defaults;
6pub use manager::ConfigManager;
7
8use std::collections::HashMap;
9use std::time::Duration;
10
11/// Resolved configuration for a specific step (after 4-layer merge)
12#[derive(Debug, Clone, Default)]
13pub struct StepConfig {
14    pub values: HashMap<String, serde_json::Value>,
15}
16
17#[allow(dead_code)]
18impl StepConfig {
19    pub fn get_str(&self, key: &str) -> Option<&str> {
20        self.values.get(key).and_then(|v| v.as_str())
21    }
22
23    pub fn get_bool(&self, key: &str) -> bool {
24        self.values
25            .get(key)
26            .and_then(|v| v.as_bool())
27            .unwrap_or(false)
28    }
29
30    pub fn get_duration(&self, key: &str) -> Option<Duration> {
31        let s = self.get_str(key)?;
32        parse_duration(s)
33    }
34
35    pub fn get_u64(&self, key: &str) -> Option<u64> {
36        self.values.get(key).and_then(|v| v.as_u64())
37    }
38}
39
40pub fn parse_duration(s: &str) -> Option<Duration> {
41    let s = s.trim();
42    // Check "ms" before "s" to avoid "100ms" matching as seconds
43    if let Some(ms) = s.strip_suffix("ms") {
44        ms.trim().parse::<u64>().ok().map(Duration::from_millis)
45    } else if let Some(secs) = s.strip_suffix('s') {
46        secs.trim().parse::<u64>().ok().map(Duration::from_secs)
47    } else if let Some(mins) = s.strip_suffix('m') {
48        mins.trim()
49            .parse::<u64>()
50            .ok()
51            .map(|m| Duration::from_secs(m * 60))
52    } else {
53        s.parse::<u64>().ok().map(Duration::from_secs)
54    }
55}