use std::{
fmt::Display, net::{AddrParseError, IpAddr, Ipv4Addr, SocketAddr}, str::FromStr
};
use local_ip_address::{local_ip, local_ipv6};
fn parse_socker_addr(s: &str) -> Result<Vec<SocketAddr>, AddrParseError> {
if s.starts_with(":") {
let port = s.trim_start_matches(':');
let mut results = vec![];
if let Ok(port) = port.parse::<u16>() {
if let Ok(v) = local_ip() {
results.push(SocketAddr::new(v, port));
}
if let Ok(v) = local_ipv6() {
results.push(SocketAddr::new(v, port));
}
results.push(SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), port));
} else {
results.push(format!("127.0.0.1{s}").parse::<SocketAddr>()?);
}
Ok(results)
} else {
let addr = s.parse::<SocketAddr>()?;
Ok(vec![addr])
}
}
#[derive(Debug, Clone, Copy)]
pub struct WrapAddr(pub SocketAddr);
impl FromStr for WrapAddr {
type Err = AddrParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(WrapAddr(parse_socker_addr(s)?[0]))
}
}
impl Display for WrapAddr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{}", self.0))
}
}
#[derive(Debug, Clone)]
pub struct WrapVecAddr(pub Vec<SocketAddr>);
impl FromStr for WrapVecAddr {
type Err = AddrParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s.contains("-") {
let vals = s
.split(&['-'])
.filter(|s| !s.is_empty())
.collect::<Vec<&str>>();
let start = parse_socker_addr(vals[0])?;
if vals.len() != 2 {
return Ok(WrapVecAddr(start));
} else {
let end = parse_socker_addr(vals[1])?;
let mut results = vec![];
for port in start[0].port()..=end[1].port() {
for idx in &start {
let mut addr = idx.clone();
addr.set_port(port);
results.push(addr);
}
}
return Ok(WrapVecAddr(results));
}
} else {
let vals = s
.split(&[',', ' '])
.filter(|s| !s.is_empty())
.collect::<Vec<&str>>();
let mut results = vec![];
for s in vals {
results.extend(parse_socker_addr(s)?);
}
Ok(WrapVecAddr(results))
}
}
}
impl Display for WrapVecAddr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut values = vec![];
for a in &self.0 {
values.push(format!("{}", a));
}
f.write_str(&values.join(","))
}
}
impl WrapVecAddr {
pub fn empty() -> Self {
WrapVecAddr(vec![])
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn contains(&self, port: u16) -> bool {
for v in &self.0 {
if v.port() == port {
return true;
}
}
false
}
}