use std::{
fmt::{Display, Formatter},
net::SocketAddr,
str::FromStr,
};
use anyhow::anyhow;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
pub enum DnsNameServer {
#[default]
System,
Custom {
addr: SocketAddr,
dns_name: String,
},
}
impl DnsNameServer {
pub fn custom(addr: SocketAddr, dns_name: String) -> Self {
Self::Custom { addr, dns_name }
}
}
impl Display for DnsNameServer {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
DnsNameServer::System => write!(f, "system"),
DnsNameServer::Custom { addr, dns_name } => {
write!(f, "{addr}/{dns_name}")
},
}
}
}
impl FromStr for DnsNameServer {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let s = s
.to_string()
.replace(" ", "")
.replace("\"", "")
.replace("'", "")
.to_ascii_lowercase();
let mut split = s.splitn(2, '/');
let addr = split
.next()
.ok_or_else(|| anyhow!("failed to parse DNS name server 'addr'"))?;
if addr == "system" {
return Ok(Self::System);
}
let dns_name = split.next().unwrap_or("");
Ok(Self::Custom {
addr: addr.parse()?,
dns_name: dns_name.to_string(),
})
}
}
#[cfg(test)]
mod test {
use std::net::{IpAddr, Ipv4Addr};
use super::*;
#[test]
fn dns_name_server_test() {
let ipv4 = Ipv4Addr::new(127, 0, 0, 1);
let ip = IpAddr::V4(ipv4);
let socket = SocketAddr::new(ip, 8080);
let dns = DnsNameServer::custom(socket, String::from("my_dns"));
assert_eq!(format!("{dns}"), "127.0.0.1:8080/my_dns");
let new_dns = DnsNameServer::from_str("'127.0.0.1:8080/my_dns'").unwrap();
assert_eq!(new_dns, dns);
let new_dns = DnsNameServer::from_str("\"127.0.0.1:8080/my_dns\"").unwrap();
assert_eq!(new_dns, dns);
let new_dns = DnsNameServer::from_str("127.0.0.1:8080/my_dns").unwrap();
assert_eq!(new_dns, dns);
assert_eq!(DnsNameServer::default(), DnsNameServer::System);
}
#[test]
fn to_string_from_str() {
let ipv4 = Ipv4Addr::new(127, 0, 0, 1);
let ip = IpAddr::V4(ipv4);
let socket = SocketAddr::new(ip, 8080);
let dns = DnsNameServer::custom(socket, String::from("my_dns"));
let parsed = dns.to_string().parse::<DnsNameServer>().unwrap();
assert_eq!(dns, parsed);
let parsed = DnsNameServer::System.to_string().parse::<DnsNameServer>().unwrap();
assert_eq!(parsed, DnsNameServer::System);
}
}