use std::{
error::Error,
fs::File,
io::{BufReader, Read},
};
pub struct Config {
length: usize,
}
impl Config {
pub fn build(mut args: impl Iterator<Item = String>) -> Result<Config, Box<dyn Error>> {
args.next();
let length = match args.next() {
Some(length) => length.parse()?,
None => 16,
};
Ok(Config { length })
}
pub fn new(length: usize) -> Config {
Config { length }
}
pub fn print_config() {
eprint!(
"\
Usage:
\x1B[01m{} <LENGTH>\x1B[00m\n
The LENGTH is an optional parameter specifying the desired length of the password.\n
Version: {}, {} License
",
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION"),
env!("CARGO_PKG_LICENSE")
);
}
}
pub fn run(config: &Config) -> Result<String, Box<dyn Error>> {
let mut password = vec![0u8; config.length];
{
let dev_chars = File::open("/dev/urandom")?;
let mut reader = BufReader::with_capacity(config.length, dev_chars);
reader.read_exact(&mut password)?;
}
{
let min_ascii = 32;
let diff_ascii = 95;
#[allow(clippy::needless_range_loop)]
for i in 0..config.length {
password[i] = password[i] % diff_ascii + min_ascii;
}
}
let password: String = password.into_iter().map(|c| c as char).collect();
Ok(password)
}