memo_passwords/
lib.rs

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/// PasswordGenerator is responsible for generating a memorizable password.
10///
11/// # Example
12///
13/// ```
14/// # use memo_passwords::PasswordGenerator;
15/// let pwd = PasswordGenerator::default();
16/// println!("{}", pwd.generate())
17/// ```
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct PasswordGenerator {
20    words: Vec<String>,
21    length: usize,
22}
23
24impl PasswordGenerator {
25    /// Create a new `PasswordGenerator` that generates `length` number of words.
26    pub fn new(length: usize) -> Self {
27        Self {
28            words: make_list(),
29            length,
30        }
31    }
32
33    /// Change the list that is used to generate passwords to your own.
34    ///
35    /// # Example
36    ///
37    /// ```
38    /// # use memo_passwords::PasswordGenerator;
39    /// let pwd = PasswordGenerator::default().with_list(&["foo", "bar"]);
40    /// println!("{}", pwd.generate());
41    /// ```
42    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}