async_stream_connection/
addr.rs

1use std::fmt;
2use std::net;
3use std::net::ToSocketAddrs;
4#[cfg(unix)]
5use std::os::unix::net as unix;
6#[cfg(unix)]
7use std::path::{Path, PathBuf};
8use std::str::FromStr;
9
10/// Address of a Stream Endpoint
11/// ```
12/// # use async_stream_connection::Addr;
13/// # fn main() -> Result<(),std::io::Error> {
14/// let addr: Addr = "127.0.0.1:1337".parse()?;
15/// # Ok(())
16/// # }
17/// ```
18/// or (unix only):
19/// ```
20/// # use async_stream_connection::Addr;
21/// # fn main() -> Result<(),std::io::Error> {
22/// # #[cfg(unix)]
23/// let addr: Addr = "/tmp/uds_example".parse()?;
24/// # Ok(())
25/// # }
26/// ```
27/// [`FromStr::parse`] / Deserialize also resolves to the first IP Address if it does not start with `/` or `./`.
28#[derive(Debug, Clone, PartialEq, Eq, Hash)]
29pub enum Addr {
30    /// An IP socket address
31    Inet(net::SocketAddr),
32    #[cfg(unix)]
33    #[cfg_attr(docsrs, doc(cfg(unix)))]
34    ///A UDS address
35    Unix(PathBuf),
36}
37
38impl From<net::SocketAddr> for Addr {
39    fn from(s: net::SocketAddr) -> Addr {
40        Addr::Inet(s)
41    }
42}
43
44#[cfg(unix)]
45impl From<&Path> for Addr {
46    fn from(s: &Path) -> Addr {
47        Addr::Unix(s.to_path_buf())
48    }
49}
50#[cfg(unix)]
51impl From<PathBuf> for Addr {
52    fn from(s: PathBuf) -> Addr {
53        Addr::Unix(s)
54    }
55}
56#[cfg(unix)]
57impl From<unix::SocketAddr> for Addr {
58    fn from(s: unix::SocketAddr) -> Addr {
59        Addr::Unix(match s.as_pathname() {
60            None => Path::new("unnamed").to_path_buf(),
61            Some(p) => p.to_path_buf(),
62        })
63    }
64}
65#[cfg(unix)]
66impl From<tokio::net::unix::SocketAddr> for Addr {
67    fn from(s: tokio::net::unix::SocketAddr) -> Addr {
68        Addr::Unix(match s.as_pathname() {
69            None => Path::new("unnamed").to_path_buf(),
70            Some(p) => p.to_path_buf(),
71        })
72    }
73}
74impl fmt::Display for Addr {
75    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
76        match self {
77            Addr::Inet(n) => n.fmt(f),
78            #[cfg(unix)]
79            Addr::Unix(n) => n.to_string_lossy().fmt(f),
80        }
81    }
82}
83
84impl FromStr for Addr {
85    type Err = std::io::Error;
86
87    fn from_str(v: &str) -> Result<Self, Self::Err> {
88        #[cfg(unix)]
89        if v.starts_with('/') || v.starts_with("./") {
90            return Ok(Addr::Unix(PathBuf::from(v)));
91        }
92        match v.to_socket_addrs()?.next() {
93            Some(a) => Ok(Addr::Inet(a)),
94            None => Err(std::io::ErrorKind::AddrNotAvailable.into())
95        }        
96    }
97}
98
99#[cfg(feature = "serde")]
100#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
101impl<'de> serde::de::Deserialize<'de> for Addr {
102    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
103    where
104        D: serde::Deserializer<'de>,
105    {
106        //let s = Deserialize::<&str>::deserialize(deserializer)?;
107        //Addr::from_str(&s).map_err(de::Error::custom)
108        struct Visitor;
109        impl<'de> serde::de::Visitor<'de> for Visitor {
110            type Value = Addr;
111            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
112                formatter.write_str("a Socket Address")
113            }
114            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
115            where
116                E: serde::de::Error,
117            {
118                Addr::from_str(v).map_err(E::custom)
119            }
120        }
121        deserializer.deserialize_str(Visitor)
122    }
123}
124
125#[cfg(test)]
126pub(crate) mod tests {
127    use super::*;
128
129    #[test]
130    fn parse_addr() {
131        assert!(if let Ok(Addr::Inet(net::SocketAddr::V4(f))) = Addr::from_str("127.0.0.1:9000") {
132            f.ip().is_loopback() && f.port() == 9000
133        }else{
134            false
135        });
136        assert!(if let Ok(Addr::Inet(f)) = Addr::from_str("localhost:9000") {
137            f.port() == 9000
138        }else{
139            println!("{:?}", Addr::from_str("localhost:9000"));
140            false
141        });
142        assert!(if let Ok(Addr::Inet(net::SocketAddr::V6(f))) = Addr::from_str("[::1]:9000") {
143            f.ip().is_loopback() && f.port() == 9000
144        }else{
145            false
146        });
147        #[cfg(unix)]
148        assert!(if let Ok(Addr::Unix(f)) = Addr::from_str("/path") {
149            f == std::path::Path::new("/path")
150        }else{
151            false
152        });
153    }
154    #[test]
155    fn display() {
156        assert_eq!(
157            "127.0.0.1:1234",
158            Addr::Inet(net::SocketAddr::V4(net::SocketAddrV4::new(
159                net::Ipv4Addr::new(127, 0, 0, 1),
160                1234
161            )))
162            .to_string()
163        );
164        #[cfg(unix)]
165        assert_eq!(
166            "/tmp/bla",
167            Addr::Unix(PathBuf::from_str("/tmp/bla").unwrap()).to_string()
168        );
169    }
170}