]>
Commit | Line | Data |
---|---|---|
c34b1796 AL |
1 | #![unstable(feature = "ip", reason = "extra functionality has not been \ |
2 | scrutinized to the level that it should \ | |
ea8adc8c | 3 | be to be stable", |
e9174d1e | 4 | issue = "27709")] |
c34b1796 | 5 | |
532ac7d7 XL |
6 | use crate::cmp::Ordering; |
7 | use crate::fmt; | |
8 | use crate::hash; | |
9 | use crate::sys::net::netc as c; | |
10 | use crate::sys_common::{AsInner, FromInner}; | |
85aaf69f | 11 | |
cc61c64b | 12 | /// An IP address, either IPv4 or IPv6. |
9e0c209e | 13 | /// |
cc61c64b XL |
14 | /// This enum can contain either an [`Ipv4Addr`] or an [`Ipv6Addr`], see their |
15 | /// respective documentation for more details. | |
9e0c209e | 16 | /// |
0531ce1d XL |
17 | /// The size of an `IpAddr` instance may vary depending on the target operating |
18 | /// system. | |
19 | /// | |
cc61c64b XL |
20 | /// [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html |
21 | /// [`Ipv6Addr`]: ../../std/net/struct.Ipv6Addr.html | |
9e0c209e | 22 | /// |
cc61c64b | 23 | /// # Examples |
9e0c209e | 24 | /// |
9e0c209e | 25 | /// ``` |
cc61c64b | 26 | /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; |
9e0c209e | 27 | /// |
cc61c64b XL |
28 | /// let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)); |
29 | /// let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); | |
9e0c209e | 30 | /// |
cc61c64b XL |
31 | /// assert_eq!("127.0.0.1".parse(), Ok(localhost_v4)); |
32 | /// assert_eq!("::1".parse(), Ok(localhost_v6)); | |
9e0c209e | 33 | /// |
cc61c64b XL |
34 | /// assert_eq!(localhost_v4.is_ipv6(), false); |
35 | /// assert_eq!(localhost_v4.is_ipv4(), true); | |
9e0c209e | 36 | /// ``` |
9cc50fc6 | 37 | #[stable(feature = "ip_addr", since = "1.7.0")] |
c34b1796 AL |
38 | #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)] |
39 | pub enum IpAddr { | |
cc61c64b | 40 | /// An IPv4 address. |
9cc50fc6 | 41 | #[stable(feature = "ip_addr", since = "1.7.0")] |
7453a54e | 42 | V4(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv4Addr), |
cc61c64b | 43 | /// An IPv6 address. |
9cc50fc6 | 44 | #[stable(feature = "ip_addr", since = "1.7.0")] |
7453a54e | 45 | V6(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv6Addr), |
c34b1796 AL |
46 | } |
47 | ||
cc61c64b XL |
48 | /// An IPv4 address. |
49 | /// | |
50 | /// IPv4 addresses are defined as 32-bit integers in [IETF RFC 791]. | |
51 | /// They are usually represented as four octets. | |
52 | /// | |
53 | /// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses. | |
54 | /// | |
0531ce1d XL |
55 | /// The size of an `Ipv4Addr` struct may vary depending on the target operating |
56 | /// system. | |
57 | /// | |
cc61c64b XL |
58 | /// [IETF RFC 791]: https://tools.ietf.org/html/rfc791 |
59 | /// [`IpAddr`]: ../../std/net/enum.IpAddr.html | |
60 | /// | |
61 | /// # Textual representation | |
62 | /// | |
63 | /// `Ipv4Addr` provides a [`FromStr`] implementation. The four octets are in decimal | |
64 | /// notation, divided by `.` (this is called "dot-decimal notation"). | |
65 | /// | |
66 | /// [`FromStr`]: ../../std/str/trait.FromStr.html | |
67 | /// | |
68 | /// # Examples | |
69 | /// | |
70 | /// ``` | |
71 | /// use std::net::Ipv4Addr; | |
72 | /// | |
73 | /// let localhost = Ipv4Addr::new(127, 0, 0, 1); | |
74 | /// assert_eq!("127.0.0.1".parse(), Ok(localhost)); | |
75 | /// assert_eq!(localhost.is_loopback(), true); | |
76 | /// ``` | |
85aaf69f | 77 | #[derive(Copy)] |
c34b1796 | 78 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 79 | pub struct Ipv4Addr { |
92a42be0 | 80 | inner: c::in_addr, |
85aaf69f SL |
81 | } |
82 | ||
cc61c64b XL |
83 | /// An IPv6 address. |
84 | /// | |
85 | /// IPv6 addresses are defined as 128-bit integers in [IETF RFC 4291]. | |
86 | /// They are usually represented as eight 16-bit segments. | |
87 | /// | |
88 | /// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses. | |
89 | /// | |
0531ce1d XL |
90 | /// The size of an `Ipv6Addr` struct may vary depending on the target operating |
91 | /// system. | |
92 | /// | |
cc61c64b XL |
93 | /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 |
94 | /// [`IpAddr`]: ../../std/net/enum.IpAddr.html | |
95 | /// | |
96 | /// # Textual representation | |
97 | /// | |
98 | /// `Ipv6Addr` provides a [`FromStr`] implementation. There are many ways to represent | |
99 | /// an IPv6 address in text, but in general, each segments is written in hexadecimal | |
100 | /// notation, and segments are separated by `:`. For more information, see | |
101 | /// [IETF RFC 5952]. | |
102 | /// | |
103 | /// [`FromStr`]: ../../std/str/trait.FromStr.html | |
104 | /// [IETF RFC 5952]: https://tools.ietf.org/html/rfc5952 | |
105 | /// | |
106 | /// # Examples | |
107 | /// | |
108 | /// ``` | |
109 | /// use std::net::Ipv6Addr; | |
110 | /// | |
111 | /// let localhost = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); | |
112 | /// assert_eq!("::1".parse(), Ok(localhost)); | |
113 | /// assert_eq!(localhost.is_loopback(), true); | |
114 | /// ``` | |
85aaf69f | 115 | #[derive(Copy)] |
c34b1796 | 116 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 117 | pub struct Ipv6Addr { |
92a42be0 | 118 | inner: c::in6_addr, |
85aaf69f SL |
119 | } |
120 | ||
121 | #[allow(missing_docs)] | |
122 | #[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)] | |
123 | pub enum Ipv6MulticastScope { | |
124 | InterfaceLocal, | |
125 | LinkLocal, | |
126 | RealmLocal, | |
127 | AdminLocal, | |
128 | SiteLocal, | |
129 | OrganizationLocal, | |
130 | Global | |
131 | } | |
132 | ||
5bcae85e | 133 | impl IpAddr { |
cc61c64b XL |
134 | /// Returns [`true`] for the special 'unspecified' address. |
135 | /// | |
136 | /// See the documentation for [`Ipv4Addr::is_unspecified`][IPv4] and | |
137 | /// [`Ipv6Addr::is_unspecified`][IPv6] for more details. | |
476ff2be | 138 | /// |
5bcae85e SL |
139 | /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_unspecified |
140 | /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_unspecified | |
cc61c64b | 141 | /// [`true`]: ../../std/primitive.bool.html |
476ff2be SL |
142 | /// |
143 | /// # Examples | |
144 | /// | |
145 | /// ``` | |
146 | /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; | |
147 | /// | |
148 | /// assert_eq!(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)).is_unspecified(), true); | |
149 | /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)).is_unspecified(), true); | |
150 | /// ``` | |
5bcae85e SL |
151 | #[stable(feature = "ip_shared", since = "1.12.0")] |
152 | pub fn is_unspecified(&self) -> bool { | |
b7449926 XL |
153 | match self { |
154 | IpAddr::V4(ip) => ip.is_unspecified(), | |
155 | IpAddr::V6(ip) => ip.is_unspecified(), | |
5bcae85e SL |
156 | } |
157 | } | |
158 | ||
cc61c64b XL |
159 | /// Returns [`true`] if this is a loopback address. |
160 | /// | |
161 | /// See the documentation for [`Ipv4Addr::is_loopback`][IPv4] and | |
162 | /// [`Ipv6Addr::is_loopback`][IPv6] for more details. | |
476ff2be | 163 | /// |
5bcae85e SL |
164 | /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_loopback |
165 | /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_loopback | |
cc61c64b | 166 | /// [`true`]: ../../std/primitive.bool.html |
476ff2be SL |
167 | /// |
168 | /// # Examples | |
169 | /// | |
170 | /// ``` | |
171 | /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; | |
172 | /// | |
173 | /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_loopback(), true); | |
174 | /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1)).is_loopback(), true); | |
175 | /// ``` | |
5bcae85e SL |
176 | #[stable(feature = "ip_shared", since = "1.12.0")] |
177 | pub fn is_loopback(&self) -> bool { | |
b7449926 XL |
178 | match self { |
179 | IpAddr::V4(ip) => ip.is_loopback(), | |
180 | IpAddr::V6(ip) => ip.is_loopback(), | |
5bcae85e SL |
181 | } |
182 | } | |
183 | ||
cc61c64b XL |
184 | /// Returns [`true`] if the address appears to be globally routable. |
185 | /// | |
186 | /// See the documentation for [`Ipv4Addr::is_global`][IPv4] and | |
187 | /// [`Ipv6Addr::is_global`][IPv6] for more details. | |
476ff2be | 188 | /// |
5bcae85e SL |
189 | /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_global |
190 | /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_global | |
cc61c64b | 191 | /// [`true`]: ../../std/primitive.bool.html |
476ff2be SL |
192 | /// |
193 | /// # Examples | |
194 | /// | |
195 | /// ``` | |
196 | /// #![feature(ip)] | |
197 | /// | |
198 | /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; | |
199 | /// | |
200 | /// fn main() { | |
201 | /// assert_eq!(IpAddr::V4(Ipv4Addr::new(80, 9, 12, 3)).is_global(), true); | |
202 | /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1)).is_global(), | |
203 | /// true); | |
204 | /// } | |
205 | /// ``` | |
5bcae85e | 206 | pub fn is_global(&self) -> bool { |
b7449926 XL |
207 | match self { |
208 | IpAddr::V4(ip) => ip.is_global(), | |
209 | IpAddr::V6(ip) => ip.is_global(), | |
5bcae85e SL |
210 | } |
211 | } | |
212 | ||
cc61c64b XL |
213 | /// Returns [`true`] if this is a multicast address. |
214 | /// | |
215 | /// See the documentation for [`Ipv4Addr::is_multicast`][IPv4] and | |
216 | /// [`Ipv6Addr::is_multicast`][IPv6] for more details. | |
476ff2be | 217 | /// |
5bcae85e SL |
218 | /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_multicast |
219 | /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_multicast | |
cc61c64b | 220 | /// [`true`]: ../../std/primitive.bool.html |
476ff2be SL |
221 | /// |
222 | /// # Examples | |
223 | /// | |
224 | /// ``` | |
225 | /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; | |
226 | /// | |
227 | /// assert_eq!(IpAddr::V4(Ipv4Addr::new(224, 254, 0, 0)).is_multicast(), true); | |
228 | /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0)).is_multicast(), true); | |
229 | /// ``` | |
5bcae85e SL |
230 | #[stable(feature = "ip_shared", since = "1.12.0")] |
231 | pub fn is_multicast(&self) -> bool { | |
b7449926 XL |
232 | match self { |
233 | IpAddr::V4(ip) => ip.is_multicast(), | |
234 | IpAddr::V6(ip) => ip.is_multicast(), | |
5bcae85e SL |
235 | } |
236 | } | |
237 | ||
cc61c64b XL |
238 | /// Returns [`true`] if this address is in a range designated for documentation. |
239 | /// | |
240 | /// See the documentation for [`Ipv4Addr::is_documentation`][IPv4] and | |
241 | /// [`Ipv6Addr::is_documentation`][IPv6] for more details. | |
476ff2be | 242 | /// |
5bcae85e SL |
243 | /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_documentation |
244 | /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_documentation | |
cc61c64b | 245 | /// [`true`]: ../../std/primitive.bool.html |
476ff2be SL |
246 | /// |
247 | /// # Examples | |
248 | /// | |
249 | /// ``` | |
250 | /// #![feature(ip)] | |
251 | /// | |
252 | /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; | |
253 | /// | |
254 | /// fn main() { | |
255 | /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_documentation(), true); | |
256 | /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)) | |
257 | /// .is_documentation(), true); | |
258 | /// } | |
259 | /// ``` | |
5bcae85e | 260 | pub fn is_documentation(&self) -> bool { |
b7449926 XL |
261 | match self { |
262 | IpAddr::V4(ip) => ip.is_documentation(), | |
263 | IpAddr::V6(ip) => ip.is_documentation(), | |
5bcae85e SL |
264 | } |
265 | } | |
c30ab7b3 | 266 | |
cc61c64b XL |
267 | /// Returns [`true`] if this address is an [IPv4 address], and [`false`] otherwise. |
268 | /// | |
269 | /// [`true`]: ../../std/primitive.bool.html | |
270 | /// [`false`]: ../../std/primitive.bool.html | |
271 | /// [IPv4 address]: #variant.V4 | |
476ff2be SL |
272 | /// |
273 | /// # Examples | |
274 | /// | |
275 | /// ``` | |
476ff2be SL |
276 | /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; |
277 | /// | |
278 | /// fn main() { | |
279 | /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv4(), true); | |
280 | /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv4(), | |
281 | /// false); | |
282 | /// } | |
283 | /// ``` | |
32a655c1 | 284 | #[stable(feature = "ipaddr_checker", since = "1.16.0")] |
c30ab7b3 | 285 | pub fn is_ipv4(&self) -> bool { |
b7449926 | 286 | match self { |
c30ab7b3 SL |
287 | IpAddr::V4(_) => true, |
288 | IpAddr::V6(_) => false, | |
289 | } | |
290 | } | |
291 | ||
cc61c64b XL |
292 | /// Returns [`true`] if this address is an [IPv6 address], and [`false`] otherwise. |
293 | /// | |
294 | /// [`true`]: ../../std/primitive.bool.html | |
295 | /// [`false`]: ../../std/primitive.bool.html | |
296 | /// [IPv6 address]: #variant.V6 | |
476ff2be SL |
297 | /// |
298 | /// # Examples | |
299 | /// | |
300 | /// ``` | |
476ff2be SL |
301 | /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; |
302 | /// | |
303 | /// fn main() { | |
304 | /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv6(), false); | |
305 | /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv6(), | |
306 | /// true); | |
307 | /// } | |
308 | /// ``` | |
32a655c1 | 309 | #[stable(feature = "ipaddr_checker", since = "1.16.0")] |
c30ab7b3 | 310 | pub fn is_ipv6(&self) -> bool { |
b7449926 | 311 | match self { |
c30ab7b3 SL |
312 | IpAddr::V4(_) => false, |
313 | IpAddr::V6(_) => true, | |
314 | } | |
315 | } | |
5bcae85e SL |
316 | } |
317 | ||
85aaf69f | 318 | impl Ipv4Addr { |
9346a6ac | 319 | /// Creates a new IPv4 address from four eight-bit octets. |
85aaf69f | 320 | /// |
bd371182 | 321 | /// The result will represent the IP address `a`.`b`.`c`.`d`. |
476ff2be SL |
322 | /// |
323 | /// # Examples | |
324 | /// | |
325 | /// ``` | |
326 | /// use std::net::Ipv4Addr; | |
327 | /// | |
328 | /// let addr = Ipv4Addr::new(127, 0, 0, 1); | |
329 | /// ``` | |
c34b1796 | 330 | #[stable(feature = "rust1", since = "1.0.0")] |
b7449926 | 331 | pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr { |
9fa01778 XL |
332 | // FIXME: should just be u32::from_be_bytes([a, b, c, d]), |
333 | // once that method is no longer rustc_const_unstable | |
85aaf69f | 334 | Ipv4Addr { |
92a42be0 | 335 | inner: c::in_addr { |
b7449926 XL |
336 | s_addr: u32::to_be( |
337 | ((a as u32) << 24) | | |
338 | ((b as u32) << 16) | | |
339 | ((c as u32) << 8) | | |
340 | (d as u32) | |
341 | ), | |
85aaf69f SL |
342 | } |
343 | } | |
344 | } | |
345 | ||
b7449926 | 346 | /// An IPv4 address with the address pointing to localhost: 127.0.0.1. |
ea8adc8c XL |
347 | /// |
348 | /// # Examples | |
349 | /// | |
350 | /// ``` | |
ea8adc8c XL |
351 | /// use std::net::Ipv4Addr; |
352 | /// | |
b7449926 | 353 | /// let addr = Ipv4Addr::LOCALHOST; |
ea8adc8c XL |
354 | /// assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1)); |
355 | /// ``` | |
b7449926 XL |
356 | #[stable(feature = "ip_constructors", since = "1.30.0")] |
357 | pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1); | |
ea8adc8c | 358 | |
b7449926 | 359 | /// An IPv4 address representing an unspecified address: 0.0.0.0 |
ea8adc8c XL |
360 | /// |
361 | /// # Examples | |
362 | /// | |
363 | /// ``` | |
ea8adc8c XL |
364 | /// use std::net::Ipv4Addr; |
365 | /// | |
b7449926 | 366 | /// let addr = Ipv4Addr::UNSPECIFIED; |
ea8adc8c XL |
367 | /// assert_eq!(addr, Ipv4Addr::new(0, 0, 0, 0)); |
368 | /// ``` | |
b7449926 XL |
369 | #[stable(feature = "ip_constructors", since = "1.30.0")] |
370 | pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0); | |
371 | ||
372 | /// An IPv4 address representing the broadcast address: 255.255.255.255 | |
373 | /// | |
374 | /// # Examples | |
375 | /// | |
376 | /// ``` | |
377 | /// use std::net::Ipv4Addr; | |
378 | /// | |
379 | /// let addr = Ipv4Addr::BROADCAST; | |
380 | /// assert_eq!(addr, Ipv4Addr::new(255, 255, 255, 255)); | |
381 | /// ``` | |
382 | #[stable(feature = "ip_constructors", since = "1.30.0")] | |
383 | pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255); | |
ea8adc8c | 384 | |
bd371182 | 385 | /// Returns the four eight-bit integers that make up this address. |
476ff2be SL |
386 | /// |
387 | /// # Examples | |
388 | /// | |
389 | /// ``` | |
390 | /// use std::net::Ipv4Addr; | |
391 | /// | |
392 | /// let addr = Ipv4Addr::new(127, 0, 0, 1); | |
393 | /// assert_eq!(addr.octets(), [127, 0, 0, 1]); | |
394 | /// ``` | |
c34b1796 | 395 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 396 | pub fn octets(&self) -> [u8; 4] { |
9fa01778 XL |
397 | // This returns the order we want because s_addr is stored in big-endian. |
398 | self.inner.s_addr.to_ne_bytes() | |
85aaf69f SL |
399 | } |
400 | ||
cc61c64b | 401 | /// Returns [`true`] for the special 'unspecified' address (0.0.0.0). |
5bcae85e SL |
402 | /// |
403 | /// This property is defined in _UNIX Network Programming, Second Edition_, | |
476ff2be SL |
404 | /// W. Richard Stevens, p. 891; see also [ip7]. |
405 | /// | |
406 | /// [ip7]: http://man7.org/linux/man-pages/man7/ip.7.html | |
cc61c64b | 407 | /// [`true`]: ../../std/primitive.bool.html |
476ff2be SL |
408 | /// |
409 | /// # Examples | |
410 | /// | |
411 | /// ``` | |
412 | /// use std::net::Ipv4Addr; | |
413 | /// | |
414 | /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_unspecified(), true); | |
415 | /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_unspecified(), false); | |
416 | /// ``` | |
5bcae85e | 417 | #[stable(feature = "ip_shared", since = "1.12.0")] |
a1dfa0c6 | 418 | pub const fn is_unspecified(&self) -> bool { |
85aaf69f SL |
419 | self.inner.s_addr == 0 |
420 | } | |
421 | ||
cc61c64b | 422 | /// Returns [`true`] if this is a loopback address (127.0.0.0/8). |
9cc50fc6 | 423 | /// |
cc61c64b | 424 | /// This property is defined by [IETF RFC 1122]. |
476ff2be | 425 | /// |
cc61c64b XL |
426 | /// [IETF RFC 1122]: https://tools.ietf.org/html/rfc1122 |
427 | /// [`true`]: ../../std/primitive.bool.html | |
476ff2be SL |
428 | /// |
429 | /// # Examples | |
430 | /// | |
431 | /// ``` | |
432 | /// use std::net::Ipv4Addr; | |
433 | /// | |
434 | /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_loopback(), true); | |
435 | /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_loopback(), false); | |
436 | /// ``` | |
9cc50fc6 | 437 | #[stable(since = "1.7.0", feature = "ip_17")] |
85aaf69f SL |
438 | pub fn is_loopback(&self) -> bool { |
439 | self.octets()[0] == 127 | |
440 | } | |
441 | ||
cc61c64b | 442 | /// Returns [`true`] if this is a private address. |
85aaf69f | 443 | /// |
cc61c64b | 444 | /// The private address ranges are defined in [IETF RFC 1918] and include: |
85aaf69f SL |
445 | /// |
446 | /// - 10.0.0.0/8 | |
447 | /// - 172.16.0.0/12 | |
448 | /// - 192.168.0.0/16 | |
476ff2be | 449 | /// |
cc61c64b XL |
450 | /// [IETF RFC 1918]: https://tools.ietf.org/html/rfc1918 |
451 | /// [`true`]: ../../std/primitive.bool.html | |
476ff2be SL |
452 | /// |
453 | /// # Examples | |
454 | /// | |
455 | /// ``` | |
456 | /// use std::net::Ipv4Addr; | |
457 | /// | |
458 | /// assert_eq!(Ipv4Addr::new(10, 0, 0, 1).is_private(), true); | |
459 | /// assert_eq!(Ipv4Addr::new(10, 10, 10, 10).is_private(), true); | |
460 | /// assert_eq!(Ipv4Addr::new(172, 16, 10, 10).is_private(), true); | |
461 | /// assert_eq!(Ipv4Addr::new(172, 29, 45, 14).is_private(), true); | |
462 | /// assert_eq!(Ipv4Addr::new(172, 32, 0, 2).is_private(), false); | |
463 | /// assert_eq!(Ipv4Addr::new(192, 168, 0, 2).is_private(), true); | |
464 | /// assert_eq!(Ipv4Addr::new(192, 169, 0, 2).is_private(), false); | |
465 | /// ``` | |
9cc50fc6 | 466 | #[stable(since = "1.7.0", feature = "ip_17")] |
85aaf69f | 467 | pub fn is_private(&self) -> bool { |
b7449926 XL |
468 | match self.octets() { |
469 | [10, ..] => true, | |
470 | [172, b, ..] if b >= 16 && b <= 31 => true, | |
471 | [192, 168, ..] => true, | |
472 | _ => false, | |
85aaf69f SL |
473 | } |
474 | } | |
475 | ||
cc61c64b | 476 | /// Returns [`true`] if the address is link-local (169.254.0.0/16). |
9cc50fc6 | 477 | /// |
cc61c64b | 478 | /// This property is defined by [IETF RFC 3927]. |
476ff2be | 479 | /// |
cc61c64b XL |
480 | /// [IETF RFC 3927]: https://tools.ietf.org/html/rfc3927 |
481 | /// [`true`]: ../../std/primitive.bool.html | |
476ff2be SL |
482 | /// |
483 | /// # Examples | |
484 | /// | |
485 | /// ``` | |
486 | /// use std::net::Ipv4Addr; | |
487 | /// | |
488 | /// assert_eq!(Ipv4Addr::new(169, 254, 0, 0).is_link_local(), true); | |
489 | /// assert_eq!(Ipv4Addr::new(169, 254, 10, 65).is_link_local(), true); | |
490 | /// assert_eq!(Ipv4Addr::new(16, 89, 10, 65).is_link_local(), false); | |
491 | /// ``` | |
9cc50fc6 | 492 | #[stable(since = "1.7.0", feature = "ip_17")] |
85aaf69f | 493 | pub fn is_link_local(&self) -> bool { |
b7449926 XL |
494 | match self.octets() { |
495 | [169, 254, ..] => true, | |
496 | _ => false, | |
497 | } | |
85aaf69f SL |
498 | } |
499 | ||
cc61c64b | 500 | /// Returns [`true`] if the address appears to be globally routable. |
54a0048b | 501 | /// See [iana-ipv4-special-registry][ipv4-sr]. |
85aaf69f | 502 | /// |
d9579d0f AL |
503 | /// The following return false: |
504 | /// | |
505 | /// - private address (10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16) | |
506 | /// - the loopback address (127.0.0.0/8) | |
507 | /// - the link-local address (169.254.0.0/16) | |
508 | /// - the broadcast address (255.255.255.255/32) | |
509 | /// - test addresses used for documentation (192.0.2.0/24, 198.51.100.0/24 and 203.0.113.0/24) | |
54a0048b | 510 | /// - the unspecified address (0.0.0.0) |
476ff2be | 511 | /// |
3b2f2976 | 512 | /// [ipv4-sr]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml |
cc61c64b | 513 | /// [`true`]: ../../std/primitive.bool.html |
476ff2be SL |
514 | /// |
515 | /// # Examples | |
516 | /// | |
517 | /// ``` | |
518 | /// #![feature(ip)] | |
519 | /// | |
520 | /// use std::net::Ipv4Addr; | |
521 | /// | |
522 | /// fn main() { | |
523 | /// assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false); | |
524 | /// assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false); | |
525 | /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false); | |
526 | /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_global(), false); | |
527 | /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true); | |
528 | /// } | |
529 | /// ``` | |
85aaf69f | 530 | pub fn is_global(&self) -> bool { |
9346a6ac | 531 | !self.is_private() && !self.is_loopback() && !self.is_link_local() && |
54a0048b | 532 | !self.is_broadcast() && !self.is_documentation() && !self.is_unspecified() |
85aaf69f SL |
533 | } |
534 | ||
cc61c64b | 535 | /// Returns [`true`] if this is a multicast address (224.0.0.0/4). |
85aaf69f | 536 | /// |
9cc50fc6 | 537 | /// Multicast addresses have a most significant octet between 224 and 239, |
cc61c64b | 538 | /// and is defined by [IETF RFC 5771]. |
476ff2be | 539 | /// |
cc61c64b XL |
540 | /// [IETF RFC 5771]: https://tools.ietf.org/html/rfc5771 |
541 | /// [`true`]: ../../std/primitive.bool.html | |
476ff2be SL |
542 | /// |
543 | /// # Examples | |
544 | /// | |
545 | /// ``` | |
546 | /// use std::net::Ipv4Addr; | |
547 | /// | |
548 | /// assert_eq!(Ipv4Addr::new(224, 254, 0, 0).is_multicast(), true); | |
549 | /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_multicast(), true); | |
550 | /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_multicast(), false); | |
551 | /// ``` | |
9cc50fc6 | 552 | #[stable(since = "1.7.0", feature = "ip_17")] |
85aaf69f SL |
553 | pub fn is_multicast(&self) -> bool { |
554 | self.octets()[0] >= 224 && self.octets()[0] <= 239 | |
555 | } | |
556 | ||
cc61c64b | 557 | /// Returns [`true`] if this is a broadcast address (255.255.255.255). |
9346a6ac | 558 | /// |
cc61c64b | 559 | /// A broadcast address has all octets set to 255 as defined in [IETF RFC 919]. |
476ff2be | 560 | /// |
cc61c64b XL |
561 | /// [IETF RFC 919]: https://tools.ietf.org/html/rfc919 |
562 | /// [`true`]: ../../std/primitive.bool.html | |
476ff2be SL |
563 | /// |
564 | /// # Examples | |
565 | /// | |
566 | /// ``` | |
567 | /// use std::net::Ipv4Addr; | |
568 | /// | |
569 | /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_broadcast(), true); | |
570 | /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_broadcast(), false); | |
571 | /// ``` | |
9cc50fc6 | 572 | #[stable(since = "1.7.0", feature = "ip_17")] |
9346a6ac | 573 | pub fn is_broadcast(&self) -> bool { |
b7449926 | 574 | self == &Self::BROADCAST |
9346a6ac AL |
575 | } |
576 | ||
cc61c64b | 577 | /// Returns [`true`] if this address is in a range designated for documentation. |
9346a6ac | 578 | /// |
cc61c64b | 579 | /// This is defined in [IETF RFC 5737]: |
d9579d0f | 580 | /// |
9346a6ac AL |
581 | /// - 192.0.2.0/24 (TEST-NET-1) |
582 | /// - 198.51.100.0/24 (TEST-NET-2) | |
583 | /// - 203.0.113.0/24 (TEST-NET-3) | |
476ff2be | 584 | /// |
cc61c64b XL |
585 | /// [IETF RFC 5737]: https://tools.ietf.org/html/rfc5737 |
586 | /// [`true`]: ../../std/primitive.bool.html | |
476ff2be SL |
587 | /// |
588 | /// # Examples | |
589 | /// | |
590 | /// ``` | |
591 | /// use std::net::Ipv4Addr; | |
592 | /// | |
593 | /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_documentation(), true); | |
594 | /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_documentation(), true); | |
595 | /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_documentation(), true); | |
596 | /// assert_eq!(Ipv4Addr::new(193, 34, 17, 19).is_documentation(), false); | |
597 | /// ``` | |
9cc50fc6 | 598 | #[stable(since = "1.7.0", feature = "ip_17")] |
9346a6ac | 599 | pub fn is_documentation(&self) -> bool { |
b7449926 XL |
600 | match self.octets() { |
601 | [192, 0, 2, _] => true, | |
602 | [198, 51, 100, _] => true, | |
603 | [203, 0, 113, _] => true, | |
604 | _ => false, | |
9346a6ac AL |
605 | } |
606 | } | |
607 | ||
cc61c64b | 608 | /// Converts this address to an IPv4-compatible [IPv6 address]. |
85aaf69f SL |
609 | /// |
610 | /// a.b.c.d becomes ::a.b.c.d | |
476ff2be | 611 | /// |
cc61c64b XL |
612 | /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html |
613 | /// | |
476ff2be SL |
614 | /// # Examples |
615 | /// | |
616 | /// ``` | |
617 | /// use std::net::{Ipv4Addr, Ipv6Addr}; | |
618 | /// | |
619 | /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_compatible(), | |
620 | /// Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 767)); | |
621 | /// ``` | |
c34b1796 | 622 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 623 | pub fn to_ipv6_compatible(&self) -> Ipv6Addr { |
9fa01778 XL |
624 | let octets = self.octets(); |
625 | Ipv6Addr::from([ | |
626 | 0, 0, 0, 0, | |
627 | 0, 0, 0, 0, | |
628 | 0, 0, 0, 0, | |
629 | octets[0], octets[1], octets[2], octets[3], | |
630 | ]) | |
85aaf69f SL |
631 | } |
632 | ||
cc61c64b | 633 | /// Converts this address to an IPv4-mapped [IPv6 address]. |
85aaf69f SL |
634 | /// |
635 | /// a.b.c.d becomes ::ffff:a.b.c.d | |
476ff2be | 636 | /// |
cc61c64b XL |
637 | /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html |
638 | /// | |
476ff2be SL |
639 | /// # Examples |
640 | /// | |
641 | /// ``` | |
642 | /// use std::net::{Ipv4Addr, Ipv6Addr}; | |
643 | /// | |
644 | /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(), | |
645 | /// Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 49152, 767)); | |
646 | /// ``` | |
c34b1796 | 647 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 648 | pub fn to_ipv6_mapped(&self) -> Ipv6Addr { |
9fa01778 XL |
649 | let octets = self.octets(); |
650 | Ipv6Addr::from([ | |
651 | 0, 0, 0, 0, | |
652 | 0, 0, 0, 0, | |
653 | 0, 0, 0xFF, 0xFF, | |
654 | octets[0], octets[1], octets[2], octets[3], | |
655 | ]) | |
85aaf69f | 656 | } |
85aaf69f SL |
657 | } |
658 | ||
c30ab7b3 | 659 | #[stable(feature = "ip_addr", since = "1.7.0")] |
c34b1796 | 660 | impl fmt::Display for IpAddr { |
532ac7d7 | 661 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
b7449926 XL |
662 | match self { |
663 | IpAddr::V4(ip) => ip.fmt(fmt), | |
664 | IpAddr::V6(ip) => ip.fmt(fmt), | |
c34b1796 AL |
665 | } |
666 | } | |
667 | } | |
668 | ||
32a655c1 SL |
669 | #[stable(feature = "ip_from_ip", since = "1.16.0")] |
670 | impl From<Ipv4Addr> for IpAddr { | |
671 | fn from(ipv4: Ipv4Addr) -> IpAddr { | |
672 | IpAddr::V4(ipv4) | |
673 | } | |
674 | } | |
675 | ||
676 | #[stable(feature = "ip_from_ip", since = "1.16.0")] | |
677 | impl From<Ipv6Addr> for IpAddr { | |
678 | fn from(ipv6: Ipv6Addr) -> IpAddr { | |
679 | IpAddr::V6(ipv6) | |
680 | } | |
681 | } | |
682 | ||
c34b1796 | 683 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 684 | impl fmt::Display for Ipv4Addr { |
532ac7d7 | 685 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
85aaf69f SL |
686 | let octets = self.octets(); |
687 | write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3]) | |
688 | } | |
689 | } | |
690 | ||
c34b1796 | 691 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 692 | impl fmt::Debug for Ipv4Addr { |
532ac7d7 | 693 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
85aaf69f SL |
694 | fmt::Display::fmt(self, fmt) |
695 | } | |
696 | } | |
697 | ||
c34b1796 | 698 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
699 | impl Clone for Ipv4Addr { |
700 | fn clone(&self) -> Ipv4Addr { *self } | |
701 | } | |
702 | ||
c34b1796 | 703 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
704 | impl PartialEq for Ipv4Addr { |
705 | fn eq(&self, other: &Ipv4Addr) -> bool { | |
706 | self.inner.s_addr == other.inner.s_addr | |
707 | } | |
708 | } | |
c34b1796 | 709 | |
7cac9316 | 710 | #[stable(feature = "ip_cmp", since = "1.16.0")] |
32a655c1 SL |
711 | impl PartialEq<Ipv4Addr> for IpAddr { |
712 | fn eq(&self, other: &Ipv4Addr) -> bool { | |
b7449926 XL |
713 | match self { |
714 | IpAddr::V4(v4) => v4 == other, | |
32a655c1 SL |
715 | IpAddr::V6(_) => false, |
716 | } | |
717 | } | |
718 | } | |
719 | ||
7cac9316 | 720 | #[stable(feature = "ip_cmp", since = "1.16.0")] |
32a655c1 SL |
721 | impl PartialEq<IpAddr> for Ipv4Addr { |
722 | fn eq(&self, other: &IpAddr) -> bool { | |
b7449926 XL |
723 | match other { |
724 | IpAddr::V4(v4) => self == v4, | |
32a655c1 SL |
725 | IpAddr::V6(_) => false, |
726 | } | |
727 | } | |
728 | } | |
729 | ||
c34b1796 | 730 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
731 | impl Eq for Ipv4Addr {} |
732 | ||
85aaf69f SL |
733 | #[stable(feature = "rust1", since = "1.0.0")] |
734 | impl hash::Hash for Ipv4Addr { | |
735 | fn hash<H: hash::Hasher>(&self, s: &mut H) { | |
ff7c6d11 XL |
736 | // `inner` is #[repr(packed)], so we need to copy `s_addr`. |
737 | {self.inner.s_addr}.hash(s) | |
85aaf69f SL |
738 | } |
739 | } | |
740 | ||
c34b1796 | 741 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
742 | impl PartialOrd for Ipv4Addr { |
743 | fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> { | |
744 | Some(self.cmp(other)) | |
745 | } | |
746 | } | |
747 | ||
7cac9316 | 748 | #[stable(feature = "ip_cmp", since = "1.16.0")] |
32a655c1 SL |
749 | impl PartialOrd<Ipv4Addr> for IpAddr { |
750 | fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> { | |
b7449926 XL |
751 | match self { |
752 | IpAddr::V4(v4) => v4.partial_cmp(other), | |
32a655c1 SL |
753 | IpAddr::V6(_) => Some(Ordering::Greater), |
754 | } | |
755 | } | |
756 | } | |
757 | ||
7cac9316 | 758 | #[stable(feature = "ip_cmp", since = "1.16.0")] |
32a655c1 SL |
759 | impl PartialOrd<IpAddr> for Ipv4Addr { |
760 | fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> { | |
b7449926 XL |
761 | match other { |
762 | IpAddr::V4(v4) => self.partial_cmp(v4), | |
32a655c1 SL |
763 | IpAddr::V6(_) => Some(Ordering::Less), |
764 | } | |
765 | } | |
766 | } | |
767 | ||
c34b1796 | 768 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
769 | impl Ord for Ipv4Addr { |
770 | fn cmp(&self, other: &Ipv4Addr) -> Ordering { | |
b7449926 | 771 | u32::from_be(self.inner.s_addr).cmp(&u32::from_be(other.inner.s_addr)) |
85aaf69f SL |
772 | } |
773 | } | |
774 | ||
92a42be0 SL |
775 | impl AsInner<c::in_addr> for Ipv4Addr { |
776 | fn as_inner(&self) -> &c::in_addr { &self.inner } | |
85aaf69f | 777 | } |
92a42be0 SL |
778 | impl FromInner<c::in_addr> for Ipv4Addr { |
779 | fn from_inner(addr: c::in_addr) -> Ipv4Addr { | |
85aaf69f SL |
780 | Ipv4Addr { inner: addr } |
781 | } | |
782 | } | |
783 | ||
d9579d0f AL |
784 | #[stable(feature = "ip_u32", since = "1.1.0")] |
785 | impl From<Ipv4Addr> for u32 { | |
9fa01778 | 786 | /// Converts an `Ipv4Addr` into a host byte order `u32`. |
0531ce1d XL |
787 | /// |
788 | /// # Examples | |
789 | /// | |
790 | /// ``` | |
791 | /// use std::net::Ipv4Addr; | |
792 | /// | |
793 | /// let addr = Ipv4Addr::new(13, 12, 11, 10); | |
794 | /// assert_eq!(0x0d0c0b0au32, u32::from(addr)); | |
795 | /// ``` | |
d9579d0f AL |
796 | fn from(ip: Ipv4Addr) -> u32 { |
797 | let ip = ip.octets(); | |
9fa01778 | 798 | u32::from_be_bytes(ip) |
d9579d0f AL |
799 | } |
800 | } | |
801 | ||
802 | #[stable(feature = "ip_u32", since = "1.1.0")] | |
803 | impl From<u32> for Ipv4Addr { | |
9fa01778 | 804 | /// Converts a host byte order `u32` into an `Ipv4Addr`. |
0531ce1d XL |
805 | /// |
806 | /// # Examples | |
807 | /// | |
808 | /// ``` | |
809 | /// use std::net::Ipv4Addr; | |
810 | /// | |
811 | /// let addr = Ipv4Addr::from(0x0d0c0b0au32); | |
812 | /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr); | |
813 | /// ``` | |
d9579d0f | 814 | fn from(ip: u32) -> Ipv4Addr { |
9fa01778 | 815 | Ipv4Addr::from(ip.to_be_bytes()) |
d9579d0f AL |
816 | } |
817 | } | |
818 | ||
54a0048b SL |
819 | #[stable(feature = "from_slice_v4", since = "1.9.0")] |
820 | impl From<[u8; 4]> for Ipv4Addr { | |
0531ce1d XL |
821 | /// # Examples |
822 | /// | |
823 | /// ``` | |
824 | /// use std::net::Ipv4Addr; | |
825 | /// | |
826 | /// let addr = Ipv4Addr::from([13u8, 12u8, 11u8, 10u8]); | |
827 | /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr); | |
828 | /// ``` | |
54a0048b SL |
829 | fn from(octets: [u8; 4]) -> Ipv4Addr { |
830 | Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3]) | |
831 | } | |
832 | } | |
833 | ||
8bb4bdeb XL |
834 | #[stable(feature = "ip_from_slice", since = "1.17.0")] |
835 | impl From<[u8; 4]> for IpAddr { | |
9fa01778 | 836 | /// Creates an `IpAddr::V4` from a four element byte array. |
0531ce1d XL |
837 | /// |
838 | /// # Examples | |
839 | /// | |
840 | /// ``` | |
841 | /// use std::net::{IpAddr, Ipv4Addr}; | |
842 | /// | |
843 | /// let addr = IpAddr::from([13u8, 12u8, 11u8, 10u8]); | |
844 | /// assert_eq!(IpAddr::V4(Ipv4Addr::new(13, 12, 11, 10)), addr); | |
845 | /// ``` | |
8bb4bdeb XL |
846 | fn from(octets: [u8; 4]) -> IpAddr { |
847 | IpAddr::V4(Ipv4Addr::from(octets)) | |
848 | } | |
849 | } | |
850 | ||
85aaf69f | 851 | impl Ipv6Addr { |
9346a6ac | 852 | /// Creates a new IPv6 address from eight 16-bit segments. |
85aaf69f | 853 | /// |
a1dfa0c6 | 854 | /// The result will represent the IP address `a:b:c:d:e:f:g:h`. |
476ff2be SL |
855 | /// |
856 | /// # Examples | |
857 | /// | |
858 | /// ``` | |
859 | /// use std::net::Ipv6Addr; | |
860 | /// | |
861 | /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff); | |
862 | /// ``` | |
c34b1796 | 863 | #[stable(feature = "rust1", since = "1.0.0")] |
b7449926 XL |
864 | pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, |
865 | g: u16, h: u16) -> Ipv6Addr { | |
866 | Ipv6Addr { | |
867 | inner: c::in6_addr { | |
868 | s6_addr: [ | |
869 | (a >> 8) as u8, a as u8, | |
870 | (b >> 8) as u8, b as u8, | |
871 | (c >> 8) as u8, c as u8, | |
872 | (d >> 8) as u8, d as u8, | |
873 | (e >> 8) as u8, e as u8, | |
874 | (f >> 8) as u8, f as u8, | |
875 | (g >> 8) as u8, g as u8, | |
876 | (h >> 8) as u8, h as u8 | |
877 | ], | |
878 | } | |
879 | } | |
880 | ||
85aaf69f SL |
881 | } |
882 | ||
b7449926 | 883 | /// An IPv6 address representing localhost: `::1`. |
ea8adc8c XL |
884 | /// |
885 | /// # Examples | |
886 | /// | |
887 | /// ``` | |
ea8adc8c XL |
888 | /// use std::net::Ipv6Addr; |
889 | /// | |
b7449926 | 890 | /// let addr = Ipv6Addr::LOCALHOST; |
ea8adc8c XL |
891 | /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); |
892 | /// ``` | |
b7449926 XL |
893 | #[stable(feature = "ip_constructors", since = "1.30.0")] |
894 | pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); | |
ea8adc8c | 895 | |
b7449926 | 896 | /// An IPv6 address representing the unspecified address: `::` |
ea8adc8c XL |
897 | /// |
898 | /// # Examples | |
899 | /// | |
900 | /// ``` | |
ea8adc8c XL |
901 | /// use std::net::Ipv6Addr; |
902 | /// | |
b7449926 | 903 | /// let addr = Ipv6Addr::UNSPECIFIED; |
ea8adc8c XL |
904 | /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)); |
905 | /// ``` | |
b7449926 XL |
906 | #[stable(feature = "ip_constructors", since = "1.30.0")] |
907 | pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0); | |
ea8adc8c | 908 | |
bd371182 | 909 | /// Returns the eight 16-bit segments that make up this address. |
476ff2be SL |
910 | /// |
911 | /// # Examples | |
912 | /// | |
913 | /// ``` | |
914 | /// use std::net::Ipv6Addr; | |
915 | /// | |
916 | /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(), | |
917 | /// [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]); | |
918 | /// ``` | |
c34b1796 | 919 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 920 | pub fn segments(&self) -> [u16; 8] { |
92a42be0 SL |
921 | let arr = &self.inner.s6_addr; |
922 | [ | |
9fa01778 XL |
923 | u16::from_be_bytes([arr[0], arr[1]]), |
924 | u16::from_be_bytes([arr[2], arr[3]]), | |
925 | u16::from_be_bytes([arr[4], arr[5]]), | |
926 | u16::from_be_bytes([arr[6], arr[7]]), | |
927 | u16::from_be_bytes([arr[8], arr[9]]), | |
928 | u16::from_be_bytes([arr[10], arr[11]]), | |
929 | u16::from_be_bytes([arr[12], arr[13]]), | |
930 | u16::from_be_bytes([arr[14], arr[15]]), | |
92a42be0 | 931 | ] |
85aaf69f SL |
932 | } |
933 | ||
cc61c64b | 934 | /// Returns [`true`] for the special 'unspecified' address (::). |
9cc50fc6 | 935 | /// |
cc61c64b | 936 | /// This property is defined in [IETF RFC 4291]. |
476ff2be | 937 | /// |
cc61c64b XL |
938 | /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 |
939 | /// [`true`]: ../../std/primitive.bool.html | |
476ff2be SL |
940 | /// |
941 | /// # Examples | |
942 | /// | |
943 | /// ``` | |
944 | /// use std::net::Ipv6Addr; | |
945 | /// | |
946 | /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unspecified(), false); | |
947 | /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).is_unspecified(), true); | |
948 | /// ``` | |
9cc50fc6 | 949 | #[stable(since = "1.7.0", feature = "ip_17")] |
85aaf69f SL |
950 | pub fn is_unspecified(&self) -> bool { |
951 | self.segments() == [0, 0, 0, 0, 0, 0, 0, 0] | |
952 | } | |
953 | ||
cc61c64b | 954 | /// Returns [`true`] if this is a loopback address (::1). |
9cc50fc6 | 955 | /// |
cc61c64b | 956 | /// This property is defined in [IETF RFC 4291]. |
476ff2be | 957 | /// |
cc61c64b XL |
958 | /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 |
959 | /// [`true`]: ../../std/primitive.bool.html | |
476ff2be SL |
960 | /// |
961 | /// # Examples | |
962 | /// | |
963 | /// ``` | |
964 | /// use std::net::Ipv6Addr; | |
965 | /// | |
966 | /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false); | |
967 | /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true); | |
968 | /// ``` | |
9cc50fc6 | 969 | #[stable(since = "1.7.0", feature = "ip_17")] |
85aaf69f SL |
970 | pub fn is_loopback(&self) -> bool { |
971 | self.segments() == [0, 0, 0, 0, 0, 0, 0, 1] | |
972 | } | |
973 | ||
cc61c64b | 974 | /// Returns [`true`] if the address appears to be globally routable. |
85aaf69f | 975 | /// |
cc61c64b | 976 | /// The following return [`false`]: |
d9579d0f AL |
977 | /// |
978 | /// - the loopback address | |
979 | /// - link-local, site-local, and unique local unicast addresses | |
980 | /// - interface-, link-, realm-, admin- and site-local multicast addresses | |
476ff2be | 981 | /// |
cc61c64b XL |
982 | /// [`true`]: ../../std/primitive.bool.html |
983 | /// [`false`]: ../../std/primitive.bool.html | |
984 | /// | |
476ff2be SL |
985 | /// # Examples |
986 | /// | |
987 | /// ``` | |
988 | /// #![feature(ip)] | |
989 | /// | |
990 | /// use std::net::Ipv6Addr; | |
991 | /// | |
992 | /// fn main() { | |
993 | /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), true); | |
994 | /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_global(), false); | |
995 | /// assert_eq!(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1).is_global(), true); | |
996 | /// } | |
997 | /// ``` | |
85aaf69f SL |
998 | pub fn is_global(&self) -> bool { |
999 | match self.multicast_scope() { | |
1000 | Some(Ipv6MulticastScope::Global) => true, | |
1001 | None => self.is_unicast_global(), | |
1002 | _ => false | |
1003 | } | |
1004 | } | |
1005 | ||
cc61c64b | 1006 | /// Returns [`true`] if this is a unique local address (fc00::/7). |
85aaf69f | 1007 | /// |
cc61c64b | 1008 | /// This property is defined in [IETF RFC 4193]. |
476ff2be | 1009 | /// |
cc61c64b XL |
1010 | /// [IETF RFC 4193]: https://tools.ietf.org/html/rfc4193 |
1011 | /// [`true`]: ../../std/primitive.bool.html | |
476ff2be SL |
1012 | /// |
1013 | /// # Examples | |
1014 | /// | |
1015 | /// ``` | |
1016 | /// #![feature(ip)] | |
1017 | /// | |
1018 | /// use std::net::Ipv6Addr; | |
1019 | /// | |
1020 | /// fn main() { | |
1021 | /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), | |
1022 | /// false); | |
1023 | /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true); | |
1024 | /// } | |
1025 | /// ``` | |
85aaf69f SL |
1026 | pub fn is_unique_local(&self) -> bool { |
1027 | (self.segments()[0] & 0xfe00) == 0xfc00 | |
1028 | } | |
1029 | ||
cc61c64b | 1030 | /// Returns [`true`] if the address is unicast and link-local (fe80::/10). |
3157f602 | 1031 | /// |
cc61c64b | 1032 | /// This property is defined in [IETF RFC 4291]. |
476ff2be | 1033 | /// |
cc61c64b XL |
1034 | /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 |
1035 | /// [`true`]: ../../std/primitive.bool.html | |
476ff2be SL |
1036 | /// |
1037 | /// # Examples | |
1038 | /// | |
1039 | /// ``` | |
1040 | /// #![feature(ip)] | |
1041 | /// | |
1042 | /// use std::net::Ipv6Addr; | |
1043 | /// | |
1044 | /// fn main() { | |
1045 | /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_link_local(), | |
1046 | /// false); | |
1047 | /// assert_eq!(Ipv6Addr::new(0xfe8a, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true); | |
1048 | /// } | |
1049 | /// ``` | |
85aaf69f SL |
1050 | pub fn is_unicast_link_local(&self) -> bool { |
1051 | (self.segments()[0] & 0xffc0) == 0xfe80 | |
1052 | } | |
1053 | ||
cc61c64b | 1054 | /// Returns [`true`] if this is a deprecated unicast site-local address |
3157f602 | 1055 | /// (fec0::/10). |
476ff2be | 1056 | /// |
cc61c64b XL |
1057 | /// [`true`]: ../../std/primitive.bool.html |
1058 | /// | |
476ff2be SL |
1059 | /// # Examples |
1060 | /// | |
1061 | /// ``` | |
1062 | /// #![feature(ip)] | |
1063 | /// | |
1064 | /// use std::net::Ipv6Addr; | |
1065 | /// | |
1066 | /// fn main() { | |
1067 | /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_site_local(), | |
1068 | /// false); | |
1069 | /// assert_eq!(Ipv6Addr::new(0xfec2, 0, 0, 0, 0, 0, 0, 0).is_unicast_site_local(), true); | |
1070 | /// } | |
1071 | /// ``` | |
85aaf69f SL |
1072 | pub fn is_unicast_site_local(&self) -> bool { |
1073 | (self.segments()[0] & 0xffc0) == 0xfec0 | |
1074 | } | |
1075 | ||
cc61c64b | 1076 | /// Returns [`true`] if this is an address reserved for documentation |
3157f602 XL |
1077 | /// (2001:db8::/32). |
1078 | /// | |
cc61c64b | 1079 | /// This property is defined in [IETF RFC 3849]. |
476ff2be | 1080 | /// |
cc61c64b XL |
1081 | /// [IETF RFC 3849]: https://tools.ietf.org/html/rfc3849 |
1082 | /// [`true`]: ../../std/primitive.bool.html | |
476ff2be SL |
1083 | /// |
1084 | /// # Examples | |
1085 | /// | |
1086 | /// ``` | |
1087 | /// #![feature(ip)] | |
1088 | /// | |
1089 | /// use std::net::Ipv6Addr; | |
1090 | /// | |
1091 | /// fn main() { | |
1092 | /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), | |
1093 | /// false); | |
1094 | /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true); | |
1095 | /// } | |
1096 | /// ``` | |
54a0048b SL |
1097 | pub fn is_documentation(&self) -> bool { |
1098 | (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8) | |
1099 | } | |
1100 | ||
cc61c64b | 1101 | /// Returns [`true`] if the address is a globally routable unicast address. |
85aaf69f | 1102 | /// |
d9579d0f AL |
1103 | /// The following return false: |
1104 | /// | |
1105 | /// - the loopback address | |
1106 | /// - the link-local addresses | |
1107 | /// - the (deprecated) site-local addresses | |
1108 | /// - unique local addresses | |
54a0048b SL |
1109 | /// - the unspecified address |
1110 | /// - the address range reserved for documentation | |
476ff2be | 1111 | /// |
cc61c64b XL |
1112 | /// [`true`]: ../../std/primitive.bool.html |
1113 | /// | |
476ff2be SL |
1114 | /// # Examples |
1115 | /// | |
1116 | /// ``` | |
1117 | /// #![feature(ip)] | |
1118 | /// | |
1119 | /// use std::net::Ipv6Addr; | |
1120 | /// | |
1121 | /// fn main() { | |
1122 | /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false); | |
1123 | /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), | |
1124 | /// true); | |
1125 | /// } | |
1126 | /// ``` | |
85aaf69f SL |
1127 | pub fn is_unicast_global(&self) -> bool { |
1128 | !self.is_multicast() | |
1129 | && !self.is_loopback() && !self.is_unicast_link_local() | |
1130 | && !self.is_unicast_site_local() && !self.is_unique_local() | |
54a0048b | 1131 | && !self.is_unspecified() && !self.is_documentation() |
85aaf69f SL |
1132 | } |
1133 | ||
1134 | /// Returns the address's multicast scope if the address is multicast. | |
476ff2be SL |
1135 | /// |
1136 | /// # Examples | |
1137 | /// | |
1138 | /// ``` | |
1139 | /// #![feature(ip)] | |
1140 | /// | |
1141 | /// use std::net::{Ipv6Addr, Ipv6MulticastScope}; | |
1142 | /// | |
1143 | /// fn main() { | |
1144 | /// assert_eq!(Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0).multicast_scope(), | |
1145 | /// Some(Ipv6MulticastScope::Global)); | |
1146 | /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None); | |
1147 | /// } | |
1148 | /// ``` | |
85aaf69f SL |
1149 | pub fn multicast_scope(&self) -> Option<Ipv6MulticastScope> { |
1150 | if self.is_multicast() { | |
1151 | match self.segments()[0] & 0x000f { | |
1152 | 1 => Some(Ipv6MulticastScope::InterfaceLocal), | |
1153 | 2 => Some(Ipv6MulticastScope::LinkLocal), | |
1154 | 3 => Some(Ipv6MulticastScope::RealmLocal), | |
1155 | 4 => Some(Ipv6MulticastScope::AdminLocal), | |
1156 | 5 => Some(Ipv6MulticastScope::SiteLocal), | |
1157 | 8 => Some(Ipv6MulticastScope::OrganizationLocal), | |
1158 | 14 => Some(Ipv6MulticastScope::Global), | |
1159 | _ => None | |
1160 | } | |
1161 | } else { | |
1162 | None | |
1163 | } | |
1164 | } | |
1165 | ||
cc61c64b XL |
1166 | /// Returns [`true`] if this is a multicast address (ff00::/8). |
1167 | /// | |
1168 | /// This property is defined by [IETF RFC 4291]. | |
85aaf69f | 1169 | /// |
cc61c64b XL |
1170 | /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 |
1171 | /// [`true`]: ../../std/primitive.bool.html | |
476ff2be | 1172 | /// |
476ff2be SL |
1173 | /// # Examples |
1174 | /// | |
1175 | /// ``` | |
1176 | /// use std::net::Ipv6Addr; | |
1177 | /// | |
1178 | /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_multicast(), true); | |
1179 | /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_multicast(), false); | |
1180 | /// ``` | |
9cc50fc6 | 1181 | #[stable(since = "1.7.0", feature = "ip_17")] |
85aaf69f SL |
1182 | pub fn is_multicast(&self) -> bool { |
1183 | (self.segments()[0] & 0xff00) == 0xff00 | |
1184 | } | |
1185 | ||
cc61c64b | 1186 | /// Converts this address to an [IPv4 address]. Returns [`None`] if this address is |
85aaf69f SL |
1187 | /// neither IPv4-compatible or IPv4-mapped. |
1188 | /// | |
1189 | /// ::a.b.c.d and ::ffff:a.b.c.d become a.b.c.d | |
476ff2be | 1190 | /// |
cc61c64b XL |
1191 | /// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html |
1192 | /// [`None`]: ../../std/option/enum.Option.html#variant.None | |
1193 | /// | |
1194 | /// # Examples | |
1195 | /// | |
476ff2be SL |
1196 | /// ``` |
1197 | /// use std::net::{Ipv4Addr, Ipv6Addr}; | |
1198 | /// | |
1199 | /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4(), None); | |
1200 | /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4(), | |
1201 | /// Some(Ipv4Addr::new(192, 10, 2, 255))); | |
1202 | /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(), | |
1203 | /// Some(Ipv4Addr::new(0, 0, 0, 1))); | |
1204 | /// ``` | |
c34b1796 | 1205 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
1206 | pub fn to_ipv4(&self) -> Option<Ipv4Addr> { |
1207 | match self.segments() { | |
1208 | [0, 0, 0, 0, 0, f, g, h] if f == 0 || f == 0xffff => { | |
1209 | Some(Ipv4Addr::new((g >> 8) as u8, g as u8, | |
1210 | (h >> 8) as u8, h as u8)) | |
1211 | }, | |
1212 | _ => None | |
1213 | } | |
1214 | } | |
54a0048b SL |
1215 | |
1216 | /// Returns the sixteen eight-bit integers the IPv6 address consists of. | |
476ff2be SL |
1217 | /// |
1218 | /// ``` | |
1219 | /// use std::net::Ipv6Addr; | |
1220 | /// | |
1221 | /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).octets(), | |
1222 | /// [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); | |
1223 | /// ``` | |
5bcae85e | 1224 | #[stable(feature = "ipv6_to_octets", since = "1.12.0")] |
a1dfa0c6 | 1225 | pub const fn octets(&self) -> [u8; 16] { |
54a0048b SL |
1226 | self.inner.s6_addr |
1227 | } | |
85aaf69f SL |
1228 | } |
1229 | ||
c34b1796 | 1230 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 1231 | impl fmt::Display for Ipv6Addr { |
532ac7d7 | 1232 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
85aaf69f SL |
1233 | match self.segments() { |
1234 | // We need special cases for :: and ::1, otherwise they're formatted | |
1235 | // as ::0.0.0.[01] | |
1236 | [0, 0, 0, 0, 0, 0, 0, 0] => write!(fmt, "::"), | |
1237 | [0, 0, 0, 0, 0, 0, 0, 1] => write!(fmt, "::1"), | |
1238 | // Ipv4 Compatible address | |
1239 | [0, 0, 0, 0, 0, 0, g, h] => { | |
1240 | write!(fmt, "::{}.{}.{}.{}", (g >> 8) as u8, g as u8, | |
1241 | (h >> 8) as u8, h as u8) | |
1242 | } | |
1243 | // Ipv4-Mapped address | |
1244 | [0, 0, 0, 0, 0, 0xffff, g, h] => { | |
1245 | write!(fmt, "::ffff:{}.{}.{}.{}", (g >> 8) as u8, g as u8, | |
1246 | (h >> 8) as u8, h as u8) | |
1247 | }, | |
1248 | _ => { | |
1249 | fn find_zero_slice(segments: &[u16; 8]) -> (usize, usize) { | |
1250 | let mut longest_span_len = 0; | |
1251 | let mut longest_span_at = 0; | |
1252 | let mut cur_span_len = 0; | |
1253 | let mut cur_span_at = 0; | |
1254 | ||
c34b1796 | 1255 | for i in 0..8 { |
85aaf69f SL |
1256 | if segments[i] == 0 { |
1257 | if cur_span_len == 0 { | |
1258 | cur_span_at = i; | |
1259 | } | |
1260 | ||
1261 | cur_span_len += 1; | |
1262 | ||
1263 | if cur_span_len > longest_span_len { | |
1264 | longest_span_len = cur_span_len; | |
1265 | longest_span_at = cur_span_at; | |
1266 | } | |
1267 | } else { | |
1268 | cur_span_len = 0; | |
1269 | cur_span_at = 0; | |
1270 | } | |
1271 | } | |
1272 | ||
1273 | (longest_span_at, longest_span_len) | |
1274 | } | |
1275 | ||
1276 | let (zeros_at, zeros_len) = find_zero_slice(&self.segments()); | |
1277 | ||
1278 | if zeros_len > 1 { | |
532ac7d7 | 1279 | fn fmt_subslice(segments: &[u16], fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
92a42be0 | 1280 | if !segments.is_empty() { |
54a0048b | 1281 | write!(fmt, "{:x}", segments[0])?; |
92a42be0 | 1282 | for &seg in &segments[1..] { |
54a0048b | 1283 | write!(fmt, ":{:x}", seg)?; |
92a42be0 SL |
1284 | } |
1285 | } | |
1286 | Ok(()) | |
85aaf69f SL |
1287 | } |
1288 | ||
54a0048b SL |
1289 | fmt_subslice(&self.segments()[..zeros_at], fmt)?; |
1290 | fmt.write_str("::")?; | |
92a42be0 | 1291 | fmt_subslice(&self.segments()[zeros_at + zeros_len..], fmt) |
85aaf69f SL |
1292 | } else { |
1293 | let &[a, b, c, d, e, f, g, h] = &self.segments(); | |
1294 | write!(fmt, "{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}", | |
1295 | a, b, c, d, e, f, g, h) | |
1296 | } | |
1297 | } | |
1298 | } | |
1299 | } | |
1300 | } | |
1301 | ||
c34b1796 | 1302 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 1303 | impl fmt::Debug for Ipv6Addr { |
532ac7d7 | 1304 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
85aaf69f SL |
1305 | fmt::Display::fmt(self, fmt) |
1306 | } | |
1307 | } | |
1308 | ||
c34b1796 | 1309 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
1310 | impl Clone for Ipv6Addr { |
1311 | fn clone(&self) -> Ipv6Addr { *self } | |
1312 | } | |
1313 | ||
c34b1796 | 1314 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
1315 | impl PartialEq for Ipv6Addr { |
1316 | fn eq(&self, other: &Ipv6Addr) -> bool { | |
1317 | self.inner.s6_addr == other.inner.s6_addr | |
1318 | } | |
1319 | } | |
c34b1796 | 1320 | |
7cac9316 | 1321 | #[stable(feature = "ip_cmp", since = "1.16.0")] |
32a655c1 SL |
1322 | impl PartialEq<IpAddr> for Ipv6Addr { |
1323 | fn eq(&self, other: &IpAddr) -> bool { | |
b7449926 | 1324 | match other { |
32a655c1 | 1325 | IpAddr::V4(_) => false, |
b7449926 | 1326 | IpAddr::V6(v6) => self == v6, |
32a655c1 SL |
1327 | } |
1328 | } | |
1329 | } | |
1330 | ||
7cac9316 | 1331 | #[stable(feature = "ip_cmp", since = "1.16.0")] |
32a655c1 SL |
1332 | impl PartialEq<Ipv6Addr> for IpAddr { |
1333 | fn eq(&self, other: &Ipv6Addr) -> bool { | |
b7449926 | 1334 | match self { |
32a655c1 | 1335 | IpAddr::V4(_) => false, |
b7449926 | 1336 | IpAddr::V6(v6) => v6 == other, |
32a655c1 SL |
1337 | } |
1338 | } | |
1339 | } | |
1340 | ||
c34b1796 | 1341 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
1342 | impl Eq for Ipv6Addr {} |
1343 | ||
85aaf69f SL |
1344 | #[stable(feature = "rust1", since = "1.0.0")] |
1345 | impl hash::Hash for Ipv6Addr { | |
1346 | fn hash<H: hash::Hasher>(&self, s: &mut H) { | |
1347 | self.inner.s6_addr.hash(s) | |
1348 | } | |
1349 | } | |
1350 | ||
c34b1796 | 1351 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
1352 | impl PartialOrd for Ipv6Addr { |
1353 | fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> { | |
1354 | Some(self.cmp(other)) | |
1355 | } | |
1356 | } | |
1357 | ||
7cac9316 | 1358 | #[stable(feature = "ip_cmp", since = "1.16.0")] |
32a655c1 SL |
1359 | impl PartialOrd<Ipv6Addr> for IpAddr { |
1360 | fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> { | |
b7449926 | 1361 | match self { |
32a655c1 | 1362 | IpAddr::V4(_) => Some(Ordering::Less), |
b7449926 | 1363 | IpAddr::V6(v6) => v6.partial_cmp(other), |
32a655c1 SL |
1364 | } |
1365 | } | |
1366 | } | |
1367 | ||
7cac9316 | 1368 | #[stable(feature = "ip_cmp", since = "1.16.0")] |
32a655c1 SL |
1369 | impl PartialOrd<IpAddr> for Ipv6Addr { |
1370 | fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> { | |
b7449926 | 1371 | match other { |
32a655c1 | 1372 | IpAddr::V4(_) => Some(Ordering::Greater), |
b7449926 | 1373 | IpAddr::V6(v6) => self.partial_cmp(v6), |
32a655c1 SL |
1374 | } |
1375 | } | |
1376 | } | |
1377 | ||
c34b1796 | 1378 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
1379 | impl Ord for Ipv6Addr { |
1380 | fn cmp(&self, other: &Ipv6Addr) -> Ordering { | |
92a42be0 | 1381 | self.segments().cmp(&other.segments()) |
85aaf69f SL |
1382 | } |
1383 | } | |
1384 | ||
92a42be0 SL |
1385 | impl AsInner<c::in6_addr> for Ipv6Addr { |
1386 | fn as_inner(&self) -> &c::in6_addr { &self.inner } | |
85aaf69f | 1387 | } |
92a42be0 SL |
1388 | impl FromInner<c::in6_addr> for Ipv6Addr { |
1389 | fn from_inner(addr: c::in6_addr) -> Ipv6Addr { | |
85aaf69f SL |
1390 | Ipv6Addr { inner: addr } |
1391 | } | |
1392 | } | |
9346a6ac | 1393 | |
0531ce1d | 1394 | #[stable(feature = "i128", since = "1.26.0")] |
8bb4bdeb | 1395 | impl From<Ipv6Addr> for u128 { |
9fa01778 XL |
1396 | /// Convert an `Ipv6Addr` into a host byte order `u128`. |
1397 | /// | |
1398 | /// # Examples | |
1399 | /// | |
1400 | /// ``` | |
1401 | /// use std::net::Ipv6Addr; | |
1402 | /// | |
1403 | /// let addr = Ipv6Addr::new( | |
1404 | /// 0x1020, 0x3040, 0x5060, 0x7080, | |
1405 | /// 0x90A0, 0xB0C0, 0xD0E0, 0xF00D, | |
1406 | /// ); | |
1407 | /// assert_eq!(0x102030405060708090A0B0C0D0E0F00D_u128, u128::from(addr)); | |
1408 | /// ``` | |
8bb4bdeb | 1409 | fn from(ip: Ipv6Addr) -> u128 { |
9fa01778 XL |
1410 | let ip = ip.octets(); |
1411 | u128::from_be_bytes(ip) | |
8bb4bdeb XL |
1412 | } |
1413 | } | |
0531ce1d | 1414 | #[stable(feature = "i128", since = "1.26.0")] |
8bb4bdeb | 1415 | impl From<u128> for Ipv6Addr { |
9fa01778 XL |
1416 | /// Convert a host byte order `u128` into an `Ipv6Addr`. |
1417 | /// | |
1418 | /// # Examples | |
1419 | /// | |
1420 | /// ``` | |
1421 | /// use std::net::Ipv6Addr; | |
1422 | /// | |
1423 | /// let addr = Ipv6Addr::from(0x102030405060708090A0B0C0D0E0F00D_u128); | |
1424 | /// assert_eq!( | |
1425 | /// Ipv6Addr::new( | |
1426 | /// 0x1020, 0x3040, 0x5060, 0x7080, | |
1427 | /// 0x90A0, 0xB0C0, 0xD0E0, 0xF00D, | |
1428 | /// ), | |
1429 | /// addr); | |
1430 | /// ``` | |
8bb4bdeb | 1431 | fn from(ip: u128) -> Ipv6Addr { |
9fa01778 | 1432 | Ipv6Addr::from(ip.to_be_bytes()) |
8bb4bdeb XL |
1433 | } |
1434 | } | |
1435 | ||
54a0048b SL |
1436 | #[stable(feature = "ipv6_from_octets", since = "1.9.0")] |
1437 | impl From<[u8; 16]> for Ipv6Addr { | |
1438 | fn from(octets: [u8; 16]) -> Ipv6Addr { | |
b7449926 | 1439 | let inner = c::in6_addr { s6_addr: octets }; |
54a0048b SL |
1440 | Ipv6Addr::from_inner(inner) |
1441 | } | |
1442 | } | |
1443 | ||
7cac9316 | 1444 | #[stable(feature = "ipv6_from_segments", since = "1.16.0")] |
32a655c1 SL |
1445 | impl From<[u16; 8]> for Ipv6Addr { |
1446 | fn from(segments: [u16; 8]) -> Ipv6Addr { | |
1447 | let [a, b, c, d, e, f, g, h] = segments; | |
1448 | Ipv6Addr::new(a, b, c, d, e, f, g, h) | |
1449 | } | |
1450 | } | |
1451 | ||
8bb4bdeb XL |
1452 | |
1453 | #[stable(feature = "ip_from_slice", since = "1.17.0")] | |
1454 | impl From<[u8; 16]> for IpAddr { | |
9fa01778 | 1455 | /// Creates an `IpAddr::V6` from a sixteen element byte array. |
0531ce1d XL |
1456 | /// |
1457 | /// # Examples | |
1458 | /// | |
1459 | /// ``` | |
1460 | /// use std::net::{IpAddr, Ipv6Addr}; | |
1461 | /// | |
1462 | /// let addr = IpAddr::from([ | |
1463 | /// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8, | |
1464 | /// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8, | |
1465 | /// ]); | |
1466 | /// assert_eq!( | |
1467 | /// IpAddr::V6(Ipv6Addr::new( | |
1468 | /// 0x1918, 0x1716, | |
1469 | /// 0x1514, 0x1312, | |
1470 | /// 0x1110, 0x0f0e, | |
1471 | /// 0x0d0c, 0x0b0a | |
1472 | /// )), | |
1473 | /// addr | |
1474 | /// ); | |
1475 | /// ``` | |
8bb4bdeb XL |
1476 | fn from(octets: [u8; 16]) -> IpAddr { |
1477 | IpAddr::V6(Ipv6Addr::from(octets)) | |
1478 | } | |
1479 | } | |
1480 | ||
1481 | #[stable(feature = "ip_from_slice", since = "1.17.0")] | |
1482 | impl From<[u16; 8]> for IpAddr { | |
9fa01778 | 1483 | /// Creates an `IpAddr::V6` from an eight element 16-bit array. |
0531ce1d XL |
1484 | /// |
1485 | /// # Examples | |
1486 | /// | |
1487 | /// ``` | |
1488 | /// use std::net::{IpAddr, Ipv6Addr}; | |
1489 | /// | |
1490 | /// let addr = IpAddr::from([ | |
1491 | /// 525u16, 524u16, 523u16, 522u16, | |
1492 | /// 521u16, 520u16, 519u16, 518u16, | |
1493 | /// ]); | |
1494 | /// assert_eq!( | |
1495 | /// IpAddr::V6(Ipv6Addr::new( | |
1496 | /// 0x20d, 0x20c, | |
1497 | /// 0x20b, 0x20a, | |
1498 | /// 0x209, 0x208, | |
1499 | /// 0x207, 0x206 | |
1500 | /// )), | |
1501 | /// addr | |
1502 | /// ); | |
1503 | /// ``` | |
8bb4bdeb XL |
1504 | fn from(segments: [u16; 8]) -> IpAddr { |
1505 | IpAddr::V6(Ipv6Addr::from(segments)) | |
1506 | } | |
1507 | } | |
1508 | ||
9346a6ac | 1509 | // Tests for this module |
c30ab7b3 | 1510 | #[cfg(all(test, not(target_os = "emscripten")))] |
9346a6ac | 1511 | mod tests { |
532ac7d7 XL |
1512 | use crate::net::*; |
1513 | use crate::net::Ipv6MulticastScope::*; | |
1514 | use crate::net::test::{tsa, sa6, sa4}; | |
9346a6ac AL |
1515 | |
1516 | #[test] | |
1517 | fn test_from_str_ipv4() { | |
1518 | assert_eq!(Ok(Ipv4Addr::new(127, 0, 0, 1)), "127.0.0.1".parse()); | |
1519 | assert_eq!(Ok(Ipv4Addr::new(255, 255, 255, 255)), "255.255.255.255".parse()); | |
1520 | assert_eq!(Ok(Ipv4Addr::new(0, 0, 0, 0)), "0.0.0.0".parse()); | |
1521 | ||
1522 | // out of range | |
1523 | let none: Option<Ipv4Addr> = "256.0.0.1".parse().ok(); | |
1524 | assert_eq!(None, none); | |
1525 | // too short | |
1526 | let none: Option<Ipv4Addr> = "255.0.0".parse().ok(); | |
1527 | assert_eq!(None, none); | |
1528 | // too long | |
1529 | let none: Option<Ipv4Addr> = "255.0.0.1.2".parse().ok(); | |
1530 | assert_eq!(None, none); | |
1531 | // no number between dots | |
1532 | let none: Option<Ipv4Addr> = "255.0..1".parse().ok(); | |
1533 | assert_eq!(None, none); | |
1534 | } | |
1535 | ||
1536 | #[test] | |
1537 | fn test_from_str_ipv6() { | |
1538 | assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "0:0:0:0:0:0:0:0".parse()); | |
1539 | assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "0:0:0:0:0:0:0:1".parse()); | |
1540 | ||
1541 | assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "::1".parse()); | |
1542 | assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "::".parse()); | |
1543 | ||
1544 | assert_eq!(Ok(Ipv6Addr::new(0x2a02, 0x6b8, 0, 0, 0, 0, 0x11, 0x11)), | |
1545 | "2a02:6b8::11:11".parse()); | |
1546 | ||
1547 | // too long group | |
1548 | let none: Option<Ipv6Addr> = "::00000".parse().ok(); | |
1549 | assert_eq!(None, none); | |
1550 | // too short | |
1551 | let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7".parse().ok(); | |
1552 | assert_eq!(None, none); | |
1553 | // too long | |
1554 | let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7:8:9".parse().ok(); | |
1555 | assert_eq!(None, none); | |
1556 | // triple colon | |
1557 | let none: Option<Ipv6Addr> = "1:2:::6:7:8".parse().ok(); | |
1558 | assert_eq!(None, none); | |
1559 | // two double colons | |
1560 | let none: Option<Ipv6Addr> = "1:2::6::8".parse().ok(); | |
1561 | assert_eq!(None, none); | |
ff7c6d11 XL |
1562 | // `::` indicating zero groups of zeros |
1563 | let none: Option<Ipv6Addr> = "1:2:3:4::5:6:7:8".parse().ok(); | |
1564 | assert_eq!(None, none); | |
9346a6ac AL |
1565 | } |
1566 | ||
1567 | #[test] | |
1568 | fn test_from_str_ipv4_in_ipv6() { | |
1569 | assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 545)), | |
1570 | "::192.0.2.33".parse()); | |
1571 | assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0xFFFF, 49152, 545)), | |
1572 | "::FFFF:192.0.2.33".parse()); | |
1573 | assert_eq!(Ok(Ipv6Addr::new(0x64, 0xff9b, 0, 0, 0, 0, 49152, 545)), | |
1574 | "64:ff9b::192.0.2.33".parse()); | |
1575 | assert_eq!(Ok(Ipv6Addr::new(0x2001, 0xdb8, 0x122, 0xc000, 0x2, 0x2100, 49152, 545)), | |
1576 | "2001:db8:122:c000:2:2100:192.0.2.33".parse()); | |
1577 | ||
1578 | // colon after v4 | |
1579 | let none: Option<Ipv4Addr> = "::127.0.0.1:".parse().ok(); | |
1580 | assert_eq!(None, none); | |
1581 | // not enough groups | |
1582 | let none: Option<Ipv6Addr> = "1.2.3.4.5:127.0.0.1".parse().ok(); | |
1583 | assert_eq!(None, none); | |
1584 | // too many groups | |
1585 | let none: Option<Ipv6Addr> = "1.2.3.4.5:6:7:127.0.0.1".parse().ok(); | |
1586 | assert_eq!(None, none); | |
1587 | } | |
1588 | ||
1589 | #[test] | |
1590 | fn test_from_str_socket_addr() { | |
1591 | assert_eq!(Ok(sa4(Ipv4Addr::new(77, 88, 21, 11), 80)), | |
1592 | "77.88.21.11:80".parse()); | |
b039eaaf SL |
1593 | assert_eq!(Ok(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80)), |
1594 | "77.88.21.11:80".parse()); | |
9346a6ac AL |
1595 | assert_eq!(Ok(sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53)), |
1596 | "[2a02:6b8:0:1::1]:53".parse()); | |
b039eaaf SL |
1597 | assert_eq!(Ok(SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, |
1598 | 0, 0, 0, 1), 53, 0, 0)), | |
1599 | "[2a02:6b8:0:1::1]:53".parse()); | |
9346a6ac AL |
1600 | assert_eq!(Ok(sa6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22)), |
1601 | "[::127.0.0.1]:22".parse()); | |
b039eaaf SL |
1602 | assert_eq!(Ok(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, |
1603 | 0x7F00, 1), 22, 0, 0)), | |
1604 | "[::127.0.0.1]:22".parse()); | |
9346a6ac AL |
1605 | |
1606 | // without port | |
1607 | let none: Option<SocketAddr> = "127.0.0.1".parse().ok(); | |
1608 | assert_eq!(None, none); | |
1609 | // without port | |
1610 | let none: Option<SocketAddr> = "127.0.0.1:".parse().ok(); | |
1611 | assert_eq!(None, none); | |
1612 | // wrong brackets around v4 | |
1613 | let none: Option<SocketAddr> = "[127.0.0.1]:22".parse().ok(); | |
1614 | assert_eq!(None, none); | |
1615 | // port out of range | |
1616 | let none: Option<SocketAddr> = "127.0.0.1:123456".parse().ok(); | |
1617 | assert_eq!(None, none); | |
1618 | } | |
1619 | ||
1620 | #[test] | |
1621 | fn ipv6_addr_to_string() { | |
1622 | // ipv4-mapped address | |
1623 | let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280); | |
1624 | assert_eq!(a1.to_string(), "::ffff:192.0.2.128"); | |
1625 | ||
1626 | // ipv4-compatible address | |
1627 | let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x280); | |
1628 | assert_eq!(a1.to_string(), "::192.0.2.128"); | |
1629 | ||
1630 | // v6 address with no zero segments | |
1631 | assert_eq!(Ipv6Addr::new(8, 9, 10, 11, 12, 13, 14, 15).to_string(), | |
1632 | "8:9:a:b:c:d:e:f"); | |
1633 | ||
1634 | // reduce a single run of zeros | |
1635 | assert_eq!("ae::ffff:102:304", | |
1636 | Ipv6Addr::new(0xae, 0, 0, 0, 0, 0xffff, 0x0102, 0x0304).to_string()); | |
1637 | ||
1638 | // don't reduce just a single zero segment | |
1639 | assert_eq!("1:2:3:4:5:6:0:8", | |
1640 | Ipv6Addr::new(1, 2, 3, 4, 5, 6, 0, 8).to_string()); | |
1641 | ||
1642 | // 'any' address | |
1643 | assert_eq!("::", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).to_string()); | |
1644 | ||
1645 | // loopback address | |
1646 | assert_eq!("::1", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_string()); | |
1647 | ||
1648 | // ends in zeros | |
1649 | assert_eq!("1::", Ipv6Addr::new(1, 0, 0, 0, 0, 0, 0, 0).to_string()); | |
1650 | ||
1651 | // two runs of zeros, second one is longer | |
1652 | assert_eq!("1:0:0:4::8", Ipv6Addr::new(1, 0, 0, 4, 0, 0, 0, 8).to_string()); | |
1653 | ||
1654 | // two runs of zeros, equal length | |
1655 | assert_eq!("1::4:5:0:0:8", Ipv6Addr::new(1, 0, 0, 4, 5, 0, 0, 8).to_string()); | |
1656 | } | |
1657 | ||
1658 | #[test] | |
1659 | fn ipv4_to_ipv6() { | |
1660 | assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678), | |
1661 | Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_mapped()); | |
1662 | assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678), | |
1663 | Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_compatible()); | |
1664 | } | |
1665 | ||
1666 | #[test] | |
1667 | fn ipv6_to_ipv4() { | |
1668 | assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4(), | |
1669 | Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))); | |
1670 | assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4(), | |
1671 | Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))); | |
1672 | assert_eq!(Ipv6Addr::new(0, 0, 1, 0, 0, 0, 0x1234, 0x5678).to_ipv4(), | |
1673 | None); | |
1674 | } | |
1675 | ||
5bcae85e SL |
1676 | #[test] |
1677 | fn ip_properties() { | |
1678 | fn check4(octets: &[u8; 4], unspec: bool, loopback: bool, | |
1679 | global: bool, multicast: bool, documentation: bool) { | |
1680 | let ip = IpAddr::V4(Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3])); | |
1681 | assert_eq!(ip.is_unspecified(), unspec); | |
1682 | assert_eq!(ip.is_loopback(), loopback); | |
1683 | assert_eq!(ip.is_global(), global); | |
1684 | assert_eq!(ip.is_multicast(), multicast); | |
1685 | assert_eq!(ip.is_documentation(), documentation); | |
1686 | } | |
1687 | ||
1688 | fn check6(str_addr: &str, unspec: bool, loopback: bool, | |
1689 | global: bool, u_doc: bool, mcast: bool) { | |
1690 | let ip = IpAddr::V6(str_addr.parse().unwrap()); | |
1691 | assert_eq!(ip.is_unspecified(), unspec); | |
1692 | assert_eq!(ip.is_loopback(), loopback); | |
1693 | assert_eq!(ip.is_global(), global); | |
1694 | assert_eq!(ip.is_documentation(), u_doc); | |
1695 | assert_eq!(ip.is_multicast(), mcast); | |
1696 | } | |
1697 | ||
1698 | // address unspec loopbk global multicast doc | |
1699 | check4(&[0, 0, 0, 0], true, false, false, false, false); | |
1700 | check4(&[0, 0, 0, 1], false, false, true, false, false); | |
1701 | check4(&[0, 1, 0, 0], false, false, true, false, false); | |
1702 | check4(&[10, 9, 8, 7], false, false, false, false, false); | |
1703 | check4(&[127, 1, 2, 3], false, true, false, false, false); | |
1704 | check4(&[172, 31, 254, 253], false, false, false, false, false); | |
1705 | check4(&[169, 254, 253, 242], false, false, false, false, false); | |
1706 | check4(&[192, 0, 2, 183], false, false, false, false, true); | |
1707 | check4(&[192, 1, 2, 183], false, false, true, false, false); | |
1708 | check4(&[192, 168, 254, 253], false, false, false, false, false); | |
1709 | check4(&[198, 51, 100, 0], false, false, false, false, true); | |
1710 | check4(&[203, 0, 113, 0], false, false, false, false, true); | |
1711 | check4(&[203, 2, 113, 0], false, false, true, false, false); | |
1712 | check4(&[224, 0, 0, 0], false, false, true, true, false); | |
1713 | check4(&[239, 255, 255, 255], false, false, true, true, false); | |
1714 | check4(&[255, 255, 255, 255], false, false, false, false, false); | |
1715 | ||
1716 | // address unspec loopbk global doc mcast | |
1717 | check6("::", true, false, false, false, false); | |
1718 | check6("::1", false, true, false, false, false); | |
1719 | check6("::0.0.0.2", false, false, true, false, false); | |
1720 | check6("1::", false, false, true, false, false); | |
1721 | check6("fc00::", false, false, false, false, false); | |
1722 | check6("fdff:ffff::", false, false, false, false, false); | |
1723 | check6("fe80:ffff::", false, false, false, false, false); | |
1724 | check6("febf:ffff::", false, false, false, false, false); | |
1725 | check6("fec0::", false, false, false, false, false); | |
1726 | check6("ff01::", false, false, false, false, true); | |
1727 | check6("ff02::", false, false, false, false, true); | |
1728 | check6("ff03::", false, false, false, false, true); | |
1729 | check6("ff04::", false, false, false, false, true); | |
1730 | check6("ff05::", false, false, false, false, true); | |
1731 | check6("ff08::", false, false, false, false, true); | |
1732 | check6("ff0e::", false, false, true, false, true); | |
1733 | check6("2001:db8:85a3::8a2e:370:7334", false, false, false, true, false); | |
1734 | check6("102:304:506:708:90a:b0c:d0e:f10", false, false, true, false, false); | |
1735 | } | |
1736 | ||
9346a6ac AL |
1737 | #[test] |
1738 | fn ipv4_properties() { | |
1739 | fn check(octets: &[u8; 4], unspec: bool, loopback: bool, | |
1740 | private: bool, link_local: bool, global: bool, | |
1741 | multicast: bool, broadcast: bool, documentation: bool) { | |
1742 | let ip = Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3]); | |
1743 | assert_eq!(octets, &ip.octets()); | |
1744 | ||
1745 | assert_eq!(ip.is_unspecified(), unspec); | |
1746 | assert_eq!(ip.is_loopback(), loopback); | |
1747 | assert_eq!(ip.is_private(), private); | |
1748 | assert_eq!(ip.is_link_local(), link_local); | |
1749 | assert_eq!(ip.is_global(), global); | |
1750 | assert_eq!(ip.is_multicast(), multicast); | |
1751 | assert_eq!(ip.is_broadcast(), broadcast); | |
1752 | assert_eq!(ip.is_documentation(), documentation); | |
1753 | } | |
1754 | ||
1755 | // address unspec loopbk privt linloc global multicast brdcast doc | |
54a0048b SL |
1756 | check(&[0, 0, 0, 0], true, false, false, false, false, false, false, false); |
1757 | check(&[0, 0, 0, 1], false, false, false, false, true, false, false, false); | |
1758 | check(&[0, 1, 0, 0], false, false, false, false, true, false, false, false); | |
1759 | check(&[10, 9, 8, 7], false, false, true, false, false, false, false, false); | |
1760 | check(&[127, 1, 2, 3], false, true, false, false, false, false, false, false); | |
1761 | check(&[172, 31, 254, 253], false, false, true, false, false, false, false, false); | |
1762 | check(&[169, 254, 253, 242], false, false, false, true, false, false, false, false); | |
1763 | check(&[192, 0, 2, 183], false, false, false, false, false, false, false, true); | |
1764 | check(&[192, 1, 2, 183], false, false, false, false, true, false, false, false); | |
1765 | check(&[192, 168, 254, 253], false, false, true, false, false, false, false, false); | |
1766 | check(&[198, 51, 100, 0], false, false, false, false, false, false, false, true); | |
1767 | check(&[203, 0, 113, 0], false, false, false, false, false, false, false, true); | |
1768 | check(&[203, 2, 113, 0], false, false, false, false, true, false, false, false); | |
1769 | check(&[224, 0, 0, 0], false, false, false, false, true, true, false, false); | |
1770 | check(&[239, 255, 255, 255], false, false, false, false, true, true, false, false); | |
1771 | check(&[255, 255, 255, 255], false, false, false, false, false, false, true, false); | |
9346a6ac AL |
1772 | } |
1773 | ||
1774 | #[test] | |
1775 | fn ipv6_properties() { | |
54a0048b | 1776 | fn check(str_addr: &str, octets: &[u8; 16], unspec: bool, loopback: bool, |
9346a6ac | 1777 | unique_local: bool, global: bool, |
54a0048b | 1778 | u_link_local: bool, u_site_local: bool, u_global: bool, u_doc: bool, |
9346a6ac AL |
1779 | m_scope: Option<Ipv6MulticastScope>) { |
1780 | let ip: Ipv6Addr = str_addr.parse().unwrap(); | |
1781 | assert_eq!(str_addr, ip.to_string()); | |
54a0048b SL |
1782 | assert_eq!(&ip.octets(), octets); |
1783 | assert_eq!(Ipv6Addr::from(*octets), ip); | |
9346a6ac AL |
1784 | |
1785 | assert_eq!(ip.is_unspecified(), unspec); | |
1786 | assert_eq!(ip.is_loopback(), loopback); | |
1787 | assert_eq!(ip.is_unique_local(), unique_local); | |
1788 | assert_eq!(ip.is_global(), global); | |
1789 | assert_eq!(ip.is_unicast_link_local(), u_link_local); | |
1790 | assert_eq!(ip.is_unicast_site_local(), u_site_local); | |
1791 | assert_eq!(ip.is_unicast_global(), u_global); | |
54a0048b | 1792 | assert_eq!(ip.is_documentation(), u_doc); |
9346a6ac AL |
1793 | assert_eq!(ip.multicast_scope(), m_scope); |
1794 | assert_eq!(ip.is_multicast(), m_scope.is_some()); | |
1795 | } | |
1796 | ||
54a0048b SL |
1797 | // unspec loopbk uniqlo global unill unisl uniglo doc mscope |
1798 | check("::", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
1799 | true, false, false, false, false, false, false, false, None); | |
1800 | check("::1", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], | |
1801 | false, true, false, false, false, false, false, false, None); | |
1802 | check("::0.0.0.2", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], | |
1803 | false, false, false, true, false, false, true, false, None); | |
1804 | check("1::", &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
1805 | false, false, false, true, false, false, true, false, None); | |
1806 | check("fc00::", &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
1807 | false, false, true, false, false, false, false, false, None); | |
1808 | check("fdff:ffff::", &[0xfd, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
1809 | false, false, true, false, false, false, false, false, None); | |
1810 | check("fe80:ffff::", &[0xfe, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
1811 | false, false, false, false, true, false, false, false, None); | |
1812 | check("febf:ffff::", &[0xfe, 0xbf, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
1813 | false, false, false, false, true, false, false, false, None); | |
1814 | check("fec0::", &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
1815 | false, false, false, false, false, true, false, false, None); | |
1816 | check("ff01::", &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
1817 | false, false, false, false, false, false, false, false, Some(InterfaceLocal)); | |
1818 | check("ff02::", &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
1819 | false, false, false, false, false, false, false, false, Some(LinkLocal)); | |
1820 | check("ff03::", &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
1821 | false, false, false, false, false, false, false, false, Some(RealmLocal)); | |
1822 | check("ff04::", &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
1823 | false, false, false, false, false, false, false, false, Some(AdminLocal)); | |
1824 | check("ff05::", &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
1825 | false, false, false, false, false, false, false, false, Some(SiteLocal)); | |
1826 | check("ff08::", &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
1827 | false, false, false, false, false, false, false, false, Some(OrganizationLocal)); | |
1828 | check("ff0e::", &[0xff, 0xe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
1829 | false, false, false, true, false, false, false, false, Some(Global)); | |
1830 | check("2001:db8:85a3::8a2e:370:7334", | |
1831 | &[0x20, 1, 0xd, 0xb8, 0x85, 0xa3, 0, 0, 0, 0, 0x8a, 0x2e, 3, 0x70, 0x73, 0x34], | |
1832 | false, false, false, false, false, false, false, true, None); | |
1833 | check("102:304:506:708:90a:b0c:d0e:f10", | |
1834 | &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], | |
1835 | false, false, false, true, false, false, true, false, None); | |
9346a6ac AL |
1836 | } |
1837 | ||
1838 | #[test] | |
1839 | fn to_socket_addr_socketaddr() { | |
1840 | let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 12345); | |
1841 | assert_eq!(Ok(vec![a]), tsa(a)); | |
1842 | } | |
d9579d0f AL |
1843 | |
1844 | #[test] | |
1845 | fn test_ipv4_to_int() { | |
8bb4bdeb XL |
1846 | let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44); |
1847 | assert_eq!(u32::from(a), 0x11223344); | |
d9579d0f AL |
1848 | } |
1849 | ||
1850 | #[test] | |
1851 | fn test_int_to_ipv4() { | |
8bb4bdeb XL |
1852 | let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44); |
1853 | assert_eq!(Ipv4Addr::from(0x11223344), a); | |
1854 | } | |
1855 | ||
1856 | #[test] | |
1857 | fn test_ipv6_to_int() { | |
1858 | let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11); | |
1859 | assert_eq!(u128::from(a), 0x112233445566778899aabbccddeeff11u128); | |
1860 | } | |
1861 | ||
1862 | #[test] | |
1863 | fn test_int_to_ipv6() { | |
1864 | let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11); | |
1865 | assert_eq!(Ipv6Addr::from(0x112233445566778899aabbccddeeff11u128), a); | |
d9579d0f | 1866 | } |
92a42be0 | 1867 | |
ea8adc8c XL |
1868 | #[test] |
1869 | fn ipv4_from_constructors() { | |
b7449926 XL |
1870 | assert_eq!(Ipv4Addr::LOCALHOST, Ipv4Addr::new(127, 0, 0, 1)); |
1871 | assert!(Ipv4Addr::LOCALHOST.is_loopback()); | |
1872 | assert_eq!(Ipv4Addr::UNSPECIFIED, Ipv4Addr::new(0, 0, 0, 0)); | |
1873 | assert!(Ipv4Addr::UNSPECIFIED.is_unspecified()); | |
1874 | assert_eq!(Ipv4Addr::BROADCAST, Ipv4Addr::new(255, 255, 255, 255)); | |
1875 | assert!(Ipv4Addr::BROADCAST.is_broadcast()); | |
ea8adc8c XL |
1876 | } |
1877 | ||
1878 | #[test] | |
1879 | fn ipv6_from_contructors() { | |
b7449926 XL |
1880 | assert_eq!(Ipv6Addr::LOCALHOST, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); |
1881 | assert!(Ipv6Addr::LOCALHOST.is_loopback()); | |
1882 | assert_eq!(Ipv6Addr::UNSPECIFIED, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)); | |
1883 | assert!(Ipv6Addr::UNSPECIFIED.is_unspecified()); | |
ea8adc8c XL |
1884 | } |
1885 | ||
54a0048b | 1886 | #[test] |
32a655c1 | 1887 | fn ipv4_from_octets() { |
54a0048b SL |
1888 | assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1)) |
1889 | } | |
1890 | ||
92a42be0 | 1891 | #[test] |
32a655c1 SL |
1892 | fn ipv6_from_segments() { |
1893 | let from_u16s = Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, | |
1894 | 0x8899, 0xaabb, 0xccdd, 0xeeff]); | |
1895 | let new = Ipv6Addr::new(0x0011, 0x2233, 0x4455, 0x6677, | |
1896 | 0x8899, 0xaabb, 0xccdd, 0xeeff); | |
1897 | assert_eq!(new, from_u16s); | |
1898 | } | |
1899 | ||
1900 | #[test] | |
1901 | fn ipv6_from_octets() { | |
1902 | let from_u16s = Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, | |
1903 | 0x8899, 0xaabb, 0xccdd, 0xeeff]); | |
1904 | let from_u8s = Ipv6Addr::from([0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, | |
1905 | 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]); | |
1906 | assert_eq!(from_u16s, from_u8s); | |
1907 | } | |
1908 | ||
1909 | #[test] | |
1910 | fn cmp() { | |
1911 | let v41 = Ipv4Addr::new(100, 64, 3, 3); | |
1912 | let v42 = Ipv4Addr::new(192, 0, 2, 2); | |
1913 | let v61 = "2001:db8:f00::1002".parse::<Ipv6Addr>().unwrap(); | |
1914 | let v62 = "2001:db8:f00::2001".parse::<Ipv6Addr>().unwrap(); | |
1915 | assert!(v41 < v42); | |
1916 | assert!(v61 < v62); | |
1917 | ||
1918 | assert_eq!(v41, IpAddr::V4(v41)); | |
1919 | assert_eq!(v61, IpAddr::V6(v61)); | |
1920 | assert!(v41 != IpAddr::V4(v42)); | |
1921 | assert!(v61 != IpAddr::V6(v62)); | |
1922 | ||
1923 | assert!(v41 < IpAddr::V4(v42)); | |
1924 | assert!(v61 < IpAddr::V6(v62)); | |
1925 | assert!(IpAddr::V4(v41) < v42); | |
1926 | assert!(IpAddr::V6(v61) < v62); | |
1927 | ||
1928 | assert!(v41 < IpAddr::V6(v61)); | |
1929 | assert!(IpAddr::V4(v41) < v61); | |
92a42be0 | 1930 | } |
c30ab7b3 SL |
1931 | |
1932 | #[test] | |
1933 | fn is_v4() { | |
1934 | let ip = IpAddr::V4(Ipv4Addr::new(100, 64, 3, 3)); | |
1935 | assert!(ip.is_ipv4()); | |
1936 | assert!(!ip.is_ipv6()); | |
1937 | } | |
1938 | ||
1939 | #[test] | |
1940 | fn is_v6() { | |
1941 | let ip = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678)); | |
1942 | assert!(!ip.is_ipv4()); | |
1943 | assert!(ip.is_ipv6()); | |
1944 | } | |
9346a6ac | 1945 | } |