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