use crate::errors::Result;
use rand::{RngExt, rng};
pub fn generate_token(length: usize) -> String {
generate_secure_token(length).expect("CSPRNG token generation failed")
}
pub fn generate_secure_token(length: usize) -> Result<String> {
const CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
abcdefghijklmnopqrstuvwxyz\
0123456789";
let token: String = (0..length)
.map(|_| {
let idx = rng().random_range(0..CHARSET.len());
CHARSET[idx] as char
})
.collect();
Ok(token)
}
pub fn generate_hex_token(byte_length: usize) -> Result<String> {
let mut bytes = vec![0u8; byte_length];
rng().fill(&mut bytes[..]);
Ok(hex::encode(bytes))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_generate_token() {
let token = generate_token(32);
assert_eq!(token.len(), 32);
assert!(token.chars().all(|c| c.is_alphanumeric()));
}
#[test]
fn test_generate_secure_token() {
let token = generate_secure_token(32).unwrap();
assert_eq!(token.len(), 32);
assert!(token.chars().all(|c| c.is_alphanumeric()));
}
#[test]
fn test_generate_hex_token() {
let token = generate_hex_token(16).unwrap();
assert_eq!(token.len(), 32); assert!(token.chars().all(|c| c.is_ascii_hexdigit()));
}
}