1use crate::error::ModCliError;
10
11pub fn flag(args: &[String], name: &str) -> bool {
14 if !name.starts_with("--") {
15 return false;
16 }
17 let key = name.trim_start_matches('-');
18 for a in args {
19 let a = a.as_str();
20 if a == name {
21 return true;
22 }
23 if let Some((k, v)) = a.strip_prefix("--").and_then(|s| s.split_once('=')) {
24 if k == key {
25 let v = v.to_ascii_lowercase();
26 return matches!(v.as_str(), "1" | "true" | "yes" | "y");
27 }
28 }
29 }
30 false
31}
32
33pub fn get_string(args: &[String], name: &str) -> Option<String> {
35 if !name.starts_with("--") {
36 return None;
37 }
38 let key = name.trim_start_matches('-');
39 let mut i = 0;
40 while i < args.len() {
41 let a = args[i].as_str();
42 if a == name {
43 if let Some(next) = args.get(i + 1) {
44 return Some(next.clone());
45 }
46 return None;
47 }
48 if let Some((k, v)) = a.strip_prefix("--").and_then(|s| s.split_once('=')) {
49 if k == key {
50 return Some(v.to_string());
51 }
52 }
53 i += 1;
54 }
55 None
56}
57
58pub fn get_int<T>(args: &[String], name: &str) -> Result<T, ModCliError>
61where
62 T: std::str::FromStr,
63{
64 if let Some(s) = get_string(args, name) {
65 match s.parse::<T>() {
66 Ok(v) => Ok(v),
67 Err(_) => Err(ModCliError::InvalidUsage(format!(
68 "expected numeric value for {name}, got '{s}'"
69 ))),
70 }
71 } else {
72 Err(ModCliError::InvalidUsage(format!(
73 "missing required argument: {name}"
74 )))
75 }
76}
77
78pub fn get_bool(args: &[String], name: &str) -> Result<bool, ModCliError> {
82 if flag(args, name) {
83 return Ok(true);
84 }
85 if let Some(s) = get_string(args, name) {
86 let v = s.to_ascii_lowercase();
87 return Ok(matches!(v.as_str(), "1" | "true" | "yes" | "y"));
88 }
89 Err(ModCliError::InvalidUsage(format!(
90 "missing required argument: {name}"
91 )))
92}