use crate::RngExt as _;
use rand::{Rng, seq::IndexedRandom as _};
const PREFIXES: &[&str] = &["www."];
const SUFFIXES: &[&str] = &[".com", ".net", ".org"];
const CHARSET: &[u8] = b"abcdefghijklmnopqrstuvwxyz-0123456789";
const MIN_LEN: usize = 16;
const MAX_LEN: usize = 32;
pub fn random_hostname<R: Rng>(rng: &mut R) -> String {
let prefix = PREFIXES.choose(rng).expect("TLDS was empty!?");
let suffix = SUFFIXES.choose(rng).expect("TLDS was empty!?");
let length: usize = rng
.gen_range_checked(MIN_LEN..=MAX_LEN)
.expect("Somehow MIN..=MAX wasn't a valid range?");
let center_length = length
.checked_sub(prefix.len() + suffix.len())
.expect("prefix and suffix exceeded MIN_LEN");
let mut output = String::from(*prefix);
for _ in 0..center_length {
output.push(*CHARSET.choose(rng).expect("CHARSET was empty!?") as char);
}
output.push_str(suffix);
assert_eq!(length, output.len());
output
}
#[cfg(test)]
mod test {
#![allow(clippy::bool_assert_comparison)]
#![allow(clippy::clone_on_copy)]
#![allow(clippy::dbg_macro)]
#![allow(clippy::mixed_attributes_style)]
#![allow(clippy::print_stderr)]
#![allow(clippy::print_stdout)]
#![allow(clippy::single_char_pattern)]
#![allow(clippy::unwrap_used)]
#![allow(clippy::unchecked_time_subtraction)]
#![allow(clippy::useless_vec)]
#![allow(clippy::needless_pass_by_value)]
use super::*;
use crate::test_rng::testing_rng;
#[test]
fn generate_names() {
let mut rng = testing_rng();
for _ in 0..100 {
let name = random_hostname(&mut rng);
assert!(PREFIXES.iter().any(|tld| name.starts_with(tld)));
assert!(SUFFIXES.iter().any(|tld| name.ends_with(tld)));
assert!(name.len() >= MIN_LEN);
assert!(name.len() <= MAX_LEN);
for ch in name.chars() {
assert!(matches!(ch, '.' | '-' | '0'..='9' | 'a'..='z'));
}
}
}
}