coreplus/net/
addr.rs

1use core::{fmt, option, str};
2
3use crate::{
4    io::Write,
5    net::{AddrParseError, IpAddr, Ipv4Addr, Ipv6Addr},
6};
7
8/// An internet socket address, either IPv4 or IPv6.
9///
10/// Internet socket addresses consist of an [IP address], a 16-bit port number, as well
11/// as possibly some version-dependent additional information. See [`SocketAddrV4`]'s and
12/// [`SocketAddrV6`]'s respective documentation for more details.
13///
14/// The size of a `SocketAddr` instance may vary depending on the target operating
15/// system.
16///
17/// [IP address]: IpAddr
18///
19/// # Examples
20///
21/// ```
22/// use coreplus::net::{IpAddr, Ipv4Addr, SocketAddr};
23///
24/// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
25///
26/// assert_eq!("127.0.0.1:8080".parse(), Ok(socket));
27/// assert_eq!(socket.port(), 8080);
28/// assert_eq!(socket.is_ipv4(), true);
29/// ```
30#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
31pub enum SocketAddr {
32    /// An IPv4 socket address.
33    V4(SocketAddrV4),
34    /// An IPv6 socket address.
35    V6(SocketAddrV6),
36}
37
38/// An IPv4 socket address.
39///
40/// IPv4 socket addresses consist of an [`IPv4` address] and a 16-bit port number, as
41/// stated in [IETF RFC 793].
42///
43/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses.
44///
45/// The size of a `SocketAddrV4` struct may vary depending on the target operating
46/// system. Do not assume that this type has the same memory layout as the underlying
47/// system representation.
48///
49/// [IETF RFC 793]: https://tools.ietf.org/html/rfc793
50/// [`IPv4` address]: Ipv4Addr
51///
52/// # Examples
53///
54/// ```
55/// use coreplus::net::{Ipv4Addr, SocketAddrV4};
56///
57/// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
58///
59/// assert_eq!("127.0.0.1:8080".parse(), Ok(socket));
60/// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1));
61/// assert_eq!(socket.port(), 8080);
62/// ```
63#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
64pub struct SocketAddrV4 {
65    // Do not assume that this struct is implemented as the underlying system representation.
66    // The memory layout is not part of the stable interface that std exposes.
67    ip: Ipv4Addr,
68    port: u16,
69}
70
71/// An IPv6 socket address.
72///
73/// IPv6 socket addresses consist of an [`IPv6` address], a 16-bit port number, as well
74/// as fields containing the traffic class, the flow label, and a scope identifier
75/// (see [IETF RFC 2553, Section 3.3] for more details).
76///
77/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses.
78///
79/// The size of a `SocketAddrV6` struct may vary depending on the target operating
80/// system. Do not assume that this type has the same memory layout as the underlying
81/// system representation.
82///
83/// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
84/// [`IPv6` address]: Ipv6Addr
85///
86/// # Examples
87///
88/// ```
89/// use coreplus::net::{Ipv6Addr, SocketAddrV6};
90///
91/// let socket = SocketAddrV6::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
92///
93/// assert_eq!("[2001:db8::1]:8080".parse(), Ok(socket));
94/// assert_eq!(socket.ip(), &Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1));
95/// assert_eq!(socket.port(), 8080);
96/// ```
97#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
98pub struct SocketAddrV6 {
99    // Do not assume that this struct is implemented as the underlying system representation.
100    // The memory layout is not part of the stable interface that std exposes.
101    ip: Ipv6Addr,
102    port: u16,
103    flowinfo: u32,
104    scope_id: u32,
105}
106
107impl SocketAddr {
108    /// Creates a new socket address from an [IP address] and a port number.
109    ///
110    /// [IP address]: IpAddr
111    ///
112    /// # Examples
113    ///
114    /// ```
115    /// use coreplus::net::{IpAddr, Ipv4Addr, SocketAddr};
116    ///
117    /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
118    /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
119    /// assert_eq!(socket.port(), 8080);
120    /// ```
121    pub fn new(ip: IpAddr, port: u16) -> SocketAddr {
122        match ip {
123            IpAddr::V4(a) => SocketAddr::V4(SocketAddrV4::new(a, port)),
124            IpAddr::V6(a) => SocketAddr::V6(SocketAddrV6::new(a, port, 0, 0)),
125        }
126    }
127
128    /// Returns the IP address associated with this socket address.
129    ///
130    /// # Examples
131    ///
132    /// ```
133    /// use coreplus::net::{IpAddr, Ipv4Addr, SocketAddr};
134    ///
135    /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
136    /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
137    /// ```
138    pub const fn ip(&self) -> IpAddr {
139        match *self {
140            SocketAddr::V4(ref a) => IpAddr::V4(*a.ip()),
141            SocketAddr::V6(ref a) => IpAddr::V6(*a.ip()),
142        }
143    }
144
145    /// Changes the IP address associated with this socket address.
146    ///
147    /// # Examples
148    ///
149    /// ```
150    /// use coreplus::net::{IpAddr, Ipv4Addr, SocketAddr};
151    ///
152    /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
153    /// socket.set_ip(IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1)));
154    /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1)));
155    /// ```
156    pub fn set_ip(&mut self, new_ip: IpAddr) {
157        // `match (*self, new_ip)` would have us mutate a copy of self only to throw it away.
158        match (self, new_ip) {
159            (&mut SocketAddr::V4(ref mut a), IpAddr::V4(new_ip)) => a.set_ip(new_ip),
160            (&mut SocketAddr::V6(ref mut a), IpAddr::V6(new_ip)) => a.set_ip(new_ip),
161            (self_, new_ip) => *self_ = Self::new(new_ip, self_.port()),
162        }
163    }
164
165    /// Returns the port number associated with this socket address.
166    ///
167    /// # Examples
168    ///
169    /// ```
170    /// use coreplus::net::{IpAddr, Ipv4Addr, SocketAddr};
171    ///
172    /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
173    /// assert_eq!(socket.port(), 8080);
174    /// ```
175    pub const fn port(&self) -> u16 {
176        match *self {
177            SocketAddr::V4(ref a) => a.port(),
178            SocketAddr::V6(ref a) => a.port(),
179        }
180    }
181
182    /// Changes the port number associated with this socket address.
183    ///
184    /// # Examples
185    ///
186    /// ```
187    /// use coreplus::net::{IpAddr, Ipv4Addr, SocketAddr};
188    ///
189    /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
190    /// socket.set_port(1025);
191    /// assert_eq!(socket.port(), 1025);
192    /// ```
193    pub fn set_port(&mut self, new_port: u16) {
194        match *self {
195            SocketAddr::V4(ref mut a) => a.set_port(new_port),
196            SocketAddr::V6(ref mut a) => a.set_port(new_port),
197        }
198    }
199
200    /// Returns [`true`] if the [IP address] in this `SocketAddr` is an
201    /// [`IPv4` address], and [`false`] otherwise.
202    ///
203    /// [IP address]: IpAddr
204    /// [`IPv4` address]: IpAddr::V4
205    ///
206    /// # Examples
207    ///
208    /// ```
209    /// use coreplus::net::{IpAddr, Ipv4Addr, SocketAddr};
210    ///
211    /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
212    /// assert_eq!(socket.is_ipv4(), true);
213    /// assert_eq!(socket.is_ipv6(), false);
214    /// ```
215    pub const fn is_ipv4(&self) -> bool {
216        matches!(*self, SocketAddr::V4(_))
217    }
218
219    /// Returns [`true`] if the [IP address] in this `SocketAddr` is an
220    /// [`IPv6` address], and [`false`] otherwise.
221    ///
222    /// [IP address]: IpAddr
223    /// [`IPv6` address]: IpAddr::V6
224    ///
225    /// # Examples
226    ///
227    /// ```
228    /// use coreplus::net::{IpAddr, Ipv6Addr, SocketAddr};
229    ///
230    /// let socket = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 0, 1)), 8080);
231    /// assert_eq!(socket.is_ipv4(), false);
232    /// assert_eq!(socket.is_ipv6(), true);
233    /// ```
234    pub const fn is_ipv6(&self) -> bool {
235        matches!(*self, SocketAddr::V6(_))
236    }
237}
238
239impl SocketAddrV4 {
240    /// Creates a new socket address from an [`IPv4` address] and a port number.
241    ///
242    /// [`IPv4` address]: Ipv4Addr
243    ///
244    /// # Examples
245    ///
246    /// ```
247    /// use coreplus::net::{SocketAddrV4, Ipv4Addr};
248    ///
249    /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
250    /// ```
251    pub fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 {
252        SocketAddrV4 { ip, port }
253    }
254
255    /// Returns the IP address associated with this socket address.
256    ///
257    /// # Examples
258    ///
259    /// ```
260    /// use coreplus::net::{SocketAddrV4, Ipv4Addr};
261    ///
262    /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
263    /// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1));
264    /// ```
265    pub const fn ip(&self) -> &Ipv4Addr {
266        &self.ip
267    }
268
269    /// Changes the IP address associated with this socket address.
270    ///
271    /// # Examples
272    ///
273    /// ```
274    /// use coreplus::net::{SocketAddrV4, Ipv4Addr};
275    ///
276    /// let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
277    /// socket.set_ip(Ipv4Addr::new(192, 168, 0, 1));
278    /// assert_eq!(socket.ip(), &Ipv4Addr::new(192, 168, 0, 1));
279    /// ```
280    pub fn set_ip(&mut self, new_ip: Ipv4Addr) {
281        self.ip = new_ip
282    }
283
284    /// Returns the port number associated with this socket address.
285    ///
286    /// # Examples
287    ///
288    /// ```
289    /// use coreplus::net::{SocketAddrV4, Ipv4Addr};
290    ///
291    /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
292    /// assert_eq!(socket.port(), 8080);
293    /// ```
294    pub const fn port(&self) -> u16 {
295        self.port
296    }
297
298    /// Changes the port number associated with this socket address.
299    ///
300    /// # Examples
301    ///
302    /// ```
303    /// use coreplus::net::{SocketAddrV4, Ipv4Addr};
304    ///
305    /// let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
306    /// socket.set_port(4242);
307    /// assert_eq!(socket.port(), 4242);
308    /// ```
309    pub fn set_port(&mut self, new_port: u16) {
310        self.port = new_port
311    }
312}
313
314impl SocketAddrV6 {
315    /// Creates a new socket address from an [`IPv6` address], a 16-bit port number,
316    /// and the `flowinfo` and `scope_id` fields.
317    ///
318    /// For more information on the meaning and layout of the `flowinfo` and `scope_id`
319    /// parameters, see [IETF RFC 2553, Section 3.3].
320    ///
321    /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
322    /// [`IPv6` address]: Ipv6Addr
323    ///
324    /// # Examples
325    ///
326    /// ```
327    /// use coreplus::net::{SocketAddrV6, Ipv6Addr};
328    ///
329    /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
330    /// ```
331    pub fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) -> SocketAddrV6 {
332        SocketAddrV6 {
333            ip,
334            port,
335            flowinfo,
336            scope_id,
337        }
338    }
339
340    /// Returns the IP address associated with this socket address.
341    ///
342    /// # Examples
343    ///
344    /// ```
345    /// use coreplus::net::{SocketAddrV6, Ipv6Addr};
346    ///
347    /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
348    /// assert_eq!(socket.ip(), &Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
349    /// ```
350    pub const fn ip(&self) -> &Ipv6Addr {
351        &self.ip
352    }
353
354    /// Changes the IP address associated with this socket address.
355    ///
356    /// # Examples
357    ///
358    /// ```
359    /// use coreplus::net::{SocketAddrV6, Ipv6Addr};
360    ///
361    /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
362    /// socket.set_ip(Ipv6Addr::new(76, 45, 0, 0, 0, 0, 0, 0));
363    /// assert_eq!(socket.ip(), &Ipv6Addr::new(76, 45, 0, 0, 0, 0, 0, 0));
364    /// ```
365    pub fn set_ip(&mut self, new_ip: Ipv6Addr) {
366        self.ip = new_ip
367    }
368
369    /// Returns the port number associated with this socket address.
370    ///
371    /// # Examples
372    ///
373    /// ```
374    /// use coreplus::net::{SocketAddrV6, Ipv6Addr};
375    ///
376    /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
377    /// assert_eq!(socket.port(), 8080);
378    /// ```
379    pub const fn port(&self) -> u16 {
380        self.port
381    }
382
383    /// Changes the port number associated with this socket address.
384    ///
385    /// # Examples
386    ///
387    /// ```
388    /// use coreplus::net::{SocketAddrV6, Ipv6Addr};
389    ///
390    /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
391    /// socket.set_port(4242);
392    /// assert_eq!(socket.port(), 4242);
393    /// ```
394    pub fn set_port(&mut self, new_port: u16) {
395        self.port = new_port
396    }
397
398    /// Returns the flow information associated with this address.
399    ///
400    /// This information corresponds to the `sin6_flowinfo` field in C's `netinet/in.h`,
401    /// as specified in [IETF RFC 2553, Section 3.3].
402    /// It combines information about the flow label and the traffic class as specified
403    /// in [IETF RFC 2460], respectively [Section 6] and [Section 7].
404    ///
405    /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
406    /// [IETF RFC 2460]: https://tools.ietf.org/html/rfc2460
407    /// [Section 6]: https://tools.ietf.org/html/rfc2460#section-6
408    /// [Section 7]: https://tools.ietf.org/html/rfc2460#section-7
409    ///
410    /// # Examples
411    ///
412    /// ```
413    /// use coreplus::net::{SocketAddrV6, Ipv6Addr};
414    ///
415    /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 10, 0);
416    /// assert_eq!(socket.flowinfo(), 10);
417    /// ```
418    pub const fn flowinfo(&self) -> u32 {
419        self.flowinfo
420    }
421
422    /// Changes the flow information associated with this socket address.
423    ///
424    /// See [`SocketAddrV6::flowinfo`]'s documentation for more details.
425    ///
426    /// # Examples
427    ///
428    /// ```
429    /// use coreplus::net::{SocketAddrV6, Ipv6Addr};
430    ///
431    /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 10, 0);
432    /// socket.set_flowinfo(56);
433    /// assert_eq!(socket.flowinfo(), 56);
434    /// ```
435    pub fn set_flowinfo(&mut self, new_flowinfo: u32) {
436        self.flowinfo = new_flowinfo
437    }
438
439    /// Returns the scope ID associated with this address.
440    ///
441    /// This information corresponds to the `sin6_scope_id` field in C's `netinet/in.h`,
442    /// as specified in [IETF RFC 2553, Section 3.3].
443    ///
444    /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
445    ///
446    /// # Examples
447    ///
448    /// ```
449    /// use coreplus::net::{SocketAddrV6, Ipv6Addr};
450    ///
451    /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 78);
452    /// assert_eq!(socket.scope_id(), 78);
453    /// ```
454    pub const fn scope_id(&self) -> u32 {
455        self.scope_id
456    }
457
458    /// Changes the scope ID associated with this socket address.
459    ///
460    /// See [`SocketAddrV6::scope_id`]'s documentation for more details.
461    ///
462    /// # Examples
463    ///
464    /// ```
465    /// use coreplus::net::{SocketAddrV6, Ipv6Addr};
466    ///
467    /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 78);
468    /// socket.set_scope_id(42);
469    /// assert_eq!(socket.scope_id(), 42);
470    /// ```
471    pub fn set_scope_id(&mut self, new_scope_id: u32) {
472        self.scope_id = new_scope_id
473    }
474}
475
476impl From<SocketAddrV4> for SocketAddr {
477    /// Converts a [`SocketAddrV4`] into a [`SocketAddr::V4`].
478    fn from(sock4: SocketAddrV4) -> SocketAddr {
479        SocketAddr::V4(sock4)
480    }
481}
482
483impl From<SocketAddrV6> for SocketAddr {
484    /// Converts a [`SocketAddrV6`] into a [`SocketAddr::V6`].
485    fn from(sock6: SocketAddrV6) -> SocketAddr {
486        SocketAddr::V6(sock6)
487    }
488}
489
490impl<I: Into<IpAddr>> From<(I, u16)> for SocketAddr {
491    /// Converts a tuple struct (Into<[`IpAddr`]>, `u16`) into a [`SocketAddr`].
492    ///
493    /// This conversion creates a [`SocketAddr::V4`] for a [`IpAddr::V4`]
494    /// and creates a [`SocketAddr::V6`] for a [`IpAddr::V6`].
495    ///
496    /// `u16` is treated as port of the newly created [`SocketAddr`].
497    fn from(pieces: (I, u16)) -> SocketAddr {
498        SocketAddr::new(pieces.0.into(), pieces.1)
499    }
500}
501
502impl fmt::Display for SocketAddr {
503    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
504        match *self {
505            SocketAddr::V4(ref a) => a.fmt(f),
506            SocketAddr::V6(ref a) => a.fmt(f),
507        }
508    }
509}
510
511impl fmt::Debug for SocketAddr {
512    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
513        fmt::Display::fmt(self, fmt)
514    }
515}
516
517impl fmt::Display for SocketAddrV4 {
518    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
519        // Fast path: if there's no alignment stuff, write to the output buffer
520        // directly
521        if f.precision().is_none() && f.width().is_none() {
522            write!(f, "{}:{}", self.ip(), self.port())
523        } else {
524            const IPV4_SOCKET_BUF_LEN: usize = (3 * 4)  // the segments
525                + 3  // the separators
526                + 1 + 5; // the port
527            let mut buf = [0; IPV4_SOCKET_BUF_LEN];
528            let mut buf_slice = &mut buf[..];
529
530            // Unwrap is fine because writing to a sufficiently-sized
531            // buffer is infallible
532            write!(buf_slice, "{}:{}", self.ip(), self.port()).unwrap();
533            let len = IPV4_SOCKET_BUF_LEN - buf_slice.len();
534
535            // This unsafe is OK because we know what is being written to the buffer
536            let buf = unsafe { str::from_utf8_unchecked(&buf[..len]) };
537            f.pad(buf)
538        }
539    }
540}
541
542impl fmt::Debug for SocketAddrV4 {
543    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
544        fmt::Display::fmt(self, fmt)
545    }
546}
547
548impl fmt::Display for SocketAddrV6 {
549    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
550        // Fast path: if there's no alignment stuff, write to the output
551        // buffer directly
552        if f.precision().is_none() && f.width().is_none() {
553            match self.scope_id() {
554                0 => write!(f, "[{}]:{}", self.ip(), self.port()),
555                scope_id => write!(f, "[{}%{}]:{}", self.ip(), scope_id, self.port()),
556            }
557        } else {
558            const IPV6_SOCKET_BUF_LEN: usize = (4 * 8)  // The address
559            + 7  // The colon separators
560            + 2  // The brackets
561            + 1 + 10 // The scope id
562            + 1 + 5; // The port
563
564            let mut buf = [0; IPV6_SOCKET_BUF_LEN];
565            let mut buf_slice = &mut buf[..];
566
567            match self.scope_id() {
568                0 => write!(buf_slice, "[{}]:{}", self.ip(), self.port()),
569                scope_id => write!(buf_slice, "[{}%{}]:{}", self.ip(), scope_id, self.port()),
570            }
571            // Unwrap is fine because writing to a sufficiently-sized
572            // buffer is infallible
573            .unwrap();
574            let len = IPV6_SOCKET_BUF_LEN - buf_slice.len();
575
576            // This unsafe is OK because we know what is being written to the buffer
577            let buf = unsafe { str::from_utf8_unchecked(&buf[..len]) };
578            f.pad(buf)
579        }
580    }
581}
582
583impl fmt::Debug for SocketAddrV6 {
584    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
585        fmt::Display::fmt(self, fmt)
586    }
587}
588
589/// Do a DNS query to lookup ip addresses associated with a hostname.
590///
591/// Implement this for your network stack.
592///
593/// This is blocking.
594pub trait GetSocketAddrs {
595    type Iter: Iterator<Item = SocketAddr>;
596    type Error: From<AddrParseError>;
597
598    fn get_socket_addrs(&self, host: &str, port: u16) -> Result<Self::Iter, Self::Error>;
599}
600
601pub enum OneOrMany<I: Iterator> {
602    One(option::IntoIter<I::Item>),
603    Many(I),
604}
605
606impl<I: Iterator> OneOrMany<I> {
607    pub fn one(item: I::Item) -> Self {
608        Self::One(Some(item).into_iter())
609    }
610}
611
612/// Retrive the addresses associated with a hostname.
613///
614/// To use this, you must pass in a type that implements [`GetSocketAddrs`].
615pub trait ToSocketAddrs<T: GetSocketAddrs> {
616    /// Converts this object to an iterator of resolved `SocketAddr`s.
617    ///
618    /// The returned iterator may not actually yield any values depending on the
619    /// outcome of any resolution performed.
620    ///
621    /// Note that this function may block the current thread while resolution is
622    /// performed.
623    fn to_socket_addrs(&self, get: &T) -> Result<OneOrMany<T::Iter>, T::Error>;
624}
625
626impl<T: GetSocketAddrs> ToSocketAddrs<T> for SocketAddr {
627    fn to_socket_addrs(&self, _get: &T) -> Result<OneOrMany<T::Iter>, T::Error> {
628        Ok(OneOrMany::one(*self))
629    }
630}
631
632impl<T: GetSocketAddrs> ToSocketAddrs<T> for SocketAddrV4 {
633    fn to_socket_addrs(&self, get: &T) -> Result<OneOrMany<T::Iter>, T::Error> {
634        SocketAddr::V4(*self).to_socket_addrs(get)
635    }
636}
637
638impl<T: GetSocketAddrs> ToSocketAddrs<T> for SocketAddrV6 {
639    fn to_socket_addrs(&self, get: &T) -> Result<OneOrMany<T::Iter>, T::Error> {
640        SocketAddr::V6(*self).to_socket_addrs(get)
641    }
642}
643
644impl<T: GetSocketAddrs> ToSocketAddrs<T> for (IpAddr, u16) {
645    fn to_socket_addrs(&self, get: &T) -> Result<OneOrMany<T::Iter>, T::Error> {
646        let (ip, port) = *self;
647        match ip {
648            IpAddr::V4(ref a) => (*a, port).to_socket_addrs(get),
649            IpAddr::V6(ref a) => (*a, port).to_socket_addrs(get),
650        }
651    }
652}
653
654impl<T: GetSocketAddrs> ToSocketAddrs<T> for (Ipv4Addr, u16) {
655    fn to_socket_addrs(&self, get: &T) -> Result<OneOrMany<T::Iter>, T::Error> {
656        let (ip, port) = *self;
657        SocketAddrV4::new(ip, port).to_socket_addrs(get)
658    }
659}
660
661impl<T: GetSocketAddrs> ToSocketAddrs<T> for (Ipv6Addr, u16) {
662    fn to_socket_addrs(&self, get: &T) -> Result<OneOrMany<T::Iter>, T::Error> {
663        let (ip, port) = *self;
664        SocketAddrV6::new(ip, port, 0, 0).to_socket_addrs(get)
665    }
666}
667
668impl<T: GetSocketAddrs> ToSocketAddrs<T> for (&str, u16) {
669    fn to_socket_addrs(&self, get: &T) -> Result<OneOrMany<T::Iter>, T::Error> {
670        let (host, port) = *self;
671
672        // try to parse the host as a regular IP address first
673        if let Ok(addr) = host.parse::<Ipv4Addr>() {
674            let addr = SocketAddrV4::new(addr, port);
675            return Ok(OneOrMany::one(SocketAddr::V4(addr)));
676        }
677        if let Ok(addr) = host.parse::<Ipv6Addr>() {
678            let addr = SocketAddrV6::new(addr, port, 0, 0);
679            return Ok(OneOrMany::one(SocketAddr::V6(addr)));
680        }
681
682        get.get_socket_addrs(host, port)
683            .map(|iter| OneOrMany::Many(iter))
684    }
685}
686
687// TODO: alloc feature?
688// impl<T: GetSocketAddrs> ToSocketAddrs<T> for (String, u16) {
689//     fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<SocketAddr>> {
690//         (&*self.0, self.1).to_socket_addrs()
691//     }
692// }
693
694// accepts strings like 'localhost:12345'
695impl<T: GetSocketAddrs> ToSocketAddrs<T> for str {
696    fn to_socket_addrs(&self, get: &T) -> Result<OneOrMany<T::Iter>, T::Error> {
697        // try to parse as a regular SocketAddr first
698        if let Ok(addr) = self.parse() {
699            return Ok(OneOrMany::one(addr));
700        }
701
702        let (host, port_str) = self.rsplit_once(':').ok_or(AddrParseError(()))?;
703        let port: u16 = port_str.parse().map_err(|_| AddrParseError(()))?;
704
705        get.get_socket_addrs(host, port)
706            .map(|iter| OneOrMany::Many(iter))
707    }
708}
709
710// #[stable(feature = "slice_to_socket_addrs", since = "1.8.0")]
711// impl<'a> ToSocketAddrs for &'a [SocketAddr] {
712//     type Iter = iter::Cloned<slice::Iter<'a, SocketAddr>>;
713
714//     fn to_socket_addrs(&self) -> io::Result<Self::Iter> {
715//         Ok(self.iter().cloned())
716//     }
717// }
718
719impl<T: GetSocketAddrs, U: ToSocketAddrs<T> + ?Sized> ToSocketAddrs<T> for &U {
720    fn to_socket_addrs(&self, get: &T) -> Result<OneOrMany<T::Iter>, T::Error> {
721        (**self).to_socket_addrs(get)
722    }
723}
724
725// TODO: alloc feature?
726// #[stable(feature = "string_to_socket_addrs", since = "1.16.0")]
727// impl ToSocketAddrs for String {
728//     type Iter = vec::IntoIter<SocketAddr>;
729//     fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<SocketAddr>> {
730//         (&**self).to_socket_addrs()
731//     }
732// }
733
734#[cfg(feature = "std")]
735impl From<std::net::SocketAddrV4> for SocketAddrV4 {
736    fn from(addr: std::net::SocketAddrV4) -> Self {
737        Self::new((*addr.ip()).into(), addr.port())
738    }
739}
740
741#[cfg(feature = "std")]
742impl From<std::net::SocketAddrV4> for SocketAddr {
743    fn from(addr: std::net::SocketAddrV4) -> Self {
744        let a: SocketAddrV4 = addr.into();
745        a.into()
746    }
747}
748
749#[cfg(feature = "std")]
750impl From<std::net::SocketAddrV6> for SocketAddrV6 {
751    fn from(addr: std::net::SocketAddrV6) -> Self {
752        Self::new(
753            (*addr.ip()).into(),
754            addr.port(),
755            addr.flowinfo(),
756            addr.scope_id(),
757        )
758    }
759}
760
761#[cfg(feature = "std")]
762impl From<std::net::SocketAddrV6> for SocketAddr {
763    fn from(addr: std::net::SocketAddrV6) -> Self {
764        let a: SocketAddrV6 = addr.into();
765        a.into()
766    }
767}
768
769#[cfg(feature = "std")]
770impl From<std::net::SocketAddr> for SocketAddr {
771    fn from(addr: std::net::SocketAddr) -> Self {
772        match addr {
773            std::net::SocketAddr::V4(ip) => ip.into(),
774            std::net::SocketAddr::V6(ip) => ip.into(),
775        }
776    }
777}
778
779#[cfg(feature = "std")]
780impl From<SocketAddrV4> for std::net::SocketAddrV4 {
781    fn from(addr: SocketAddrV4) -> Self {
782        Self::new((*addr.ip()).into(), addr.port())
783    }
784}
785
786#[cfg(feature = "std")]
787impl From<SocketAddrV4> for std::net::SocketAddr {
788    fn from(addr: SocketAddrV4) -> Self {
789        let a: std::net::SocketAddrV4 = addr.into();
790        a.into()
791    }
792}
793
794#[cfg(feature = "std")]
795impl From<SocketAddrV6> for std::net::SocketAddrV6 {
796    fn from(addr: SocketAddrV6) -> Self {
797        Self::new(
798            (*addr.ip()).into(),
799            addr.port(),
800            addr.flowinfo(),
801            addr.scope_id(),
802        )
803    }
804}
805
806#[cfg(feature = "std")]
807impl From<SocketAddrV6> for std::net::SocketAddr {
808    fn from(addr: SocketAddrV6) -> Self {
809        let a: std::net::SocketAddrV6 = addr.into();
810        a.into()
811    }
812}
813
814#[cfg(feature = "std")]
815impl From<SocketAddr> for std::net::SocketAddr {
816    fn from(addr: SocketAddr) -> Self {
817        match addr {
818            SocketAddr::V4(ip) => ip.into(),
819            SocketAddr::V6(ip) => ip.into(),
820        }
821    }
822}