use std::net::IpAddr;
use std::str::FromStr;
use std::sync::LazyLock;
use regex::Regex;
static DOMAIN_NAME_PATTERN: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"^([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.?$").unwrap());
pub fn check_host(host: &str) -> Result<(), String> {
if IpAddr::from_str(host).is_err() {
if !DOMAIN_NAME_PATTERN.is_match(host) {
return Err("Host portion is not IPv4, IPv6, or domain name".to_string());
}
}
Ok(())
}
pub fn parse_address(addr: &str) -> Result<(&str, u16), String> {
match addr.rsplit_once(':') {
None => Err("Missing port. Use HOST:PORT format.".to_string()),
Some((host, port)) => {
check_host(host)?;
let port = match port.parse::<u16>() {
Ok(parsed) => parsed,
Err(err) => return Err(format!("Invalid port: {err}")),
};
Ok((host, port))
}
}
}