agnostic_net/
to_socket_addrs.rs1use std::{
2 future::Future,
3 io,
4 net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
5 pin::Pin,
6 task::Poll,
7 vec,
8};
9
10use agnostic_lite::AsyncBlockingSpawner;
11
12use super::{RuntimeLite, ToSocketAddrs};
13
14#[doc(hidden)]
15pub enum ToSocketAddrsFuture<H> {
16 Ready(Option<SocketAddr>),
17 Blocking(H),
18}
19
20type ReadyFuture<T> = std::future::Ready<io::Result<T>>;
21
22impl<T, R: RuntimeLite> ToSocketAddrs<R> for &T
23where
24 T: ToSocketAddrs<R> + ?Sized + Send + Sync,
25{
26 type Iter = T::Iter;
27 type Future = T::Future;
28
29 fn to_socket_addrs(&self) -> Self::Future {
30 (**self).to_socket_addrs()
31 }
32}
33
34impl<R: RuntimeLite> ToSocketAddrs<R> for SocketAddr {
35 type Iter = std::option::IntoIter<SocketAddr>;
36 type Future = ReadyFuture<Self::Iter>;
37
38 fn to_socket_addrs(&self) -> Self::Future {
39 let iter = Some(*self).into_iter();
40 std::future::ready(Ok(iter))
41 }
42}
43
44impl<R: RuntimeLite> ToSocketAddrs<R> for SocketAddrV4 {
45 type Iter = std::option::IntoIter<SocketAddr>;
46 type Future = ReadyFuture<Self::Iter>;
47
48 fn to_socket_addrs(&self) -> Self::Future {
49 ToSocketAddrs::<R>::to_socket_addrs(&SocketAddr::V4(*self))
50 }
51}
52
53impl<R: RuntimeLite> ToSocketAddrs<R> for SocketAddrV6 {
54 type Iter = std::option::IntoIter<SocketAddr>;
55 type Future = ReadyFuture<Self::Iter>;
56
57 fn to_socket_addrs(&self) -> Self::Future {
58 ToSocketAddrs::<R>::to_socket_addrs(&SocketAddr::V6(*self))
59 }
60}
61
62impl<R: RuntimeLite> ToSocketAddrs<R> for (IpAddr, u16) {
63 type Iter = std::option::IntoIter<SocketAddr>;
64 type Future = ReadyFuture<Self::Iter>;
65
66 fn to_socket_addrs(&self) -> Self::Future {
67 ToSocketAddrs::<R>::to_socket_addrs(&SocketAddr::from(*self))
68 }
69}
70
71impl<R: RuntimeLite> ToSocketAddrs<R> for (Ipv4Addr, u16) {
72 type Iter = std::option::IntoIter<SocketAddr>;
73 type Future = ReadyFuture<Self::Iter>;
74
75 fn to_socket_addrs(&self) -> Self::Future {
76 let (ip, port) = *self;
77 ToSocketAddrs::<R>::to_socket_addrs(&SocketAddrV4::new(ip, port))
78 }
79}
80
81impl<R: RuntimeLite> ToSocketAddrs<R> for (Ipv6Addr, u16) {
82 type Iter = std::option::IntoIter<SocketAddr>;
83 type Future = ReadyFuture<Self::Iter>;
84
85 fn to_socket_addrs(&self) -> Self::Future {
86 let (ip, port) = *self;
87 ToSocketAddrs::<R>::to_socket_addrs(&SocketAddrV6::new(ip, port, 0, 0))
88 }
89}
90
91impl<R: RuntimeLite> ToSocketAddrs<R> for [SocketAddr] {
92 type Iter = std::vec::IntoIter<SocketAddr>;
93 type Future = ReadyFuture<Self::Iter>;
94
95 fn to_socket_addrs(&self) -> Self::Future {
96 #[inline]
97 fn slice_to_vec(addrs: &[SocketAddr]) -> Vec<SocketAddr> {
98 addrs.to_vec()
99 }
100
101 let iter = slice_to_vec(self).into_iter();
112 std::future::ready(Ok(iter))
113 }
114}
115
116impl<R: RuntimeLite> ToSocketAddrs<R> for (String, u16)
117where
118 ToSocketAddrsFuture<
119 <R::BlockingSpawner as AsyncBlockingSpawner>::JoinHandle<io::Result<sealed::OneOrMore>>,
120 >: Future<Output = io::Result<sealed::OneOrMore>> + Send,
121{
122 type Iter = sealed::OneOrMore;
123 type Future = ToSocketAddrsFuture<
124 <R::BlockingSpawner as AsyncBlockingSpawner>::JoinHandle<io::Result<sealed::OneOrMore>>,
125 >;
126
127 fn to_socket_addrs(&self) -> Self::Future {
128 ToSocketAddrs::<R>::to_socket_addrs(&(self.0.as_str(), self.1))
129 }
130}
131
132impl<R: RuntimeLite> ToSocketAddrs<R> for String
133where
134 ToSocketAddrsFuture<
135 <R::BlockingSpawner as AsyncBlockingSpawner>::JoinHandle<io::Result<sealed::OneOrMore>>,
136 >: Future<Output = io::Result<sealed::OneOrMore>> + Send,
137{
138 type Iter = <str as ToSocketAddrs<R>>::Iter;
139 type Future = <str as ToSocketAddrs<R>>::Future;
140
141 fn to_socket_addrs(&self) -> Self::Future {
142 ToSocketAddrs::<R>::to_socket_addrs(&self[..])
143 }
144}
145
146impl<R: RuntimeLite> ToSocketAddrs<R> for str
147where
148 ToSocketAddrsFuture<
149 <R::BlockingSpawner as AsyncBlockingSpawner>::JoinHandle<io::Result<sealed::OneOrMore>>,
150 >: Future<Output = io::Result<sealed::OneOrMore>> + Send,
151{
152 type Iter = sealed::OneOrMore;
153
154 type Future = ToSocketAddrsFuture<
155 <R::BlockingSpawner as AsyncBlockingSpawner>::JoinHandle<io::Result<sealed::OneOrMore>>,
156 >;
157
158 fn to_socket_addrs(&self) -> Self::Future {
159 let res: Result<SocketAddr, _> = self.parse();
161
162 if let Ok(addr) = res {
163 return ToSocketAddrsFuture::Ready(Some(addr));
164 }
165
166 let s = self.to_owned();
168
169 ToSocketAddrsFuture::Blocking(R::spawn_blocking(move || {
170 std::net::ToSocketAddrs::to_socket_addrs(&s).map(sealed::OneOrMore::More)
171 }))
172 }
173}
174
175impl<R: RuntimeLite> ToSocketAddrs<R> for (&str, u16)
176where
177 ToSocketAddrsFuture<
178 <R::BlockingSpawner as AsyncBlockingSpawner>::JoinHandle<io::Result<sealed::OneOrMore>>,
179 >: Future<Output = io::Result<sealed::OneOrMore>> + Send,
180{
181 type Iter = sealed::OneOrMore;
182 type Future = ToSocketAddrsFuture<
183 <R::BlockingSpawner as AsyncBlockingSpawner>::JoinHandle<io::Result<sealed::OneOrMore>>,
184 >;
185
186 fn to_socket_addrs(&self) -> Self::Future {
187 let (host, port) = *self;
188
189 if let Ok(addr) = host.parse::<Ipv4Addr>() {
191 let addr = SocketAddrV4::new(addr, port);
192 let addr = SocketAddr::V4(addr);
193
194 return ToSocketAddrsFuture::Ready(Some(addr));
195 }
196
197 if let Ok(addr) = host.parse::<Ipv6Addr>() {
198 let addr = SocketAddrV6::new(addr, port, 0, 0);
199 let addr = SocketAddr::V6(addr);
200
201 return ToSocketAddrsFuture::Ready(Some(addr));
202 }
203
204 let host = host.to_owned();
205 ToSocketAddrsFuture::Blocking(R::spawn_blocking(move || {
206 std::net::ToSocketAddrs::to_socket_addrs(&(&host[..], port)).map(sealed::OneOrMore::More)
207 }))
208 }
209}
210
211impl<R: agnostic_lite::JoinHandle<io::Result<sealed::OneOrMore>>> Future
212 for ToSocketAddrsFuture<R>
213{
214 type Output = io::Result<sealed::OneOrMore>;
215
216 fn poll(
217 self: std::pin::Pin<&mut Self>,
218 cx: &mut std::task::Context<'_>,
219 ) -> std::task::Poll<Self::Output> {
220 match self.get_mut() {
221 Self::Ready(i) => Poll::Ready(Ok(sealed::OneOrMore::One(i.take().into_iter()))),
222 Self::Blocking(i) => {
223 let res = Pin::new(i).poll(cx).map_err(Into::into)?;
224 match res {
225 Poll::Ready(res) => match res {
226 Ok(res) => Poll::Ready(Ok(res)),
227 Err(e) => Poll::Ready(Err(e)),
228 },
229 Poll::Pending => Poll::Pending,
230 }
231 }
232 }
233 }
234}
235
236mod sealed {
237 use super::*;
238 use std::option;
239
240 #[derive(Debug)]
241 #[doc(hidden)]
242 pub enum OneOrMore {
243 One(option::IntoIter<SocketAddr>),
244 More(vec::IntoIter<SocketAddr>),
245 }
246
247 impl Iterator for OneOrMore {
248 type Item = SocketAddr;
249
250 fn next(&mut self) -> Option<Self::Item> {
251 match self {
252 OneOrMore::One(i) => i.next(),
253 OneOrMore::More(i) => i.next(),
254 }
255 }
256
257 fn size_hint(&self) -> (usize, Option<usize>) {
258 match self {
259 OneOrMore::One(i) => i.size_hint(),
260 OneOrMore::More(i) => i.size_hint(),
261 }
262 }
263 }
264}