1use alloc::vec::Vec;
2use core::cmp::{min, max};
3use core::cmp::Ordering::{Less, Equal};
4use core::convert::From;
5use core::fmt;
6use core::iter::FusedIterator;
7use core::option::Option::{Some, None};
8#[cfg(not(feature = "std"))]
9use core::error::Error;
10#[cfg(feature = "std")]
11use std::error::Error;
12#[cfg(not(feature = "std"))]
13use core::net::{IpAddr, Ipv4Addr, Ipv6Addr};
14#[cfg(feature = "std")]
15use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
16
17use crate::ipext::{IpAdd, IpSub, IpStep, IpAddrRange, Ipv4AddrRange, Ipv6AddrRange};
18use crate::mask::{ip_mask_to_prefix, ipv4_mask_to_prefix, ipv6_mask_to_prefix};
19
20/// An IP network address, either IPv4 or IPv6.
21///
22/// This enum can contain either an [`Ipv4Net`] or an [`Ipv6Net`]. A
23/// [`From`] implementation is provided to convert these into an
24/// `IpNet`.
25///
26/// # Textual representation
27///
28/// `IpNet` provides a [`FromStr`] implementation for parsing network
29/// addresses represented in CIDR notation. See [IETF RFC 4632] for the
30/// CIDR notation.
31///
32/// [`Ipv4Net`]: struct.Ipv4Net.html
33/// [`Ipv6Net`]: struct.Ipv6Net.html
34/// [`From`]: https://doc.rust-lang.org/std/convert/trait.From.html
35/// [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html
36/// [IETF RFC 4632]: https://tools.ietf.org/html/rfc4632
37///
38/// # Examples
39///
40/// ```
41/// use std::net::IpAddr;
42/// use ipnet::IpNet;
43///
44/// let net: IpNet = "10.1.1.0/24".parse().unwrap();
45/// assert_eq!(Ok(net.network()), "10.1.1.0".parse());
46///
47/// let net: IpNet = "fd00::/32".parse().unwrap();
48/// assert_eq!(Ok(net.network()), "fd00::".parse());
49/// ```
50#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
51pub enum IpNet {
52 V4(Ipv4Net),
53 V6(Ipv6Net),
54}
55
56/// An IPv4 network address.
57///
58/// See [`IpNet`] for a type encompassing both IPv4 and IPv6 network
59/// addresses.
60///
61/// # Textual representation
62///
63/// `Ipv4Net` provides a [`FromStr`] implementation for parsing network
64/// addresses represented in CIDR notation. See [IETF RFC 4632] for the
65/// CIDR notation.
66///
67/// [`IpNet`]: enum.IpNet.html
68/// [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html
69/// [IETF RFC 4632]: https://tools.ietf.org/html/rfc4632
70///
71/// # Examples
72///
73/// ```
74/// # #![cfg_attr(not(feature = "std"), feature(ip_in_core))]
75/// # #[cfg(feature = "std")]
76/// # use std::net::Ipv6Addr;
77/// # #[cfg(not(feature = "std"))]
78/// # use core::net::Ipv6Addr;
79/// use ipnet::Ipv4Net;
80///
81/// let net: Ipv4Net = "10.1.1.0/24".parse().unwrap();
82/// assert_eq!(Ok(net.network()), "10.1.1.0".parse());
83/// ```
84#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
85pub struct Ipv4Net {
86 addr: Ipv4Addr,
87 prefix_len: u8,
88}
89
90/// An IPv6 network address.
91///
92/// See [`IpNet`] for a type encompassing both IPv4 and IPv6 network
93/// addresses.
94///
95/// # Textual representation
96///
97/// `Ipv6Net` provides a [`FromStr`] implementation for parsing network
98/// addresses represented in CIDR notation. See [IETF RFC 4632] for the
99/// CIDR notation.
100///
101/// [`IpNet`]: enum.IpNet.html
102/// [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html
103/// [IETF RFC 4632]: https://tools.ietf.org/html/rfc4632
104///
105/// # Examples
106///
107/// ```
108/// use std::net::Ipv6Addr;
109/// use ipnet::Ipv6Net;
110///
111/// let net: Ipv6Net = "fd00::/32".parse().unwrap();
112/// assert_eq!(Ok(net.network()), "fd00::".parse());
113/// ```
114#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
115pub struct Ipv6Net {
116 addr: Ipv6Addr,
117 prefix_len: u8,
118}
119
120/// An error which can be returned when the prefix length is invalid.
121///
122/// Valid prefix lengths are 0 to 32 for IPv4 and 0 to 128 for IPv6.
123#[derive(Debug, Clone, PartialEq, Eq)]
124pub struct PrefixLenError;
125
126impl fmt::Display for PrefixLenError {
127 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
128 fmt.write_str(data:"invalid IP prefix length")
129 }
130}
131
132impl Error for PrefixLenError {}
133
134impl IpNet {
135 /// Creates a new IP network address from an `IpAddr` and prefix
136 /// length.
137 ///
138 /// # Examples
139 ///
140 /// ```
141 /// use std::net::Ipv6Addr;
142 /// use ipnet::{IpNet, PrefixLenError};
143 ///
144 /// let net = IpNet::new(Ipv6Addr::LOCALHOST.into(), 48);
145 /// assert!(net.is_ok());
146 ///
147 /// let bad_prefix_len = IpNet::new(Ipv6Addr::LOCALHOST.into(), 129);
148 /// assert_eq!(bad_prefix_len, Err(PrefixLenError));
149 /// ```
150 pub fn new(ip: IpAddr, prefix_len: u8) -> Result<IpNet, PrefixLenError> {
151 Ok(match ip {
152 IpAddr::V4(a) => Ipv4Net::new(a, prefix_len)?.into(),
153 IpAddr::V6(a) => Ipv6Net::new(a, prefix_len)?.into(),
154 })
155 }
156
157 /// Creates a new IP network address from an `IpAddr` and netmask.
158 ///
159 /// # Examples
160 ///
161 /// ```
162 /// use std::net::Ipv6Addr;
163 /// use ipnet::{IpNet, PrefixLenError};
164 ///
165 /// let net = IpNet::with_netmask(Ipv6Addr::LOCALHOST.into(), Ipv6Addr::from(0xffff_ffff_ffff_0000_0000_0000_0000_0000).into());
166 /// assert!(net.is_ok());
167 ///
168 /// let bad_prefix_len = IpNet::with_netmask(Ipv6Addr::LOCALHOST.into(), Ipv6Addr::from(0xffff_ffff_ffff_0000_0001_0000_0000_0000).into());
169 /// assert_eq!(bad_prefix_len, Err(PrefixLenError));
170 /// ```
171 pub fn with_netmask(ip: IpAddr, netmask: IpAddr) -> Result<IpNet, PrefixLenError> {
172 let prefix = ip_mask_to_prefix(netmask)?;
173 Self::new(ip, prefix)
174 }
175
176 /// Returns a copy of the network with the address truncated to the
177 /// prefix length.
178 ///
179 /// # Examples
180 ///
181 /// ```
182 /// # use ipnet::IpNet;
183 /// #
184 /// assert_eq!(
185 /// "192.168.12.34/16".parse::<IpNet>().unwrap().trunc(),
186 /// "192.168.0.0/16".parse().unwrap()
187 /// );
188 ///
189 /// assert_eq!(
190 /// "fd00::1:2:3:4/16".parse::<IpNet>().unwrap().trunc(),
191 /// "fd00::/16".parse().unwrap()
192 /// );
193 /// ```
194 pub fn trunc(&self) -> IpNet {
195 match *self {
196 IpNet::V4(ref a) => IpNet::V4(a.trunc()),
197 IpNet::V6(ref a) => IpNet::V6(a.trunc()),
198 }
199 }
200
201 /// Returns the address.
202 pub fn addr(&self) -> IpAddr {
203 match *self {
204 IpNet::V4(ref a) => IpAddr::V4(a.addr),
205 IpNet::V6(ref a) => IpAddr::V6(a.addr),
206 }
207 }
208
209 /// Returns the prefix length.
210 pub fn prefix_len(&self) -> u8 {
211 match *self {
212 IpNet::V4(ref a) => a.prefix_len(),
213 IpNet::V6(ref a) => a.prefix_len(),
214 }
215 }
216
217 /// Returns the maximum valid prefix length.
218 pub fn max_prefix_len(&self) -> u8 {
219 match *self {
220 IpNet::V4(ref a) => a.max_prefix_len(),
221 IpNet::V6(ref a) => a.max_prefix_len(),
222 }
223 }
224
225 /// Returns the network mask.
226 ///
227 /// # Examples
228 ///
229 /// ```
230 /// # use std::net::IpAddr;
231 /// # use ipnet::IpNet;
232 /// #
233 /// let net: IpNet = "10.1.0.0/20".parse().unwrap();
234 /// assert_eq!(Ok(net.netmask()), "255.255.240.0".parse());
235 ///
236 /// let net: IpNet = "fd00::/24".parse().unwrap();
237 /// assert_eq!(Ok(net.netmask()), "ffff:ff00::".parse());
238 /// ```
239 pub fn netmask(&self) -> IpAddr {
240 match *self {
241 IpNet::V4(ref a) => IpAddr::V4(a.netmask()),
242 IpNet::V6(ref a) => IpAddr::V6(a.netmask()),
243 }
244 }
245
246 /// Returns the host mask.
247 ///
248 /// # Examples
249 ///
250 /// ```
251 /// # use std::net::IpAddr;
252 /// # use ipnet::IpNet;
253 /// #
254 /// let net: IpNet = "10.1.0.0/20".parse().unwrap();
255 /// assert_eq!(Ok(net.hostmask()), "0.0.15.255".parse());
256 ///
257 /// let net: IpNet = "fd00::/24".parse().unwrap();
258 /// assert_eq!(Ok(net.hostmask()), "::ff:ffff:ffff:ffff:ffff:ffff:ffff".parse());
259 /// ```
260 pub fn hostmask(&self) -> IpAddr {
261 match *self {
262 IpNet::V4(ref a) => IpAddr::V4(a.hostmask()),
263 IpNet::V6(ref a) => IpAddr::V6(a.hostmask()),
264 }
265 }
266
267 /// Returns the network address.
268 ///
269 /// # Examples
270 ///
271 /// ```
272 /// # use std::net::IpAddr;
273 /// # use ipnet::IpNet;
274 /// #
275 /// let net: IpNet = "172.16.123.123/16".parse().unwrap();
276 /// assert_eq!(Ok(net.network()), "172.16.0.0".parse());
277 ///
278 /// let net: IpNet = "fd00:1234:5678::/24".parse().unwrap();
279 /// assert_eq!(Ok(net.network()), "fd00:1200::".parse());
280 /// ```
281 pub fn network(&self) -> IpAddr {
282 match *self {
283 IpNet::V4(ref a) => IpAddr::V4(a.network()),
284 IpNet::V6(ref a) => IpAddr::V6(a.network()),
285 }
286 }
287
288 /// Returns the broadcast address.
289 ///
290 /// # Examples
291 ///
292 /// ```
293 /// # use std::net::IpAddr;
294 /// # use ipnet::IpNet;
295 /// #
296 /// let net: IpNet = "172.16.0.0/22".parse().unwrap();
297 /// assert_eq!(Ok(net.broadcast()), "172.16.3.255".parse());
298 ///
299 /// let net: IpNet = "fd00:1234:5678::/24".parse().unwrap();
300 /// assert_eq!(Ok(net.broadcast()), "fd00:12ff:ffff:ffff:ffff:ffff:ffff:ffff".parse());
301 /// ```
302 pub fn broadcast(&self) -> IpAddr {
303 match *self {
304 IpNet::V4(ref a) => IpAddr::V4(a.broadcast()),
305 IpNet::V6(ref a) => IpAddr::V6(a.broadcast()),
306 }
307 }
308
309 /// Returns the `IpNet` that contains this one.
310 ///
311 /// # Examples
312 ///
313 /// ```
314 /// # use ipnet::IpNet;
315 /// #
316 /// let n1: IpNet = "172.16.1.0/24".parse().unwrap();
317 /// let n2: IpNet = "172.16.0.0/23".parse().unwrap();
318 /// let n3: IpNet = "172.16.0.0/0".parse().unwrap();
319 ///
320 /// assert_eq!(n1.supernet().unwrap(), n2);
321 /// assert_eq!(n3.supernet(), None);
322 ///
323 /// let n1: IpNet = "fd00:ff00::/24".parse().unwrap();
324 /// let n2: IpNet = "fd00:fe00::/23".parse().unwrap();
325 /// let n3: IpNet = "fd00:fe00::/0".parse().unwrap();
326 ///
327 /// assert_eq!(n1.supernet().unwrap(), n2);
328 /// assert_eq!(n3.supernet(), None);
329 /// ```
330 pub fn supernet(&self) -> Option<IpNet> {
331 match *self {
332 IpNet::V4(ref a) => a.supernet().map(IpNet::V4),
333 IpNet::V6(ref a) => a.supernet().map(IpNet::V6),
334 }
335 }
336
337 /// Returns `true` if this network and the given network are
338 /// children of the same supernet.
339 ///
340 /// # Examples
341 ///
342 /// ```
343 /// # use ipnet::IpNet;
344 /// #
345 /// let n4_1: IpNet = "10.1.0.0/24".parse().unwrap();
346 /// let n4_2: IpNet = "10.1.1.0/24".parse().unwrap();
347 /// let n4_3: IpNet = "10.1.2.0/24".parse().unwrap();
348 /// let n6_1: IpNet = "fd00::/18".parse().unwrap();
349 /// let n6_2: IpNet = "fd00:4000::/18".parse().unwrap();
350 /// let n6_3: IpNet = "fd00:8000::/18".parse().unwrap();
351 ///
352 /// assert!( n4_1.is_sibling(&n4_2));
353 /// assert!(!n4_2.is_sibling(&n4_3));
354 /// assert!( n6_1.is_sibling(&n6_2));
355 /// assert!(!n6_2.is_sibling(&n6_3));
356 /// assert!(!n4_1.is_sibling(&n6_2));
357 /// ```
358 pub fn is_sibling(&self, other: &IpNet) -> bool {
359 match (*self, *other) {
360 (IpNet::V4(ref a), IpNet::V4(ref b)) => a.is_sibling(b),
361 (IpNet::V6(ref a), IpNet::V6(ref b)) => a.is_sibling(b),
362 _ => false,
363 }
364 }
365
366 /// Return an `Iterator` over the host addresses in this network.
367 ///
368 /// # Examples
369 ///
370 /// ```
371 /// # use std::net::IpAddr;
372 /// # use ipnet::IpNet;
373 /// #
374 /// let net: IpNet = "10.0.0.0/30".parse().unwrap();
375 /// assert_eq!(net.hosts().collect::<Vec<IpAddr>>(), vec![
376 /// "10.0.0.1".parse::<IpAddr>().unwrap(),
377 /// "10.0.0.2".parse().unwrap(),
378 /// ]);
379 ///
380 /// let net: IpNet = "10.0.0.0/31".parse().unwrap();
381 /// assert_eq!(net.hosts().collect::<Vec<IpAddr>>(), vec![
382 /// "10.0.0.0".parse::<IpAddr>().unwrap(),
383 /// "10.0.0.1".parse().unwrap(),
384 /// ]);
385 ///
386 /// let net: IpNet = "fd00::/126".parse().unwrap();
387 /// assert_eq!(net.hosts().collect::<Vec<IpAddr>>(), vec![
388 /// "fd00::".parse::<IpAddr>().unwrap(),
389 /// "fd00::1".parse().unwrap(),
390 /// "fd00::2".parse().unwrap(),
391 /// "fd00::3".parse().unwrap(),
392 /// ]);
393 /// ```
394 pub fn hosts(&self) -> IpAddrRange {
395 match *self {
396 IpNet::V4(ref a) => IpAddrRange::V4(a.hosts()),
397 IpNet::V6(ref a) => IpAddrRange::V6(a.hosts()),
398 }
399 }
400
401 /// Returns an `Iterator` over the subnets of this network with the
402 /// given prefix length.
403 ///
404 /// # Examples
405 ///
406 /// ```
407 /// # use ipnet::{IpNet, PrefixLenError};
408 /// #
409 /// let net: IpNet = "10.0.0.0/24".parse().unwrap();
410 /// assert_eq!(net.subnets(26).unwrap().collect::<Vec<IpNet>>(), vec![
411 /// "10.0.0.0/26".parse::<IpNet>().unwrap(),
412 /// "10.0.0.64/26".parse().unwrap(),
413 /// "10.0.0.128/26".parse().unwrap(),
414 /// "10.0.0.192/26".parse().unwrap(),
415 /// ]);
416 ///
417 /// let net: IpNet = "fd00::/16".parse().unwrap();
418 /// assert_eq!(net.subnets(18).unwrap().collect::<Vec<IpNet>>(), vec![
419 /// "fd00::/18".parse::<IpNet>().unwrap(),
420 /// "fd00:4000::/18".parse().unwrap(),
421 /// "fd00:8000::/18".parse().unwrap(),
422 /// "fd00:c000::/18".parse().unwrap(),
423 /// ]);
424 ///
425 /// let net: IpNet = "10.0.0.0/24".parse().unwrap();
426 /// assert_eq!(net.subnets(23), Err(PrefixLenError));
427 ///
428 /// let net: IpNet = "10.0.0.0/24".parse().unwrap();
429 /// assert_eq!(net.subnets(33), Err(PrefixLenError));
430 ///
431 /// let net: IpNet = "fd00::/16".parse().unwrap();
432 /// assert_eq!(net.subnets(15), Err(PrefixLenError));
433 ///
434 /// let net: IpNet = "fd00::/16".parse().unwrap();
435 /// assert_eq!(net.subnets(129), Err(PrefixLenError));
436 /// ```
437 pub fn subnets(&self, new_prefix_len: u8) -> Result<IpSubnets, PrefixLenError> {
438 match *self {
439 IpNet::V4(ref a) => a.subnets(new_prefix_len).map(IpSubnets::V4),
440 IpNet::V6(ref a) => a.subnets(new_prefix_len).map(IpSubnets::V6),
441 }
442 }
443
444 /// Test if a network address contains either another network
445 /// address or an IP address.
446 ///
447 /// # Examples
448 ///
449 /// ```
450 /// # use std::net::IpAddr;
451 /// # use ipnet::IpNet;
452 /// #
453 /// let net4: IpNet = "192.168.0.0/24".parse().unwrap();
454 /// let net4_yes: IpNet = "192.168.0.0/25".parse().unwrap();
455 /// let net4_no: IpNet = "192.168.0.0/23".parse().unwrap();
456 /// let ip4_yes: IpAddr = "192.168.0.1".parse().unwrap();
457 /// let ip4_no: IpAddr = "192.168.1.0".parse().unwrap();
458 ///
459 /// assert!(net4.contains(&net4));
460 /// assert!(net4.contains(&net4_yes));
461 /// assert!(!net4.contains(&net4_no));
462 /// assert!(net4.contains(&ip4_yes));
463 /// assert!(!net4.contains(&ip4_no));
464 ///
465 ///
466 /// let net6: IpNet = "fd00::/16".parse().unwrap();
467 /// let net6_yes: IpNet = "fd00::/17".parse().unwrap();
468 /// let net6_no: IpNet = "fd00::/15".parse().unwrap();
469 /// let ip6_yes: IpAddr = "fd00::1".parse().unwrap();
470 /// let ip6_no: IpAddr = "fd01::".parse().unwrap();
471 ///
472 /// assert!(net6.contains(&net6));
473 /// assert!(net6.contains(&net6_yes));
474 /// assert!(!net6.contains(&net6_no));
475 /// assert!(net6.contains(&ip6_yes));
476 /// assert!(!net6.contains(&ip6_no));
477 ///
478 /// assert!(!net4.contains(&net6));
479 /// assert!(!net6.contains(&net4));
480 /// assert!(!net4.contains(&ip6_no));
481 /// assert!(!net6.contains(&ip4_no));
482 /// ```
483 pub fn contains<T>(&self, other: T) -> bool where Self: Contains<T> {
484 Contains::contains(self, other)
485 }
486
487 /// Aggregate a `Vec` of `IpNet`s and return the result as a new
488 /// `Vec`.
489 ///
490 /// # Examples
491 ///
492 /// ```
493 /// # use ipnet::IpNet;
494 /// #
495 /// let nets = vec![
496 /// "10.0.0.0/24".parse::<IpNet>().unwrap(),
497 /// "10.0.1.0/24".parse().unwrap(),
498 /// "10.0.2.0/24".parse().unwrap(),
499 /// "fd00::/18".parse().unwrap(),
500 /// "fd00:4000::/18".parse().unwrap(),
501 /// "fd00:8000::/18".parse().unwrap(),
502 /// ];
503 ///
504 /// assert_eq!(IpNet::aggregate(&nets), vec![
505 /// "10.0.0.0/23".parse::<IpNet>().unwrap(),
506 /// "10.0.2.0/24".parse().unwrap(),
507 /// "fd00::/17".parse().unwrap(),
508 /// "fd00:8000::/18".parse().unwrap(),
509 /// ]);
510 /// ```
511 pub fn aggregate(networks: &Vec<IpNet>) -> Vec<IpNet> {
512 // It's 2.5x faster to split the input up and run them using the
513 // specific IPv4 and IPV6 implementations. merge_intervals() and
514 // the comparisons are much faster running over integers.
515 let mut ipv4nets: Vec<Ipv4Net> = Vec::new();
516 let mut ipv6nets: Vec<Ipv6Net> = Vec::new();
517
518 for n in networks {
519 match *n {
520 IpNet::V4(x) => ipv4nets.push(x),
521 IpNet::V6(x) => ipv6nets.push(x),
522 }
523 }
524
525 let mut res: Vec<IpNet> = Vec::new();
526 let ipv4aggs = Ipv4Net::aggregate(&ipv4nets);
527 let ipv6aggs = Ipv6Net::aggregate(&ipv6nets);
528 res.extend::<Vec<IpNet>>(ipv4aggs.into_iter().map(IpNet::V4).collect::<Vec<IpNet>>());
529 res.extend::<Vec<IpNet>>(ipv6aggs.into_iter().map(IpNet::V6).collect::<Vec<IpNet>>());
530 res
531 }
532}
533
534impl Default for IpNet {
535 fn default() -> Self {
536 Self::V4(Ipv4Net::default())
537 }
538}
539
540impl fmt::Debug for IpNet {
541 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
542 fmt::Display::fmt(self, f:fmt)
543 }
544}
545
546impl fmt::Display for IpNet {
547 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
548 match *self {
549 IpNet::V4(ref a: &Ipv4Net) => a.fmt(fmt),
550 IpNet::V6(ref a: &Ipv6Net) => a.fmt(fmt),
551 }
552 }
553}
554
555impl From<Ipv4Net> for IpNet {
556 fn from(net: Ipv4Net) -> IpNet {
557 IpNet::V4(net)
558 }
559}
560
561impl From<Ipv6Net> for IpNet {
562 fn from(net: Ipv6Net) -> IpNet {
563 IpNet::V6(net)
564 }
565}
566
567impl From<IpAddr> for IpNet {
568 fn from(addr: IpAddr) -> IpNet {
569 match addr {
570 IpAddr::V4(a: Ipv4Addr) => IpNet::V4(a.into()),
571 IpAddr::V6(a: Ipv6Addr) => IpNet::V6(a.into()),
572 }
573 }
574}
575
576impl Ipv4Net {
577 /// Creates a new IPv4 network address from an `Ipv4Addr` and prefix
578 /// length.
579 ///
580 /// # Examples
581 ///
582 /// ```
583 /// use std::net::Ipv4Addr;
584 /// use ipnet::{Ipv4Net, PrefixLenError};
585 ///
586 /// let net = Ipv4Net::new(Ipv4Addr::new(10, 1, 1, 0), 24);
587 /// assert!(net.is_ok());
588 ///
589 /// let bad_prefix_len = Ipv4Net::new(Ipv4Addr::new(10, 1, 1, 0), 33);
590 /// assert_eq!(bad_prefix_len, Err(PrefixLenError));
591 /// ```
592 #[inline]
593 pub const fn new(ip: Ipv4Addr, prefix_len: u8) -> Result<Ipv4Net, PrefixLenError> {
594 if prefix_len > 32 {
595 return Err(PrefixLenError);
596 }
597 Ok(Ipv4Net { addr: ip, prefix_len: prefix_len })
598 }
599
600 /// Creates a new IPv4 network address from an `Ipv4Addr` and netmask.
601 ///
602 /// # Examples
603 ///
604 /// ```
605 /// use std::net::Ipv4Addr;
606 /// use ipnet::{Ipv4Net, PrefixLenError};
607 ///
608 /// let net = Ipv4Net::with_netmask(Ipv4Addr::new(10, 1, 1, 0), Ipv4Addr::new(255, 255, 255, 0));
609 /// assert!(net.is_ok());
610 ///
611 /// let bad_prefix_len = Ipv4Net::with_netmask(Ipv4Addr::new(10, 1, 1, 0), Ipv4Addr::new(255, 255, 0, 1));
612 /// assert_eq!(bad_prefix_len, Err(PrefixLenError));
613 /// ```
614 pub fn with_netmask(ip: Ipv4Addr, netmask: Ipv4Addr) -> Result<Ipv4Net, PrefixLenError> {
615 let prefix = ipv4_mask_to_prefix(netmask)?;
616 Self::new(ip, prefix)
617 }
618
619 /// Returns a copy of the network with the address truncated to the
620 /// prefix length.
621 ///
622 /// # Examples
623 ///
624 /// ```
625 /// # use ipnet::Ipv4Net;
626 /// #
627 /// assert_eq!(
628 /// "192.168.12.34/16".parse::<Ipv4Net>().unwrap().trunc(),
629 /// "192.168.0.0/16".parse().unwrap()
630 /// );
631 /// ```
632 pub fn trunc(&self) -> Ipv4Net {
633 Ipv4Net::new(self.network(), self.prefix_len).unwrap()
634 }
635
636 /// Returns the address.
637 #[inline]
638 pub const fn addr(&self) -> Ipv4Addr {
639 self.addr
640 }
641
642 /// Returns the prefix length.
643 #[inline]
644 pub const fn prefix_len(&self) -> u8 {
645 self.prefix_len
646 }
647
648 /// Returns the maximum valid prefix length.
649 #[inline]
650 pub const fn max_prefix_len(&self) -> u8 {
651 32
652 }
653
654 /// Returns the network mask.
655 ///
656 /// # Examples
657 ///
658 /// ```
659 /// # use std::net::Ipv4Addr;
660 /// # use ipnet::Ipv4Net;
661 /// #
662 /// let net: Ipv4Net = "10.1.0.0/20".parse().unwrap();
663 /// assert_eq!(Ok(net.netmask()), "255.255.240.0".parse());
664 /// ```
665 pub fn netmask(&self) -> Ipv4Addr {
666 Ipv4Addr::from(self.netmask_u32())
667 }
668
669 fn netmask_u32(&self) -> u32 {
670 u32::max_value().checked_shl(32 - self.prefix_len as u32).unwrap_or(0)
671 }
672
673 /// Returns the host mask.
674 ///
675 /// # Examples
676 ///
677 /// ```
678 /// # use std::net::Ipv4Addr;
679 /// # use ipnet::Ipv4Net;
680 /// #
681 /// let net: Ipv4Net = "10.1.0.0/20".parse().unwrap();
682 /// assert_eq!(Ok(net.hostmask()), "0.0.15.255".parse());
683 /// ```
684 pub fn hostmask(&self) -> Ipv4Addr {
685 Ipv4Addr::from(self.hostmask_u32())
686 }
687
688 fn hostmask_u32(&self) -> u32 {
689 u32::max_value().checked_shr(self.prefix_len as u32).unwrap_or(0)
690 }
691
692 /// Returns the network address.
693 ///
694 /// # Examples
695 ///
696 /// ```
697 /// # use std::net::Ipv4Addr;
698 /// # use ipnet::Ipv4Net;
699 /// #
700 /// let net: Ipv4Net = "172.16.123.123/16".parse().unwrap();
701 /// assert_eq!(Ok(net.network()), "172.16.0.0".parse());
702 /// ```
703 pub fn network(&self) -> Ipv4Addr {
704 Ipv4Addr::from(u32::from(self.addr) & self.netmask_u32())
705 }
706
707 /// Returns the broadcast address.
708 ///
709 /// # Examples
710 ///
711 /// ```
712 /// # use std::net::Ipv4Addr;
713 /// # use ipnet::Ipv4Net;
714 /// #
715 /// let net: Ipv4Net = "172.16.0.0/22".parse().unwrap();
716 /// assert_eq!(Ok(net.broadcast()), "172.16.3.255".parse());
717 /// ```
718 pub fn broadcast(&self) -> Ipv4Addr {
719 Ipv4Addr::from(u32::from(self.addr) | self.hostmask_u32())
720 }
721
722 /// Returns the `Ipv4Net` that contains this one.
723 ///
724 /// # Examples
725 ///
726 /// ```
727 /// # use ipnet::Ipv4Net;
728 /// #
729 /// let n1: Ipv4Net = "172.16.1.0/24".parse().unwrap();
730 /// let n2: Ipv4Net = "172.16.0.0/23".parse().unwrap();
731 /// let n3: Ipv4Net = "172.16.0.0/0".parse().unwrap();
732 ///
733 /// assert_eq!(n1.supernet().unwrap(), n2);
734 /// assert_eq!(n3.supernet(), None);
735 /// ```
736 pub fn supernet(&self) -> Option<Ipv4Net> {
737 Ipv4Net::new(self.addr, self.prefix_len.wrapping_sub(1)).map(|n| n.trunc()).ok()
738 }
739
740 /// Returns `true` if this network and the given network are
741 /// children of the same supernet.
742 ///
743 /// # Examples
744 ///
745 /// ```
746 /// # use ipnet::Ipv4Net;
747 /// #
748 /// let n1: Ipv4Net = "10.1.0.0/24".parse().unwrap();
749 /// let n2: Ipv4Net = "10.1.1.0/24".parse().unwrap();
750 /// let n3: Ipv4Net = "10.1.2.0/24".parse().unwrap();
751 ///
752 /// assert!(n1.is_sibling(&n2));
753 /// assert!(!n2.is_sibling(&n3));
754 /// ```
755 pub fn is_sibling(&self, other: &Ipv4Net) -> bool {
756 self.prefix_len > 0 &&
757 self.prefix_len == other.prefix_len &&
758 self.supernet().unwrap().contains(other)
759 }
760
761 /// Return an `Iterator` over the host addresses in this network.
762 ///
763 /// If the prefix length is less than 31 both the network address
764 /// and broadcast address are excluded. These are only valid host
765 /// addresses when the prefix length is 31.
766 ///
767 /// # Examples
768 ///
769 /// ```
770 /// # use std::net::Ipv4Addr;
771 /// # use ipnet::Ipv4Net;
772 /// #
773 /// let net: Ipv4Net = "10.0.0.0/30".parse().unwrap();
774 /// assert_eq!(net.hosts().collect::<Vec<Ipv4Addr>>(), vec![
775 /// "10.0.0.1".parse::<Ipv4Addr>().unwrap(),
776 /// "10.0.0.2".parse().unwrap(),
777 /// ]);
778 ///
779 /// let net: Ipv4Net = "10.0.0.0/31".parse().unwrap();
780 /// assert_eq!(net.hosts().collect::<Vec<Ipv4Addr>>(), vec![
781 /// "10.0.0.0".parse::<Ipv4Addr>().unwrap(),
782 /// "10.0.0.1".parse().unwrap(),
783 /// ]);
784 /// ```
785 pub fn hosts(&self) -> Ipv4AddrRange {
786 let mut start = self.network();
787 let mut end = self.broadcast();
788
789 if self.prefix_len < 31 {
790 start = start.saturating_add(1);
791 end = end.saturating_sub(1);
792 }
793
794 Ipv4AddrRange::new(start, end)
795 }
796
797 /// Returns an `Iterator` over the subnets of this network with the
798 /// given prefix length.
799 ///
800 /// # Examples
801 ///
802 /// ```
803 /// # use ipnet::{Ipv4Net, PrefixLenError};
804 /// #
805 /// let net: Ipv4Net = "10.0.0.0/24".parse().unwrap();
806 /// assert_eq!(net.subnets(26).unwrap().collect::<Vec<Ipv4Net>>(), vec![
807 /// "10.0.0.0/26".parse::<Ipv4Net>().unwrap(),
808 /// "10.0.0.64/26".parse().unwrap(),
809 /// "10.0.0.128/26".parse().unwrap(),
810 /// "10.0.0.192/26".parse().unwrap(),
811 /// ]);
812 ///
813 /// let net: Ipv4Net = "10.0.0.0/30".parse().unwrap();
814 /// assert_eq!(net.subnets(32).unwrap().collect::<Vec<Ipv4Net>>(), vec![
815 /// "10.0.0.0/32".parse::<Ipv4Net>().unwrap(),
816 /// "10.0.0.1/32".parse().unwrap(),
817 /// "10.0.0.2/32".parse().unwrap(),
818 /// "10.0.0.3/32".parse().unwrap(),
819 /// ]);
820 ///
821 /// let net: Ipv4Net = "10.0.0.0/24".parse().unwrap();
822 /// assert_eq!(net.subnets(23), Err(PrefixLenError));
823 ///
824 /// let net: Ipv4Net = "10.0.0.0/24".parse().unwrap();
825 /// assert_eq!(net.subnets(33), Err(PrefixLenError));
826 /// ```
827 pub fn subnets(&self, new_prefix_len: u8) -> Result<Ipv4Subnets, PrefixLenError> {
828 if self.prefix_len > new_prefix_len || new_prefix_len > 32 {
829 return Err(PrefixLenError);
830 }
831
832 Ok(Ipv4Subnets::new(
833 self.network(),
834 self.broadcast(),
835 new_prefix_len,
836 ))
837 }
838
839 /// Test if a network address contains either another network
840 /// address or an IP address.
841 ///
842 /// # Examples
843 ///
844 /// ```
845 /// # use std::net::Ipv4Addr;
846 /// # use ipnet::Ipv4Net;
847 /// #
848 /// let net: Ipv4Net = "192.168.0.0/24".parse().unwrap();
849 /// let net_yes: Ipv4Net = "192.168.0.0/25".parse().unwrap();
850 /// let net_no: Ipv4Net = "192.168.0.0/23".parse().unwrap();
851 /// let ip_yes: Ipv4Addr = "192.168.0.1".parse().unwrap();
852 /// let ip_no: Ipv4Addr = "192.168.1.0".parse().unwrap();
853 ///
854 /// assert!(net.contains(&net));
855 /// assert!(net.contains(&net_yes));
856 /// assert!(!net.contains(&net_no));
857 /// assert!(net.contains(&ip_yes));
858 /// assert!(!net.contains(&ip_no));
859 /// ```
860 pub fn contains<T>(&self, other: T) -> bool where Self: Contains<T> {
861 Contains::contains(self, other)
862 }
863
864 // It is significantly faster to work on u32 than Ipv4Addr.
865 fn interval(&self) -> (u32, u32) {
866 (
867 u32::from(self.network()),
868 u32::from(self.broadcast()).saturating_add(1),
869 )
870 }
871
872 /// Aggregate a `Vec` of `Ipv4Net`s and return the result as a new
873 /// `Vec`.
874 ///
875 /// # Examples
876 ///
877 /// ```
878 /// # use ipnet::Ipv4Net;
879 /// #
880 /// let nets = vec![
881 /// "10.0.0.0/24".parse::<Ipv4Net>().unwrap(),
882 /// "10.0.1.0/24".parse().unwrap(),
883 /// "10.0.2.0/24".parse().unwrap(),
884 /// ];
885 ///
886 /// assert_eq!(Ipv4Net::aggregate(&nets), vec![
887 /// "10.0.0.0/23".parse::<Ipv4Net>().unwrap(),
888 /// "10.0.2.0/24".parse().unwrap(),
889 /// ]);
890 pub fn aggregate(networks: &Vec<Ipv4Net>) -> Vec<Ipv4Net> {
891 let mut intervals: Vec<(_, _)> = networks.iter().map(|n| n.interval()).collect();
892 intervals = merge_intervals(intervals);
893 let mut res: Vec<Ipv4Net> = Vec::new();
894
895 for (start, mut end) in intervals {
896 if end != core::u32::MAX {
897 end = end.saturating_sub(1)
898 }
899 let iter = Ipv4Subnets::new(start.into(), end.into(), 0);
900 res.extend(iter);
901 }
902 res
903 }
904}
905
906impl Default for Ipv4Net {
907 fn default() -> Self {
908 Self {
909 addr: Ipv4Addr::from(0),
910 prefix_len: 0,
911 }
912 }
913}
914
915impl fmt::Debug for Ipv4Net {
916 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
917 fmt::Display::fmt(self, f:fmt)
918 }
919}
920
921impl fmt::Display for Ipv4Net {
922 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
923 write!(fmt, "{}/{}", self.addr, self.prefix_len)
924 }
925}
926
927impl From<Ipv4Addr> for Ipv4Net {
928 fn from(addr: Ipv4Addr) -> Ipv4Net {
929 Ipv4Net { addr, prefix_len: 32 }
930 }
931}
932
933impl Ipv6Net {
934 /// Creates a new IPv6 network address from an `Ipv6Addr` and prefix
935 /// length.
936 ///
937 /// # Examples
938 ///
939 /// ```
940 /// use std::net::Ipv6Addr;
941 /// use ipnet::{Ipv6Net, PrefixLenError};
942 ///
943 /// let net = Ipv6Net::new(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), 24);
944 /// assert!(net.is_ok());
945 ///
946 /// let bad_prefix_len = Ipv6Net::new(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), 129);
947 /// assert_eq!(bad_prefix_len, Err(PrefixLenError));
948 /// ```
949 #[inline]
950 pub const fn new(ip: Ipv6Addr, prefix_len: u8) -> Result<Ipv6Net, PrefixLenError> {
951 if prefix_len > 128 {
952 return Err(PrefixLenError);
953 }
954 Ok(Ipv6Net { addr: ip, prefix_len: prefix_len })
955 }
956
957 /// Creates a new IPv6 network address from an `Ipv6Addr` and netmask.
958 ///
959 /// # Examples
960 ///
961 /// ```
962 /// use std::net::Ipv6Addr;
963 /// use ipnet::{Ipv6Net, PrefixLenError};
964 ///
965 /// let net = Ipv6Net::with_netmask(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), Ipv6Addr::from(0xffff_ff00_0000_0000_0000_0000_0000_0000));
966 /// assert!(net.is_ok());
967 ///
968 /// let bad_prefix_len = Ipv6Net::with_netmask(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), Ipv6Addr::from(0xffff_ff00_0000_0000_0001_0000_0000_0000));
969 /// assert_eq!(bad_prefix_len, Err(PrefixLenError));
970 /// ```
971 pub fn with_netmask(ip: Ipv6Addr, netmask: Ipv6Addr) -> Result<Ipv6Net, PrefixLenError> {
972 let prefix = ipv6_mask_to_prefix(netmask)?;
973 Self::new(ip, prefix)
974 }
975
976 /// Returns a copy of the network with the address truncated to the
977 /// prefix length.
978 ///
979 /// # Examples
980 ///
981 /// ```
982 /// # use ipnet::Ipv6Net;
983 /// #
984 /// assert_eq!(
985 /// "fd00::1:2:3:4/16".parse::<Ipv6Net>().unwrap().trunc(),
986 /// "fd00::/16".parse().unwrap()
987 /// );
988 /// ```
989 pub fn trunc(&self) -> Ipv6Net {
990 Ipv6Net::new(self.network(), self.prefix_len).unwrap()
991 }
992
993 /// Returns the address.
994 #[inline]
995 pub const fn addr(&self) -> Ipv6Addr {
996 self.addr
997 }
998
999 /// Returns the prefix length.
1000 #[inline]
1001 pub const fn prefix_len(&self) -> u8 {
1002 self.prefix_len
1003 }
1004
1005 /// Returns the maximum valid prefix length.
1006 #[inline]
1007 pub const fn max_prefix_len(&self) -> u8 {
1008 128
1009 }
1010
1011 /// Returns the network mask.
1012 ///
1013 /// # Examples
1014 ///
1015 /// ```
1016 /// # use std::net::Ipv6Addr;
1017 /// # use ipnet::Ipv6Net;
1018 /// #
1019 /// let net: Ipv6Net = "fd00::/24".parse().unwrap();
1020 /// assert_eq!(Ok(net.netmask()), "ffff:ff00::".parse());
1021 /// ```
1022 pub fn netmask(&self) -> Ipv6Addr {
1023 self.netmask_u128().into()
1024 }
1025
1026 fn netmask_u128(&self) -> u128 {
1027 u128::max_value().checked_shl((128 - self.prefix_len) as u32).unwrap_or(u128::min_value())
1028 }
1029
1030 /// Returns the host mask.
1031 ///
1032 /// # Examples
1033 ///
1034 /// ```
1035 /// # use std::net::Ipv6Addr;
1036 /// # use ipnet::Ipv6Net;
1037 /// #
1038 /// let net: Ipv6Net = "fd00::/24".parse().unwrap();
1039 /// assert_eq!(Ok(net.hostmask()), "::ff:ffff:ffff:ffff:ffff:ffff:ffff".parse());
1040 /// ```
1041 pub fn hostmask(&self) -> Ipv6Addr {
1042 self.hostmask_u128().into()
1043 }
1044
1045 fn hostmask_u128(&self) -> u128 {
1046 u128::max_value().checked_shr(self.prefix_len as u32).unwrap_or(u128::min_value())
1047 }
1048
1049 /// Returns the network address.
1050 ///
1051 /// # Examples
1052 ///
1053 /// ```
1054 /// # use std::net::Ipv6Addr;
1055 /// # use ipnet::Ipv6Net;
1056 /// #
1057 /// let net: Ipv6Net = "fd00:1234:5678::/24".parse().unwrap();
1058 /// assert_eq!(Ok(net.network()), "fd00:1200::".parse());
1059 /// ```
1060 pub fn network(&self) -> Ipv6Addr {
1061 (u128::from(self.addr) & self.netmask_u128()).into()
1062 }
1063
1064 /// Returns the last address.
1065 ///
1066 /// Technically there is no such thing as a broadcast address for
1067 /// IPv6. The name is used for consistency with colloquial usage.
1068 ///
1069 /// # Examples
1070 ///
1071 /// ```
1072 /// # use std::net::Ipv6Addr;
1073 /// # use ipnet::Ipv6Net;
1074 /// #
1075 /// let net: Ipv6Net = "fd00:1234:5678::/24".parse().unwrap();
1076 /// assert_eq!(Ok(net.broadcast()), "fd00:12ff:ffff:ffff:ffff:ffff:ffff:ffff".parse());
1077 /// ```
1078 pub fn broadcast(&self) -> Ipv6Addr {
1079 (u128::from(self.addr) | self.hostmask_u128()).into()
1080 }
1081
1082 /// Returns the `Ipv6Net` that contains this one.
1083 ///
1084 /// # Examples
1085 ///
1086 /// ```
1087 /// # use std::str::FromStr;
1088 /// # use ipnet::Ipv6Net;
1089 /// #
1090 /// let n1: Ipv6Net = "fd00:ff00::/24".parse().unwrap();
1091 /// let n2: Ipv6Net = "fd00:fe00::/23".parse().unwrap();
1092 /// let n3: Ipv6Net = "fd00:fe00::/0".parse().unwrap();
1093 ///
1094 /// assert_eq!(n1.supernet().unwrap(), n2);
1095 /// assert_eq!(n3.supernet(), None);
1096 /// ```
1097 pub fn supernet(&self) -> Option<Ipv6Net> {
1098 Ipv6Net::new(self.addr, self.prefix_len.wrapping_sub(1)).map(|n| n.trunc()).ok()
1099 }
1100
1101 /// Returns `true` if this network and the given network are
1102 /// children of the same supernet.
1103 ///
1104 /// # Examples
1105 ///
1106 /// ```
1107 /// # use ipnet::Ipv6Net;
1108 /// #
1109 /// let n1: Ipv6Net = "fd00::/18".parse().unwrap();
1110 /// let n2: Ipv6Net = "fd00:4000::/18".parse().unwrap();
1111 /// let n3: Ipv6Net = "fd00:8000::/18".parse().unwrap();
1112 ///
1113 /// assert!(n1.is_sibling(&n2));
1114 /// assert!(!n2.is_sibling(&n3));
1115 /// ```
1116 pub fn is_sibling(&self, other: &Ipv6Net) -> bool {
1117 self.prefix_len > 0 &&
1118 self.prefix_len == other.prefix_len &&
1119 self.supernet().unwrap().contains(other)
1120 }
1121
1122 /// Return an `Iterator` over the host addresses in this network.
1123 ///
1124 /// # Examples
1125 ///
1126 /// ```
1127 /// # use std::net::Ipv6Addr;
1128 /// # use ipnet::Ipv6Net;
1129 /// #
1130 /// let net: Ipv6Net = "fd00::/126".parse().unwrap();
1131 /// assert_eq!(net.hosts().collect::<Vec<Ipv6Addr>>(), vec![
1132 /// "fd00::".parse::<Ipv6Addr>().unwrap(),
1133 /// "fd00::1".parse().unwrap(),
1134 /// "fd00::2".parse().unwrap(),
1135 /// "fd00::3".parse().unwrap(),
1136 /// ]);
1137 /// ```
1138 pub fn hosts(&self) -> Ipv6AddrRange {
1139 Ipv6AddrRange::new(self.network(), self.broadcast())
1140 }
1141
1142 /// Returns an `Iterator` over the subnets of this network with the
1143 /// given prefix length.
1144 ///
1145 /// # Examples
1146 ///
1147 /// ```
1148 /// # use ipnet::{Ipv6Net, PrefixLenError};
1149 /// #
1150 /// let net: Ipv6Net = "fd00::/16".parse().unwrap();
1151 /// assert_eq!(net.subnets(18).unwrap().collect::<Vec<Ipv6Net>>(), vec![
1152 /// "fd00::/18".parse::<Ipv6Net>().unwrap(),
1153 /// "fd00:4000::/18".parse().unwrap(),
1154 /// "fd00:8000::/18".parse().unwrap(),
1155 /// "fd00:c000::/18".parse().unwrap(),
1156 /// ]);
1157 ///
1158 /// let net: Ipv6Net = "fd00::/126".parse().unwrap();
1159 /// assert_eq!(net.subnets(128).unwrap().collect::<Vec<Ipv6Net>>(), vec![
1160 /// "fd00::/128".parse::<Ipv6Net>().unwrap(),
1161 /// "fd00::1/128".parse().unwrap(),
1162 /// "fd00::2/128".parse().unwrap(),
1163 /// "fd00::3/128".parse().unwrap(),
1164 /// ]);
1165 ///
1166 /// let net: Ipv6Net = "fd00::/16".parse().unwrap();
1167 /// assert_eq!(net.subnets(15), Err(PrefixLenError));
1168 ///
1169 /// let net: Ipv6Net = "fd00::/16".parse().unwrap();
1170 /// assert_eq!(net.subnets(129), Err(PrefixLenError));
1171 /// ```
1172 pub fn subnets(&self, new_prefix_len: u8) -> Result<Ipv6Subnets, PrefixLenError> {
1173 if self.prefix_len > new_prefix_len || new_prefix_len > 128 {
1174 return Err(PrefixLenError);
1175 }
1176
1177 Ok(Ipv6Subnets::new(
1178 self.network(),
1179 self.broadcast(),
1180 new_prefix_len,
1181 ))
1182 }
1183
1184 /// Test if a network address contains either another network
1185 /// address or an IP address.
1186 ///
1187 /// # Examples
1188 ///
1189 /// ```
1190 /// # use std::net::Ipv6Addr;
1191 /// # use ipnet::Ipv6Net;
1192 /// #
1193 /// let net: Ipv6Net = "fd00::/16".parse().unwrap();
1194 /// let net_yes: Ipv6Net = "fd00::/17".parse().unwrap();
1195 /// let net_no: Ipv6Net = "fd00::/15".parse().unwrap();
1196 /// let ip_yes: Ipv6Addr = "fd00::1".parse().unwrap();
1197 /// let ip_no: Ipv6Addr = "fd01::".parse().unwrap();
1198 ///
1199 /// assert!(net.contains(&net));
1200 /// assert!(net.contains(&net_yes));
1201 /// assert!(!net.contains(&net_no));
1202 /// assert!(net.contains(&ip_yes));
1203 /// assert!(!net.contains(&ip_no));
1204 /// ```
1205 pub fn contains<T>(&self, other: T) -> bool where Self: Contains<T> {
1206 Contains::contains(self, other)
1207 }
1208
1209 // It is significantly faster to work on u128 that Ipv6Addr.
1210 fn interval(&self) -> (u128, u128) {
1211 (
1212 u128::from(self.network()),
1213 u128::from(self.broadcast()).saturating_add(1),
1214 )
1215 }
1216
1217 /// Aggregate a `Vec` of `Ipv6Net`s and return the result as a new
1218 /// `Vec`.
1219 ///
1220 /// # Examples
1221 ///
1222 /// ```
1223 /// # use ipnet::Ipv6Net;
1224 /// #
1225 /// let nets = vec![
1226 /// "fd00::/18".parse::<Ipv6Net>().unwrap(),
1227 /// "fd00:4000::/18".parse().unwrap(),
1228 /// "fd00:8000::/18".parse().unwrap(),
1229 /// ];
1230 /// assert_eq!(Ipv6Net::aggregate(&nets), vec![
1231 /// "fd00::/17".parse::<Ipv6Net>().unwrap(),
1232 /// "fd00:8000::/18".parse().unwrap(),
1233 /// ]);
1234 /// ```
1235 pub fn aggregate(networks: &Vec<Ipv6Net>) -> Vec<Ipv6Net> {
1236 let mut intervals: Vec<(_, _)> = networks.iter().map(|n| n.interval()).collect();
1237 intervals = merge_intervals(intervals);
1238 let mut res: Vec<Ipv6Net> = Vec::new();
1239
1240 for (start, mut end) in intervals {
1241 if end != core::u128::MAX {
1242 end = end.saturating_sub(1)
1243 }
1244 let iter = Ipv6Subnets::new(start.into(), end.into(), 0);
1245 res.extend(iter);
1246 }
1247 res
1248 }
1249}
1250
1251impl Default for Ipv6Net {
1252 fn default() -> Self {
1253 Self {
1254 addr: Ipv6Addr::from(0),
1255 prefix_len: 0,
1256 }
1257 }
1258}
1259
1260impl fmt::Debug for Ipv6Net {
1261 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1262 fmt::Display::fmt(self, f:fmt)
1263 }
1264}
1265
1266impl fmt::Display for Ipv6Net {
1267 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1268 write!(fmt, "{}/{}", self.addr, self.prefix_len)
1269 }
1270}
1271
1272impl From<Ipv6Addr> for Ipv6Net {
1273 fn from(addr: Ipv6Addr) -> Ipv6Net {
1274 Ipv6Net { addr, prefix_len: 128 }
1275 }
1276}
1277
1278/// Provides a method to test if a network address contains either
1279/// another network address or an IP address.
1280///
1281/// # Examples
1282///
1283/// ```
1284/// # use std::net::IpAddr;
1285/// # use ipnet::IpNet;
1286/// #
1287/// let n4_1: IpNet = "10.1.1.0/24".parse().unwrap();
1288/// let n4_2: IpNet = "10.1.1.0/26".parse().unwrap();
1289/// let n4_3: IpNet = "10.1.2.0/26".parse().unwrap();
1290/// let ip4_1: IpAddr = "10.1.1.1".parse().unwrap();
1291/// let ip4_2: IpAddr = "10.1.2.1".parse().unwrap();
1292///
1293/// let n6_1: IpNet = "fd00::/16".parse().unwrap();
1294/// let n6_2: IpNet = "fd00::/17".parse().unwrap();
1295/// let n6_3: IpNet = "fd01::/17".parse().unwrap();
1296/// let ip6_1: IpAddr = "fd00::1".parse().unwrap();
1297/// let ip6_2: IpAddr = "fd01::1".parse().unwrap();
1298///
1299/// assert!(n4_1.contains(&n4_2));
1300/// assert!(!n4_1.contains(&n4_3));
1301/// assert!(n4_1.contains(&ip4_1));
1302/// assert!(!n4_1.contains(&ip4_2));
1303///
1304/// assert!(n6_1.contains(&n6_2));
1305/// assert!(!n6_1.contains(&n6_3));
1306/// assert!(n6_1.contains(&ip6_1));
1307/// assert!(!n6_1.contains(&ip6_2));
1308///
1309/// assert!(!n4_1.contains(&n6_1) && !n6_1.contains(&n4_1));
1310/// assert!(!n4_1.contains(&ip6_1) && !n6_1.contains(&ip4_1));
1311/// ```
1312pub trait Contains<T> {
1313 fn contains(&self, other: T) -> bool;
1314}
1315
1316impl<'a> Contains<&'a IpNet> for IpNet {
1317 fn contains(&self, other: &IpNet) -> bool {
1318 match (*self, *other) {
1319 (IpNet::V4(ref a: &Ipv4Net), IpNet::V4(ref b: &Ipv4Net)) => a.contains(b),
1320 (IpNet::V6(ref a: &Ipv6Net), IpNet::V6(ref b: &Ipv6Net)) => a.contains(b),
1321 _ => false,
1322 }
1323 }
1324}
1325
1326impl<'a> Contains<&'a IpAddr> for IpNet {
1327 fn contains(&self, other: &IpAddr) -> bool {
1328 match (*self, *other) {
1329 (IpNet::V4(ref a: &Ipv4Net), IpAddr::V4(ref b: &Ipv4Addr)) => a.contains(b),
1330 (IpNet::V6(ref a: &Ipv6Net), IpAddr::V6(ref b: &Ipv6Addr)) => a.contains(b),
1331 _ => false,
1332 }
1333 }
1334}
1335
1336impl<'a> Contains<&'a Ipv4Net> for Ipv4Net {
1337 fn contains(&self, other: &'a Ipv4Net) -> bool {
1338 self.network() <= other.network() && other.broadcast() <= self.broadcast()
1339 }
1340}
1341
1342impl<'a> Contains<&'a Ipv4Addr> for Ipv4Net {
1343 fn contains(&self, other: &'a Ipv4Addr) -> bool {
1344 self.network() <= *other && *other <= self.broadcast()
1345 }
1346}
1347
1348impl<'a> Contains<&'a Ipv6Net> for Ipv6Net {
1349 fn contains(&self, other: &'a Ipv6Net) -> bool {
1350 self.network() <= other.network() && other.broadcast() <= self.broadcast()
1351 }
1352}
1353
1354impl<'a> Contains<&'a Ipv6Addr> for Ipv6Net {
1355 fn contains(&self, other: &'a Ipv6Addr) -> bool {
1356 self.network() <= *other && *other <= self.broadcast()
1357 }
1358}
1359
1360/// An `Iterator` that generates IP network addresses, either IPv4 or
1361/// IPv6.
1362///
1363/// Generates the subnets between the provided `start` and `end` IP
1364/// addresses inclusive of `end`. Each iteration generates the next
1365/// network address of the largest valid size it can, while using a
1366/// prefix length not less than `min_prefix_len`.
1367///
1368/// # Examples
1369///
1370/// ```
1371/// # use std::net::{Ipv4Addr, Ipv6Addr};
1372/// # use std::str::FromStr;
1373/// # use ipnet::{IpNet, IpSubnets, Ipv4Subnets, Ipv6Subnets};
1374/// let subnets = IpSubnets::from(Ipv4Subnets::new(
1375/// "10.0.0.0".parse().unwrap(),
1376/// "10.0.0.239".parse().unwrap(),
1377/// 26,
1378/// ));
1379///
1380/// assert_eq!(subnets.collect::<Vec<IpNet>>(), vec![
1381/// "10.0.0.0/26".parse().unwrap(),
1382/// "10.0.0.64/26".parse().unwrap(),
1383/// "10.0.0.128/26".parse().unwrap(),
1384/// "10.0.0.192/27".parse().unwrap(),
1385/// "10.0.0.224/28".parse().unwrap(),
1386/// ]);
1387///
1388/// let subnets = IpSubnets::from(Ipv6Subnets::new(
1389/// "fd00::".parse().unwrap(),
1390/// "fd00:ef:ffff:ffff:ffff:ffff:ffff:ffff".parse().unwrap(),
1391/// 26,
1392/// ));
1393///
1394/// assert_eq!(subnets.collect::<Vec<IpNet>>(), vec![
1395/// "fd00::/26".parse().unwrap(),
1396/// "fd00:40::/26".parse().unwrap(),
1397/// "fd00:80::/26".parse().unwrap(),
1398/// "fd00:c0::/27".parse().unwrap(),
1399/// "fd00:e0::/28".parse().unwrap(),
1400/// ]);
1401/// ```
1402#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
1403pub enum IpSubnets {
1404 V4(Ipv4Subnets),
1405 V6(Ipv6Subnets),
1406}
1407
1408/// An `Iterator` that generates IPv4 network addresses.
1409///
1410/// Generates the subnets between the provided `start` and `end` IP
1411/// addresses inclusive of `end`. Each iteration generates the next
1412/// network address of the largest valid size it can, while using a
1413/// prefix length not less than `min_prefix_len`.
1414///
1415/// # Examples
1416///
1417/// ```
1418/// # use std::net::Ipv4Addr;
1419/// # use std::str::FromStr;
1420/// # use ipnet::{Ipv4Net, Ipv4Subnets};
1421/// let subnets = Ipv4Subnets::new(
1422/// "10.0.0.0".parse().unwrap(),
1423/// "10.0.0.239".parse().unwrap(),
1424/// 26,
1425/// );
1426///
1427/// assert_eq!(subnets.collect::<Vec<Ipv4Net>>(), vec![
1428/// "10.0.0.0/26".parse().unwrap(),
1429/// "10.0.0.64/26".parse().unwrap(),
1430/// "10.0.0.128/26".parse().unwrap(),
1431/// "10.0.0.192/27".parse().unwrap(),
1432/// "10.0.0.224/28".parse().unwrap(),
1433/// ]);
1434/// ```
1435#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
1436pub struct Ipv4Subnets {
1437 start: Ipv4Addr,
1438 end: Ipv4Addr, // end is inclusive
1439 min_prefix_len: u8,
1440}
1441
1442/// An `Iterator` that generates IPv6 network addresses.
1443///
1444/// Generates the subnets between the provided `start` and `end` IP
1445/// addresses inclusive of `end`. Each iteration generates the next
1446/// network address of the largest valid size it can, while using a
1447/// prefix length not less than `min_prefix_len`.
1448///
1449/// # Examples
1450///
1451/// ```
1452/// # use std::net::Ipv6Addr;
1453/// # use std::str::FromStr;
1454/// # use ipnet::{Ipv6Net, Ipv6Subnets};
1455/// let subnets = Ipv6Subnets::new(
1456/// "fd00::".parse().unwrap(),
1457/// "fd00:ef:ffff:ffff:ffff:ffff:ffff:ffff".parse().unwrap(),
1458/// 26,
1459/// );
1460///
1461/// assert_eq!(subnets.collect::<Vec<Ipv6Net>>(), vec![
1462/// "fd00::/26".parse().unwrap(),
1463/// "fd00:40::/26".parse().unwrap(),
1464/// "fd00:80::/26".parse().unwrap(),
1465/// "fd00:c0::/27".parse().unwrap(),
1466/// "fd00:e0::/28".parse().unwrap(),
1467/// ]);
1468/// ```
1469#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
1470pub struct Ipv6Subnets {
1471 start: Ipv6Addr,
1472 end: Ipv6Addr, // end is inclusive
1473 min_prefix_len: u8,
1474}
1475
1476impl Ipv4Subnets {
1477 pub fn new(start: Ipv4Addr, end: Ipv4Addr, min_prefix_len: u8) -> Self {
1478 Ipv4Subnets {
1479 start: start,
1480 end: end,
1481 min_prefix_len: min_prefix_len,
1482 }
1483 }
1484}
1485
1486impl Ipv6Subnets {
1487 pub fn new(start: Ipv6Addr, end: Ipv6Addr, min_prefix_len: u8) -> Self {
1488 Ipv6Subnets {
1489 start: start,
1490 end: end,
1491 min_prefix_len: min_prefix_len,
1492 }
1493 }
1494}
1495
1496impl From<Ipv4Subnets> for IpSubnets {
1497 fn from(i: Ipv4Subnets) -> IpSubnets {
1498 IpSubnets::V4(i)
1499 }
1500}
1501
1502impl From<Ipv6Subnets> for IpSubnets {
1503 fn from(i: Ipv6Subnets) -> IpSubnets {
1504 IpSubnets::V6(i)
1505 }
1506}
1507
1508impl Iterator for IpSubnets {
1509 type Item = IpNet;
1510
1511 fn next(&mut self) -> Option<Self::Item> {
1512 match *self {
1513 IpSubnets::V4(ref mut a: &mut Ipv4Subnets) => a.next().map(IpNet::V4),
1514 IpSubnets::V6(ref mut a: &mut Ipv6Subnets) => a.next().map(IpNet::V6),
1515 }
1516 }
1517}
1518
1519fn next_ipv4_subnet(start: Ipv4Addr, end: Ipv4Addr, min_prefix_len: u8) -> Ipv4Net {
1520 let range: u32 = end.saturating_sub(start).saturating_add(1);
1521 if range == core::u32::MAX && min_prefix_len == 0 {
1522 Ipv4Net::new(ip:start, min_prefix_len).unwrap()
1523 }
1524 else {
1525 let range_bits: u32 = 32u32.saturating_sub(range.leading_zeros()).saturating_sub(1);
1526 let start_tz: u32 = u32::from(start).trailing_zeros();
1527 let new_prefix_len: u32 = 32 - min(v1:range_bits, v2:start_tz);
1528 let next_prefix_len: u8 = max(v1:new_prefix_len as u8, v2:min_prefix_len);
1529 Ipv4Net::new(ip:start, next_prefix_len).unwrap()
1530 }
1531}
1532
1533fn next_ipv6_subnet(start: Ipv6Addr, end: Ipv6Addr, min_prefix_len: u8) -> Ipv6Net {
1534 let range: u128 = end.saturating_sub(start).saturating_add(1);
1535 if range == core::u128::MAX && min_prefix_len == 0 {
1536 Ipv6Net::new(ip:start, min_prefix_len).unwrap()
1537 }
1538 else {
1539 let range: u128 = end.saturating_sub(start).saturating_add(1);
1540 let range_bits: u32 = 128u32.saturating_sub(range.leading_zeros()).saturating_sub(1);
1541 let start_tz: u32 = u128::from(start).trailing_zeros();
1542 let new_prefix_len: u32 = 128 - min(v1:range_bits, v2:start_tz);
1543 let next_prefix_len: u8 = max(v1:new_prefix_len as u8, v2:min_prefix_len);
1544 Ipv6Net::new(ip:start, next_prefix_len).unwrap()
1545 }
1546}
1547
1548impl Iterator for Ipv4Subnets {
1549 type Item = Ipv4Net;
1550
1551 fn next(&mut self) -> Option<Self::Item> {
1552 match self.start.partial_cmp(&self.end) {
1553 Some(Less) => {
1554 let next = next_ipv4_subnet(self.start, self.end, self.min_prefix_len);
1555 self.start = next.broadcast().saturating_add(1);
1556
1557 // Stop the iterator if we saturated self.start. This
1558 // check worsens performance slightly but overall this
1559 // approach of operating on Ipv4Addr types is faster
1560 // than what we were doing before using Ipv4Net.
1561 if self.start == next.broadcast() {
1562 self.end.replace_zero();
1563 }
1564 Some(next)
1565 },
1566 Some(Equal) => {
1567 let next = next_ipv4_subnet(self.start, self.end, self.min_prefix_len);
1568 self.start = next.broadcast().saturating_add(1);
1569 self.end.replace_zero();
1570 Some(next)
1571 },
1572 _ => None,
1573 }
1574 }
1575}
1576
1577impl Iterator for Ipv6Subnets {
1578 type Item = Ipv6Net;
1579
1580 fn next(&mut self) -> Option<Self::Item> {
1581 match self.start.partial_cmp(&self.end) {
1582 Some(Less) => {
1583 let next = next_ipv6_subnet(self.start, self.end, self.min_prefix_len);
1584 self.start = next.broadcast().saturating_add(1);
1585
1586 // Stop the iterator if we saturated self.start. This
1587 // check worsens performance slightly but overall this
1588 // approach of operating on Ipv6Addr types is faster
1589 // than what we were doing before using Ipv6Net.
1590 if self.start == next.broadcast() {
1591 self.end.replace_zero();
1592 }
1593 Some(next)
1594 },
1595 Some(Equal) => {
1596 let next = next_ipv6_subnet(self.start, self.end, self.min_prefix_len);
1597 self.start = next.broadcast().saturating_add(1);
1598 self.end.replace_zero();
1599 Some(next)
1600 },
1601 _ => None,
1602 }
1603 }
1604}
1605
1606impl FusedIterator for IpSubnets {}
1607impl FusedIterator for Ipv4Subnets {}
1608impl FusedIterator for Ipv6Subnets {}
1609
1610// Generic function for merging a vector of intervals.
1611fn merge_intervals<T: Copy + Ord>(mut intervals: Vec<(T, T)>) -> Vec<(T, T)> {
1612 if intervals.len() == 0 {
1613 return intervals;
1614 }
1615
1616 intervals.sort();
1617 let mut res: Vec<(T, T)> = Vec::new();
1618 let (mut start, mut end) = intervals[0];
1619
1620 let mut i = 1;
1621 let len = intervals.len();
1622 while i < len {
1623 let (next_start, next_end) = intervals[i];
1624 if end >= next_start {
1625 start = min(start, next_start);
1626 end = max(end, next_end);
1627 }
1628 else {
1629 res.push((start, end));
1630 start = next_start;
1631 end = next_end;
1632 }
1633 i += 1;
1634 }
1635
1636 res.push((start, end));
1637 res
1638}
1639
1640#[cfg(test)]
1641mod tests {
1642 use super::*;
1643
1644 macro_rules! make_ipnet_vec {
1645 ($($x:expr),*) => ( vec![$($x.parse::<IpNet>().unwrap(),)*] );
1646 ($($x:expr,)*) => ( make_ipnet_vec![$($x),*] );
1647 }
1648
1649 #[test]
1650 fn test_make_ipnet_vec() {
1651 assert_eq!(
1652 make_ipnet_vec![
1653 "10.1.1.1/32", "10.2.2.2/24", "10.3.3.3/16",
1654 "fd00::1/128", "fd00::2/127", "fd00::3/126",
1655 ],
1656 vec![
1657 "10.1.1.1/32".parse().unwrap(),
1658 "10.2.2.2/24".parse().unwrap(),
1659 "10.3.3.3/16".parse().unwrap(),
1660 "fd00::1/128".parse().unwrap(),
1661 "fd00::2/127".parse().unwrap(),
1662 "fd00::3/126".parse().unwrap(),
1663 ]
1664 );
1665 }
1666
1667 #[test]
1668 fn test_merge_intervals() {
1669 let v = vec![
1670 (0, 1), (1, 2), (2, 3),
1671 (11, 12), (13, 14), (10, 15), (11, 13),
1672 (20, 25), (24, 29),
1673 ];
1674
1675 let v_ok = vec![
1676 (0, 3),
1677 (10, 15),
1678 (20, 29),
1679 ];
1680
1681 let vv = vec![
1682 ([0, 1], [0, 2]), ([0, 2], [0, 3]), ([0, 0], [0, 1]),
1683 ([10, 15], [11, 0]), ([10, 0], [10, 16]),
1684 ];
1685
1686 let vv_ok = vec![
1687 ([0, 0], [0, 3]),
1688 ([10, 0], [11, 0]),
1689 ];
1690
1691 assert_eq!(merge_intervals(v), v_ok);
1692 assert_eq!(merge_intervals(vv), vv_ok);
1693 }
1694
1695 macro_rules! make_ipv4_subnets_test {
1696 ($name:ident, $start:expr, $end:expr, $min_prefix_len:expr, $($x:expr),*) => (
1697 #[test]
1698 fn $name() {
1699 let subnets = IpSubnets::from(Ipv4Subnets::new(
1700 $start.parse().unwrap(),
1701 $end.parse().unwrap(),
1702 $min_prefix_len,
1703 ));
1704 let results = make_ipnet_vec![$($x),*];
1705 assert_eq!(subnets.collect::<Vec<IpNet>>(), results);
1706 }
1707 );
1708 ($name:ident, $start:expr, $end:expr, $min_prefix_len:expr, $($x:expr,)*) => (
1709 make_ipv4_subnets_test!($name, $start, $end, $min_prefix_len, $($x),*);
1710 );
1711 }
1712
1713 macro_rules! make_ipv6_subnets_test {
1714 ($name:ident, $start:expr, $end:expr, $min_prefix_len:expr, $($x:expr),*) => (
1715 #[test]
1716 fn $name() {
1717 let subnets = IpSubnets::from(Ipv6Subnets::new(
1718 $start.parse().unwrap(),
1719 $end.parse().unwrap(),
1720 $min_prefix_len,
1721 ));
1722 let results = make_ipnet_vec![$($x),*];
1723 assert_eq!(subnets.collect::<Vec<IpNet>>(), results);
1724 }
1725 );
1726 ($name:ident, $start:expr, $end:expr, $min_prefix_len:expr, $($x:expr,)*) => (
1727 make_ipv6_subnets_test!($name, $start, $end, $min_prefix_len, $($x),*);
1728 );
1729 }
1730
1731 make_ipv4_subnets_test!(
1732 test_ipv4_subnets_zero_zero,
1733 "0.0.0.0", "0.0.0.0", 0,
1734 "0.0.0.0/32",
1735 );
1736
1737 make_ipv4_subnets_test!(
1738 test_ipv4_subnets_zero_max,
1739 "0.0.0.0", "255.255.255.255", 0,
1740 "0.0.0.0/0",
1741 );
1742
1743 make_ipv4_subnets_test!(
1744 test_ipv4_subnets_max_max,
1745 "255.255.255.255", "255.255.255.255", 0,
1746 "255.255.255.255/32",
1747 );
1748
1749 make_ipv4_subnets_test!(
1750 test_ipv4_subnets_none,
1751 "0.0.0.1", "0.0.0.0", 0,
1752 );
1753
1754 make_ipv4_subnets_test!(
1755 test_ipv4_subnets_one,
1756 "0.0.0.0", "0.0.0.1", 0,
1757 "0.0.0.0/31",
1758 );
1759
1760 make_ipv4_subnets_test!(
1761 test_ipv4_subnets_two,
1762 "0.0.0.0", "0.0.0.2", 0,
1763 "0.0.0.0/31",
1764 "0.0.0.2/32",
1765 );
1766
1767 make_ipv4_subnets_test!(
1768 test_ipv4_subnets_taper,
1769 "0.0.0.0", "0.0.0.10", 30,
1770 "0.0.0.0/30",
1771 "0.0.0.4/30",
1772 "0.0.0.8/31",
1773 "0.0.0.10/32",
1774 );
1775
1776 make_ipv6_subnets_test!(
1777 test_ipv6_subnets_zero_zero,
1778 "::", "::", 0,
1779 "::/128",
1780 );
1781
1782 make_ipv6_subnets_test!(
1783 test_ipv6_subnets_zero_max,
1784 "::", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0,
1785 "::/0",
1786 );
1787
1788 make_ipv6_subnets_test!(
1789 test_ipv6_subnets_max_max,
1790 "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0,
1791 "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128",
1792 );
1793
1794 make_ipv6_subnets_test!(
1795 test_ipv6_subnets_none,
1796 "::1", "::", 0,
1797 );
1798
1799 make_ipv6_subnets_test!(
1800 test_ipv6_subnets_one,
1801 "::", "::1", 0,
1802 "::/127",
1803 );
1804
1805 make_ipv6_subnets_test!(
1806 test_ipv6_subnets_two,
1807 "::", "::2", 0,
1808 "::/127",
1809 "::2/128",
1810 );
1811
1812 make_ipv6_subnets_test!(
1813 test_ipv6_subnets_taper,
1814 "::", "::a", 126,
1815 "::/126",
1816 "::4/126",
1817 "::8/127",
1818 "::a/128",
1819 );
1820
1821 #[test]
1822 fn test_aggregate() {
1823 let ip_nets = make_ipnet_vec![
1824 "10.0.0.0/24", "10.0.1.0/24", "10.0.1.1/24", "10.0.1.2/24",
1825 "10.0.2.0/24",
1826 "10.1.0.0/24", "10.1.1.0/24",
1827 "192.168.0.0/24", "192.168.1.0/24", "192.168.2.0/24", "192.168.3.0/24",
1828 "fd00::/32", "fd00:1::/32",
1829 "fd00:2::/32",
1830 ];
1831
1832 let ip_aggs = make_ipnet_vec![
1833 "10.0.0.0/23",
1834 "10.0.2.0/24",
1835 "10.1.0.0/23",
1836 "192.168.0.0/22",
1837 "fd00::/31",
1838 "fd00:2::/32",
1839 ];
1840
1841 let ipv4_nets: Vec<Ipv4Net> = ip_nets.iter().filter_map(|p| if let IpNet::V4(x) = *p { Some(x) } else { None }).collect();
1842 let ipv4_aggs: Vec<Ipv4Net> = ip_aggs.iter().filter_map(|p| if let IpNet::V4(x) = *p { Some(x) } else { None }).collect();
1843 let ipv6_nets: Vec<Ipv6Net> = ip_nets.iter().filter_map(|p| if let IpNet::V6(x) = *p { Some(x) } else { None }).collect();
1844 let ipv6_aggs: Vec<Ipv6Net> = ip_aggs.iter().filter_map(|p| if let IpNet::V6(x) = *p { Some(x) } else { None }).collect();
1845
1846 assert_eq!(IpNet::aggregate(&ip_nets), ip_aggs);
1847 assert_eq!(Ipv4Net::aggregate(&ipv4_nets), ipv4_aggs);
1848 assert_eq!(Ipv6Net::aggregate(&ipv6_nets), ipv6_aggs);
1849 }
1850
1851 #[test]
1852 fn test_aggregate_issue44() {
1853 let nets: Vec<Ipv4Net> = vec!["128.0.0.0/1".parse().unwrap()];
1854 assert_eq!(Ipv4Net::aggregate(&nets), nets);
1855
1856 let nets: Vec<Ipv4Net> = vec!["0.0.0.0/1".parse().unwrap(), "128.0.0.0/1".parse().unwrap()];
1857 assert_eq!(Ipv4Net::aggregate(&nets), vec!["0.0.0.0/0".parse().unwrap()]);
1858
1859 let nets: Vec<Ipv6Net> = vec!["8000::/1".parse().unwrap()];
1860 assert_eq!(Ipv6Net::aggregate(&nets), nets);
1861
1862 let nets: Vec<Ipv6Net> = vec!["::/1".parse().unwrap(), "8000::/1".parse().unwrap()];
1863 assert_eq!(Ipv6Net::aggregate(&nets), vec!["::/0".parse().unwrap()]);
1864 }
1865
1866 #[test]
1867 fn ipnet_default() {
1868 let ipnet: IpNet = "0.0.0.0/0".parse().unwrap();
1869 assert_eq!(ipnet, IpNet::default());
1870 }
1871
1872 #[test]
1873 fn ipv4net_default() {
1874 let ipnet: Ipv4Net = "0.0.0.0/0".parse().unwrap();
1875 assert_eq!(ipnet, Ipv4Net::default());
1876 }
1877
1878 #[test]
1879 fn ipv6net_default() {
1880 let ipnet: Ipv6Net = "::/0".parse().unwrap();
1881 assert_eq!(ipnet, Ipv6Net::default());
1882 }
1883}
1884