use multimap::MultiMap;
pub struct Arguments {
arg_map: MultiMap<String, Option<String>>,
}
impl Arguments {
pub fn parse<S: AsRef<str>>(args: &[S]) -> Arguments {
let mut arg_map = MultiMap::new();
for (key, val) in args.iter().map(|s| s.as_ref()).zip(
args.iter()
.map(|s| s.as_ref())
.skip(1)
.chain(std::iter::once("")),
) {
if let Some(stripped) = key.strip_prefix('-') {
arg_map.insert(
stripped.to_string(),
if val.is_empty() || val.starts_with('-') {
None
} else {
Some(val.to_string())
},
);
}
}
Arguments { arg_map }
}
pub fn contains(&self, key: &str) -> bool {
self.arg_map.contains_key(key)
}
pub fn contains_val(&self, key: &str) -> bool {
self.arg_map
.get_vec(key)
.and_then(|vals| vals.iter().find(|&val| val.is_some()))
.is_some()
}
pub fn is_empty(&self) -> bool {
self.arg_map.is_empty()
}
pub fn get(&self, key: &str) -> Option<Option<&str>> {
Some(self.arg_map.get(key)?.as_ref().map(String::as_ref))
}
pub fn get_vec(&self, key: &str) -> Option<&Vec<Option<String>>> {
self.arg_map.get_vec(key)
}
pub fn len(&self) -> usize {
self.arg_map.len()
}
}
#[cfg(test)]
mod test {
use super::Arguments;
#[test]
fn empty() {
let args = Arguments::parse::<String>(&[]);
assert!(args.is_empty());
assert_eq!(args.len(), 0);
}
#[test]
fn no_arg() {
let args = Arguments::parse(&["arg"]);
assert!(args.is_empty());
assert_eq!(args.len(), 0);
}
#[test]
fn one_empty() {
let args = Arguments::parse(&["-key"]);
assert!(!args.is_empty());
assert_eq!(args.len(), 1);
assert!(args.contains("key"));
assert!(!args.contains_val("key"));
assert!(args.get("key").is_some());
assert_eq!(args.get_vec("key").unwrap().len(), 1);
}
#[test]
fn one_key() {
let args = Arguments::parse(&["-key", "val"]);
assert!(!args.is_empty());
assert_eq!(args.len(), 1);
assert!(args.contains("key"));
assert!(args.contains_val("key"));
assert!(args.get("key").is_some());
assert_eq!(args.get("key").unwrap().unwrap(), "val");
assert_eq!(args.get_vec("key").unwrap().len(), 1);
}
#[test]
fn one_key_repeated() {
let args = Arguments::parse(&["-key", "val", "-key", "val2"]);
assert!(!args.is_empty());
assert_eq!(args.len(), 1);
assert!(args.contains("key"));
assert!(args.contains_val("key"));
assert!(args.get("key").is_some());
assert_eq!(args.get("key").unwrap().unwrap(), "val");
assert_eq!(
args.get_vec("key").unwrap(),
&vec!(Some("val".to_string()), Some("val2".to_string()))
);
assert_eq!(args.get_vec("key").unwrap().len(), 2);
}
#[test]
fn one_key_cut_short() {
let args = Arguments::parse(&["-key", "-key", "val2"]);
assert!(!args.is_empty());
assert_eq!(args.len(), 1);
assert!(args.contains("key"));
assert!(args.contains_val("key"));
assert!(args.get("key").is_some());
assert_eq!(args.get("key").unwrap(), None);
assert_eq!(
args.get_vec("key").unwrap(),
&vec!(None, Some("val2".to_string()))
);
assert_eq!(args.get_vec("key").unwrap().len(), 2);
}
#[test]
fn two_keys() {
let args = Arguments::parse(&["-key", "val", "-key2", "val2"]);
assert!(!args.is_empty());
assert_eq!(args.len(), 2);
assert!(args.contains("key"));
assert!(args.contains("key2"));
assert!(args.contains_val("key"));
assert!(args.contains_val("key2"));
assert!(args.get("key").is_some());
assert!(args.get("key2").is_some());
assert_eq!(args.get("key").unwrap().unwrap(), "val");
assert_eq!(args.get("key2").unwrap().unwrap(), "val2");
assert_eq!(args.get_vec("key").unwrap().len(), 1);
assert_eq!(args.get_vec("key2").unwrap().len(), 1);
}
#[test]
fn two_keys_cut_short() {
let args = Arguments::parse(&["-key", "-key2", "val2"]);
assert!(!args.is_empty());
assert_eq!(args.len(), 2);
assert!(args.contains("key"));
assert!(args.contains("key2"));
assert!(!args.contains_val("key"));
assert!(args.contains_val("key2"));
assert!(args.get("key").is_some());
assert!(args.get("key2").is_some());
assert_eq!(args.get("key").unwrap(), None);
assert_eq!(args.get("key2").unwrap().unwrap(), "val2");
assert_eq!(args.get_vec("key").unwrap().len(), 1);
assert_eq!(args.get_vec("key2").unwrap().len(), 1);
}
#[test]
fn ergonomics() {
let sys_args: Vec<String> = vec!["-key".into(), "val".into()];
let args = Arguments::parse(&sys_args);
assert!(!args.is_empty());
assert_eq!(args.len(), 1);
assert!(args.contains("key"));
assert!(args.contains_val("key"));
assert!(args.get("key").is_some());
assert_eq!(args.get("key").unwrap().unwrap(), "val");
assert_eq!(args.get_vec("key").unwrap().len(), 1);
}
}