Coverage Report

Created: 2025-08-29 06:13

/rust/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.47.1/src/net/addr.rs
Line
Count
Source (jump to first uncovered line)
1
use std::future;
2
use std::io;
3
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
4
5
/// Converts or resolves without blocking to one or more `SocketAddr` values.
6
///
7
/// # DNS
8
///
9
/// Implementations of `ToSocketAddrs` for string types require a DNS lookup.
10
///
11
/// # Calling
12
///
13
/// Currently, this trait is only used as an argument to Tokio functions that
14
/// need to reference a target socket address. To perform a `SocketAddr`
15
/// conversion directly, use [`lookup_host()`](super::lookup_host()).
16
///
17
/// This trait is sealed and is intended to be opaque. The details of the trait
18
/// will change. Stabilization is pending enhancements to the Rust language.
19
pub trait ToSocketAddrs: sealed::ToSocketAddrsPriv {}
20
21
type ReadyFuture<T> = future::Ready<io::Result<T>>;
22
23
cfg_net! {
24
0
    pub(crate) fn to_socket_addrs<T>(arg: T) -> T::Future
25
0
    where
26
0
        T: ToSocketAddrs,
27
0
    {
28
0
        arg.to_socket_addrs(sealed::Internal)
29
0
    }
30
}
31
32
// ===== impl &impl ToSocketAddrs =====
33
34
impl<T: ToSocketAddrs + ?Sized> ToSocketAddrs for &T {}
35
36
impl<T> sealed::ToSocketAddrsPriv for &T
37
where
38
    T: sealed::ToSocketAddrsPriv + ?Sized,
