use std::ffi::OsString;
pub fn os_arg<'a>(args: &'a [OsString], index: usize, command: &str) -> Result<&'a str, String> {
args.get(index)
.and_then(|arg| arg.to_str())
.ok_or_else(|| format!("{command} arguments must be UTF-8"))
}
pub fn split_flag(token: &str) -> (&str, Option<&str>) {
token
.split_once('=')
.map_or((token, None), |(flag, value)| (flag, Some(value)))
}
pub fn flag_value(
args: &[OsString],
index: usize,
flag: &str,
inline_value: Option<&str>,
command: &str,
) -> Result<(String, usize), String> {
if let Some(value) = inline_value {
return Ok((value.to_owned(), index + 1));
}
let value = os_arg(args, index + 1, command).map_err(|_| format!("{flag} requires a value"))?;
if value.starts_with("--") {
return Err(format!("{flag} requires a value"));
}
Ok((value.to_owned(), index + 2))
}
pub fn optional_flag_value(
args: &[OsString],
index: usize,
inline_value: Option<&str>,
command: &str,
) -> Result<(Option<String>, usize), String> {
if let Some(value) = inline_value {
return Ok((Some(value.to_owned()), index + 1));
}
let Some(value) = args.get(index + 1).and_then(|arg| arg.to_str()) else {
return Ok((None, index + 1));
};
if value.starts_with('-') {
return Ok((None, index + 1));
}
os_arg(args, index + 1, command)?;
Ok((Some(value.to_owned()), index + 2))
}
pub fn optional_flag_value_or(
args: &[OsString],
index: usize,
inline_value: Option<&str>,
default_value: &str,
command: &str,
) -> Result<(String, usize), String> {
if let Some(value) = inline_value {
if value.is_empty() {
return Ok((default_value.to_owned(), index + 1));
}
return Ok((value.to_owned(), index + 1));
}
match args.get(index + 1).and_then(|arg| arg.to_str()) {
Some(value) if !value.starts_with("--") => {
os_arg(args, index + 1, command)?;
Ok((value.to_owned(), index + 2))
}
_ => Ok((default_value.to_owned(), index + 1)),
}
}