diff options
author | Jesse Luehrs <doy@tozt.net> | 2021-04-17 02:02:18 -0400 |
---|---|---|
committer | Jesse Luehrs <doy@tozt.net> | 2021-04-17 02:02:18 -0400 |
commit | c248016ea7ebc20551913cc1dfb5dc022fa3440d (patch) | |
tree | 1961a74e3862509220f30fe77366ae34163c6803 /src | |
parent | 9e77724efff281f0fe6d05440ad65c5ab561f380 (diff) | |
download | rbw-c248016ea7ebc20551913cc1dfb5dc022fa3440d.tar.gz rbw-c248016ea7ebc20551913cc1dfb5dc022fa3440d.zip |
choose characters from alphabet with replacement for pwgen
Diffstat (limited to 'src')
-rw-r--r-- | src/pwgen.rs | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/src/pwgen.rs b/src/pwgen.rs index dc6808f..cf63bb2 100644 --- a/src/pwgen.rs +++ b/src/pwgen.rs @@ -56,8 +56,50 @@ pub fn pwgen(ty: Type, len: usize) -> String { let mut rng = rand::thread_rng(); let mut pass = vec![]; - pass.extend(alphabet.choose_multiple(&mut rng, len).copied()); + pass.extend( + std::iter::repeat_with(|| alphabet.choose(&mut rng).unwrap()) + .take(len), + ); // unwrap is safe because the method of generating passwords guarantees // valid utf8 String::from_utf8(pass).unwrap() } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_pwgen() { + let pw = pwgen(Type::AllChars, 50); + assert_eq!(pw.len(), 50); + // technically this could fail, but the chances are incredibly low + // (around 0.000009%) + assert_duplicates(&pw); + + let pw = pwgen(Type::AllChars, 100); + assert_eq!(pw.len(), 100); + assert_duplicates(&pw); + + let pw = pwgen(Type::NoSymbols, 100); + assert_eq!(pw.len(), 100); + assert_duplicates(&pw); + + let pw = pwgen(Type::Numbers, 100); + assert_eq!(pw.len(), 100); + assert_duplicates(&pw); + + let pw = pwgen(Type::NonConfusables, 100); + assert_eq!(pw.len(), 100); + assert_duplicates(&pw); + } + + #[track_caller] + fn assert_duplicates(s: &str) { + let mut set = std::collections::HashSet::new(); + for c in s.chars() { + set.insert(c); + } + assert!(set.len() < s.len()) + } +} |