1use std::{
2 fmt,
3 io::{Error, ErrorKind, Result},
4 net::{IpAddr, SocketAddr},
5};
6
7#[derive(Debug, PartialEq, Clone, PartialOrd, Eq, Ord)]
9pub enum Address {
10 SocketAddr(SocketAddr),
11 Domain(String, u16),
12}
13
14pub trait IntoAddress: Send {
16 fn into_address(self) -> Result<Address>;
17 fn into_socket_addr(self) -> Result<SocketAddr>
18 where
19 Self: Sized,
20 {
21 self.into_address()?.to_socket_addr()
22 }
23}
24
25fn no_addr() -> Error {
26 ErrorKind::AddrNotAvailable.into()
27}
28
29fn host_to_address(host: &str, port: u16) -> Address {
30 match str::parse::<IpAddr>(host) {
31 Ok(ip) => {
32 let addr = SocketAddr::new(ip, port);
33 addr.into()
34 }
35 Err(_) => Address::Domain(host.to_string(), port),
36 }
37}
38
39impl IntoAddress for &str {
40 fn into_address(self) -> Result<Address> {
41 let mut parts = self.splitn(2, ":");
42 let host = parts.next().ok_or_else(no_addr)?;
43 let port: u16 = parts
44 .next()
45 .ok_or_else(no_addr)?
46 .parse()
47 .map_err(|_| no_addr())?;
48 Ok(host_to_address(host, port))
49 }
50}
51
52impl IntoAddress for (&str, u16) {
53 fn into_address(self) -> Result<Address> {
54 Ok(host_to_address(self.0, self.1))
55 }
56}
57
58impl IntoAddress for (String, u16) {
59 fn into_address(self) -> Result<Address> {
60 Ok(host_to_address(&self.0, self.1))
61 }
62}
63
64impl IntoAddress for (IpAddr, u16) {
65 fn into_address(self) -> Result<Address> {
66 let addr = SocketAddr::new(self.0, self.1);
67 Ok(addr.into())
68 }
69}
70
71impl IntoAddress for SocketAddr {
72 fn into_address(self) -> Result<Address> {
73 Ok(self.into())
74 }
75}
76
77impl IntoAddress for Address {
78 fn into_address(self) -> Result<Address> {
79 Ok(self)
80 }
81}
82
83impl From<SocketAddr> for Address {
84 fn from(addr: SocketAddr) -> Self {
85 Address::SocketAddr(addr)
86 }
87}
88
89impl From<(IpAddr, u16)> for Address {
90 fn from((ip, port): (IpAddr, u16)) -> Self {
91 Address::SocketAddr(SocketAddr::new(ip, port))
92 }
93}
94
95impl Address {
96 pub fn to_socket_addr(self) -> Result<SocketAddr> {
99 match self {
100 Address::SocketAddr(s) => Ok(s),
101 _ => Err(no_addr()),
102 }
103 }
104
105 pub async fn resolve<Fut>(&self, f: impl FnOnce(String, u16) -> Fut) -> Result<SocketAddr>
107 where
108 Fut: std::future::Future<Output = Result<SocketAddr>>,
109 {
110 match self {
111 Address::SocketAddr(s) => Ok(*s),
112 Address::Domain(d, p) => match str::parse::<IpAddr>(d) {
113 Ok(ip) => Ok(SocketAddr::new(ip, *p)),
114 Err(_) => f(d.to_string(), *p).await,
115 },
116 }
117 }
118}
119
120impl fmt::Display for Address {
121 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122 match self {
123 Address::Domain(domain, port) => write!(f, "{}:{}", domain, port),
124 Address::SocketAddr(s) => write!(f, "{}", s),
125 }
126 }
127}