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}