use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
pub trait ToServerAddrs {
#[cfg(feature = "async")]
#[doc(hidden)]
type Return: std::net::ToSocketAddrs + tokio::net::ToSocketAddrs;
#[cfg(not(feature = "async"))]
#[doc(hidden)]
type Return: std::net::ToSocketAddrs;
#[doc(hidden)]
fn to_server_addrs(&self, default_port: u16) -> Self::Return;
}
impl ToServerAddrs for SocketAddr {
type Return = SocketAddr;
fn to_server_addrs(&self, _default_port: u16) -> Self::Return {
*self
}
}
impl ToServerAddrs for SocketAddrV4 {
type Return = SocketAddrV4;
fn to_server_addrs(&self, _default_port: u16) -> Self::Return {
*self
}
}
impl ToServerAddrs for SocketAddrV6 {
type Return = SocketAddrV6;
fn to_server_addrs(&self, _default_port: u16) -> Self::Return {
*self
}
}
impl ToServerAddrs for IpAddr {
type Return = (IpAddr, u16);
fn to_server_addrs(&self, default_port: u16) -> Self::Return {
(*self, default_port)
}
}
impl ToServerAddrs for (IpAddr, u16) {
type Return = (IpAddr, u16);
fn to_server_addrs(&self, _default_port: u16) -> Self::Return {
*self
}
}
impl ToServerAddrs for Ipv4Addr {
type Return = (Ipv4Addr, u16);
fn to_server_addrs(&self, default_port: u16) -> Self::Return {
(*self, default_port)
}
}
impl ToServerAddrs for (Ipv4Addr, u16) {
type Return = (Ipv4Addr, u16);
fn to_server_addrs(&self, _default_port: u16) -> Self::Return {
*self
}
}
impl ToServerAddrs for Ipv6Addr {
type Return = (Ipv6Addr, u16);
fn to_server_addrs(&self, default_port: u16) -> Self::Return {
(*self, default_port)
}
}
impl ToServerAddrs for (Ipv6Addr, u16) {
type Return = (Ipv6Addr, u16);
fn to_server_addrs(&self, _default_port: u16) -> Self::Return {
*self
}
}
impl ToServerAddrs for str {
type Return = String;
fn to_server_addrs(&self, default_port: u16) -> Self::Return {
if self.parse::<Ipv4Addr>().is_ok() {
self.to_string() + ":" + &default_port.to_string()
} else if self.parse::<Ipv6Addr>().is_ok() {
"[".to_string() + self + "]:" + &default_port.to_string()
} else if self.starts_with("[") && self.ends_with("]") {
self.to_string() + ":" + &default_port.to_string()
} else if !self.contains(":") {
self.to_string() + ":" + &default_port.to_string()
} else {
self.to_string()
}
}
}
impl ToServerAddrs for String {
type Return = String;
fn to_server_addrs(&self, default_port: u16) -> Self::Return {
(**self).to_server_addrs(default_port)
}
}
impl<'a> ToServerAddrs for (&'a str, u16) {
type Return = (&'a str, u16);
fn to_server_addrs(&self, _default_port: u16) -> Self::Return {
*self
}
}
impl ToServerAddrs for (String, u16) {
type Return = String;
fn to_server_addrs(&self, _default_port: u16) -> Self::Return {
self.0.clone() + ":" + &self.1.to_string()
}
}
impl<T: ToServerAddrs + ?Sized> ToServerAddrs for &T {
type Return = T::Return;
fn to_server_addrs(&self, default_port: u16) -> Self::Return {
(**self).to_server_addrs(default_port)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn works_for_socket_addr() {
let s = SocketAddr::from(([127, 0, 0, 1], 1234));
let s4 = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 1234);
let s6 = SocketAddrV6::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 1234, 0, 0);
assert_eq!(s.to_server_addrs(456), s);
assert_eq!(s4.to_server_addrs(456), s4);
assert_eq!(s6.to_server_addrs(456), s6);
}
#[test]
fn works_for_ip_addr() {
let ip = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
let ip4 = Ipv4Addr::new(127, 0, 0, 1);
let ip6 = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1);
assert_eq!(ip.to_server_addrs(456), (ip, 456));
assert_eq!(ip4.to_server_addrs(456), (ip4, 456));
assert_eq!(ip6.to_server_addrs(456), (ip6, 456));
assert_eq!((ip, 1234).to_server_addrs(456), (ip, 1234));
assert_eq!((ip4, 1234).to_server_addrs(456), (ip4, 1234));
assert_eq!((ip6, 1234).to_server_addrs(456), (ip6, 1234));
}
#[test]
fn works_for_ipv4_strings() {
assert_eq!("127.0.0.1".to_server_addrs(456), "127.0.0.1:456");
assert_eq!("127.0.0.1:1234".to_server_addrs(456), "127.0.0.1:1234");
assert_eq!(
"127.0.0.1".to_string().to_server_addrs(456),
"127.0.0.1:456"
);
assert_eq!(
"127.0.0.1:1234".to_string().to_server_addrs(456),
"127.0.0.1:1234"
);
assert_eq!(
("127.0.0.1", 1234).to_server_addrs(456),
("127.0.0.1", 1234)
);
assert_eq!(
("127.0.0.1".to_string(), 1234).to_server_addrs(456),
"127.0.0.1:1234"
);
}
#[test]
fn works_for_ip6_string() {
assert_eq!("::1".to_server_addrs(456), "[::1]:456");
assert_eq!("[::1]".to_server_addrs(456), "[::1]:456");
assert_eq!("[::1]:1234".to_server_addrs(456), "[::1]:1234");
assert_eq!("::1".to_string().to_server_addrs(456), "[::1]:456");
assert_eq!("[::1]".to_string().to_server_addrs(456), "[::1]:456");
assert_eq!("[::1]:1234".to_string().to_server_addrs(456), "[::1]:1234");
}
}