ip_network/ipv4_network.rs
1use std::cmp;
2use std::fmt;
3use std::net::Ipv4Addr;
4use std::str::FromStr;
5use std::hash::{Hash, Hasher};
6use crate::{IpNetworkError, IpNetworkParseError};
7use crate::helpers;
8use crate::iterator;
9use std::collections::HashMap;
10use std::collections::hash_map::Entry;
11
12/// IPv4 Network.
13#[derive(Clone, Copy, Debug, Eq, PartialOrd, Ord)]
14pub struct Ipv4Network {
15 pub(crate) network_address: Ipv4Addr,
16 pub(crate) netmask: u8,
17}
18
19impl Ipv4Network {
20 /// IPv4 address length in bits.
21 pub const LENGTH: u8 = 32;
22
23 /// Default route that contains all IP addresses, IP network 0.0.0.0/0
24 pub const DEFAULT_ROUTE: Self = Self {
25 network_address: Ipv4Addr::UNSPECIFIED,
26 netmask: 0,
27 };
28
29 /// Constructs new `Ipv4Network` based on [`Ipv4Addr`] and `netmask`.
30 ///
31 /// Returns error if netmask is bigger than 32 or if host bits are set in `network_address`.
32 ///
33 /// [`Ipv4Addr`]: https://doc.rust-lang.org/std/net/struct.Ipv4Addr.html
34 ///
35 /// # Examples
36 ///
37 /// ```
38 /// use std::net::Ipv4Addr;
39 /// use ip_network::Ipv4Network;
40 ///
41 /// let ip_network = Ipv4Network::new(Ipv4Addr::new(192, 168, 1, 0), 24)?;
42 /// assert_eq!(ip_network.network_address(), Ipv4Addr::new(192, 168, 1, 0));
43 /// assert_eq!(ip_network.netmask(), 24);
44 /// # Ok::<(), ip_network::IpNetworkError>(())
45 /// ```
46 #[allow(clippy::new_ret_no_self)]
47 pub fn new(network_address: Ipv4Addr, netmask: u8) -> Result<Self, IpNetworkError> {
48 if netmask > Self::LENGTH {
49 return Err(IpNetworkError::NetmaskError(netmask));
50 }
51
52 if u32::from(network_address).trailing_zeros() < u32::from(Self::LENGTH - netmask) {
53 return Err(IpNetworkError::HostBitsSet);
54 }
55
56 Ok(Self {
57 network_address,
58 netmask,
59 })
60 }
61
62 /// Constructs new `Ipv4Network` based on [`Ipv4Addr`] and `netmask` with truncating host bits
63 /// from given `network_address`.
64 ///
65 /// Returns error if netmask is bigger than 32.
66 ///
67 /// [`Ipv4Addr`]: https://doc.rust-lang.org/std/net/struct.Ipv4Addr.html
68 ///
69 /// # Examples
70 ///
71 /// ```
72 /// use std::net::Ipv4Addr;
73 /// use ip_network::Ipv4Network;
74 ///
75 /// let ip_network = Ipv4Network::new_truncate(Ipv4Addr::new(192, 168, 1, 100), 24)?;
76 /// assert_eq!(ip_network.network_address(), Ipv4Addr::new(192, 168, 1, 0));
77 /// assert_eq!(ip_network.netmask(), 24);
78 /// # Ok::<(), ip_network::IpNetworkError>(())
79 /// ```
80 pub fn new_truncate(network_address: Ipv4Addr, netmask: u8) -> Result<Self, IpNetworkError> {
81 if netmask > Self::LENGTH {
82 return Err(IpNetworkError::NetmaskError(netmask));
83 }
84
85 let network_address =
86 Ipv4Addr::from(u32::from(network_address) & helpers::bite_mask(netmask));
87
88 Ok(Self {
89 network_address,
90 netmask,
91 })
92 }
93
94 /// Returns network IP address (first address in range).
95 ///
96 /// # Examples
97 ///
98 /// ```
99 /// use std::net::Ipv4Addr;
100 /// use ip_network::Ipv4Network;
101 ///
102 /// let ip_network = Ipv4Network::new(Ipv4Addr::new(192, 168, 1, 0), 24)?;
103 /// assert_eq!(ip_network.network_address(), Ipv4Addr::new(192, 168, 1, 0));
104 /// # Ok::<(), ip_network::IpNetworkError>(())
105 /// ```
106 #[inline]
107 pub fn network_address(&self) -> Ipv4Addr {
108 self.network_address
109 }
110
111 /// Returns broadcast address of network (last address in range).
112 ///
113 /// # Examples
114 ///
115 /// ```
116 /// use std::net::Ipv4Addr;
117 /// use ip_network::Ipv4Network;
118 ///
119 /// let ip_network = Ipv4Network::new(Ipv4Addr::new(192, 168, 1, 0), 24)?;
120 /// assert_eq!(ip_network.broadcast_address(), Ipv4Addr::new(192, 168, 1, 255));
121 /// # Ok::<(), ip_network::IpNetworkError>(())
122 /// ```
123 pub fn broadcast_address(&self) -> Ipv4Addr {
124 Ipv4Addr::from(u32::from(self.network_address) | !helpers::bite_mask(self.netmask))
125 }
126
127 /// Returns network mask as integer.
128 ///
129 /// # Examples
130 ///
131 /// ```
132 /// use std::net::Ipv4Addr;
133 /// use ip_network::Ipv4Network;
134 ///
135 /// let ip_network = Ipv4Network::new(Ipv4Addr::new(192, 168, 1, 0), 24)?;
136 /// assert_eq!(ip_network.netmask(), 24);
137 /// # Ok::<(), ip_network::IpNetworkError>(())
138 /// ```
139 #[inline]
140 pub fn netmask(&self) -> u8 {
141 self.netmask
142 }
143
144 /// Returns network mask as IPv4 address.
145 ///
146 /// # Examples
147 ///
148 /// ```
149 /// use std::net::Ipv4Addr;
150 /// use ip_network::Ipv4Network;
151 ///
152 /// let ip_network = Ipv4Network::new(Ipv4Addr::new(192, 168, 1, 0), 24)?;
153 /// assert_eq!(ip_network.full_netmask(), Ipv4Addr::new(255, 255, 255, 0));
154 /// # Ok::<(), ip_network::IpNetworkError>(())
155 /// ```
156 pub fn full_netmask(&self) -> Ipv4Addr {
157 Ipv4Addr::from(helpers::bite_mask(self.netmask))
158 }
159
160 /// Returns [`true`] if given [`IPv4Addr`] is inside this network.
161 ///
162 /// [`true`]: https://doc.rust-lang.org/std/primitive.bool.html
163 /// [`Ipv4Addr`]: https://doc.rust-lang.org/std/net/struct.Ipv4Addr.html
164 ///
165 /// # Examples
166 ///
167 /// ```
168 /// use std::net::Ipv4Addr;
169 /// use ip_network::Ipv4Network;
170 ///
171 /// let ip_network = Ipv4Network::new(Ipv4Addr::new(192, 168, 1, 0), 24)?;
172 /// assert!(ip_network.contains(Ipv4Addr::new(192, 168, 1, 2)));
173 /// assert!(!ip_network.contains(Ipv4Addr::new(192, 168, 2, 2)));
174 /// # Ok::<(), ip_network::IpNetworkError>(())
175 /// ```
176 pub fn contains(&self, ip: Ipv4Addr) -> bool {
177 u32::from(ip) & helpers::bite_mask(self.netmask) == u32::from(self.network_address)
178 }
179
180 /// Returns iterator over host IP addresses in range (without network and broadcast address). You
181 /// can also use this method to check how much hosts address are in range by calling [`len()`] method
182 /// on iterator (see Examples).
183 ///
184 /// [`len()`]: https://doc.rust-lang.org/std/iter/trait.ExactSizeIterator.html#method.len
185 ///
186 /// # Examples
187 ///
188 /// ```
189 /// use std::net::Ipv4Addr;
190 /// use ip_network::Ipv4Network;
191 ///
192 /// let ip = Ipv4Addr::new(192, 168, 1, 0);
193 /// let mut hosts = Ipv4Network::new(ip, 24)?.hosts();
194 /// assert_eq!(254, hosts.len());
195 /// assert_eq!(hosts.next().unwrap(), Ipv4Addr::new(192, 168, 1, 1));
196 /// assert_eq!(hosts.last().unwrap(), Ipv4Addr::new(192, 168, 1, 254));
197 /// # Ok::<(), ip_network::IpNetworkError>(())
198 /// ```
199 pub fn hosts(&self) -> impl ExactSizeIterator<Item = Ipv4Addr> {
200 iterator::Ipv4RangeIterator::hosts(*self)
201 }
202
203 /// Returns network with smaller netmask by one. If netmask is already zero, `None` will be returned.
204 ///
205 /// # Examples
206 ///
207 /// ```
208 /// use std::net::Ipv4Addr;
209 /// use ip_network::Ipv4Network;
210 ///
211 /// let ip = Ipv4Addr::new(192, 168, 1, 0);
212 /// let mut hosts = Ipv4Network::new(ip, 24)?;
213 /// assert_eq!(hosts.supernet(), Some(Ipv4Network::new(Ipv4Addr::new(192, 168, 0, 0), 23)?));
214 /// # Ok::<(), ip_network::IpNetworkError>(())
215 /// ```
216 pub fn supernet(&self) -> Option<Self> {
217 if self.netmask == 0 {
218 None
219 } else {
220 Some(Self::new_truncate(self.network_address, self.netmask - 1).unwrap())
221 }
222 }
223
224 /// Returns iterator over networks with bigger netmask by one. If netmask is already 32,
225 /// iterator is empty.
226 ///
227 /// # Examples
228 ///
229 /// ```
230 /// use std::net::Ipv4Addr;
231 /// use ip_network::Ipv4Network;
232 ///
233 /// let ip_network = Ipv4Network::new(Ipv4Addr::new(192, 168, 1, 0), 24)?;
234 /// let mut iterator = ip_network.subnets();
235 /// assert_eq!(iterator.next().unwrap(), Ipv4Network::new(Ipv4Addr::new(192, 168, 1, 0), 25)?);
236 /// assert_eq!(iterator.last().unwrap(), Ipv4Network::new(Ipv4Addr::new(192, 168, 1, 128), 25)?);
237 /// # Ok::<(), ip_network::IpNetworkError>(())
238 /// ```
239 pub fn subnets(&self) -> impl ExactSizeIterator<Item = Ipv4Network> {
240 let new_netmask = cmp::min(self.netmask + 1, Self::LENGTH);
241 iterator::Ipv4NetworkIterator::new(*self, new_netmask)
242 }
243
244 /// Returns `Ipv4NetworkIterator` over networks with defined netmask.
245 ///
246 /// # Panics
247 ///
248 /// This method panics when prefix is bigger than 32 or when prefix is lower or equal than netmask.
249 ///
250 /// # Examples
251 ///
252 /// ```
253 /// use std::net::Ipv4Addr;
254 /// use ip_network::Ipv4Network;
255 ///
256 /// let ip = Ipv4Addr::new(192, 168, 1, 0);
257 /// let mut iterator = Ipv4Network::new(ip, 24)?.subnets_with_prefix(25);
258 /// assert_eq!(iterator.next().unwrap(), Ipv4Network::new(Ipv4Addr::new(192, 168, 1, 0), 25)?);
259 /// assert_eq!(iterator.last().unwrap(), Ipv4Network::new(Ipv4Addr::new(192, 168, 1, 128), 25)?);
260 /// # Ok::<(), ip_network::IpNetworkError>(())
261 /// ```
262 pub fn subnets_with_prefix(&self, prefix: u8) -> impl ExactSizeIterator<Item = Ipv4Network> {
263 iterator::Ipv4NetworkIterator::new(*self, prefix)
264 }
265
266 /// Returns [`true`] for the default route network (0.0.0.0/0), that contains all IPv4 addresses.
267 ///
268 /// [`true`]: https://doc.rust-lang.org/std/primitive.bool.html
269 ///
270 /// # Examples
271 ///
272 /// ```
273 /// use std::net::Ipv4Addr;
274 /// use ip_network::Ipv4Network;
275 ///
276 /// assert!(Ipv4Network::new(Ipv4Addr::new(0, 0, 0, 0), 0)?.is_default_route());
277 /// # Ok::<(), ip_network::IpNetworkError>(())
278 /// ```
279 pub fn is_default_route(&self) -> bool {
280 self.netmask == 0
281 }
282
283 /// Returns [`true`] for network in local identification range (0.0.0.0/8).
284 ///
285 /// This property is defined by [IETF RFC 1122].
286 ///
287 /// [IETF RFC 1122]: https://tools.ietf.org/html/rfc1122
288 /// [`true`]: https://doc.rust-lang.org/std/primitive.bool.html
289 ///
290 /// # Examples
291 ///
292 /// ```
293 /// use std::net::Ipv4Addr;
294 /// use ip_network::Ipv4Network;
295 ///
296 /// assert!(Ipv4Network::new(Ipv4Addr::new(0, 0, 0, 0), 8)?.is_local_identification());
297 /// # Ok::<(), ip_network::IpNetworkError>(())
298 /// ```
299 pub fn is_local_identification(&self) -> bool {
300 self.network_address.octets()[0] == 0 && self.netmask >= 8
301 }
302
303 /// Returns [`true`] for the special 'unspecified' network (0.0.0.0/32).
304 ///
305 /// This property is defined in _UNIX Network Programming, Second Edition_,
306 /// W. Richard Stevens, p. 891; see also [ip7].
307 ///
308 /// [ip7]: http://man7.org/linux/man-pages/man7/ip.7.html
309 /// [`true`]: https://doc.rust-lang.org/std/primitive.bool.html
310 ///
311 /// # Examples
312 ///
313 /// ```
314 /// use std::net::Ipv4Addr;
315 /// use ip_network::Ipv4Network;
316 ///
317 /// assert!(Ipv4Network::new(Ipv4Addr::new(0, 0, 0, 0), 32)?.is_unspecified());
318 /// # Ok::<(), ip_network::IpNetworkError>(())
319 /// ```
320 pub fn is_unspecified(&self) -> bool {
321 self.netmask == Self::LENGTH && self.network_address.is_unspecified()
322 }
323
324 /// Returns [`true`] if this network is inside loopback address range (127.0.0.0/8).
325 ///
326 /// This property is defined by [IETF RFC 1122].
327 ///
328 /// [IETF RFC 1122]: https://tools.ietf.org/html/rfc1122
329 /// [`true`]: https://doc.rust-lang.org/std/primitive.bool.html
330 ///
331 /// # Examples
332 ///
333 /// ```
334 /// use std::net::Ipv4Addr;
335 /// use ip_network::Ipv4Network;
336 ///
337 /// assert!(Ipv4Network::new(Ipv4Addr::new(127, 0, 0, 0), 8)?.is_loopback());
338 /// # Ok::<(), ip_network::IpNetworkError>(())
339 /// ```
340 pub fn is_loopback(&self) -> bool {
341 self.network_address.is_loopback()
342 }
343
344 /// Returns [`true`] if this is a broadcast network (255.255.255.255/32).
345 ///
346 /// A broadcast address has all octets set to 255 as defined in [IETF RFC 919].
347 ///
348 /// [IETF RFC 919]: https://tools.ietf.org/html/rfc919
349 /// [`true`]: https://doc.rust-lang.org/std/primitive.bool.html
350 ///
351 /// # Examples
352 ///
353 /// ```
354 /// use std::net::Ipv4Addr;
355 /// use ip_network::Ipv4Network;
356 ///
357 /// assert!(Ipv4Network::new(Ipv4Addr::new(255, 255, 255, 255), 32)?.is_broadcast());
358 /// # Ok::<(), ip_network::IpNetworkError>(())
359 /// ```
360 pub fn is_broadcast(&self) -> bool {
361 self.network_address.is_broadcast()
362 }
363
364 /// Returns [`true`] if this whole network range is inside private address ranges.
365 ///
366 /// The private address ranges are defined in [IETF RFC 1918] and include:
367 ///
368 /// - 10.0.0.0/8
369 /// - 172.16.0.0/12
370 /// - 192.168.0.0/16
371 ///
372 /// [IETF RFC 1918]: https://tools.ietf.org/html/rfc1918
373 /// [`true`]: https://doc.rust-lang.org/std/primitive.bool.html
374 ///
375 /// # Examples
376 ///
377 /// ```
378 /// use std::net::Ipv4Addr;
379 /// use ip_network::Ipv4Network;
380 ///
381 /// assert!(Ipv4Network::new(Ipv4Addr::new(192, 168, 1, 0), 24)?.is_private());
382 /// # Ok::<(), ip_network::IpNetworkError>(())
383 /// ```
384 pub fn is_private(&self) -> bool {
385 let octets = self.network_address.octets();
386 match octets[0] {
387 10 if self.netmask >= 8 => true,
388 172 if octets[1] >= 16 && octets[1] <= 31 && self.netmask >= 12 => true,
389 192 if octets[1] == 168 && self.netmask >= 16 => true,
390 _ => false,
391 }
392 }
393
394 /// Returns [`true`] if this whole network is inside IETF Protocol Assignments range (192.0.0.0/24).
395 ///
396 /// This property is defined by [IETF RFC 6890, Section 2.1].
397 ///
398 /// [IETF RFC 6890, Section 2.1]: https://tools.ietf.org/html/rfc6890#section-2.1
399 /// [`true`]: https://doc.rust-lang.org/std/primitive.bool.html
400 ///
401 /// # Examples
402 ///
403 /// ```
404 /// use std::net::Ipv4Addr;
405 /// use ip_network::Ipv4Network;
406 ///
407 /// assert!(Ipv4Network::new(Ipv4Addr::new(192, 0, 0, 0), 24)?.is_ietf_protocol_assignments());
408 /// # Ok::<(), ip_network::IpNetworkError>(())
409 /// ```
410 pub fn is_ietf_protocol_assignments(&self) -> bool {
411 let octets = self.network_address.octets();
412 octets[0] == 192 && octets[1] == 0 && octets[2] == 0 && self.netmask >= 24
413 }
414
415 /// Returns [`true`] if this whole network is inside Shared Address Space (100.64.0.0/10).
416 ///
417 /// This property is defined by [IETF RFC 6598].
418 ///
419 /// [IETF RFC 6598]: https://tools.ietf.org/html/rfc6598
420 /// [`true`]: https://doc.rust-lang.org/std/primitive.bool.html
421 ///
422 /// # Examples
423 ///
424 /// ```
425 /// use std::net::Ipv4Addr;
426 /// use ip_network::Ipv4Network;
427 ///
428 /// assert!(Ipv4Network::new(Ipv4Addr::new(100, 64, 0, 0), 10)?.is_shared_address_space());
429 /// # Ok::<(), ip_network::IpNetworkError>(())
430 /// ```
431 pub fn is_shared_address_space(&self) -> bool {
432 let octets = self.network_address.octets();
433 octets[0] == 100 && octets[1] & 0xc0 == 64
434 }
435
436 /// Returns [`true`] if the network is is inside link-local range (169.254.0.0/16).
437 ///
438 /// This property is defined by [IETF RFC 3927].
439 ///
440 /// [IETF RFC 3927]: https://tools.ietf.org/html/rfc3927
441 /// [`true`]: https://doc.rust-lang.org/std/primitive.bool.html
442 ///
443 /// # Examples
444 ///
445 /// ```
446 /// use std::net::Ipv4Addr;
447 /// use ip_network::Ipv4Network;
448 ///
449 /// assert!(Ipv4Network::new(Ipv4Addr::new(169, 254, 1, 0), 24)?.is_link_local());
450 /// # Ok::<(), ip_network::IpNetworkError>(())
451 /// ```
452 pub fn is_link_local(&self) -> bool {
453 self.network_address.is_link_local() && self.netmask >= 16
454 }
455
456 /// Returns [`true`] if this whole network is inside multicast address range (224.0.0.0/4).
457 ///
458 /// Multicast network addresses have a most significant octet between 224 and 239,
459 /// and is defined by [IETF RFC 5771].
460 ///
461 /// [IETF RFC 5771]: https://tools.ietf.org/html/rfc5771
462 /// [`true`]: https://doc.rust-lang.org/std/primitive.bool.html
463 ///
464 /// # Examples
465 ///
466 /// ```
467 /// use std::net::Ipv4Addr;
468 /// use ip_network::Ipv4Network;
469 ///
470 /// assert!(Ipv4Network::new(Ipv4Addr::new(224, 168, 1, 0), 24)?.is_multicast());
471 /// # Ok::<(), ip_network::IpNetworkError>(())
472 /// ```
473 pub fn is_multicast(&self) -> bool {
474 self.network_address.octets()[0] & 0xf0 == 224 && self.netmask >= 4
475 }
476
477 /// Returns [`true`] if this whole network is inside benchmarking address range (198.18.0.0/15).
478 ///
479 /// This property is defined by [IETF RFC 2544].
480 ///
481 /// [IETF RFC 2544]: https://tools.ietf.org/html/rfc2544
482 /// [`true`]: https://doc.rust-lang.org/std/primitive.bool.html
483 ///
484 /// # Examples
485 ///
486 /// ```
487 /// use std::net::Ipv4Addr;
488 /// use ip_network::Ipv4Network;
489 ///
490 /// assert!(Ipv4Network::new(Ipv4Addr::new(198, 19, 1, 0), 24)?.is_benchmarking());
491 /// # Ok::<(), ip_network::IpNetworkError>(())
492 /// ```
493 pub fn is_benchmarking(&self) -> bool {
494 // Not necessary to check netmask
495 let octets = self.network_address.octets();
496 octets[0] == 198 && octets[1] & 0xfe == 18
497 }
498
499 /// Returns [`true`] if this whole network is inside reserved address range (240.0.0.0/4), except
500 /// broadcast address (255.255.255.255/32).
501 ///
502 /// Reserved network addresses have a most significant octet between 240 and 255,
503 /// and is defined by [IETF RFC 1112].
504 ///
505 /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112
506 /// [`true`]: https://doc.rust-lang.org/std/primitive.bool.html
507 ///
508 /// # Examples
509 ///
510 /// ```
511 /// use std::net::Ipv4Addr;
512 /// use ip_network::Ipv4Network;
513 ///
514 /// assert!(Ipv4Network::new(Ipv4Addr::new(240, 168, 1, 0), 24)?.is_reserved());
515 /// assert!(!Ipv4Network::new(Ipv4Addr::new(255, 255, 255, 255), 32)?.is_reserved());
516 /// # Ok::<(), ip_network::IpNetworkError>(())
517 /// ```
518 pub fn is_reserved(&self) -> bool {
519 // Not necessary to check netmask
520 self.network_address.octets()[0] & 0xf0 == 240 && !self.network_address.is_broadcast()
521 }
522
523 /// Returns [`true`] if this network is in a range designated for documentation.
524 ///
525 /// This is defined in [IETF RFC 5737]:
526 ///
527 /// - 192.0.2.0/24 (TEST-NET-1)
528 /// - 198.51.100.0/24 (TEST-NET-2)
529 /// - 203.0.113.0/24 (TEST-NET-3)
530 ///
531 /// [IETF RFC 5737]: https://tools.ietf.org/html/rfc5737
532 /// [`true`]: https://doc.rust-lang.org/std/primitive.bool.html
533 ///
534 /// # Examples
535 ///
536 /// ```
537 /// use std::net::Ipv4Addr;
538 /// use ip_network::Ipv4Network;
539 ///
540 /// assert!(Ipv4Network::new(Ipv4Addr::new(192, 0, 2, 0), 24)?.is_documentation());
541 /// # Ok::<(), ip_network::IpNetworkError>(())
542 /// ```
543 pub fn is_documentation(&self) -> bool {
544 self.network_address.is_documentation() && self.netmask >= 24
545 }
546
547 /// Returns [`true`] if the network appears to be globally routable.
548 /// See [IANA IPv4 Special-Purpose Address Registry][ipv4-sr].
549 ///
550 /// The following return [`false`]:
551 ///
552 /// - local identification (0.0.0.0/8)
553 /// - private address (10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16)
554 /// - Shared Address Space (100.64.0.0/10)
555 /// - the loopback address (127.0.0.0/8)
556 /// - the link-local address (169.254.0.0/16)
557 /// - IETF Protocol Assignments (192.0.0.0/24, except 192.0.0.9/32 and 192.0.0.10/32)
558 /// - the broadcast address (255.255.255.255/32)
559 /// - test addresses used for documentation (192.0.2.0/24, 198.51.100.0/24 and 203.0.113.0/24)
560 /// - benchmarking (198.18.0.0/15)
561 /// - reserved range (240.0.0.0/4)
562 ///
563 /// [ipv4-sr]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
564 /// [`true`]: https://doc.rust-lang.org/std/primitive.bool.html
565 /// [`false`]: https://doc.rust-lang.org/std/primitive.bool.html
566 ///
567 /// # Examples
568 ///
569 /// ```
570 /// use std::net::Ipv4Addr;
571 /// use ip_network::Ipv4Network;
572 ///
573 /// assert!(!Ipv4Network::new(Ipv4Addr::new(10, 254, 0, 0), 16)?.is_global());
574 /// assert!(!Ipv4Network::new(Ipv4Addr::new(192, 168, 10, 65), 32)?.is_global());
575 /// assert!(!Ipv4Network::new(Ipv4Addr::new(172, 16, 10, 65), 32)?.is_global());
576 /// assert!(!Ipv4Network::new(Ipv4Addr::new(0, 0, 0, 0), 32)?.is_global());
577 /// assert!(Ipv4Network::new(Ipv4Addr::new(80, 9, 12, 3), 32)?.is_global());
578 /// # Ok::<(), ip_network::IpNetworkError>(())
579 /// ```
580 pub fn is_global(&self) -> bool {
581 let octets = self.network_address.octets();
582 // These address are only two globally routable from IETF Protocol Assignments.
583 if self.netmask == 32 && (octets == [192, 0, 0, 9] || octets == [192, 0, 0, 10]) {
584 return true;
585 }
586
587 !self.is_local_identification()
588 && !self.is_private()
589 && !self.is_ietf_protocol_assignments()
590 && !self.is_shared_address_space()
591 && !self.is_loopback()
592 && !self.is_link_local()
593 && !self.is_broadcast()
594 && !self.is_documentation()
595 && !self.is_benchmarking()
596 && !self.is_reserved()
597 }
598
599 /// Return a vector of the summarized network range given the first and last IPv4 addresses.
600 /// Implementation of this method was inspired by Python [`ipaddress.summarize_address_range`]
601 /// method. If first IP address is bigger than last, empty vector is returned.
602 ///
603 /// [`ipaddress.summarize_address_range`]: https://docs.python.org/3/library/ipaddress.html#ipaddress.summarize_address_range
604 ///
605 /// # Examples
606 ///
607 /// ```
608 /// use std::net::Ipv4Addr;
609 /// use ip_network::Ipv4Network;
610 ///
611 /// let ranges = Ipv4Network::summarize_address_range(
612 /// Ipv4Addr::new(10, 254, 0, 0),
613 /// Ipv4Addr::new(10, 255, 255, 255),
614 /// );
615 ///
616 /// assert_eq!(Ipv4Network::new(Ipv4Addr::new(10, 254, 0, 0), 15)?, ranges[0]);
617 /// # Ok::<(), ip_network::IpNetworkError>(())
618 /// ```
619 pub fn summarize_address_range(first: Ipv4Addr, last: Ipv4Addr) -> Vec<Self> {
620 let mut first_int = u32::from(first);
621 let last_int = u32::from(last);
622
623 let mut vector = vec![];
624
625 while first_int <= last_int {
626 let bit_length_diff = if last_int - first_int == u32::MAX {
627 Self::LENGTH
628 } else {
629 helpers::bit_length(last_int - first_int + 1) - 1
630 };
631
632 let nbits = cmp::min(first_int.trailing_zeros() as u8, bit_length_diff);
633
634 vector.push(Self {
635 network_address: Ipv4Addr::from(first_int),
636 netmask: Self::LENGTH - nbits,
637 });
638
639 if nbits == Self::LENGTH {
640 break;
641 }
642
643 match first_int.checked_add(1 << nbits) {
644 Some(x) => first_int = x,
645 None => break,
646 }
647 }
648
649 vector
650 }
651
652 /// Return an iterator of the collapsed Ipv4Networks.
653 ///
654 /// Implementation of this method was inspired by Python [`ipaddress.collapse_addresses`]
655 ///
656 /// [`ipaddress.collapse_addresses`]: https://docs.python.org/3/library/ipaddress.html#ipaddress.collapse_addresses
657 ///
658 /// # Examples
659 ///
660 /// ```
661 /// use std::net::Ipv4Addr;
662 /// use ip_network::Ipv4Network;
663 ///
664 /// let collapsed = Ipv4Network::collapse_addresses(&[
665 /// Ipv4Network::new(Ipv4Addr::new(192, 0, 2, 0), 25)?,
666 /// Ipv4Network::new(Ipv4Addr::new(192, 0, 2, 128), 25)?,
667 /// ]);
668 ///
669 /// assert_eq!(Ipv4Network::new(Ipv4Addr::new(192, 0, 2, 0), 24)?, collapsed[0]);
670 /// # Ok::<(), ip_network::IpNetworkError>(())
671 /// ```
672 pub fn collapse_addresses(addresses: &[Self]) -> Vec<Self> {
673 let mut subnets = HashMap::new();
674
675 let mut to_merge = addresses.to_vec();
676 while let Some(net) = to_merge.pop() {
677 let supernet = net.supernet().unwrap_or(Ipv4Network::DEFAULT_ROUTE);
678 match subnets.entry(supernet) {
679 Entry::Vacant(vacant) => {
680 vacant.insert(net);
681 }
682 Entry::Occupied(occupied) => {
683 if *occupied.get() != net {
684 occupied.remove();
685 to_merge.push(supernet);
686 }
687 }
688 }
689 }
690
691 let mut output: Vec<Ipv4Network> = vec![];
692 let mut values = subnets.values().collect::<Vec<_>>();
693 values.sort_unstable();
694
695 for net in values {
696 if let Some(last) = output.last() {
697 // Since they are sorted, last.network_address <= net.network_address is a given.
698 if last.broadcast_address() >= net.broadcast_address() {
699 continue;
700 }
701 }
702 output.push(*net);
703 }
704 output
705 }
706
707 /// Converts string in format X.X.X.X/Y (CIDR notation) to `Ipv4Network`, but truncating host bits.
708 ///
709 /// # Examples
710 ///
711 /// ```
712 /// use std::net::Ipv4Addr;
713 /// use ip_network::Ipv4Network;
714 ///
715 /// let ip_network = Ipv4Network::from_str_truncate("192.168.1.255/24")?;
716 /// assert_eq!(ip_network.network_address(), Ipv4Addr::new(192, 168, 1, 0));
717 /// assert_eq!(ip_network.netmask(), 24);
718 /// # Ok::<(), ip_network::IpNetworkParseError>(())
719 /// ```
720 pub fn from_str_truncate(s: &str) -> Result<Self, IpNetworkParseError> {
721 let (ip, netmask) =
722 helpers::split_ip_netmask(s).ok_or(IpNetworkParseError::InvalidFormatError)?;
723
724 let network_address =
725 Ipv4Addr::from_str(ip).map_err(|_| IpNetworkParseError::AddrParseError)?;
726 let netmask =
727 u8::from_str(netmask).map_err(|_| IpNetworkParseError::InvalidNetmaskFormat)?;
728
729 Self::new_truncate(network_address, netmask).map_err(IpNetworkParseError::IpNetworkError)
730 }
731}
732
733impl fmt::Display for Ipv4Network {
734 /// Converts `Ipv4Network` to string in format X.X.X.X/Y (CIDR notation).
735 ///
736 /// # Examples
737 ///
738 /// ```
739 /// use std::net::Ipv4Addr;
740 /// use ip_network::Ipv4Network;
741 ///
742 /// assert_eq!(Ipv4Network::new(Ipv4Addr::new(192, 168, 1, 0), 24)?.to_string(), "192.168.1.0/24");
743 /// # Ok::<(), ip_network::IpNetworkError>(())
744 /// ```
745 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
746 write!(fmt, "{}/{}", self.network_address, self.netmask)
747 }
748}
749
750impl FromStr for Ipv4Network {
751 type Err = IpNetworkParseError;
752
753 /// Converts string in format X.X.X.X/Y (CIDR notation) to `Ipv4Network`.
754 ///
755 /// # Examples
756 ///
757 /// ```
758 /// use std::net::Ipv4Addr;
759 /// use ip_network::Ipv4Network;
760 /// use std::str::FromStr;
761 ///
762 /// let ip_network = Ipv4Network::from_str("192.168.1.0/24")?;
763 /// assert_eq!(ip_network.network_address(), Ipv4Addr::new(192, 168, 1, 0));
764 /// assert_eq!(ip_network.netmask(), 24);
765 /// # Ok::<(), ip_network::IpNetworkParseError>(())
766 /// ```
767 fn from_str(s: &str) -> Result<Ipv4Network, IpNetworkParseError> {
768 let (ip, netmask) =
769 helpers::split_ip_netmask(s).ok_or(IpNetworkParseError::InvalidFormatError)?;
770
771 let network_address =
772 Ipv4Addr::from_str(ip).map_err(|_| IpNetworkParseError::AddrParseError)?;
773 let netmask =
774 u8::from_str(netmask).map_err(|_| IpNetworkParseError::InvalidNetmaskFormat)?;
775
776 Self::new(network_address, netmask).map_err(IpNetworkParseError::IpNetworkError)
777 }
778}
779
780impl From<Ipv4Addr> for Ipv4Network {
781 /// Converts `Ipv4Addr` to `Ipv4Network` with netmask 32.
782 #[inline]
783 fn from(ip: Ipv4Addr) -> Self {
784 Self {
785 network_address: ip,
786 netmask: Self::LENGTH,
787 }
788 }
789}
790
791impl PartialEq for Ipv4Network {
792 #[inline]
793 fn eq(&self, other: &Ipv4Network) -> bool {
794 self.netmask == other.netmask && self.network_address == other.network_address
795 }
796}
797
798impl Hash for Ipv4Network {
799 fn hash<H: Hasher>(&self, state: &mut H) {
800 self.network_address.hash(state);
801 self.netmask.hash(state);
802 }
803}
804
805impl IntoIterator for Ipv4Network {
806 type Item = Ipv4Addr;
807 type IntoIter = iterator::Ipv4RangeIterator;
808
809 /// Returns iterator over all IP addresses in range including network and broadcast addresses.
810 ///
811 /// # Examples
812 ///
813 /// ```
814 /// use std::net::Ipv4Addr;
815 /// use ip_network::Ipv4Network;
816 ///
817 /// let ip = Ipv4Addr::new(192, 168, 1, 0);
818 /// let mut iter = Ipv4Network::new(ip, 24)?.into_iter();
819 /// assert_eq!(iter.next().unwrap(), Ipv4Addr::new(192, 168, 1, 0));
820 /// assert_eq!(iter.next().unwrap(), Ipv4Addr::new(192, 168, 1, 1));
821 /// assert_eq!(iter.last().unwrap(), Ipv4Addr::new(192, 168, 1, 255));
822 /// # Ok::<(), ip_network::IpNetworkError>(())
823 /// ```
824 fn into_iter(self) -> Self::IntoIter {
825 Self::IntoIter::new(self.network_address, self.broadcast_address())
826 }
827}
828
829#[cfg(test)]
830mod tests {
831 use std::net::Ipv4Addr;
832 use crate::{IpNetworkError, Ipv4Network};
833 use std::str::FromStr;
834 use std::collections::hash_map::DefaultHasher;
835 use std::hash::{Hash, Hasher};
836
837 fn return_test_ipv4_network() -> Ipv4Network {
838 Ipv4Network::new(Ipv4Addr::new(192, 168, 0, 0), 16).unwrap()
839 }
840
841 #[test]
842 fn default_route() {
843 let network = Ipv4Network::DEFAULT_ROUTE;
844 assert!(network.is_default_route());
845 }
846
847 #[test]
848 fn new_host_bits_set() {
849 let ip = Ipv4Addr::new(127, 0, 0, 1);
850 let ip_network = Ipv4Network::new(ip, 8);
851 assert!(ip_network.is_err());
852 assert_eq!(IpNetworkError::HostBitsSet, ip_network.unwrap_err());
853 }
854
855 #[test]
856 fn new_host_bits_set_no_31() {
857 let ip = Ipv4Addr::new(127, 0, 0, 2);
858 let ip_network = Ipv4Network::new(ip, 31);
859 assert!(ip_network.is_ok());
860 }
861
862 #[test]
863 fn new_host_bits_set_no_32() {
864 let ip = Ipv4Addr::new(127, 0, 0, 1);
865 let ip_network = Ipv4Network::new(ip, 32);
866 assert!(ip_network.is_ok());
867 }
868
869 #[test]
870 fn new_host_bits_set_no_zero() {
871 let ip = Ipv4Addr::new(0, 0, 0, 0);
872 let ip_network = Ipv4Network::new(ip, 0);
873 assert!(ip_network.is_ok());
874 }
875
876 #[test]
877 fn new_big_invalid_netmask() {
878 let ip = Ipv4Addr::new(127, 0, 0, 1);
879 let ip_network = Ipv4Network::new(ip, 33);
880 assert!(ip_network.is_err());
881 assert_eq!(IpNetworkError::NetmaskError(33), ip_network.unwrap_err());
882 }
883
884 #[test]
885 fn new_truncate_host_bits_set() {
886 let ip = Ipv4Addr::new(127, 0, 0, 1);
887 let ip_network = Ipv4Network::new_truncate(ip, 8).unwrap();
888 assert_eq!(ip_network.network_address(), Ipv4Addr::new(127, 0, 0, 0));
889 }
890
891 #[test]
892 fn new_truncate_big_invalid_netmask() {
893 let ip = Ipv4Addr::new(127, 0, 0, 1);
894 let ip_network = Ipv4Network::new_truncate(ip, 33);
895 assert!(ip_network.is_err());
896 assert_eq!(IpNetworkError::NetmaskError(33), ip_network.unwrap_err());
897 }
898
899 #[test]
900 fn basic_getters() {
901 let ip_network = return_test_ipv4_network();
902 assert_eq!(ip_network.network_address(), Ipv4Addr::new(192, 168, 0, 0));
903 assert_eq!(ip_network.netmask(), 16);
904 assert_eq!(
905 ip_network.broadcast_address(),
906 Ipv4Addr::new(192, 168, 255, 255)
907 );
908 assert_eq!(ip_network.full_netmask(), Ipv4Addr::new(255, 255, 0, 0));
909 assert_eq!(
910 ip_network.supernet(),
911 Some(Ipv4Network::new(Ipv4Addr::new(192, 168, 0, 0), 15).unwrap())
912 );
913 assert_eq!(ip_network.hosts().len(), 256 * 256 - 2);
914 }
915
916 #[test]
917 fn host_network_without_hosts() {
918 let ip = Ipv4Addr::new(127, 0, 0, 1);
919 let ip_network = Ipv4Network::new(ip, 32).unwrap();
920 assert_eq!(0, ip_network.hosts().len());
921 }
922
923 #[test]
924 fn supernet_none() {
925 let ipv4_network = Ipv4Network::new(Ipv4Addr::new(0, 0, 0, 0), 0).unwrap();
926 assert_eq!(None, ipv4_network.supernet());
927 }
928
929 #[test]
930 fn iterator() {
931 let ip_network = return_test_ipv4_network();
932 assert_eq!(ip_network.into_iter().len(), 256 * 256);
933 }
934
935 #[test]
936 fn iterator_for() {
937 let mut i = 0;
938 for _ in return_test_ipv4_network() {
939 i += 1;
940 }
941 assert_eq!(i, 256 * 256);
942 }
943
944 #[test]
945 fn contains() {
946 let ip_network = return_test_ipv4_network();
947 assert!(!ip_network.contains(Ipv4Addr::new(192, 167, 255, 255)));
948 assert!(ip_network.contains(Ipv4Addr::new(192, 168, 0, 0)));
949 assert!(ip_network.contains(Ipv4Addr::new(192, 168, 255, 255)));
950 assert!(!ip_network.contains(Ipv4Addr::new(192, 169, 0, 0)));
951 }
952
953 #[test]
954 fn subnets() {
955 let ip_network = return_test_ipv4_network();
956 let mut subnets = ip_network.subnets();
957 assert_eq!(subnets.len(), 2);
958 assert_eq!(
959 subnets.next().unwrap(),
960 Ipv4Network::new(Ipv4Addr::new(192, 168, 0, 0), 17).unwrap()
961 );
962 assert_eq!(
963 subnets.next().unwrap(),
964 Ipv4Network::new(Ipv4Addr::new(192, 168, 128, 0), 17).unwrap()
965 );
966 assert!(subnets.next().is_none());
967 }
968
969 #[test]
970 fn subnets_none() {
971 let ipv4_network = Ipv4Network::new(Ipv4Addr::new(0, 0, 0, 0), 32).unwrap();
972 assert_eq!(0, ipv4_network.subnets().len());
973 }
974
975 #[test]
976 fn subnets_with_prefix() {
977 let ip_network = return_test_ipv4_network();
978 let mut subnets = ip_network.subnets_with_prefix(18);
979 assert_eq!(subnets.len(), 4);
980 assert_eq!(
981 subnets.next().unwrap(),
982 Ipv4Network::new(Ipv4Addr::new(192, 168, 0, 0), 18).unwrap()
983 );
984 assert_eq!(
985 subnets.next().unwrap(),
986 Ipv4Network::new(Ipv4Addr::new(192, 168, 64, 0), 18).unwrap()
987 );
988 assert_eq!(
989 subnets.next().unwrap(),
990 Ipv4Network::new(Ipv4Addr::new(192, 168, 128, 0), 18).unwrap()
991 );
992 assert_eq!(
993 subnets.next().unwrap(),
994 Ipv4Network::new(Ipv4Addr::new(192, 168, 192, 0), 18).unwrap()
995 );
996 assert!(subnets.next().is_none());
997 }
998
999 #[test]
1000 fn parse() {
1001 let ip_network: Ipv4Network = "192.168.0.0/16".parse().unwrap();
1002 assert_eq!(ip_network, return_test_ipv4_network());
1003 }
1004
1005 #[test]
1006 fn format() {
1007 let ip_network = return_test_ipv4_network();
1008 assert_eq!(ip_network.to_string(), "192.168.0.0/16");
1009 }
1010
1011 #[test]
1012 fn cmd_different_ip() {
1013 let a = Ipv4Network::new(Ipv4Addr::new(127, 0, 0, 0), 8).unwrap();
1014 let b = Ipv4Network::new(Ipv4Addr::new(128, 0, 0, 0), 8).unwrap();
1015 assert!(b > a);
1016 }
1017
1018 #[test]
1019 fn cmd_different_netmask() {
1020 let a = Ipv4Network::new(Ipv4Addr::new(127, 0, 0, 0), 8).unwrap();
1021 let b = Ipv4Network::new(Ipv4Addr::new(127, 0, 0, 0), 16).unwrap();
1022 assert!(b > a);
1023 }
1024
1025 #[test]
1026 fn is_private() {
1027 let is_private = |ip, netmask| Ipv4Network::new(ip, netmask).unwrap().is_private();
1028
1029 assert!(is_private(Ipv4Addr::new(10, 0, 0, 0), 8));
1030 assert!(!is_private(Ipv4Addr::new(10, 0, 0, 0), 7));
1031 assert!(is_private(Ipv4Addr::new(10, 0, 0, 0), 32));
1032 assert!(!is_private(Ipv4Addr::new(11, 0, 0, 0), 32));
1033
1034 assert!(is_private(Ipv4Addr::new(172, 16, 0, 0), 12));
1035 assert!(is_private(Ipv4Addr::new(172, 16, 0, 0), 32));
1036 assert!(is_private(Ipv4Addr::new(172, 31, 255, 255), 32));
1037 assert!(!is_private(Ipv4Addr::new(172, 32, 0, 0), 32));
1038
1039 assert!(is_private(Ipv4Addr::new(192, 168, 0, 0), 16));
1040 assert!(is_private(Ipv4Addr::new(192, 168, 0, 0), 32));
1041 assert!(!is_private(Ipv4Addr::new(192, 168, 0, 0), 15));
1042 }
1043
1044 #[test]
1045 fn is_global() {
1046 let is_global = |ip, netmask| Ipv4Network::new(ip, netmask).unwrap().is_global();
1047
1048 assert!(is_global(Ipv4Addr::new(0, 0, 0, 0), 4));
1049 assert!(!is_global(Ipv4Addr::new(0, 0, 0, 0), 8));
1050 assert!(!is_global(Ipv4Addr::new(0, 0, 0, 0), 16));
1051
1052 assert!(!is_global(Ipv4Addr::new(100, 64, 0, 0), 10)); // Shared Address Space
1053 assert!(!is_global(Ipv4Addr::new(100, 127, 0, 0), 16)); // Shared Address Space
1054
1055 assert!(!is_global(Ipv4Addr::new(10, 0, 0, 0), 8));
1056 assert!(is_global(Ipv4Addr::new(10, 0, 0, 0), 7));
1057 assert!(!is_global(Ipv4Addr::new(10, 0, 0, 0), 32));
1058 assert!(is_global(Ipv4Addr::new(11, 0, 0, 0), 32));
1059
1060 assert!(!is_global(Ipv4Addr::new(172, 16, 0, 0), 12));
1061 assert!(!is_global(Ipv4Addr::new(172, 16, 0, 0), 32));
1062 assert!(!is_global(Ipv4Addr::new(172, 31, 255, 255), 32));
1063 assert!(is_global(Ipv4Addr::new(172, 32, 0, 0), 32));
1064
1065 assert!(!is_global(Ipv4Addr::new(192, 168, 0, 0), 16));
1066 assert!(!is_global(Ipv4Addr::new(192, 168, 0, 0), 32));
1067 assert!(is_global(Ipv4Addr::new(192, 168, 0, 0), 15));
1068
1069 assert!(!is_global(Ipv4Addr::new(127, 0, 0, 0), 8));
1070 assert!(!is_global(Ipv4Addr::new(169, 254, 0, 0), 16));
1071 assert!(!is_global(Ipv4Addr::new(255, 255, 255, 255), 32));
1072 assert!(!is_global(Ipv4Addr::new(192, 0, 2, 0), 24));
1073 assert!(!is_global(Ipv4Addr::new(198, 51, 100, 0), 24));
1074 assert!(!is_global(Ipv4Addr::new(203, 0, 113, 0), 24));
1075
1076 assert!(!is_global(Ipv4Addr::new(198, 18, 0, 0), 15)); // benchmarking
1077 assert!(!is_global(Ipv4Addr::new(198, 19, 0, 0), 16)); // benchmarking
1078
1079 assert!(!is_global(Ipv4Addr::new(240, 0, 0, 0), 4));
1080 assert!(!is_global(Ipv4Addr::new(240, 0, 0, 0), 8));
1081 assert!(!is_global(Ipv4Addr::new(255, 0, 0, 0), 8));
1082
1083 assert!(!is_global(Ipv4Addr::new(192, 0, 0, 0), 24)); // IETF Protocol Assignments
1084 }
1085
1086 #[test]
1087 fn hash_same_for_same_input() {
1088 use std::hash::{Hash, Hasher};
1089 use std::collections::hash_map::DefaultHasher;
1090
1091 let mut hasher = DefaultHasher::new();
1092 let ip = Ipv4Addr::new(127, 0, 0, 0);
1093 let network = Ipv4Network::new(ip, 8).unwrap();
1094 network.hash(&mut hasher);
1095 let first_hash = hasher.finish();
1096
1097 let mut hasher = DefaultHasher::new();
1098 let ip = Ipv4Addr::new(127, 0, 0, 0);
1099 let network = Ipv4Network::new(ip, 8).unwrap();
1100 network.hash(&mut hasher);
1101 let second_hash = hasher.finish();
1102
1103 assert_eq!(first_hash, second_hash);
1104 }
1105
1106 #[test]
1107 fn summarize_address_range() {
1108 let networks = Ipv4Network::summarize_address_range(
1109 Ipv4Addr::new(194, 249, 198, 0),
1110 Ipv4Addr::new(194, 249, 198, 159),
1111 );
1112 assert_eq!(networks.len(), 2);
1113 assert_eq!(
1114 networks[0],
1115 Ipv4Network::new(Ipv4Addr::new(194, 249, 198, 0), 25).unwrap()
1116 );
1117 assert_eq!(
1118 networks[1],
1119 Ipv4Network::new(Ipv4Addr::new(194, 249, 198, 128), 27).unwrap()
1120 );
1121 }
1122
1123 #[test]
1124 fn summarize_address_range_whole_range() {
1125 let networks = Ipv4Network::summarize_address_range(
1126 Ipv4Addr::new(0, 0, 0, 0),
1127 Ipv4Addr::new(255, 255, 255, 255),
1128 );
1129 assert_eq!(networks.len(), 1);
1130 assert_eq!(
1131 networks[0],
1132 Ipv4Network::new(Ipv4Addr::new(0, 0, 0, 0), 0).unwrap()
1133 );
1134 }
1135
1136 #[test]
1137 fn summarize_address_range_first_is_bigger() {
1138 let networks = Ipv4Network::summarize_address_range(
1139 Ipv4Addr::new(255, 255, 255, 255),
1140 Ipv4Addr::new(0, 0, 0, 0),
1141 );
1142 assert_eq!(0, networks.len());
1143 }
1144
1145 #[test]
1146 fn collapse_addresses() {
1147 let addresses = [
1148 Ipv4Network::from_str("192.0.2.0/26").unwrap(),
1149 Ipv4Network::from_str("192.0.2.64/26").unwrap(),
1150 Ipv4Network::from_str("192.0.2.128/26").unwrap(),
1151 Ipv4Network::from_str("192.0.2.192/26").unwrap(),
1152 ];
1153 let collapsed = Ipv4Network::collapse_addresses(&addresses);
1154 assert_eq!(1, collapsed.len());
1155 assert_eq!(Ipv4Network::from_str("192.0.2.0/24").unwrap(), collapsed[0]);
1156 }
1157
1158 #[test]
1159 fn collapse_addresses_2() {
1160 let addresses = [
1161 Ipv4Network::from_str("192.0.2.0/25").unwrap(),
1162 Ipv4Network::from_str("192.0.2.128/25").unwrap(),
1163 ];
1164 let collapsed = Ipv4Network::collapse_addresses(&addresses);
1165 assert_eq!(1, collapsed.len());
1166 assert_eq!(Ipv4Network::from_str("192.0.2.0/24").unwrap(), collapsed[0]);
1167 }
1168
1169 #[test]
1170 fn collapse_addresses_3() {
1171 // test only IP addresses including some duplicates
1172 let addresses = [
1173 Ipv4Network::from_str("1.1.1.0/32").unwrap(),
1174 Ipv4Network::from_str("1.1.1.1/32").unwrap(),
1175 Ipv4Network::from_str("1.1.1.2/32").unwrap(),
1176 Ipv4Network::from_str("1.1.1.3/32").unwrap(),
1177 Ipv4Network::from_str("1.1.1.4/32").unwrap(),
1178 Ipv4Network::from_str("1.1.1.0/32").unwrap(),
1179 ];
1180 let collapsed = Ipv4Network::collapse_addresses(&addresses);
1181 assert_eq!(2, collapsed.len());
1182 assert_eq!(Ipv4Network::from_str("1.1.1.0/30").unwrap(), collapsed[0]);
1183 assert_eq!(Ipv4Network::from_str("1.1.1.4/32").unwrap(), collapsed[1]);
1184 }
1185
1186 #[test]
1187 fn collapse_addresses_4() {
1188 // test a mix of IP addresses and networks including some duplicates
1189 let addresses = [
1190 Ipv4Network::from_str("1.1.1.0/32").unwrap(),
1191 Ipv4Network::from_str("1.1.1.1/32").unwrap(),
1192 Ipv4Network::from_str("1.1.1.2/32").unwrap(),
1193 Ipv4Network::from_str("1.1.1.3/32").unwrap(),
1194 ];
1195 let collapsed = Ipv4Network::collapse_addresses(&addresses);
1196 assert_eq!(1, collapsed.len());
1197 assert_eq!(Ipv4Network::from_str("1.1.1.0/30").unwrap(), collapsed[0]);
1198 }
1199
1200 #[test]
1201 fn collapse_addresses_5() {
1202 // test only IP networks
1203 let addresses = [
1204 Ipv4Network::from_str("1.1.0.0/24").unwrap(),
1205 Ipv4Network::from_str("1.1.1.0/24").unwrap(),
1206 Ipv4Network::from_str("1.1.2.0/24").unwrap(),
1207 Ipv4Network::from_str("1.1.3.0/24").unwrap(),
1208 Ipv4Network::from_str("1.1.4.0/24").unwrap(),
1209 Ipv4Network::from_str("1.1.0.0/22").unwrap(),
1210 ];
1211 let collapsed = Ipv4Network::collapse_addresses(&addresses);
1212 assert_eq!(2, collapsed.len());
1213 assert_eq!(Ipv4Network::from_str("1.1.0.0/22").unwrap(), collapsed[0]);
1214 assert_eq!(Ipv4Network::from_str("1.1.4.0/24").unwrap(), collapsed[1]);
1215 }
1216
1217 #[test]
1218 fn collapse_addresses_5_order() {
1219 let addresses = [
1220 Ipv4Network::from_str("1.1.3.0/24").unwrap(),
1221 Ipv4Network::from_str("1.1.4.0/24").unwrap(),
1222 Ipv4Network::from_str("1.1.0.0/22").unwrap(),
1223 Ipv4Network::from_str("1.1.2.0/24").unwrap(),
1224 Ipv4Network::from_str("1.1.0.0/24").unwrap(),
1225 Ipv4Network::from_str("1.1.1.0/24").unwrap(),
1226 ];
1227
1228 let collapsed = Ipv4Network::collapse_addresses(&addresses);
1229 assert_eq!(2, collapsed.len());
1230 assert_eq!(Ipv4Network::from_str("1.1.0.0/22").unwrap(), collapsed[0]);
1231 assert_eq!(Ipv4Network::from_str("1.1.4.0/24").unwrap(), collapsed[1]);
1232 }
1233
1234 #[test]
1235 fn collapse_addresses_6() {
1236 // test that two addresses are supernet'ed properly
1237 let addresses = [
1238 Ipv4Network::from_str("1.1.0.0/24").unwrap(),
1239 Ipv4Network::from_str("1.1.1.0/24").unwrap(),
1240 ];
1241 let collapsed = Ipv4Network::collapse_addresses(&addresses);
1242 assert_eq!(1, collapsed.len());
1243 assert_eq!(Ipv4Network::from_str("1.1.0.0/23").unwrap(), collapsed[0]);
1244 }
1245
1246 #[test]
1247 fn collapse_addresses_7() {
1248 // test same IP networks
1249 let addresses = [
1250 Ipv4Network::from_str("1.1.1.1/32").unwrap(),
1251 Ipv4Network::from_str("1.1.1.1/32").unwrap(),
1252 ];
1253 let collapsed = Ipv4Network::collapse_addresses(&addresses);
1254 assert_eq!(1, collapsed.len());
1255 assert_eq!(Ipv4Network::from_str("1.1.1.1/32").unwrap(), collapsed[0]);
1256 }
1257
1258 #[test]
1259 fn collapse_addresses_8() {
1260 let addresses = [
1261 Ipv4Network::from_str("0.0.0.0/0").unwrap(),
1262 Ipv4Network::from_str("1.1.1.1/32").unwrap(),
1263 ];
1264 let collapsed = Ipv4Network::collapse_addresses(&addresses);
1265 assert_eq!(1, collapsed.len());
1266 assert_eq!(Ipv4Network::from_str("0.0.0.0/0").unwrap(), collapsed[0]);
1267 }
1268
1269 #[test]
1270 fn collapse_addresses_9() {
1271 let addresses = [
1272 Ipv4Network::from_str("1.228.0.0/16").unwrap(),
1273 Ipv4Network::from_str("1.230.0.0/15").unwrap(),
1274 ];
1275 let collapsed = Ipv4Network::collapse_addresses(&addresses);
1276 assert_eq!(2, collapsed.len());
1277 }
1278
1279 #[test]
1280 fn from_ipv4addr() {
1281 let ip = Ipv4Addr::new(127, 0, 0, 1);
1282 let ipv4_network = Ipv4Network::from(ip);
1283 assert_eq!(ip, ipv4_network.network_address());
1284 assert_eq!(32, ipv4_network.netmask());
1285 }
1286
1287 #[test]
1288 fn hash() {
1289 let network1 = Ipv4Network::from_str("192.0.2.0/26").unwrap();
1290 let network2 = Ipv4Network::from_str("192.0.2.64/26").unwrap();
1291
1292 let mut hasher1 = DefaultHasher::new();
1293 network1.hash(&mut hasher1);
1294
1295 let mut hasher2 = DefaultHasher::new();
1296 network2.hash(&mut hasher2);
1297
1298 assert_ne!(hasher1.finish(), hasher2.finish());
1299 }
1300}