#[allow(unused)]
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
pub enum Password {
Legacy, #[default]
Distinct, Emoji, Mixture, }
impl Password {
#[inline]
pub(crate) fn char_at(&self, index: usize) -> char {
match &self {
Password::Legacy => char::from_u32(LEGACY_BYTES[index] as u32).unwrap(),
Password::Distinct => char::from_u32(DISTINCT_BYTES[index] as u32).unwrap(),
Password::Emoji => EMOJI_CHARS[index],
Password::Mixture => match index & 0b0100_0000 {
0 => char::from_u32(DISTINCT_BYTES[index] as u32).unwrap(),
_ => EMOJI_CHARS[index >> 1],
},
}
}
#[inline]
pub(crate) fn bits(&self) -> usize {
match &self {
Password::Mixture => 7,
_ => 6,
}
}
}
const LEGACY_BYTES: &[u8; 64] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const DISTINCT_BYTES: &[u8; 64] =
b"@#$%&*123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
const EMOJI_CHARS: &[char; 64] = &[
'😊', '😍', '😛', '😭', '😎', '👽', '💀', '👻',
'✋', '👌', '👉', '👍', '❤', '💋', '🙏', '💪',
'🐵', '🐶', '🐴', '🐷', '🐔', '🐸', '🐍', '🐬',
'🌻', '🌷', '🌱', '🌴', '🌵', '🍀', '🍄', '🍒',
'🍔', '🍟', '🍕', '🍦', '🍺', '🍉', '🍌', '🍎',
'🏠', '⏰', '💊', '☕', '🚗', '🚲', '✈', '🚀',
'☀', '🌙', '⭐', '⚡', '☔', '🌈', '🔥', '💧',
'🎄', '🎁', '🎈', '🎉', '🔔', '🏆', '🔒', '🔑',
];
#[cfg(test)]
mod password_test {
use super::*;
#[test]
fn test_password() {
let password = Password::Legacy;
assert_eq!(password.char_at(0), 'A');
assert_eq!(password.char_at(63), '/');
let password = Password::Distinct;
assert_eq!(password.char_at(0), '@');
assert_eq!(password.char_at(63), 'z');
let password = Password::Emoji;
assert_eq!(password.char_at(0), '😊');
assert_eq!(password.char_at(63), '🔑');
let pwd = Password::Mixture;
assert_eq!(pwd.bits(), 7);
assert_eq!(
[pwd.char_at(0), pwd.char_at(33), pwd.char_at(55)],
['@', 'U', 'r']
);
assert_eq!(
[pwd.char_at(65), pwd.char_at(77), pwd.char_at(121)],
['🍔', '🍌', '🔔']
);
}
}