use clap::{Args, Parser, ValueEnum};
use passgen::{
pattern::Pattern,
random::{Random, RandomSource},
Config, DataStore,
};
use passgen_cli::*;
use std::{path::PathBuf, str::FromStr};
fn main() {
let options = Options::parse();
let mut config = Config::default();
for wordlist in &options.wordlist {
config.wordlist_add(&wordlist.name, &wordlist.path);
}
let random = options.random();
let pattern = Pattern::parse(&options.pattern.unwrap()).unwrap();
let (pattern, dependencies) = pattern.optimize();
let mut data = DataStore::default();
for dependency in &dependencies {
data.resolve(&config, dependency).unwrap();
}
let pattern = pattern.prepare(&data).unwrap();
if let Some(threads) = options.threads {
use std::sync::{atomic::*, *};
let pattern = Arc::new(pattern);
let counter = Arc::new(AtomicUsize::new(0));
let amount = options.amount;
let (sender, receiver) = mpsc::sync_channel(1024);
let threads = (0..threads)
.map(move |_index| {
let random = random.clone();
let counter = counter.clone();
let pattern = pattern.clone();
let sender = sender.clone();
std::thread::spawn(move || {
loop {
let index = counter.fetch_add(1, Ordering::SeqCst);
if index >= options.amount {
break;
}
let mut rng = random.get_rng_boxed(index);
let output = pattern.generate(&mut rng).unwrap();
sender.send(output);
}
drop(sender);
})
})
.collect::<Vec<_>>();
while let Ok(message) = receiver.recv() {
println!("{message}");
}
for thread in threads {
thread.join().unwrap();
}
} else {
for index in 0..options.amount {
let mut rng = random.get_rng_boxed(index);
let output = pattern.generate(&mut rng).unwrap();
println!("{output}");
}
}
}