use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::str::FromStr;
use crate::error::XdbError;
pub trait IntoIpAddr {
fn into_ip_addr(self) -> Result<IpAddr, XdbError>;
}
impl IntoIpAddr for IpAddr {
fn into_ip_addr(self) -> Result<IpAddr, XdbError> {
Ok(self)
}
}
impl IntoIpAddr for Ipv4Addr {
fn into_ip_addr(self) -> Result<IpAddr, XdbError> {
Ok(IpAddr::V4(self))
}
}
impl IntoIpAddr for Ipv6Addr {
fn into_ip_addr(self) -> Result<IpAddr, XdbError> {
Ok(IpAddr::V6(self))
}
}
impl IntoIpAddr for u32 {
fn into_ip_addr(self) -> Result<IpAddr, XdbError> {
Ok(IpAddr::V4(Ipv4Addr::from(self)))
}
}
impl IntoIpAddr for u128 {
fn into_ip_addr(self) -> Result<IpAddr, XdbError> {
Ok(IpAddr::V6(Ipv6Addr::from(self)))
}
}
impl IntoIpAddr for &str {
fn into_ip_addr(self) -> Result<IpAddr, XdbError> {
parse_ip(self)
}
}
impl IntoIpAddr for String {
fn into_ip_addr(self) -> Result<IpAddr, XdbError> {
parse_ip(&self)
}
}
impl IntoIpAddr for &String {
fn into_ip_addr(self) -> Result<IpAddr, XdbError> {
parse_ip(self)
}
}
pub(crate) fn parse_ip(ip: &str) -> Result<IpAddr, XdbError> {
if ip.contains('.') || ip.contains(':') {
return Ok(IpAddr::from_str(ip)?);
}
if let Ok(num) = ip.parse::<u32>() {
return Ok(IpAddr::V4(Ipv4Addr::from(num)));
}
if let Ok(num) = ip.parse::<u128>() {
return Ok(IpAddr::V6(Ipv6Addr::from(num)));
}
Err(XdbError::InvalidIP("invalid IP or number".into()))
}