use std::collections::{HashSet, HashMap};
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct CLIParser {
pub posits: Vec<String>,
pub flags: HashSet<String>,
pub pairs: HashMap<String, String>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum CLIError {
FlagWithSign(String),
FlagMalformed(String),
PairMissingSign(String),
PairBadSign(String),
PairMalformed(String),
DashesMalformed(String)
}
impl std::error::Error for CLIError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match *self {
CLIError::FlagWithSign(_) => None,
CLIError::FlagMalformed(_) => None,
CLIError::PairMissingSign(_) => None,
CLIError::PairBadSign(_) => None,
CLIError::PairMalformed(_) => None,
CLIError::DashesMalformed(_) => None,
}
}
}
impl std::fmt::Display for CLIError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match *self {
CLIError::FlagWithSign(ref arg) => write!(f, "Equal signs not allowed in flags: `{0}`\nProper syntax: `./my_program -flag`", arg),
CLIError::FlagMalformed(ref arg) => write!(f, "Malformed flag: `{0}`\nProper syntax: `./my_program -flag`", arg),
CLIError::PairMissingSign(ref arg) => write!(f, "Key-value pair arguments need an equal sign: `{0}`\nProper syntax: `./my_program --key=value`", arg),
CLIError::PairBadSign(ref arg) => write!(f, "Improper use of equal sign in key-value pair: `{0}`\nProper syntax: `./my_program --key=value`", arg),
CLIError::PairMalformed(ref arg) => write!(f, "Malformed key-value pair: `{0}`\nProper syntax: `./my_program --key=value`", arg),
CLIError::DashesMalformed(ref arg) => write!(f, "Arguments cannot start with 3 or more dash lines: `{0}`", arg),
}
}
}
impl Default for CLIParser {
fn default() -> Self {
Self {
posits: Vec::new(),
flags: HashSet::new(),
pairs: HashMap::new(),
}
}
}
impl CLIParser {
pub fn new() -> Self {
Self::default()
}
pub fn init(mut self) -> Result<Self, CLIError> {
for argument in std::env::args() {
if !argument.starts_with("-") {
self.posits.push(argument);
continue;
}
else if !argument.starts_with("--") {
if argument.contains("=") {
return Err(CLIError::FlagWithSign(argument));
}
if argument.len() < 2 {
return Err(CLIError::FlagWithSign(argument));
}
self.flags.insert(argument[1..].to_string());
continue;
}
else if !argument.starts_with("---") {
if !argument.contains("=") {
return Err(CLIError::PairMissingSign(argument));
}
if argument.len() < 5 {
return Err(CLIError::PairMalformed(argument));
}
let equal_sign_pos: usize = argument.find('=').unwrap();
if equal_sign_pos == 2 || equal_sign_pos == argument.len() - 1 {
return Err(CLIError::PairBadSign(argument));
}
let kwarg: (&str, &str) = argument.split_once("=").unwrap();
self.pairs.insert(kwarg.0[2..].to_string(), kwarg.1.to_string());
}
else {
return Err(CLIError::DashesMalformed(argument));
}
}
Ok(self)
}
}