tokio_unix_tcp/
socket_addr.rs

1/*
2 * Copyright (c) 2023, networkException <git@nwex.de>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause OR MIT
5 */
6
7use std::io;
8use std::fmt::{self, Debug, Display, Formatter};
9use std::net::{self, AddrParseError};
10use std::str::FromStr;
11// NOTE: PathBuf is used in the signature of functions that also need to
12//       be available on non unix systems (at least for a noop).
13use std::path::PathBuf;
14
15#[cfg(unix)]
16use tokio::net::unix;
17
18#[cfg(feature = "serde")]
19use serde::{Serialize, Deserialize, Deserializer, de::Error};
20
21// NOTE: This enum is used in the signature of functions that also need to
22//       be available on non unix systems (at least for a noop).
23#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
24#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
25pub enum UnixSocketAddr {
26    #[cfg(unix)]
27    AbstractOrUnnamed,
28    #[cfg(unix)]
29    Pathname(PathBuf),
30}
31
32#[cfg(unix)]
33impl UnixSocketAddr {
34    pub fn is_pathname(input: &str) -> bool {
35        input.starts_with('/') || input.starts_with('.')
36    }
37}
38
39#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
40#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
41pub enum SocketAddr {
42    Inet(net::SocketAddr),
43    #[cfg(unix)]
44    Unix(UnixSocketAddr),
45}
46
47#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
48#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
49pub enum NamedSocketAddr {
50    Inet(net::SocketAddr),
51    #[cfg(unix)]
52    Unix(PathBuf),
53}
54
55impl SocketAddr {
56    pub fn map_inet<F: FnOnce(net::SocketAddr) -> net::SocketAddr>(self, mapper: F) -> SocketAddr {
57        match self {
58            SocketAddr::Inet(inet_socket_addr) => SocketAddr::Inet(mapper(inet_socket_addr)),
59            #[cfg(unix)]
60            SocketAddr::Unix(unix_socket_addr) => SocketAddr::Unix(unix_socket_addr),
61        }
62    }
63
64    // On non unix systems, op is not used.
65    #[cfg_attr(not(unix), allow(unused_variables))]
66    pub fn map_unix<F: FnOnce(UnixSocketAddr) -> UnixSocketAddr>(self, mapper: F) -> SocketAddr {
67        match self {
68            SocketAddr::Inet(inet_socket_addr) => SocketAddr::Inet(inet_socket_addr),
69            #[cfg(unix)]
70            SocketAddr::Unix(unix_socket_addr) => SocketAddr::Unix(mapper(unix_socket_addr)),
71        }
72    }
73
74    pub fn to_named_socket_addr(self) -> io::Result<NamedSocketAddr> {
75        match self {
76            SocketAddr::Inet(inet_socket_addr) => Ok(NamedSocketAddr::Inet(inet_socket_addr)),
77            #[cfg(unix)]
78            SocketAddr::Unix(UnixSocketAddr::Pathname(pathname)) => Ok(NamedSocketAddr::Unix(pathname)),
79            #[cfg(unix)]
80            SocketAddr::Unix(UnixSocketAddr::AbstractOrUnnamed) => Err(io::Error::new(
81                io::ErrorKind::Unsupported,
82                "Cannot connect to a abstract or unnamed unix socket.",
83            ))
84        }
85    }
86
87    #[cfg_attr(feature = "serde", allow(unused))]
88    #[cfg(feature = "serde")]
89    pub fn deserialize_from_str<'de, D>(deserializer: D) -> Result<SocketAddr, D::Error>
90    where
91        D: Deserializer<'de>,
92    {
93        let string = String::deserialize(deserializer)?;
94        FromStr::from_str(&string).map_err(Error::custom)
95    }
96
97    #[cfg_attr(feature = "serde", allow(unused))]
98    #[cfg(feature = "serde")]
99    pub fn deserialize_from_option_str<'de, D>(deserializer: D) -> Result<Option<SocketAddr>, D::Error>
100    where
101        D: Deserializer<'de>,
102    {
103        #[derive(Deserialize)]
104        struct Helper(#[serde(deserialize_with = "SocketAddr::deserialize_from_str")] SocketAddr);
105
106        let option = Option::deserialize(deserializer)?;
107        Ok(option.map(|Helper(external)| external))
108    }
109}
110
111impl NamedSocketAddr {
112    pub fn map_inet<F: FnOnce(net::SocketAddr) -> net::SocketAddr>(self, mapper: F) -> NamedSocketAddr {
113        match self {
114            NamedSocketAddr::Inet(inet_socket_addr) => NamedSocketAddr::Inet(mapper(inet_socket_addr)),
115            #[cfg(unix)]
116            NamedSocketAddr::Unix(path) => NamedSocketAddr::Unix(path),
117        }
118    }
119
120    // On non unix systems, op is not used.
121    #[cfg_attr(not(unix), allow(unused_variables))]
122    pub fn map_unix<F: FnOnce(PathBuf) -> PathBuf>(self, mapper: F) -> NamedSocketAddr {
123        match self {
124            NamedSocketAddr::Inet(inet_socket_addr) => NamedSocketAddr::Inet(inet_socket_addr),
125            #[cfg(unix)]
126            NamedSocketAddr::Unix(path) => NamedSocketAddr::Unix(mapper(path)),
127        }
128    }
129
130    pub fn to_socket_addr(self) -> SocketAddr {
131        match self {
132            NamedSocketAddr::Inet(inet_socket_addr) => SocketAddr::Inet(inet_socket_addr),
133            #[cfg(unix)]
134            NamedSocketAddr::Unix(path) => SocketAddr::Unix(UnixSocketAddr::Pathname(path)),
135        }
136    }
137
138    #[cfg_attr(feature = "serde", allow(unused))]
139    #[cfg(feature = "serde")]
140    pub fn deserialize_from_str<'de, D>(deserializer: D) -> Result<NamedSocketAddr, D::Error>
141    where
142        D: Deserializer<'de>,
143    {
144        let string = String::deserialize(deserializer)?;
145        FromStr::from_str(&string).map_err(Error::custom)
146    }
147
148    #[cfg_attr(feature = "serde", allow(unused))]
149    #[cfg(feature = "serde")]
150    pub fn deserialize_from_option_str<'de, D>(deserializer: D) -> Result<Option<NamedSocketAddr>, D::Error>
151    where
152        D: Deserializer<'de>,
153    {
154        #[derive(Deserialize)]
155        struct Helper(#[serde(deserialize_with = "NamedSocketAddr::deserialize_from_str")] NamedSocketAddr);
156
157        let option = Option::deserialize(deserializer)?;
158        Ok(option.map(|Helper(external)| external))
159    }
160}
161
162impl FromStr for SocketAddr {
163    type Err = AddrParseError;
164
165    fn from_str(string: &str) -> Result<Self, Self::Err> {
166        NamedSocketAddr::from_str(string).map(NamedSocketAddr::into)
167    }
168}
169
170impl FromStr for NamedSocketAddr {
171    type Err = AddrParseError;
172
173    fn from_str(string: &str) -> Result<Self, Self::Err> {
174        #[cfg(unix)]
175        if UnixSocketAddr::is_pathname(string) {
176            return Ok(NamedSocketAddr::Unix(PathBuf::from_str(string).unwrap()))
177        }
178
179        Ok(NamedSocketAddr::Inet(net::SocketAddr::from_str(string)?))
180    }
181}
182
183impl From<NamedSocketAddr> for SocketAddr {
184    fn from(named_socket_addr: NamedSocketAddr) -> Self {
185        named_socket_addr.to_socket_addr()
186    }
187}
188
189impl TryFrom<SocketAddr> for NamedSocketAddr {
190    type Error = io::Error;
191
192    fn try_from(socket_addr: SocketAddr) -> Result<Self, Self::Error> {
193        socket_addr.to_named_socket_addr()
194    }
195}
196
197impl From<net::SocketAddr> for SocketAddr {
198    fn from(inet_socket_addr: net::SocketAddr) -> SocketAddr {
199        SocketAddr::Inet(inet_socket_addr)
200    }
201}
202
203impl From<net::SocketAddr> for NamedSocketAddr {
204    fn from(inet_socket_addr: net::SocketAddr) -> NamedSocketAddr {
205        NamedSocketAddr::Inet(inet_socket_addr)
206    }
207}
208
209#[cfg(unix)]
210impl From<PathBuf> for SocketAddr {
211    fn from(path: PathBuf) -> SocketAddr {
212        SocketAddr::Unix(UnixSocketAddr::Pathname(path))
213    }
214}
215
216#[cfg(unix)]
217impl From<PathBuf> for NamedSocketAddr {
218    fn from(path: PathBuf) -> NamedSocketAddr {
219        NamedSocketAddr::Unix(path)
220    }
221}
222
223#[cfg(unix)]
224impl From<UnixSocketAddr> for SocketAddr {
225    fn from(unix_socket_addr: UnixSocketAddr) -> SocketAddr {
226        SocketAddr::Unix(unix_socket_addr)
227    }
228}
229
230#[cfg(unix)]
231impl From<unix::SocketAddr> for SocketAddr {
232    fn from(unix_socket_addr: unix::SocketAddr) -> Self {
233        SocketAddr::Unix(unix_socket_addr.into())
234    }
235}
236
237#[cfg(unix)]
238impl From<unix::SocketAddr> for UnixSocketAddr {
239    fn from(unix_socket_addr: unix::SocketAddr) -> Self {
240        match unix_socket_addr.as_pathname() {
241            Some(path) => UnixSocketAddr::Pathname(path.to_path_buf()),
242            None => UnixSocketAddr::AbstractOrUnnamed,
243        }
244    }
245}
246
247#[cfg(unix)]
248impl Debug for UnixSocketAddr {
249    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
250        match self {
251            UnixSocketAddr::AbstractOrUnnamed => write!(formatter, "(abstract or unnamed)"),
252            UnixSocketAddr::Pathname(path) => write!(formatter, "{path:?} (pathname)"),
253        }
254    }
255}
256
257impl Display for SocketAddr {
258    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
259        match self {
260            SocketAddr::Inet(inet_socket_addr) => write!(formatter, "{}", inet_socket_addr),
261            #[cfg(unix)]
262            SocketAddr::Unix(unix_socket_addr) => write!(formatter, "unix {:?}", unix_socket_addr),
263        }
264    }
265}
266
267impl Display for NamedSocketAddr {
268    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
269        match self {
270            NamedSocketAddr::Inet(inet_socket_addr) => write!(formatter, "{}", inet_socket_addr),
271            #[cfg(unix)]
272            NamedSocketAddr::Unix(path) => write!(formatter, "unix {:?}", path),
273        }
274    }
275}