async_stream_connection/
addr.rs1use 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#[derive(Debug, Clone, PartialEq, Eq, Hash)]
29pub enum Addr {
30 Inet(net::SocketAddr),
32 #[cfg(unix)]
33 #[cfg_attr(docsrs, doc(cfg(unix)))]
34 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 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}