Skip to main content

infraqueue_lib/
cli.rs

1use anyhow::{Context, Result};
2
3/// Parse a boolean from a variety of common string representations.
4/// Accepts: 1/0, true/false, yes/no, on/off (case-insensitive).
5pub fn parse_bool(s: &str) -> Option<bool> {
6    match s.to_ascii_lowercase().as_str() {
7        "1" | "true" | "yes" | "on" => Some(true),
8        "0" | "false" | "no" | "off" => Some(false),
9        _ => None,
10    }
11}
12
13/// Fetch the next token value for a flag from any iterator over Strings.
14/// Returns anyhow::Error when value is missing.
15pub fn take_value<I: Iterator<Item = String>>(flag: &str, it: &mut I) -> Result<String> {
16    it.next().context(format!("missing value for {flag}"))
17}
18
19#[cfg(test)]
20mod tests {
21    use super::*;
22
23    #[test]
24    fn test_parse_bool_truthy() {
25        for v in ["1", "true", "TRUE", "TrUe", "yes", "on"] {
26            assert_eq!(parse_bool(v), Some(true));
27        }
28    }
29
30    #[test]
31    fn test_parse_bool_falsy() {
32        for v in ["0", "false", "FALSE", "No", "off"] {
33            assert_eq!(parse_bool(v), Some(false));
34        }
35    }
36
37    #[test]
38    fn test_parse_bool_invalid() {
39        for v in ["", "-1", "truthy", "y", "n"] {
40            assert_eq!(parse_bool(v), None);
41        }
42    }
43
44    #[test]
45    fn test_take_value_ok_and_err() {
46        let mut it = vec!["abc".to_string()].into_iter();
47        let v = take_value("--x", &mut it).unwrap();
48        assert_eq!(v, "abc");
49
50        let mut it2 = std::iter::empty::<String>();
51        let err = take_value("--flag", &mut it2).unwrap_err();
52        let msg = format!("{err}");
53        assert!(msg.contains("missing value for --flag"));
54    }
55}