rust_auth_utils/
random.rs1use rand::{thread_rng, RngCore};
4
5#[derive(Debug, Clone, Copy)]
6pub enum Alphabet {
7 Lowercase, Uppercase, Digits, Special, }
12
13impl Alphabet {
14 fn expand(&self) -> &'static str {
15 match self {
16 Alphabet::Lowercase => "abcdefghijklmnopqrstuvwxyz",
17 Alphabet::Uppercase => "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
18 Alphabet::Digits => "0123456789",
19 Alphabet::Special => "-_",
20 }
21 }
22}
23
24#[derive(Debug)]
25pub struct Error(String);
26
27impl std::fmt::Display for Error {
28 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29 write!(f, "{}", self.0)
30 }
31}
32
33impl std::error::Error for Error {}
34
35pub struct RandomStringGenerator {
36 base_character_set: String,
37}
38
39impl RandomStringGenerator {
40 pub fn new(alphabets: &[Alphabet]) -> Result<Self, Error> {
41 if alphabets.is_empty() {
42 return Err(Error(
43 "No valid characters provided for random string generation.".to_string(),
44 ));
45 }
46
47 let base_character_set = alphabets
48 .iter()
49 .map(|a| a.expand())
50 .collect::<Vec<&str>>()
51 .join("");
52
53 Ok(Self { base_character_set })
54 }
55
56 pub fn generate(&self, length: usize, alphabet: Option<Alphabet>) -> Result<String, Error> {
57 if length == 0 {
58 return Err(Error("Length must be a positive integer.".to_string()));
59 }
60
61 let (character_set, char_set_length) = if let Some(alphabet) = alphabet {
62 let set = alphabet.expand();
63 (set, set.len())
64 } else {
65 (&self.base_character_set[..], self.base_character_set.len())
66 };
67
68 let mut rng = thread_rng();
69 let mut char_array = vec![0u8; length];
70 rng.fill_bytes(&mut char_array);
71
72 let result = char_array
73 .iter()
74 .map(|&byte| {
75 let index = byte as usize % char_set_length;
76 character_set.chars().nth(index).unwrap()
77 })
78 .collect();
79
80 Ok(result)
81 }
82}