1use rand::{seq::IndexedRandom, SeedableRng};
2use rand_pcg::Pcg64Mcg;
3
4fn make_list() -> Vec<String> {
5 const WORDS: &str = include_str!("words.txt");
6 WORDS.split("\n").map(|s| s.to_string()).collect()
7}
8
9#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct PasswordGenerator {
20 words: Vec<String>,
21 length: usize,
22}
23
24impl PasswordGenerator {
25 pub fn new(length: usize) -> Self {
27 Self {
28 words: make_list(),
29 length,
30 }
31 }
32
33 pub fn with_list(&self, list: &[&str]) -> Self {
43 Self {
44 words: list.iter().map(|s| s.to_string()).collect(),
45 ..self.clone()
46 }
47 }
48
49 pub fn generate(&self) -> String {
50 let mut pwd = String::new();
51 self.words
52 .choose_multiple(&mut Pcg64Mcg::from_os_rng(), self.length)
53 .for_each(|word| pwd.push_str(format!("{word} ").as_str()));
54 pwd.trim().to_string()
55 }
56}
57
58impl Default for PasswordGenerator {
59 fn default() -> Self {
60 Self::new(10)
61 }
62}