use docopt::Docopt; use log::debug; use rand::rngs::OsRng; use rand::seq::IteratorRandom; use rand::seq::SliceRandom; use serde::Deserialize; use std::error::Error; use std::iter::FromIterator; pub mod db; static USAGE: &'static str = " foil Usage: foil set [--db=] foil get [--db=] foil list [--db=] foil generate foil (-h | --help) Options: --db= The path to the sqlite database [default: db.sqlite3]. -h --help Show this screen. --version Show version. "; #[derive(Debug, Deserialize)] struct Args { cmd_set: bool, cmd_get: bool, cmd_list: bool, cmd_generate: bool, flag_db: Option, arg_spec: Option, } fn generate(spec: &str) { let (len, rest) = { let mut separated = spec.splitn(2, ","); let len = separated.next().unwrap(); let rest = separated.next().unwrap(); (len, rest) }; let mut rnd = OsRng::new().unwrap(); let mut password_vec: Vec = rest .chars() .cycle() .map(|c| match c { 'a' => "abcdefghijklmnopqrstuvwxyz" .chars() .choose(&mut rnd) .expect("Could not get random element"), 'A' => "ABCDEFGHIJKLMNOPQRSTUVWXYZ" .chars() .choose(&mut rnd) .expect("Could not get random element"), '1' => "1234567890" .chars() .choose(&mut rnd) .expect("Could not get random element"), '.' => ".,/?-=#%^" .chars() .choose(&mut rnd) .expect("Could not get random element"), _ => panic!("Unknown character spec: {}", c), }) .take(len.parse().unwrap()) .collect(); password_vec.shuffle(&mut rnd); let shuffled: String = String::from_iter(password_vec.into_iter()); println!("{}", shuffled); } fn main() -> Result<(), Box> { pretty_env_logger::init(); let args: Args = Docopt::new(USAGE) .and_then(|dopt| dopt.deserialize()) .unwrap_or_else(|e| e.exit()); debug!("{:?}", args); if args.cmd_generate { generate(&args.arg_spec.unwrap()); return Ok(()); } let mut db_conn: db::DbHandle = db::DbHandle::new(&args.flag_db); Ok(()) }