passworder 0.1.3

A simple strong password generator
Documentation
pub mod password {
    use rand::{thread_rng, Rng};

    const UPPER_CASE: &str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    const LOWER_CASE: &str = "abcdefghijklmnopqrstuvwxyz";
    const DIGIT: &str = "0123456789";
    const PUNCTUATION: &str = "-_!.:";
    const SPECIAL: &str = "\"#$%&'*+,/;=?@\\^`|~";
    const BRACKET: &str = "[]{}()<>";

    pub fn generate() -> String {
        let all = format!("{UPPER_CASE}{LOWER_CASE}{DIGIT}{PUNCTUATION}{SPECIAL}{BRACKET}");
        let mut pass = String::new();
        loop {
            for _n in 1..16 {
                pass.push(
                    all.chars()
                        .nth(thread_rng().gen_range(0..=(all.len() - 1)))
                        .unwrap(),
                );
            }
            if is_strong(&pass) {
                return pass;
            }
            pass = String::from("");
        }
    }

    fn is_strong(pass: &str) -> bool {
        if pass.len() < 8 {
            return false;
        }
        let mut has_upper = false;
        let mut has_lower = false;
        let mut has_digit = false;
        let mut has_symbol = false;
        for n in 0..pass.len() {
            match pass.chars().nth(n).unwrap() {
                c if c.is_ascii_uppercase() => has_upper = true,
                c if c.is_ascii_lowercase() => has_lower = true,
                c if c.is_ascii_digit() => has_digit = true,
                c if PUNCTUATION.contains(c) || SPECIAL.contains(c) || BRACKET.contains(c) => {
                    has_symbol = true
                }
                _ => {}
            }
        }
        has_upper && has_lower && has_digit && has_symbol
    }

    #[cfg(test)]
    mod tests {
        use super::*;

        #[test]
        fn it_works() {
            let pass = generate();
            assert_eq!(is_strong(&pass), true);
        }
    }
}