rustian_roulette/
cmd.rs

1use std::collections::HashMap;
2use std::env::{self, Args};
3use std::path::{Path, PathBuf};
4
5pub struct Config {
6    pub chambers: usize,
7    pub path: PathBuf,
8}
9
10const DEFAULT_CHAMBERS: usize = 6;
11const CHAMBER_ARG: &str = "chamber";
12const PATH_ARG: &str = "path";
13
14impl Config {
15    pub fn new(args: Args) -> Config {
16        let home = env::home_dir().expect("could not get home dir");
17        let args = &args.collect();
18        let args = parse_args(args);
19
20        let chambers = match args.get(CHAMBER_ARG) {
21            Some(val) => val.parse::<usize>()
22                .expect("unable to parse chamber arg as usize, should never happen"),
23            None => DEFAULT_CHAMBERS,
24        };
25
26        let path = match args.get(PATH_ARG) {
27            Some(val) => Path::new(val).to_path_buf(),
28            None => home,
29        };
30
31        Config { chambers, path }
32    }
33}
34
35// parse_args returns a hashmap of key value arguments
36// if an argument has a flag (either starts with '-' or '--')
37// that flag becomes a key, and the value is either a str value of
38// 'true' or the next non flag value.
39// Values without a flag prefix will try to be parsed as a usize
40// for the CHAMBER flag, or as a string for the PATH flag.
41fn parse_args(args: &Vec<String>) -> HashMap<&str, &str> {
42    let mut map = HashMap::new();
43    let mut arg_iter = args.iter();
44    let mut flagged = false;
45    let mut flag = "";
46
47    arg_iter.next();
48    for arg in arg_iter {
49        if arg.starts_with("-") {
50            if flagged {
51                map.entry(flag).or_insert("true");
52            } else {
53                flagged = true;
54            }
55            flag = arg.trim_matches('-');
56            continue;
57        }
58        if flagged {
59            map.entry(flag).or_insert(arg);
60            flagged = false;
61            continue;
62        }
63        if let Ok(_) = arg.parse::<usize>() {
64            map.entry(CHAMBER_ARG).or_insert(arg);
65        } else {
66            map.entry(PATH_ARG).or_insert(arg);
67        }
68    }
69    if flagged {
70        map.entry(flag).or_insert("true");
71    }
72    map
73}