diff --git a/Cargo.toml b/Cargo.toml index c1dac7c..61b2cb5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,12 +8,21 @@ description = "A simple utility to generate random passwords based on a user-spe repository = "https://github.com/kostDev/genpass" readme = "README.md" +[lib] +name = "genpass" +path = "src/lib.rs" + +[[bin]] +name = "genpass" +path = "src/main.rs" + [dependencies] rand = "0.8.5" [profile.release] +debug = 0 +codegen-units = 1 opt-level = "z" lto = "fat" -codegen-units = 1 panic = "abort" -debug = 0 \ No newline at end of file +strip = true \ No newline at end of file diff --git a/src/cli.rs b/src/cli.rs new file mode 100644 index 0000000..0c13dc6 --- /dev/null +++ b/src/cli.rs @@ -0,0 +1,14 @@ +use std::process::exit; +use super::{ + info::display_help, + consts::CMD_HELP, +}; + +pub fn handle_cli() { + let _args: Vec = std::env::args().collect(); + + if _args.contains(&CMD_HELP.to_string()) { + display_help(); + exit(0); + } +} diff --git a/src/consts.rs b/src/consts.rs new file mode 100644 index 0000000..8d622e0 --- /dev/null +++ b/src/consts.rs @@ -0,0 +1,13 @@ +// ALL Characters +pub const LOW_CASE: &str = "abcdefghijklmnopqrstuvwxyz"; +pub const UP_CASE: &str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +pub const NUMBERS: &str = "0123456789"; +pub const SYMBOLS: &str = "#$%^*_-=+~;[<{(:&|@:)}>];~.?!"; +pub const ARROWS: &str = "→←↑↓↔↕↩↪"; +pub const MATH_SYMBOLS: &str = "∑∆∞∫∏√≠≈±∂"; +pub const MOOD_SYMBOLS: &str = "😁😇🙂🙃🥳🤠😎"; +// -------------------------- +pub const DEFAULT_ARGS: [&str;4] = ["a", "aa", "s", "n"]; +// -------------------------- +// Command +pub const CMD_HELP: &str = "-help"; diff --git a/src/info.rs b/src/info.rs new file mode 100644 index 0000000..0f98b1c --- /dev/null +++ b/src/info.rs @@ -0,0 +1,25 @@ + +pub fn display_help() { + println!("═════════════════════════════════════════════════════════════"); + println!(" Password Generator Help "); + println!("═════════════════════════════════════════════════════════════"); + println!(" Use the following options to customize your password: "); + println!(" ┌───────────────┬───────────────────────────────────────┐"); + println!(" │ Option │ Description │"); + println!(" ├───────────────┼───────────────────────────────────────┤"); + println!(" │ a │ Lowercase letters (a-z) │"); + println!(" │ aa │ Uppercase letters (A-Z) │"); + println!(" │ n │ Numbers [0-9] │"); + println!(" │ s │ Symbols (e.g., @, #, %, &, etc.) │"); + println!(" │ r │ Arrows (→, ←, ↑, ↓, etc.) │"); + println!(" │ m │ Math symbols (e.g., ∑, ∆, ∞) │"); + println!(" │ mm │ Mood symbols (e.g., 😁, 🙂, 🙃) │"); + println!(" │ custom │ Custom string of characters │"); + println!(" └───────────────┴───────────────────────────────────────┘"); + println!(" Example usage:"); + println!(" genpass 16 a n s -> Generates a 16-char password with lowercase, numbers, and symbols."); + println!(" genpass 12 a aa n -> Generates a 12-char password with lowercase, uppercase, and numbers."); + println!(" genpass 20 m mm -> Generates a 20-char password with math and mood symbols."); + println!(" genpass 8 ^@_@^ -> Generates an 8-char password from your custom character set."); + println!("═════════════════════════════════════════════════════════════"); +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..3692cec --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,3 @@ +pub mod cli; +pub mod info; +pub mod consts; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index a2e5e2a..e3eb2ac 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,59 +1,52 @@ -use rand::{Rng,seq::SliceRandom, thread_rng}; -use std::iter::repeat_with; -use std::io::{stdout, stdin, Write}; - -const LOW_CASE: &str = "abcdefghijklmnopqrstuvwxyz"; -const UP_CASE: &str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; -const SYMBOLS: &str = "#$%^*_-=+~;[<{(:&|@:)}>];~.?!"; -const NUMBERS: &str = "0123456789"; - -const DEFAULT_ARGS: [&str;4] = ["a", "aa", "s", "n"]; - -fn generate_line(args: &[&str]) -> String { - let mut rng = thread_rng(); - let mut list = args.iter().map(|&x| match x { - "a" => LOW_CASE, - "aa" => UP_CASE, - "s" => SYMBOLS, - "n" => NUMBERS, +use rand::{seq::{SliceRandom, IteratorRandom}, thread_rng}; +use std::{ + io::{ stdout, stdin, Write }, + iter::repeat_with +}; +use genpass::{ consts, cli }; + +fn create_ch_pool(args: &[&str]) -> String { + let mut pool = args.iter().map(|&x| match x { + "a" | "lower" => consts::LOW_CASE, + "aa" | "upper" => consts::UP_CASE, + "n" | "nums" => consts::NUMBERS, + "s" | "symbols" => consts::SYMBOLS, + "r" | "arrows" => consts::ARROWS, + "m" | "math" => consts::MATH_SYMBOLS, + "mm" | "mood" => consts::MOOD_SYMBOLS, custom => custom, }).collect::>(); - list.shuffle(&mut rng); - list.concat() + pool.shuffle(&mut thread_rng()); + pool.concat() } -fn generate_pass(line: &str, max: usize) -> String { +fn create_password(pool: &str, n: usize) -> String { let mut rng = thread_rng(); - repeat_with(|| { line.chars().nth(rng.gen_range(0..line.len())).unwrap() }) - .take(max) - .collect() + repeat_with(|| pool.chars().choose(&mut rng).unwrap()) + .take(n).collect() } fn main() { + cli::handle_cli(); + let mut input: String = String::new(); print!(">> "); stdout().flush().unwrap(); stdin().read_line(&mut input).unwrap(); - let input_items = input.split_whitespace().collect::>(); + let tokens = input.split_whitespace().collect::>(); - if input_items.len().eq(&0usize) { - eprintln!("Empty input!"); + if tokens.is_empty() { + eprintln!("Empty input! Please provide a password length or/and optional character set!"); return; } - // first arg always number - let password_len = input_items[0].parse::() - .expect("invalid value for password length!"); - - let args = &input_items[1..]; - let line = match &args.len() { - 0 => generate_line(&DEFAULT_ARGS), // default - _ => generate_line(&args), // custom [ .., .., ... ] - }; - let password = generate_pass(&line, password_len); - - println!("Yours generated password[{password_len}]: {password}"); - // println!("Unique generated line: {}", new_line); - + // first arg always number as password length + let lens = tokens[0].parse::().expect("Invalid value for password length!"); + let args = &tokens[1..]; + let pool = create_ch_pool(if args.is_empty() { &consts::DEFAULT_ARGS } else { args }); + let password = create_password(&pool, lens); + + println!("Yours generated password[{lens}]: {password}"); + // println!("Unique pool: {}", pool); }