1//! A socket address for any kind of socket.
2//!
3//! This is similar to [`std::net::SocketAddr`], but also supports Unix-domain
4//! socket addresses.
5//!
6//! # Safety
7//!
8//! The `read` and `write` functions allow decoding and encoding from and to
9//! OS-specific socket address representations in memory.
10#![allow(unsafe_code)]
11
12#[cfg(unix)]
13use crate::net::SocketAddrUnix;
14use crate::net::{AddressFamily, SocketAddrV4, SocketAddrV6};
15use crate::{backend, io};
16#[cfg(feature = "std")]
17use core::fmt;
18
19pub use backend::net::addr::SocketAddrStorage;
20
21/// `struct sockaddr_storage` as a Rust enum.
22#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
23#[doc(alias = "sockaddr")]
24#[non_exhaustive]
25pub enum SocketAddrAny {
26    /// `struct sockaddr_in`
27    V4(SocketAddrV4),
28    /// `struct sockaddr_in6`
29    V6(SocketAddrV6),
30    /// `struct sockaddr_un`
31    #[cfg(unix)]
32    Unix(SocketAddrUnix),
33}
34
35impl From<SocketAddrV4> for SocketAddrAny {
36    #[inline]
37    fn from(from: SocketAddrV4) -> Self {
38        Self::V4(from)
39    }
40}
41
42impl From<SocketAddrV6> for SocketAddrAny {
43    #[inline]
44    fn from(from: SocketAddrV6) -> Self {
45        Self::V6(from)
46    }
47}
48
49#[cfg(unix)]
50impl From<SocketAddrUnix> for SocketAddrAny {
51    #[inline]
52    fn from(from: SocketAddrUnix) -> Self {
53        Self::Unix(from)
54    }
55}
56
57impl SocketAddrAny {
58    /// Return the address family of this socket address.
59    #[inline]
60    pub const fn address_family(&self) -> AddressFamily {
61        match self {
62            Self::V4(_) => AddressFamily::INET,
63            Self::V6(_) => AddressFamily::INET6,
64            #[cfg(unix)]
65            Self::Unix(_) => AddressFamily::UNIX,
66        }
67    }
68
69    /// Writes a platform-specific encoding of this socket address to
70    /// the memory pointed to by `storage`, and returns the number of
71    /// bytes used.
72    ///
73    /// # Safety
74    ///
75    /// `storage` must point to valid memory for encoding the socket
76    /// address.
77    pub unsafe fn write(&self, storage: *mut SocketAddrStorage) -> usize {
78        backend::net::write_sockaddr::write_sockaddr(self, storage)
79    }
80
81    /// Reads a platform-specific encoding of a socket address from
82    /// the memory pointed to by `storage`, which uses `len` bytes.
83    ///
84    /// # Safety
85    ///
86    /// `storage` must point to valid memory for decoding a socket
87    /// address.
88    pub unsafe fn read(storage: *const SocketAddrStorage, len: usize) -> io::Result<Self> {
89        backend::net::read_sockaddr::read_sockaddr(storage, len)
90    }
91}
92
93#[cfg(feature = "std")]
94impl fmt::Debug for SocketAddrAny {
95    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
96        match self {
97            Self::V4(v4) => v4.fmt(fmt),
98            Self::V6(v6) => v6.fmt(fmt),
99            #[cfg(unix)]
100            Self::Unix(unix) => unix.fmt(fmt),
101        }
102    }
103}
104