1use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
2
3pub trait ToServerAddrs {
33 #[cfg(feature = "async")]
34 #[doc(hidden)]
35 type Return: std::net::ToSocketAddrs + tokio::net::ToSocketAddrs;
36 #[cfg(not(feature = "async"))]
37 #[doc(hidden)]
38 type Return: std::net::ToSocketAddrs;
39
40 #[doc(hidden)]
41 fn to_server_addrs(&self, default_port: u16) -> Self::Return;
42}
43
44impl ToServerAddrs for SocketAddr {
45 type Return = SocketAddr;
46
47 fn to_server_addrs(&self, _default_port: u16) -> Self::Return {
48 *self
49 }
50}
51
52impl ToServerAddrs for SocketAddrV4 {
53 type Return = SocketAddrV4;
54
55 fn to_server_addrs(&self, _default_port: u16) -> Self::Return {
56 *self
57 }
58}
59
60impl ToServerAddrs for SocketAddrV6 {
61 type Return = SocketAddrV6;
62
63 fn to_server_addrs(&self, _default_port: u16) -> Self::Return {
64 *self
65 }
66}
67
68impl ToServerAddrs for IpAddr {
69 type Return = (IpAddr, u16);
70
71 fn to_server_addrs(&self, default_port: u16) -> Self::Return {
72 (*self, default_port)
73 }
74}
75
76impl ToServerAddrs for (IpAddr, u16) {
77 type Return = (IpAddr, u16);
78
79 fn to_server_addrs(&self, _default_port: u16) -> Self::Return {
80 *self
81 }
82}
83
84impl ToServerAddrs for Ipv4Addr {
85 type Return = (Ipv4Addr, u16);
86
87 fn to_server_addrs(&self, default_port: u16) -> Self::Return {
88 (*self, default_port)
89 }
90}
91
92impl ToServerAddrs for (Ipv4Addr, u16) {
93 type Return = (Ipv4Addr, u16);
94
95 fn to_server_addrs(&self, _default_port: u16) -> Self::Return {
96 *self
97 }
98}
99
100impl ToServerAddrs for Ipv6Addr {
101 type Return = (Ipv6Addr, u16);
102
103 fn to_server_addrs(&self, default_port: u16) -> Self::Return {
104 (*self, default_port)
105 }
106}
107
108impl ToServerAddrs for (Ipv6Addr, u16) {
109 type Return = (Ipv6Addr, u16);
110
111 fn to_server_addrs(&self, _default_port: u16) -> Self::Return {
112 *self
113 }
114}
115
116impl ToServerAddrs for str {
117 type Return = String;
118
119 fn to_server_addrs(&self, default_port: u16) -> Self::Return {
120 if self.parse::<Ipv4Addr>().is_ok() {
121 self.to_string() + ":" + &default_port.to_string()
122 } else if self.parse::<Ipv6Addr>().is_ok() {
123 "[".to_string() + self + "]:" + &default_port.to_string()
124 } else if self.starts_with("[") && self.ends_with("]") {
125 self.to_string() + ":" + &default_port.to_string()
127 } else if !self.contains(":") {
128 self.to_string() + ":" + &default_port.to_string()
129 } else {
130 self.to_string()
131 }
132 }
133}
134
135impl ToServerAddrs for String {
136 type Return = String;
137
138 fn to_server_addrs(&self, default_port: u16) -> Self::Return {
139 (**self).to_server_addrs(default_port)
140 }
141}
142
143impl<'a> ToServerAddrs for (&'a str, u16) {
144 type Return = (&'a str, u16);
145
146 fn to_server_addrs(&self, _default_port: u16) -> Self::Return {
147 *self
148 }
149}
150
151impl ToServerAddrs for (String, u16) {
152 type Return = String;
153
154 fn to_server_addrs(&self, _default_port: u16) -> Self::Return {
155 self.0.clone() + ":" + &self.1.to_string()
156 }
157}
158
159impl<T: ToServerAddrs + ?Sized> ToServerAddrs for &T {
160 type Return = T::Return;
161
162 fn to_server_addrs(&self, default_port: u16) -> Self::Return {
163 (**self).to_server_addrs(default_port)
164 }
165}
166
167#[cfg(test)]
168mod tests {
169 use super::*;
170
171 #[test]
172 fn works_for_socket_addr() {
173 let s = SocketAddr::from(([127, 0, 0, 1], 1234));
174 let s4 = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 1234);
175 let s6 = SocketAddrV6::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 1234, 0, 0);
176
177 assert_eq!(s.to_server_addrs(456), s);
178 assert_eq!(s4.to_server_addrs(456), s4);
179 assert_eq!(s6.to_server_addrs(456), s6);
180 }
181
182 #[test]
183 fn works_for_ip_addr() {
184 let ip = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
185 let ip4 = Ipv4Addr::new(127, 0, 0, 1);
186 let ip6 = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1);
187
188 assert_eq!(ip.to_server_addrs(456), (ip, 456));
189 assert_eq!(ip4.to_server_addrs(456), (ip4, 456));
190 assert_eq!(ip6.to_server_addrs(456), (ip6, 456));
191
192 assert_eq!((ip, 1234).to_server_addrs(456), (ip, 1234));
193 assert_eq!((ip4, 1234).to_server_addrs(456), (ip4, 1234));
194 assert_eq!((ip6, 1234).to_server_addrs(456), (ip6, 1234));
195 }
196
197 #[test]
198 fn works_for_ipv4_strings() {
199 assert_eq!("127.0.0.1".to_server_addrs(456), "127.0.0.1:456");
200 assert_eq!("127.0.0.1:1234".to_server_addrs(456), "127.0.0.1:1234");
201 assert_eq!(
202 "127.0.0.1".to_string().to_server_addrs(456),
203 "127.0.0.1:456"
204 );
205 assert_eq!(
206 "127.0.0.1:1234".to_string().to_server_addrs(456),
207 "127.0.0.1:1234"
208 );
209
210 assert_eq!(
211 ("127.0.0.1", 1234).to_server_addrs(456),
212 ("127.0.0.1", 1234)
213 );
214
215 assert_eq!(
216 ("127.0.0.1".to_string(), 1234).to_server_addrs(456),
217 "127.0.0.1:1234"
218 );
219 }
220
221 #[test]
222 fn works_for_ip6_string() {
223 assert_eq!("::1".to_server_addrs(456), "[::1]:456");
224 assert_eq!("[::1]".to_server_addrs(456), "[::1]:456");
225 assert_eq!("[::1]:1234".to_server_addrs(456), "[::1]:1234");
226
227 assert_eq!("::1".to_string().to_server_addrs(456), "[::1]:456");
228 assert_eq!("[::1]".to_string().to_server_addrs(456), "[::1]:456");
229 assert_eq!("[::1]:1234".to_string().to_server_addrs(456), "[::1]:1234");
230 }
231}