use std::iter::Peekable;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ArgType {
Flag,
Value,
ValueList,
}
#[derive(Debug, PartialEq)]
pub enum ArgResult {
Flag,
Value(String),
ValueList(Vec<String>),
}
#[derive(Debug)]
pub struct Argument {
short: Option<char>,
long: Option<String>,
arg_type: ArgType,
pub arg_result: Option<ArgResult>,
}
impl Argument {
pub fn new(
short: Option<char>,
long: Option<&str>,
arg_type: ArgType,
) -> Result<Argument, String> {
if let (Option::None, Option::None) = (short, long) {
return Err(String::from(
"At least one name of argument must be specified (short or long or both)",
));
}
let long_owned: Option<String> = if let Some(text) = long {
Option::Some(String::from(text))
} else {
None
};
Ok(Argument {
short,
long: long_owned,
arg_type,
arg_result: None,
})
}
pub fn new_short(name: char, arg_type: ArgType) -> Argument {
Argument::new(Option::Some(name), Option::None, arg_type).unwrap()
}
pub fn new_long(name: &str, arg_type: ArgType) -> Argument {
Argument::new(Option::None, Option::Some(name), arg_type).unwrap()
}
pub fn get_value(&self) -> Result<&str, &'static str> {
if let ArgType::Value = self.arg_type {
if let Some(result) = &self.arg_result {
if let ArgResult::Value(ref value) = result {
return Ok(value);
} else {
return Err("Wrong type of result. Something really bad has happened");
}
} else {
return Err("No value assigned to result");
}
} else {
return Err("This argument is not an value");
}
}
pub fn get_values(&self) -> Result<&Vec<String>, &'static str> {
if let ArgType::ValueList = self.arg_type {
if let Some(result) = &self.arg_result {
if let ArgResult::ValueList(ref list) = result {
return Ok(list);
} else {
return Err("Wrong type of result. Something really bad happened");
}
} else {
return Err("No result specified");
}
} else {
return Err("This argument is not an value list");
}
}
pub fn get_flag(&self) -> Result<bool, &'static str> {
if let ArgType::Flag = self.arg_type {
return Ok(if let Some(_) = self.arg_result {
true
} else {
false
});
} else {
return Err("Argument is not an flag type");
}
}
pub fn add_value(
&mut self,
input_iter: &mut Peekable<&mut std::slice::Iter<'_, String>>,
) -> Result<(), String> {
match self.arg_type {
ArgType::Flag => {
match self.arg_result {
Some(_) => return Err(String::from("Flag already set")),
_ => (),
}
self.arg_result = Some(ArgResult::Flag);
}
ArgType::Value => {
match self.arg_result {
Some(_) => return Err(String::from("Value already assigned")),
_ => (),
}
match input_iter.next() {
Some(word) => self.arg_result = Some(ArgResult::Value(String::from(word))),
None => return Err(String::from("Expected value")),
}
}
ArgType::ValueList => {
let mut new_result = false;
match self.arg_result {
Some(_) => (),
None => new_result = true,
}
if new_result {
self.arg_result = Some(ArgResult::ValueList(Vec::new()));
}
match input_iter.next() {
Some(word) => match self.arg_result.as_mut().expect("as mut") {
ArgResult::ValueList(ref mut values) => values.push(String::from(word)),
_ => return Err(String::from("WTF")),
},
None => return Err(String::from("Expected value")),
}
}
}
Ok(())
}
pub fn short(&self) -> &Option<char> {
&self.short
}
pub fn long(&self) -> &Option<String> {
&self.long
}
pub fn arg_type(&self) -> &ArgType {
&self.arg_type
}
}
#[cfg(test)]
mod test {
use std::borrow::BorrowMut;
use crate::argument::legacy_argument::{ArgType, Argument};
#[test]
fn new_works() {
assert!(Argument::new(Option::None, Option::Some("parameter"), ArgType::Flag).is_ok());
assert!(Argument::new(Option::Some('x'), Option::None, ArgType::Flag).is_ok());
assert!(Argument::new(Option::Some('x'), Option::Some("parameter"), ArgType::Flag).is_ok());
}
#[test]
fn new_fails() {
assert!(Argument::new(Option::None, Option::None, ArgType::Flag).is_err())
}
#[test]
fn value_works() {
let mut arg =
Argument::new(Option::None, Option::Some("parameter"), ArgType::Value).unwrap();
arg.add_value(
&mut vec![String::from("my value")]
.iter()
.borrow_mut()
.peekable(),
)
.unwrap();
let val = arg.get_value();
assert!(val.is_ok());
assert_eq!(val.unwrap(), "my value");
}
#[test]
fn value_fails_too_many_calls() {
let mut arg =
Argument::new(Option::None, Option::Some("parameter"), ArgType::Value).unwrap();
let inputs_vec = vec![String::from("my value"), String::from("second_value")];
let mut inputs_iter = inputs_vec.iter();
let mut inputs = inputs_iter.borrow_mut().peekable();
arg.add_value(&mut inputs).unwrap();
assert!(arg.add_value(&mut inputs).is_err());
}
#[test]
fn value_list_works() {
let mut arg =
Argument::new(Option::None, Option::Some("parameter"), ArgType::ValueList).unwrap();
let inputs_vec = vec![String::from("my value"), String::from("My second value")];
let mut inputs_iter = inputs_vec.iter();
let mut inputs = inputs_iter.borrow_mut().peekable();
arg.add_value(&mut inputs).unwrap();
arg.add_value(&mut inputs).unwrap();
let val = arg.get_values();
assert!(val.is_ok());
assert_eq!(val.unwrap().len(), 2);
assert_eq!(val.unwrap().get(0).unwrap(), "my value");
assert_eq!(val.unwrap().get(1).unwrap(), "My second value");
}
#[test]
fn flag_works() {
let mut arg =
Argument::new(Option::None, Option::Some("parameter"), ArgType::Flag).unwrap();
arg.add_value(
&mut vec![String::from("my value")]
.iter()
.borrow_mut()
.peekable(),
)
.unwrap();
let val = arg.get_flag();
assert!(val.is_ok());
assert_eq!(val.unwrap(), true);
}
}