rd_interface/
address.rs

1use std::{
2    fmt,
3    io::{Error, ErrorKind, Result},
4    net::{IpAddr, SocketAddr},
5};
6
7/// Address can be IPv4, IPv6 address or a domain with port.
8#[derive(Debug, PartialEq, Clone, PartialOrd, Eq, Ord)]
9pub enum Address {
10    SocketAddr(SocketAddr),
11    Domain(String, u16),
12}
13
14/// Converts to address value.
15pub 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    /// Converts to SocketAddr if Address can be convert to.
97    /// Otherwise [AddrNotAvailable](std::io::ErrorKind::AddrNotAvailable) is returned.
98    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    /// Resolve domain to SocketAddr using `f`.
106    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}