use crate::errors::CommandRunError;
use clap::ArgMatches;
use std::fmt::Display;
use std::str::FromStr;
type CommandResult<T> = Result<T, CommandRunError>;
pub trait ArgMatchesExt {
fn str_arg(&self, name: &str) -> &String;
fn string_arg(&self, name: &str) -> String;
fn required_string(&self, name: &str) -> CommandResult<String>;
fn optional_string(&self, name: &str) -> Option<String>;
fn optional_typed<T: Clone + Send + Sync + 'static>(&self, name: &str) -> Option<T>;
fn optional_typed_or<T: Clone + Send + Sync + 'static>(&self, name: &str, default: T) -> T;
fn parse_required<T: FromStr>(&self, name: &str) -> CommandResult<T>
where
T::Err: Display;
}
impl ArgMatchesExt for ArgMatches {
fn str_arg(&self, name: &str) -> &String {
self.get_one::<String>(name).unwrap()
}
fn string_arg(&self, name: &str) -> String {
self.get_one::<String>(name).cloned().unwrap()
}
fn required_string(&self, name: &str) -> CommandResult<String> {
self.get_one::<String>(name).cloned().ok_or_else(|| {
CommandRunError::MissingRequiredArgument {
name: name.to_string(),
}
})
}
fn optional_string(&self, name: &str) -> Option<String> {
self.get_one::<String>(name).cloned()
}
fn optional_typed<T: Clone + Send + Sync + 'static>(&self, name: &str) -> Option<T> {
self.get_one::<T>(name).cloned()
}
fn optional_typed_or<T: Clone + Send + Sync + 'static>(&self, name: &str, default: T) -> T {
self.get_one::<T>(name).cloned().unwrap_or(default)
}
fn parse_required<T: FromStr>(&self, name: &str) -> CommandResult<T>
where
T::Err: Display,
{
let value = self.required_string(name)?;
value
.parse::<T>()
.map_err(|e| CommandRunError::InvalidArgumentValue {
name: name.to_string(),
message: e.to_string(),
})
}
}