cloudpub_common/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::fmt::{self, Debug, Display, Formatter};
8use std::io;
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::{de::Error, Deserialize, Deserializer, Serialize};
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)) => {
79                Ok(NamedSocketAddr::Unix(pathname))
80            }
81            #[cfg(unix)]
82            SocketAddr::Unix(UnixSocketAddr::AbstractOrUnnamed) => Err(io::Error::new(
83                io::ErrorKind::Unsupported,
84                "Cannot connect to a abstract or unnamed unix socket.",
85            )),
86        }
87    }
88
89    #[cfg_attr(feature = "serde", allow(unused))]
90    #[cfg(feature = "serde")]
91    pub fn deserialize_from_str<'de, D>(deserializer: D) -> Result<SocketAddr, D::Error>
92    where
93        D: Deserializer<'de>,
94    {
95        let string = String::deserialize(deserializer)?;
96        FromStr::from_str(&string).map_err(Error::custom)
97    }
98
99    #[cfg_attr(feature = "serde", allow(unused))]
100    #[cfg(feature = "serde")]
101    pub fn deserialize_from_option_str<'de, D>(
102        deserializer: D,
103    ) -> Result<Option<SocketAddr>, D::Error>
104    where
105        D: Deserializer<'de>,
106    {
107        #[derive(Deserialize)]
108        struct Helper(#[serde(deserialize_with = "SocketAddr::deserialize_from_str")] SocketAddr);
109
110        let option = Option::deserialize(deserializer)?;
111        Ok(option.map(|Helper(external)| external))
112    }
113}
114
115impl NamedSocketAddr {
116    pub fn map_inet<F: FnOnce(net::SocketAddr) -> net::SocketAddr>(
117        self,
118        mapper: F,
119    ) -> NamedSocketAddr {
120        match self {
121            NamedSocketAddr::Inet(inet_socket_addr) => {
122                NamedSocketAddr::Inet(mapper(inet_socket_addr))
123            }
124            #[cfg(unix)]
125            NamedSocketAddr::Unix(path) => NamedSocketAddr::Unix(path),
126        }
127    }
128
129    // On non unix systems, op is not used.
130    #[cfg_attr(not(unix), allow(unused_variables))]
131    pub fn map_unix<F: FnOnce(PathBuf) -> PathBuf>(self, mapper: F) -> NamedSocketAddr {
132        match self {
133            NamedSocketAddr::Inet(inet_socket_addr) => NamedSocketAddr::Inet(inet_socket_addr),
134            #[cfg(unix)]
135            NamedSocketAddr::Unix(path) => NamedSocketAddr::Unix(mapper(path)),
136        }
137    }
138
139    pub fn to_socket_addr(self) -> SocketAddr {
140        match self {
141            NamedSocketAddr::Inet(inet_socket_addr) => SocketAddr::Inet(inet_socket_addr),
142            #[cfg(unix)]
143            NamedSocketAddr::Unix(path) => SocketAddr::Unix(UnixSocketAddr::Pathname(path)),
144        }
145    }
146
147    #[cfg_attr(feature = "serde", allow(unused))]
148    #[cfg(feature = "serde")]
149    pub fn deserialize_from_str<'de, D>(deserializer: D) -> Result<NamedSocketAddr, D::Error>
150    where
151        D: Deserializer<'de>,
152    {
153        let string = String::deserialize(deserializer)?;
154        FromStr::from_str(&string).map_err(Error::custom)
155    }
156
157    #[cfg_attr(feature = "serde", allow(unused))]
158    #[cfg(feature = "serde")]
159    pub fn deserialize_from_option_str<'de, D>(
160        deserializer: D,
161    ) -> Result<Option<NamedSocketAddr>, D::Error>
162    where
163        D: Deserializer<'de>,
164    {
165        #[derive(Deserialize)]
166        struct Helper(
167            #[serde(deserialize_with = "NamedSocketAddr::deserialize_from_str")] NamedSocketAddr,
168        );
169
170        let option = Option::deserialize(deserializer)?;
171        Ok(option.map(|Helper(external)| external))
172    }
173}
174
175impl FromStr for SocketAddr {
176    type Err = AddrParseError;
177
178    fn from_str(string: &str) -> Result<Self, Self::Err> {
179        NamedSocketAddr::from_str(string).map(NamedSocketAddr::into)
180    }
181}
182
183impl FromStr for NamedSocketAddr {
184    type Err = AddrParseError;
185
186    fn from_str(string: &str) -> Result<Self, Self::Err> {
187        #[cfg(unix)]
188        if UnixSocketAddr::is_pathname(string) {
189            return Ok(NamedSocketAddr::Unix(PathBuf::from_str(string).unwrap()));
190        }
191
192        Ok(NamedSocketAddr::Inet(net::SocketAddr::from_str(string)?))
193    }
194}
195
196impl From<NamedSocketAddr> for SocketAddr {
197    fn from(named_socket_addr: NamedSocketAddr) -> Self {
198        named_socket_addr.to_socket_addr()
199    }
200}
201
202impl TryFrom<SocketAddr> for NamedSocketAddr {
203    type Error = io::Error;
204
205    fn try_from(socket_addr: SocketAddr) -> Result<Self, Self::Error> {
206        socket_addr.to_named_socket_addr()
207    }
208}
209
210impl From<net::SocketAddr> for SocketAddr {
211    fn from(inet_socket_addr: net::SocketAddr) -> SocketAddr {
212        SocketAddr::Inet(inet_socket_addr)
213    }
214}
215
216impl From<net::SocketAddr> for NamedSocketAddr {
217    fn from(inet_socket_addr: net::SocketAddr) -> NamedSocketAddr {
218        NamedSocketAddr::Inet(inet_socket_addr)
219    }
220}
221
222#[cfg(unix)]
223impl From<PathBuf> for SocketAddr {
224    fn from(path: PathBuf) -> SocketAddr {
225        SocketAddr::Unix(UnixSocketAddr::Pathname(path))
226    }
227}
228
229#[cfg(unix)]
230impl From<PathBuf> for NamedSocketAddr {
231    fn from(path: PathBuf) -> NamedSocketAddr {
232        NamedSocketAddr::Unix(path)
233    }
234}
235
236#[cfg(unix)]
237impl From<UnixSocketAddr> for SocketAddr {
238    fn from(unix_socket_addr: UnixSocketAddr) -> SocketAddr {
239        SocketAddr::Unix(unix_socket_addr)
240    }
241}
242
243#[cfg(unix)]
244impl From<unix::SocketAddr> for SocketAddr {
245    fn from(unix_socket_addr: unix::SocketAddr) -> Self {
246        SocketAddr::Unix(unix_socket_addr.into())
247    }
248}
249
250#[cfg(unix)]
251impl From<unix::SocketAddr> for UnixSocketAddr {
252    fn from(unix_socket_addr: unix::SocketAddr) -> Self {
253        match unix_socket_addr.as_pathname() {
254            Some(path) => UnixSocketAddr::Pathname(path.to_path_buf()),
255            None => UnixSocketAddr::AbstractOrUnnamed,
256        }
257    }
258}
259
260#[cfg(unix)]
261impl Debug for UnixSocketAddr {
262    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
263        match self {
264            UnixSocketAddr::AbstractOrUnnamed => write!(formatter, "(abstract or unnamed)"),
265            UnixSocketAddr::Pathname(path) => write!(formatter, "{path:?} (pathname)"),
266        }
267    }
268}
269
270impl Display for SocketAddr {
271    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
272        match self {
273            SocketAddr::Inet(inet_socket_addr) => write!(formatter, "{}", inet_socket_addr),
274            #[cfg(unix)]
275            SocketAddr::Unix(unix_socket_addr) => write!(formatter, "unix {:?}", unix_socket_addr),
276        }
277    }
278}
279
280impl Display for NamedSocketAddr {
281    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
282        match self {
283            NamedSocketAddr::Inet(inet_socket_addr) => write!(formatter, "{}", inet_socket_addr),
284            #[cfg(unix)]
285            NamedSocketAddr::Unix(path) => write!(formatter, "unix {:?}", path),
286        }
287    }
288}