use petname::Generator;
use rand::{distr::Alphanumeric, Rng};
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
pub struct RandomURLConfig {
#[deprecated(note = "disable by commenting out [paste].random_url")]
pub enabled: Option<bool>,
pub words: Option<u8>,
pub separator: Option<String>,
pub length: Option<usize>,
#[serde(rename = "type")]
pub type_: RandomURLType,
pub suffix_mode: Option<bool>,
}
#[allow(deprecated)]
impl RandomURLConfig {
pub fn generate(&self) -> Option<String> {
if !self.enabled.unwrap_or(true) {
return None;
}
Some(match self.type_ {
RandomURLType::PetName => petname::Petnames::large().generate_one(
self.words.unwrap_or(2),
self.separator.as_deref().unwrap_or("-"),
)?,
RandomURLType::Alphanumeric => rand::rng()
.sample_iter(&Alphanumeric)
.take(self.length.unwrap_or(8))
.map(char::from)
.collect::<String>(),
})
}
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum RandomURLType {
PetName,
Alphanumeric,
}
impl Default for RandomURLType {
fn default() -> Self {
Self::PetName
}
}
#[cfg(test)]
mod tests {
use super::*;
#[allow(deprecated)]
#[test]
fn test_generate_url() {
let random_config = RandomURLConfig {
enabled: Some(true),
words: Some(3),
separator: Some(String::from("~")),
type_: RandomURLType::PetName,
..RandomURLConfig::default()
};
let random_url = random_config
.generate()
.expect("cannot generate random URL");
assert_eq!(3, random_url.split('~').count());
let random_config = RandomURLConfig {
length: Some(21),
type_: RandomURLType::Alphanumeric,
..RandomURLConfig::default()
};
let random_url = random_config
.generate()
.expect("cannot generate random URL");
assert_eq!(21, random_url.len());
let random_config = RandomURLConfig {
enabled: Some(false),
..RandomURLConfig::default()
};
assert!(random_config.generate().is_none());
}
}