use rand::RngExt;
pub struct RandomStringCustomOptions {
pub include_lowercase: bool,
pub include_uppercase: bool,
pub include_numeric: bool,
pub include_special_chars: bool,
pub special_chars: String,
pub exclude_custom_chars: bool,
pub custom_chars: String,
pub is_leading_zero: bool,
}
impl Default for RandomStringCustomOptions {
fn default() -> Self {
Self {
include_lowercase: true,
include_uppercase: true,
include_numeric: true,
include_special_chars: false,
special_chars: "!@#$%^&*()_+-={}[]:;\"'<>,.?/|~".to_string(),
exclude_custom_chars: false,
custom_chars: "l10cCOopPsSuUvVxXwWzZ".to_string(),
is_leading_zero: true,
}
}
}
pub fn random_number(min: i32, max: i32) -> i32 {
let mut rng = rand::rng();
rng.random_range(min..=max)
}
pub fn random_number_string(min: i32, max: i32) -> String {
random_number(min, max).to_string()
}
pub fn random_string_alpha_numeric(length: u32) -> String {
use rand::distr::Alphanumeric;
let mut rng = rand::rng();
(0..length)
.map(|_| rng.sample(Alphanumeric) as char)
.collect()
}
pub fn random_string_numeric(length: u32) -> String {
use rand::distr::Uniform;
let mut rng = rand::rng();
let chars: Vec<char> = "0123456789".chars().collect();
let uniform = Uniform::new(0, chars.len()).unwrap();
(0..length).map(|_| chars[rng.sample(uniform)]).collect()
}
pub fn random_string_number(length: u32) -> String {
use rand::distr::Uniform;
let mut rng = rand::rng();
if length == 0 {
return String::new();
}
let mut result = String::new();
let first_chars: Vec<char> = "123456789".chars().collect();
result.push(first_chars[rng.sample(Uniform::new(0, first_chars.len()).unwrap())]);
let all_chars: Vec<char> = "0123456789".chars().collect();
for _ in 1..length {
result.push(all_chars[rng.sample(Uniform::new(0, all_chars.len()).unwrap())]);
}
result
}
pub fn random_string_alpha(length: u32) -> String {
use rand::distr::Uniform;
let mut rng = rand::rng();
let chars: Vec<char> = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
.chars()
.collect();
let uniform = Uniform::new(0, chars.len()).unwrap();
(0..length).map(|_| chars[rng.sample(uniform)]).collect()
}
pub fn random_string_custom(length: u32, opts: RandomStringCustomOptions) -> String {
use rand::distr::Uniform;
let mut rng = rand::rng();
if length == 0 {
return String::new();
}
let mut chars = String::new();
if opts.include_lowercase {
chars.push_str("abcdefghijklmnopqrstuvwxyz");
}
if opts.include_uppercase {
chars.push_str("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
}
if opts.include_numeric {
chars.push_str("0123456789");
}
if opts.exclude_custom_chars {
chars = chars
.chars()
.filter(|c| !opts.custom_chars.contains(*c))
.collect();
}
if !opts.special_chars.is_empty() && opts.include_special_chars {
chars.push_str(&opts.special_chars);
}
if chars.is_empty() {
return String::new(); }
let char_vec: Vec<char> = chars.chars().collect();
let uniform = Uniform::new(0, char_vec.len()).unwrap();
let mut result = String::new();
if opts.include_numeric && !opts.is_leading_zero {
let non_zero_chars: Vec<char> = char_vec.iter().filter(|&&c| c != '0').copied().collect();
if !non_zero_chars.is_empty() {
let non_zero_uniform = Uniform::new(0, non_zero_chars.len()).unwrap();
result.push(non_zero_chars[rng.sample(non_zero_uniform)]);
} else {
result.push(char_vec[rng.sample(uniform)]);
}
for _ in 1..length {
result.push(char_vec[rng.sample(uniform)]);
}
} else {
for _ in 0..length {
result.push(char_vec[rng.sample(uniform)]);
}
}
result
}