1use std::future::Future;
2use std::mem;
3use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
4use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
5use std::pin::Pin;
6
7use crate::io;
8use crate::task::{spawn_blocking, Context, JoinHandle, Poll};
9use crate::utils::Context as ErrorContext;
10
11cfg_not_docs! {
12 macro_rules! ret {
13 (impl Future<Output = $out:ty>, $fut:ty) => ($fut);
14 }
15}
16
17cfg_docs! {
18 #[doc(hidden)]
19 pub struct ImplFuture<T>(std::marker::PhantomData<T>);
20
21 macro_rules! ret {
22 (impl Future<Output = $out:ty>, $fut:ty) => (ImplFuture<$out>);
23 }
24}
25
26pub trait ToSocketAddrs {
46 type Iter: Iterator<Item = SocketAddr>;
48
49 fn to_socket_addrs(
56 &self,
57 ) -> ret!(
58 impl Future<Output = Self::Iter>,
59 ToSocketAddrsFuture<Self::Iter>
60 );
61}
62
63#[doc(hidden)]
64#[allow(missing_debug_implementations)]
65pub enum ToSocketAddrsFuture<I> {
66 Resolving(JoinHandle<io::Result<I>>),
67 Ready(io::Result<I>),
68 Done,
69}
70
71impl<T> ErrorContext for ToSocketAddrsFuture<T> {
75 fn context(self, message: impl Fn() -> String) -> Self {
76 match self {
77 ToSocketAddrsFuture::Ready(res) => ToSocketAddrsFuture::Ready(res.context(message)),
78 x => x,
79 }
80 }
81}
82
83impl<I: Iterator<Item = SocketAddr>> Future for ToSocketAddrsFuture<I> {
84 type Output = io::Result<I>;
85
86 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
87 let this = unsafe { self.get_unchecked_mut() };
88 let state = mem::replace(this, ToSocketAddrsFuture::Done);
89
90 match state {
91 ToSocketAddrsFuture::Resolving(mut task) => {
92 let poll = Pin::new(&mut task).poll(cx)?;
93 if poll.is_pending() {
94 *this = ToSocketAddrsFuture::Resolving(task);
95 }
96 poll
97 }
98 ToSocketAddrsFuture::Ready(res) => Poll::Ready(res),
99 ToSocketAddrsFuture::Done => panic!("polled a completed future"),
100 }
101 }
102}
103
104impl ToSocketAddrs for SocketAddr {
105 type Iter = std::option::IntoIter<SocketAddr>;
106
107 fn to_socket_addrs(
108 &self,
109 ) -> ret!(
110 impl Future<Output = Self::Iter>,
111 ToSocketAddrsFuture<Self::Iter>
112 ) {
113 ToSocketAddrsFuture::Ready(Ok(Some(*self).into_iter()))
114 }
115}
116
117impl ToSocketAddrs for SocketAddrV4 {
118 type Iter = std::option::IntoIter<SocketAddr>;
119
120 fn to_socket_addrs(
121 &self,
122 ) -> ret!(
123 impl Future<Output = Self::Iter>,
124 ToSocketAddrsFuture<Self::Iter>
125 ) {
126 SocketAddr::V4(*self)
127 .to_socket_addrs()
128 .context(|| format!("could not resolve address `{}`", self))
129 }
130}
131
132impl ToSocketAddrs for SocketAddrV6 {
133 type Iter = std::option::IntoIter<SocketAddr>;
134
135 fn to_socket_addrs(
136 &self,
137 ) -> ret!(
138 impl Future<Output = Self::Iter>,
139 ToSocketAddrsFuture<Self::Iter>
140 ) {
141 SocketAddr::V6(*self)
142 .to_socket_addrs()
143 .context(|| format!("could not resolve address `{}`", self))
144 }
145}
146
147impl ToSocketAddrs for (IpAddr, u16) {
148 type Iter = std::option::IntoIter<SocketAddr>;
149
150 fn to_socket_addrs(
151 &self,
152 ) -> ret!(
153 impl Future<Output = Self::Iter>,
154 ToSocketAddrsFuture<Self::Iter>
155 ) {
156 let (ip, port) = *self;
157 match ip {
158 IpAddr::V4(a) => (a, port).to_socket_addrs(),
159 IpAddr::V6(a) => (a, port).to_socket_addrs(),
160 }
161 }
162}
163
164impl ToSocketAddrs for (Ipv4Addr, u16) {
165 type Iter = std::option::IntoIter<SocketAddr>;
166
167 fn to_socket_addrs(
168 &self,
169 ) -> ret!(
170 impl Future<Output = Self::Iter>,
171 ToSocketAddrsFuture<Self::Iter>
172 ) {
173 let (ip, port) = *self;
174 SocketAddrV4::new(ip, port).to_socket_addrs()
175 }
176}
177
178impl ToSocketAddrs for (Ipv6Addr, u16) {
179 type Iter = std::option::IntoIter<SocketAddr>;
180
181 fn to_socket_addrs(
182 &self,
183 ) -> ret!(
184 impl Future<Output = Self::Iter>,
185 ToSocketAddrsFuture<Self::Iter>
186 ) {
187 let (ip, port) = *self;
188 SocketAddrV6::new(ip, port, 0, 0).to_socket_addrs()
189 }
190}
191
192impl ToSocketAddrs for (&str, u16) {
193 type Iter = std::vec::IntoIter<SocketAddr>;
194
195 fn to_socket_addrs(
196 &self,
197 ) -> ret!(
198 impl Future<Output = Self::Iter>,
199 ToSocketAddrsFuture<Self::Iter>
200 ) {
201 let (host, port) = *self;
202
203 if let Ok(addr) = host.parse::<Ipv4Addr>() {
204 let addr = SocketAddrV4::new(addr, port);
205 return ToSocketAddrsFuture::Ready(Ok(vec![SocketAddr::V4(addr)].into_iter()));
206 }
207
208 if let Ok(addr) = host.parse::<Ipv6Addr>() {
209 let addr = SocketAddrV6::new(addr, port, 0, 0);
210 return ToSocketAddrsFuture::Ready(Ok(vec![SocketAddr::V6(addr)].into_iter()));
211 }
212
213 let host = host.to_string();
214 let task = spawn_blocking(move || {
215 let addr = (host.as_str(), port);
216 std::net::ToSocketAddrs::to_socket_addrs(&addr)
217 .context(|| format!("could not resolve address `{:?}`", addr))
218 });
219 ToSocketAddrsFuture::Resolving(task)
220 }
221}
222
223impl ToSocketAddrs for str {
224 type Iter = std::vec::IntoIter<SocketAddr>;
225
226 fn to_socket_addrs(
227 &self,
228 ) -> ret!(
229 impl Future<Output = Self::Iter>,
230 ToSocketAddrsFuture<Self::Iter>
231 ) {
232 if let Ok(addr) = self.parse() {
233 return ToSocketAddrsFuture::Ready(Ok(vec![addr].into_iter()));
234 }
235
236 let addr = self.to_string();
237 let task = spawn_blocking(move || {
238 std::net::ToSocketAddrs::to_socket_addrs(addr.as_str())
239 .context(|| format!("could not resolve address `{:?}`", addr))
240 });
241 ToSocketAddrsFuture::Resolving(task)
242 }
243}
244
245impl<'a> ToSocketAddrs for &'a [SocketAddr] {
246 type Iter = std::iter::Cloned<std::slice::Iter<'a, SocketAddr>>;
247
248 fn to_socket_addrs(
249 &self,
250 ) -> ret!(
251 impl Future<Output = Self::Iter>,
252 ToSocketAddrsFuture<Self::Iter>
253 ) {
254 ToSocketAddrsFuture::Ready(Ok(self.iter().cloned()))
255 }
256}
257
258impl<T: ToSocketAddrs + ?Sized> ToSocketAddrs for &T {
259 type Iter = T::Iter;
260
261 fn to_socket_addrs(
262 &self,
263 ) -> ret!(
264 impl Future<Output = Self::Iter>,
265 ToSocketAddrsFuture<Self::Iter>
266 ) {
267 (**self).to_socket_addrs()
268 }
269}
270
271impl ToSocketAddrs for String {
272 type Iter = std::vec::IntoIter<SocketAddr>;
273
274 fn to_socket_addrs(
275 &self,
276 ) -> ret!(
277 impl Future<Output = Self::Iter>,
278 ToSocketAddrsFuture<Self::Iter>
279 ) {
280 (&**self).to_socket_addrs()
281 }
282}