use lazy_static::lazy_static;
use std::{
net::{SocketAddr, ToSocketAddrs},
vec,
};
use regex::Regex;
use serde::Serialize;
use snafu::OptionExt;
use super::Result;
use crate::config::error::{Error, InvalidAddressSnafu};
lazy_static! {
static ref DOMAIN_PORT_REGEX: Regex =
Regex::new(r"^([a-zA-Z0-9.-]+):(\d+)$").expect("Failed to compile regex");
}
#[derive(Hash, PartialEq, Eq, Debug, Serialize)]
pub struct Address(String, u16);
impl Address {
pub fn new(s: String) -> Result<Self> {
let caps = DOMAIN_PORT_REGEX
.captures(&s)
.context(InvalidAddressSnafu { s: s.clone() })?;
let domain = caps
.get(1)
.context(InvalidAddressSnafu { s: s.clone() })?
.as_str()
.to_string();
let port = caps
.get(2)
.context(InvalidAddressSnafu { s: s.clone() })?
.as_str()
.parse()
.map_err(|_| Error::InvalidAddress { s })?;
Ok(Self(domain, port))
}
}
impl TryFrom<String> for Address {
type Error = Error;
fn try_from(value: String) -> std::result::Result<Self, Self::Error> {
Self::new(value)
}
}
impl From<Address> for String {
fn from(value: Address) -> Self {
format!("{}:{}", value.0, value.1)
}
}
impl ToSocketAddrs for Address {
type Iter = vec::IntoIter<SocketAddr>;
fn to_socket_addrs(&self) -> std::io::Result<Self::Iter> {
let pair = (self.0.clone(), self.1);
pair.to_socket_addrs()
}
}