39
{
40
    type Iter = T::Iter;
41
    type Future = T::Future;
42
43
0
    fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future {
44
0
        (**self).to_socket_addrs(sealed::Internal)
45
0
    }
46
}
47
48
// ===== impl SocketAddr =====
49
50
impl ToSocketAddrs for SocketAddr {}
51
52
impl sealed::ToSocketAddrsPriv for SocketAddr {
53
    type Iter = std::option::IntoIter<SocketAddr>;
54
    type Future = ReadyFuture<Self::Iter>;
55
56
0
    fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future {
57
0
        let iter = Some(*self).into_iter();
58
0
        future::ready(Ok(iter))
59
0
    }
60
}
61
62
// ===== impl SocketAddrV4 =====
63
64
impl ToSocketAddrs for SocketAddrV4 {}
65
66
impl sealed::ToSocketAddrsPriv for SocketAddrV4 {
67
    type Iter = std::option::IntoIter<SocketAddr>;
68
    type Future = ReadyFuture<Self::Iter>;
69
70
0
    fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future {
71
0
        SocketAddr::V4(*self).to_socket_addrs(sealed::Internal)
72
0
    }
73
}
74
75
// ===== impl SocketAddrV6 =====
76
77
impl ToSocketAddrs for SocketAddrV6 {}
78
79
impl sealed::ToSocketAddrsPriv for SocketAddrV6 {
80
    type Iter = std::option::IntoIter<SocketAddr>;
81
    type Future = ReadyFuture<Self::Iter>;
82
83
0
    fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future {
84
0
        SocketAddr::V6(*self).to_socket_addrs(sealed::Internal)
85
0
    }
86
}
87
88
// ===== impl (IpAddr, u16) =====
89
90
impl ToSocketAddrs for (IpAddr, u16) {}
91
92
impl sealed::ToSocketAddrsPriv for (IpAddr, u16) {
93
    type Iter = std::option::IntoIter<SocketAddr>;
94
    type Future = ReadyFuture<Self::Iter>;
95
96
0
    fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future {
97
0
        let iter = Some(SocketAddr::from(*self)).into_iter();
98
0
        future::ready(Ok(iter))
99
0
    }
100
}
101
102
// ===== impl (Ipv4Addr, u16) =====
103
104
impl ToSocketAddrs for (Ipv4Addr, u16) {}
105
106
impl sealed::ToSocketAddrsPriv for (Ipv4Addr, u16) {
107
    type Iter = std::option::IntoIter<SocketAddr>;
108
    type Future = ReadyFuture<Self::Iter>;
109
110
0
    fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future {
111
0
        let (ip, port) = *self;
112
0
        SocketAddrV4::new(ip, port).to_socket_addrs(sealed::Internal)
113
0
    }
114
}
115
116
// ===== impl (Ipv6Addr, u16) =====
117
118
impl ToSocketAddrs for (Ipv6Addr, u16) {}
119
120
impl sealed::ToSocketAddrsPriv for (Ipv6Addr, u16) {
121
    type Iter = std::option::IntoIter<SocketAddr>;
122
    type Future = ReadyFuture<Self::Iter>;
123
124
0
    fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future {
125
0
        let (ip, port) = *self;
126
0
        SocketAddrV6::new(ip, port, 0, 0).to_socket_addrs(sealed::Internal)
127
0
    }
128
}
129
130
// ===== impl &[SocketAddr] =====
131
132
impl ToSocketAddrs for &[SocketAddr] {}
133
134
impl sealed::ToSocketAddrsPriv for &[SocketAddr] {
135
    type Iter = std::vec::IntoIter<SocketAddr>;
136
    type Future = ReadyFuture<Self::Iter>;
137
138
0
    fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future {
139
        #[inline]
140
0
        fn slice_to_vec(addrs: &[SocketAddr]) -> Vec<SocketAddr> {
141
0
            addrs.to_vec()
142
0
        }
143
144
        // This uses a helper method because clippy doesn't like the `to_vec()`
145
        // call here (it will allocate, whereas `self.iter().copied()` would
146
        // not), but it's actually necessary in order to ensure that the
147
        // returned iterator is valid for the `'static` lifetime, which the
148
        // borrowed `slice::Iter` iterator would not be.
149
        //
150
        // Note that we can't actually add an `allow` attribute for
151
        // `clippy::unnecessary_to_owned` here, as Tokio's CI runs clippy lints
152
        // on Rust 1.52 to avoid breaking LTS releases of Tokio. Users of newer
153
        // Rust versions who see this lint should just ignore it.
154
0
        let iter = slice_to_vec(self).into_iter();
155
0
        future::ready(Ok(iter))
156
0
    }
157
}
158
159
cfg_net! {
160
    // ===== impl str =====
161
162
    impl ToSocketAddrs for str {}
163
164
    impl sealed::ToSocketAddrsPriv for str {
165
        type Iter = sealed::OneOrMore;
166
        type Future = sealed::MaybeReady;
167
168
0
        fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future {
169
            use crate::blocking::spawn_blocking;
170
            use sealed::MaybeReady;
171
172
            // First check if the input parses as a socket address
173
0
            let res: Result<SocketAddr, _> = self.parse();
174
175
0
            if let Ok(addr) = res {
176
0
                return MaybeReady(sealed::State::Ready(Some(addr)));
177
0
            }
178
0
179
0
            // Run DNS lookup on the blocking pool
180
0
            let s = self.to_owned();
181
0
182
0
            MaybeReady(sealed::State::Blocking(spawn_blocking(move || {
183
0
                std::net::ToSocketAddrs::to_socket_addrs(&s)
184
0
            })))
185
0
        }
186
    }
187
188
    // ===== impl (&str, u16) =====
189
190
    impl ToSocketAddrs for (&str, u16) {}
191
192
    impl sealed::ToSocketAddrsPriv for (&str, u16) {
193
        type Iter = sealed::OneOrMore;
194
        type Future = sealed::MaybeReady;
195
196
0
        fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future {
197
            use crate::blocking::spawn_blocking;
198
            use sealed::MaybeReady;
199
200
0
            let (host, port) = *self;
201
202
            // try to parse the host as a regular IP address first
203
0
            if let Ok(addr) = host.parse::<Ipv4Addr>() {
204
0
                let addr = SocketAddrV4::new(addr, port);
205
0
                let addr = SocketAddr::V4(addr);
206
0
207
0
                return MaybeReady(sealed::State::Ready(Some(addr)));
208
0
            }
209
210
0
            if let Ok(addr) = host.parse::<Ipv6Addr>() {
211
0
                let addr = SocketAddrV6::new(addr, port, 0, 0);
212
0
                let addr = SocketAddr::V6(addr);
213
0
214
0
                return MaybeReady(sealed::State::Ready(Some(addr)));
215
0
            }
216
0
217
0
            let host = host.to_owned();
218
0
219
0
            MaybeReady(sealed::State::Blocking(spawn_blocking(move || {
220
0
                std::net::ToSocketAddrs::to_socket_addrs(&(&host[..], port))
221
0
            })))
222
0
        }
223
    }
224
225
    // ===== impl (String, u16) =====
226
227
    impl ToSocketAddrs for (String, u16) {}
228
229
    impl sealed::ToSocketAddrsPriv for (String, u16) {
230
        type Iter = sealed::OneOrMore;
231
        type Future = sealed::MaybeReady;
232
233
0
        fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future {
234
0
            (self.0.as_str(), self.1).to_socket_addrs(sealed::Internal)
235
0
        }
236
    }
237
238
    // ===== impl String =====
239
240
    impl ToSocketAddrs for String {}
241
242
    impl sealed::ToSocketAddrsPriv for String {
243
        type Iter = <str as sealed::ToSocketAddrsPriv>::Iter;
244
        type Future = <str as sealed::ToSocketAddrsPriv>::Future;
245
246
0
        fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future {
247
0
            self[..].to_socket_addrs(sealed::Internal)
248
0
        }
249
    }
250
}
251
252
pub(crate) mod sealed {
253
    //! The contents of this trait are intended to remain private and __not__
254
    //! part of the `ToSocketAddrs` public API. The details will change over
255
    //! time.
256
257
    use std::future::Future;
258
    use std::io;
259
    use std::net::SocketAddr;
260
261
    #[doc(hidden)]
262
    pub trait ToSocketAddrsPriv {
263
        type Iter: Iterator<Item = SocketAddr> + Send + 'static;
264
        type Future: Future<Output = io::Result<Self::Iter>> + Send + 'static;
265
266
        fn to_socket_addrs(&self, internal: Internal) -> Self::Future;
267
    }
268
269
    #[allow(missing_debug_implementations)]
270
    pub struct Internal;
271
272
    cfg_net! {
273
        use crate::blocking::JoinHandle;
274
275
        use std::option;
276
        use std::pin::Pin;
277
        use std::task::{ready,Context, Poll};
278
        use std::vec;
279
280
        #[doc(hidden)]
281
        #[derive(Debug)]
282
        pub struct MaybeReady(pub(super) State);
283
284
        #[derive(Debug)]
285
        pub(super) enum State {
286
            Ready(Option<SocketAddr>),
287
            Blocking(JoinHandle<io::Result<vec::IntoIter<SocketAddr>>>),
288
        }
289
290
        #[doc(hidden)]
291
        #[derive(Debug)]
292
        pub enum OneOrMore {
293
            One(option::IntoIter<SocketAddr>),
294
            More(vec::IntoIter<SocketAddr>),
295
        }
296
297
        impl Future for MaybeReady {
298
            type Output = io::Result<OneOrMore>;
299
300
0
            fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
301
0
                match self.0 {
302
0
                    State::Ready(ref mut i) => {
303
0
                        let iter = OneOrMore::One(i.take().into_iter());
304
0
                        Poll::Ready(Ok(iter))
305
                    }
306
0
                    State::Blocking(ref mut rx) => {
307
0
                        let res = ready!(Pin::new(rx).poll(cx))?.map(OneOrMore::More);
308
0
309
0
                        Poll::Ready(res)
310
                    }
311
                }
312
0
            }
313
        }
314
315
        impl Iterator for OneOrMore {
316
            type Item = SocketAddr;
317
318
0
            fn next(&mut self) -> Option<Self::Item> {
319
0
                match self {
320
0
                    OneOrMore::One(i) => i.next(),
321
0
                    OneOrMore::More(i) => i.next(),
322
                }
323
0
            }
324
325
0
            fn size_hint(&self) -> (usize, Option<usize>) {
326
0
                match self {
327
0
                    OneOrMore::One(i) => i.size_hint(),
328
0
                    OneOrMore::More(i) => i.size_hint(),
329
                }
330
0
            }
331
        }
332
    }
333
}