1 | //! Extensions to the standard IP address types for common operations. |
2 | //! |
3 | //! The [`IpAdd`], [`IpSub`], [`IpBitAnd`], [`IpBitOr`] traits extend |
4 | //! the `Ipv4Addr` and `Ipv6Addr` types with methods to perform these |
5 | //! operations. |
6 | |
7 | use core::cmp::Ordering::{Less, Equal}; |
8 | use core::iter::{FusedIterator, DoubleEndedIterator}; |
9 | use core::mem; |
10 | #[cfg (not(feature = "std" ))] |
11 | use core::net::{IpAddr, Ipv4Addr, Ipv6Addr}; |
12 | #[cfg (feature = "std" )] |
13 | use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; |
14 | |
15 | /// Provides a `saturating_add()` method for `Ipv4Addr` and `Ipv6Addr`. |
16 | /// |
17 | /// Adding an integer to an IP address returns the modified IP address. |
18 | /// A `u32` may added to an IPv4 address and a `u128` may be added to |
19 | /// an IPv6 address. |
20 | /// |
21 | /// # Examples |
22 | /// |
23 | /// ``` |
24 | /// # #![cfg_attr (not(feature = "std" ), feature(ip_in_core))] |
25 | /// # #[cfg (not(feature = "std" ))] |
26 | /// # use core::net::{Ipv4Addr, Ipv6Addr}; |
27 | /// # #[cfg (feature = "std" )] |
28 | /// use std::net::{Ipv4Addr, Ipv6Addr}; |
29 | /// use ipnet::IpAdd; |
30 | /// |
31 | /// let ip0: Ipv4Addr = "192.168.0.0" .parse().unwrap(); |
32 | /// let ip1: Ipv4Addr = "192.168.0.5" .parse().unwrap(); |
33 | /// let ip2: Ipv4Addr = "255.255.255.254" .parse().unwrap(); |
34 | /// let max: Ipv4Addr = "255.255.255.255" .parse().unwrap(); |
35 | /// |
36 | /// assert_eq!(ip0.saturating_add(5), ip1); |
37 | /// assert_eq!(ip2.saturating_add(1), max); |
38 | /// assert_eq!(ip2.saturating_add(5), max); |
39 | /// |
40 | /// let ip0: Ipv6Addr = "fd00::" .parse().unwrap(); |
41 | /// let ip1: Ipv6Addr = "fd00::5" .parse().unwrap(); |
42 | /// let ip2: Ipv6Addr = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe" .parse().unwrap(); |
43 | /// let max: Ipv6Addr = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" .parse().unwrap(); |
44 | /// |
45 | /// assert_eq!(ip0.saturating_add(5), ip1); |
46 | /// assert_eq!(ip2.saturating_add(1), max); |
47 | /// assert_eq!(ip2.saturating_add(5), max); |
48 | /// ``` |
49 | pub trait IpAdd<RHS = Self> { |
50 | type Output; |
51 | fn saturating_add(self, rhs: RHS) -> Self::Output; |
52 | } |
53 | |
54 | /// Provides a `saturating_sub()` method for `Ipv4Addr` and `Ipv6Addr`. |
55 | /// |
56 | /// Subtracting an integer from an IP address returns the modified IP |
57 | /// address. A `u32` may be subtracted from an IPv4 address and a `u128` |
58 | /// may be subtracted from an IPv6 address. |
59 | /// |
60 | /// Subtracting an IP address from another IP address of the same type |
61 | /// returns an integer of the appropriate width. A `u32` for IPv4 and a |
62 | /// `u128` for IPv6. Subtracting IP addresses is useful for getting |
63 | /// the range between two IP addresses. |
64 | /// |
65 | /// # Examples |
66 | /// |
67 | /// ``` |
68 | /// # #![cfg_attr (not(feature = "std" ), feature(ip_in_core))] |
69 | /// # #[cfg (not(feature = "std" ))] |
70 | /// # use core::net::{Ipv4Addr, Ipv6Addr}; |
71 | /// # #[cfg (feature = "std" )] |
72 | /// use std::net::{Ipv4Addr, Ipv6Addr}; |
73 | /// use ipnet::IpSub; |
74 | /// |
75 | /// let min: Ipv4Addr = "0.0.0.0" .parse().unwrap(); |
76 | /// let ip1: Ipv4Addr = "192.168.1.5" .parse().unwrap(); |
77 | /// let ip2: Ipv4Addr = "192.168.1.100" .parse().unwrap(); |
78 | /// |
79 | /// assert_eq!(min.saturating_sub(ip1), 0); |
80 | /// assert_eq!(ip2.saturating_sub(ip1), 95); |
81 | /// assert_eq!(min.saturating_sub(5), min); |
82 | /// assert_eq!(ip2.saturating_sub(95), ip1); |
83 | /// |
84 | /// let min: Ipv6Addr = "::" .parse().unwrap(); |
85 | /// let ip1: Ipv6Addr = "fd00::5" .parse().unwrap(); |
86 | /// let ip2: Ipv6Addr = "fd00::64" .parse().unwrap(); |
87 | /// |
88 | /// assert_eq!(min.saturating_sub(ip1), 0); |
89 | /// assert_eq!(ip2.saturating_sub(ip1), 95); |
90 | /// assert_eq!(min.saturating_sub(5u128), min); |
91 | /// assert_eq!(ip2.saturating_sub(95u128), ip1); |
92 | /// ``` |
93 | pub trait IpSub<RHS = Self> { |
94 | type Output; |
95 | fn saturating_sub(self, rhs: RHS) -> Self::Output; |
96 | } |
97 | |
98 | /// Provides a `bitand()` method for `Ipv4Addr` and `Ipv6Addr`. |
99 | /// |
100 | /// # Examples |
101 | /// |
102 | /// ``` |
103 | /// # #![cfg_attr (not(feature = "std" ), feature(ip_in_core))] |
104 | /// # #[cfg (not(feature = "std" ))] |
105 | /// # use core::net::{Ipv4Addr, Ipv6Addr}; |
106 | /// # #[cfg (feature = "std" )] |
107 | /// use std::net::{Ipv4Addr, Ipv6Addr}; |
108 | /// use ipnet::IpBitAnd; |
109 | /// |
110 | /// let ip: Ipv4Addr = "192.168.1.1" .parse().unwrap(); |
111 | /// let mask: Ipv4Addr = "255.255.0.0" .parse().unwrap(); |
112 | /// let res: Ipv4Addr = "192.168.0.0" .parse().unwrap(); |
113 | /// |
114 | /// assert_eq!(ip.bitand(mask), res); |
115 | /// assert_eq!(ip.bitand(0xffff0000), res); |
116 | /// |
117 | /// let ip: Ipv6Addr = "fd00:1234::1" .parse().unwrap(); |
118 | /// let mask: Ipv6Addr = "ffff::" .parse().unwrap(); |
119 | /// let res: Ipv6Addr = "fd00::" .parse().unwrap(); |
120 | /// |
121 | /// assert_eq!(ip.bitand(mask), res); |
122 | /// assert_eq!(ip.bitand(0xffff_0000_0000_0000_0000_0000_0000_0000u128), res); |
123 | /// ``` |
124 | pub trait IpBitAnd<RHS = Self> { |
125 | type Output; |
126 | fn bitand(self, rhs: RHS) -> Self::Output; |
127 | } |
128 | |
129 | /// Provides a `bitor()` method for `Ipv4Addr` and `Ipv6Addr`. |
130 | /// |
131 | /// # Examples |
132 | /// |
133 | /// ``` |
134 | /// # #![cfg_attr (not(feature = "std" ), feature(ip_in_core))] |
135 | /// # #[cfg (not(feature = "std" ))] |
136 | /// # use core::net::{Ipv4Addr, Ipv6Addr}; |
137 | /// # #[cfg (feature = "std" )] |
138 | /// use std::net::{Ipv4Addr, Ipv6Addr}; |
139 | /// use ipnet::IpBitOr; |
140 | /// |
141 | /// let ip: Ipv4Addr = "10.1.1.1" .parse().unwrap(); |
142 | /// let mask: Ipv4Addr = "0.0.0.255" .parse().unwrap(); |
143 | /// let res: Ipv4Addr = "10.1.1.255" .parse().unwrap(); |
144 | /// |
145 | /// assert_eq!(ip.bitor(mask), res); |
146 | /// assert_eq!(ip.bitor(0x000000ff), res); |
147 | /// |
148 | /// let ip: Ipv6Addr = "fd00::1" .parse().unwrap(); |
149 | /// let mask: Ipv6Addr = "::ffff:ffff" .parse().unwrap(); |
150 | /// let res: Ipv6Addr = "fd00::ffff:ffff" .parse().unwrap(); |
151 | /// |
152 | /// assert_eq!(ip.bitor(mask), res); |
153 | /// assert_eq!(ip.bitor(u128::from(0xffffffffu32)), res); |
154 | /// ``` |
155 | pub trait IpBitOr<RHS = Self> { |
156 | type Output; |
157 | fn bitor(self, rhs: RHS) -> Self::Output; |
158 | } |
159 | |
160 | macro_rules! ip_add_impl { |
161 | ($lhs:ty, $rhs:ty, $output:ty, $inner:ty) => ( |
162 | impl IpAdd<$rhs> for $lhs { |
163 | type Output = $output; |
164 | |
165 | fn saturating_add(self, rhs: $rhs) -> $output { |
166 | let lhs: $inner = self.into(); |
167 | let rhs: $inner = rhs.into(); |
168 | (lhs.saturating_add(rhs.into())).into() |
169 | } |
170 | } |
171 | ) |
172 | } |
173 | |
174 | macro_rules! ip_sub_impl { |
175 | ($lhs:ty, $rhs:ty, $output:ty, $inner:ty) => ( |
176 | impl IpSub<$rhs> for $lhs { |
177 | type Output = $output; |
178 | |
179 | fn saturating_sub(self, rhs: $rhs) -> $output { |
180 | let lhs: $inner = self.into(); |
181 | let rhs: $inner = rhs.into(); |
182 | (lhs.saturating_sub(rhs.into())).into() |
183 | } |
184 | } |
185 | ) |
186 | } |
187 | |
188 | ip_add_impl!(Ipv4Addr, u32, Ipv4Addr, u32); |
189 | ip_add_impl!(Ipv6Addr, u128, Ipv6Addr, u128); |
190 | |
191 | ip_sub_impl!(Ipv4Addr, Ipv4Addr, u32, u32); |
192 | ip_sub_impl!(Ipv4Addr, u32, Ipv4Addr, u32); |
193 | ip_sub_impl!(Ipv6Addr, Ipv6Addr, u128, u128); |
194 | ip_sub_impl!(Ipv6Addr, u128, Ipv6Addr, u128); |
195 | |
196 | macro_rules! ip_bitops_impl { |
197 | ($(($lhs:ty, $rhs:ty, $t:ty),)*) => { |
198 | $( |
199 | impl IpBitAnd<$rhs> for $lhs { |
200 | type Output = $lhs; |
201 | |
202 | fn bitand(self, rhs: $rhs) -> $lhs { |
203 | let lhs: $t = self.into(); |
204 | let rhs: $t = rhs.into(); |
205 | (lhs & rhs).into() |
206 | } |
207 | } |
208 | |
209 | impl IpBitOr<$rhs> for $lhs { |
210 | type Output = $lhs; |
211 | |
212 | fn bitor(self, rhs: $rhs) -> $lhs { |
213 | let lhs: $t = self.into(); |
214 | let rhs: $t = rhs.into(); |
215 | (lhs | rhs).into() |
216 | } |
217 | } |
218 | )* |
219 | } |
220 | } |
221 | |
222 | ip_bitops_impl! { |
223 | (Ipv4Addr, Ipv4Addr, u32), |
224 | (Ipv4Addr, u32, u32), |
225 | (Ipv6Addr, Ipv6Addr, u128), |
226 | (Ipv6Addr, u128, u128), |
227 | } |
228 | |
229 | // A barebones copy of the current unstable Step trait used by the |
230 | // IpAddrRange, Ipv4AddrRange, and Ipv6AddrRange types below, and the |
231 | // Subnets types in ipnet. |
232 | pub trait IpStep { |
233 | fn replace_one(&mut self) -> Self; |
234 | fn replace_zero(&mut self) -> Self; |
235 | fn add_one(&self) -> Self; |
236 | fn sub_one(&self) -> Self; |
237 | } |
238 | |
239 | impl IpStep for Ipv4Addr { |
240 | fn replace_one(&mut self) -> Self { |
241 | mem::replace(self, src:Ipv4Addr::new(a:0, b:0, c:0, d:1)) |
242 | } |
243 | fn replace_zero(&mut self) -> Self { |
244 | mem::replace(self, src:Ipv4Addr::new(a:0, b:0, c:0, d:0)) |
245 | } |
246 | fn add_one(&self) -> Self { |
247 | self.saturating_add(1) |
248 | } |
249 | fn sub_one(&self) -> Self { |
250 | self.saturating_sub(1) |
251 | } |
252 | } |
253 | |
254 | impl IpStep for Ipv6Addr { |
255 | fn replace_one(&mut self) -> Self { |
256 | mem::replace(self, src:Ipv6Addr::new(a:0, b:0, c:0, d:0, e:0, f:0, g:0, h:1)) |
257 | } |
258 | fn replace_zero(&mut self) -> Self { |
259 | mem::replace(self, src:Ipv6Addr::new(a:0, b:0, c:0, d:0, e:0, f:0, g:0, h:0)) |
260 | } |
261 | fn add_one(&self) -> Self { |
262 | self.saturating_add(1) |
263 | } |
264 | fn sub_one(&self) -> Self { |
265 | self.saturating_sub(1) |
266 | } |
267 | } |
268 | |
269 | /// An `Iterator` over a range of IP addresses, either IPv4 or IPv6. |
270 | /// |
271 | /// # Examples |
272 | /// |
273 | /// ``` |
274 | /// use std::net::IpAddr; |
275 | /// use ipnet::{IpAddrRange, Ipv4AddrRange, Ipv6AddrRange}; |
276 | /// |
277 | /// let hosts = IpAddrRange::from(Ipv4AddrRange::new( |
278 | /// "10.0.0.0" .parse().unwrap(), |
279 | /// "10.0.0.3" .parse().unwrap(), |
280 | /// )); |
281 | /// |
282 | /// assert_eq!(hosts.collect::<Vec<IpAddr>>(), vec![ |
283 | /// "10.0.0.0" .parse::<IpAddr>().unwrap(), |
284 | /// "10.0.0.1" .parse().unwrap(), |
285 | /// "10.0.0.2" .parse().unwrap(), |
286 | /// "10.0.0.3" .parse().unwrap(), |
287 | /// ]); |
288 | /// |
289 | /// let hosts = IpAddrRange::from(Ipv6AddrRange::new( |
290 | /// "fd00::" .parse().unwrap(), |
291 | /// "fd00::3" .parse().unwrap(), |
292 | /// )); |
293 | /// |
294 | /// assert_eq!(hosts.collect::<Vec<IpAddr>>(), vec![ |
295 | /// "fd00::0" .parse::<IpAddr>().unwrap(), |
296 | /// "fd00::1" .parse().unwrap(), |
297 | /// "fd00::2" .parse().unwrap(), |
298 | /// "fd00::3" .parse().unwrap(), |
299 | /// ]); |
300 | /// ``` |
301 | #[derive (Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] |
302 | pub enum IpAddrRange { |
303 | V4(Ipv4AddrRange), |
304 | V6(Ipv6AddrRange), |
305 | } |
306 | |
307 | /// An `Iterator` over a range of IPv4 addresses. |
308 | /// |
309 | /// # Examples |
310 | /// |
311 | /// ``` |
312 | /// # #![cfg_attr (not(feature = "std" ), feature(ip_in_core))] |
313 | /// # #[cfg (not(feature = "std" ))] |
314 | /// # use core::net::Ipv4Addr; |
315 | /// # #[cfg (feature = "std" )] |
316 | /// use std::net::Ipv4Addr; |
317 | /// use ipnet::Ipv4AddrRange; |
318 | /// |
319 | /// let hosts = Ipv4AddrRange::new( |
320 | /// "10.0.0.0" .parse().unwrap(), |
321 | /// "10.0.0.3" .parse().unwrap(), |
322 | /// ); |
323 | /// |
324 | /// assert_eq!(hosts.collect::<Vec<Ipv4Addr>>(), vec![ |
325 | /// "10.0.0.0" .parse::<Ipv4Addr>().unwrap(), |
326 | /// "10.0.0.1" .parse().unwrap(), |
327 | /// "10.0.0.2" .parse().unwrap(), |
328 | /// "10.0.0.3" .parse().unwrap(), |
329 | /// ]); |
330 | /// ``` |
331 | #[derive (Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] |
332 | pub struct Ipv4AddrRange { |
333 | start: Ipv4Addr, |
334 | end: Ipv4Addr, |
335 | } |
336 | |
337 | /// An `Iterator` over a range of IPv6 addresses. |
338 | /// |
339 | /// # Examples |
340 | /// |
341 | /// ``` |
342 | /// # #![cfg_attr (not(feature = "std" ), feature(ip_in_core))] |
343 | /// # #[cfg (not(feature = "std" ))] |
344 | /// # use core::net::Ipv6Addr; |
345 | /// # #[cfg (feature = "std" )] |
346 | /// use std::net::Ipv6Addr; |
347 | /// use ipnet::Ipv6AddrRange; |
348 | /// |
349 | /// let hosts = Ipv6AddrRange::new( |
350 | /// "fd00::" .parse().unwrap(), |
351 | /// "fd00::3" .parse().unwrap(), |
352 | /// ); |
353 | /// |
354 | /// assert_eq!(hosts.collect::<Vec<Ipv6Addr>>(), vec![ |
355 | /// "fd00::" .parse::<Ipv6Addr>().unwrap(), |
356 | /// "fd00::1" .parse().unwrap(), |
357 | /// "fd00::2" .parse().unwrap(), |
358 | /// "fd00::3" .parse().unwrap(), |
359 | /// ]); |
360 | /// ``` |
361 | #[derive (Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] |
362 | pub struct Ipv6AddrRange { |
363 | start: Ipv6Addr, |
364 | end: Ipv6Addr, |
365 | } |
366 | |
367 | impl From<Ipv4AddrRange> for IpAddrRange { |
368 | fn from(i: Ipv4AddrRange) -> IpAddrRange { |
369 | IpAddrRange::V4(i) |
370 | } |
371 | } |
372 | |
373 | impl From<Ipv6AddrRange> for IpAddrRange { |
374 | fn from(i: Ipv6AddrRange) -> IpAddrRange { |
375 | IpAddrRange::V6(i) |
376 | } |
377 | } |
378 | |
379 | impl Ipv4AddrRange { |
380 | pub fn new(start: Ipv4Addr, end: Ipv4Addr) -> Self { |
381 | Ipv4AddrRange { |
382 | start: start, |
383 | end: end, |
384 | } |
385 | } |
386 | /// Counts the number of Ipv4Addr in this range. |
387 | /// This method will never overflow or panic. |
388 | fn count_u64(&self) -> u64 { |
389 | match self.start.partial_cmp(&self.end) { |
390 | Some(Less) => { |
391 | let count: u32 = self.end.saturating_sub(self.start); |
392 | let count: u64 = count as u64 + 1; // Never overflows |
393 | count |
394 | }, |
395 | Some(Equal) => 1, |
396 | _ => 0, |
397 | } |
398 | } |
399 | } |
400 | |
401 | impl Ipv6AddrRange { |
402 | pub fn new(start: Ipv6Addr, end: Ipv6Addr) -> Self { |
403 | Ipv6AddrRange { |
404 | start: start, |
405 | end: end, |
406 | } |
407 | } |
408 | /// Counts the number of Ipv6Addr in this range. |
409 | /// This method may overflow or panic if start |
410 | /// is 0 and end is u128::MAX |
411 | fn count_u128(&self) -> u128 { |
412 | match self.start.partial_cmp(&self.end) { |
413 | Some(Less) => { |
414 | let count = self.end.saturating_sub(self.start); |
415 | // May overflow or panic |
416 | count + 1 |
417 | }, |
418 | Some(Equal) => 1, |
419 | _ => 0, |
420 | } |
421 | } |
422 | /// True only if count_u128 does not overflow |
423 | fn can_count_u128(&self) -> bool { |
424 | self.start != Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0) |
425 | || self.end != Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff) |
426 | } |
427 | } |
428 | |
429 | impl Iterator for IpAddrRange { |
430 | type Item = IpAddr; |
431 | |
432 | fn next(&mut self) -> Option<Self::Item> { |
433 | match *self { |
434 | IpAddrRange::V4(ref mut a) => a.next().map(IpAddr::V4), |
435 | IpAddrRange::V6(ref mut a) => a.next().map(IpAddr::V6), |
436 | } |
437 | } |
438 | |
439 | fn count(self) -> usize { |
440 | match self { |
441 | IpAddrRange::V4(a) => a.count(), |
442 | IpAddrRange::V6(a) => a.count(), |
443 | } |
444 | } |
445 | |
446 | fn last(self) -> Option<Self::Item> { |
447 | match self { |
448 | IpAddrRange::V4(a) => a.last().map(IpAddr::V4), |
449 | IpAddrRange::V6(a) => a.last().map(IpAddr::V6), |
450 | } |
451 | } |
452 | |
453 | fn max(self) -> Option<Self::Item> { |
454 | match self { |
455 | IpAddrRange::V4(a) => Iterator::max(a).map(IpAddr::V4), |
456 | IpAddrRange::V6(a) => Iterator::max(a).map(IpAddr::V6), |
457 | } |
458 | } |
459 | |
460 | fn min(self) -> Option<Self::Item> { |
461 | match self { |
462 | IpAddrRange::V4(a) => Iterator::min(a).map(IpAddr::V4), |
463 | IpAddrRange::V6(a) => Iterator::min(a).map(IpAddr::V6), |
464 | } |
465 | } |
466 | |
467 | fn nth(&mut self, n: usize) -> Option<Self::Item> { |
468 | match *self { |
469 | IpAddrRange::V4(ref mut a) => a.nth(n).map(IpAddr::V4), |
470 | IpAddrRange::V6(ref mut a) => a.nth(n).map(IpAddr::V6), |
471 | } |
472 | } |
473 | |
474 | fn size_hint(&self) -> (usize, Option<usize>) { |
475 | match *self { |
476 | IpAddrRange::V4(ref a) => a.size_hint(), |
477 | IpAddrRange::V6(ref a) => a.size_hint(), |
478 | } |
479 | } |
480 | } |
481 | |
482 | impl Iterator for Ipv4AddrRange { |
483 | type Item = Ipv4Addr; |
484 | |
485 | fn next(&mut self) -> Option<Self::Item> { |
486 | match self.start.partial_cmp(&self.end) { |
487 | Some(Less) => { |
488 | let next = self.start.add_one(); |
489 | Some(mem::replace(&mut self.start, next)) |
490 | }, |
491 | Some(Equal) => { |
492 | self.end.replace_zero(); |
493 | Some(self.start.replace_one()) |
494 | }, |
495 | _ => None, |
496 | } |
497 | } |
498 | |
499 | #[allow (arithmetic_overflow)] |
500 | fn count(self) -> usize { |
501 | match self.start.partial_cmp(&self.end) { |
502 | Some(Less) => { |
503 | // Adding one here might overflow u32. |
504 | // Instead, wait until after converted to usize |
505 | let count: u32 = self.end.saturating_sub(self.start); |
506 | |
507 | // usize might only be 16 bits, |
508 | // so need to explicitly check for overflow. |
509 | // 'usize::MAX as u32' is okay here - if usize is 64 bits, |
510 | // value truncates to u32::MAX |
511 | if count <= core::usize::MAX as u32 { |
512 | count as usize + 1 |
513 | // count overflows usize |
514 | } else { |
515 | // emulate standard overflow/panic behavior |
516 | core::usize::MAX + 2 + count as usize |
517 | } |
518 | }, |
519 | Some(Equal) => 1, |
520 | _ => 0 |
521 | } |
522 | } |
523 | |
524 | fn last(self) -> Option<Self::Item> { |
525 | match self.start.partial_cmp(&self.end) { |
526 | Some(Less) | Some(Equal) => Some(self.end), |
527 | _ => None, |
528 | } |
529 | } |
530 | |
531 | fn max(self) -> Option<Self::Item> { |
532 | self.last() |
533 | } |
534 | |
535 | fn min(self) -> Option<Self::Item> { |
536 | match self.start.partial_cmp(&self.end) { |
537 | Some(Less) | Some(Equal) => Some(self.start), |
538 | _ => None |
539 | } |
540 | } |
541 | |
542 | fn nth(&mut self, n: usize) -> Option<Self::Item> { |
543 | let n = n as u64; |
544 | let count = self.count_u64(); |
545 | if n >= count { |
546 | self.end.replace_zero(); |
547 | self.start.replace_one(); |
548 | None |
549 | } else if n == count - 1 { |
550 | self.start.replace_one(); |
551 | Some(self.end.replace_zero()) |
552 | } else { |
553 | let nth = self.start.saturating_add(n as u32); |
554 | self.start = nth.add_one(); |
555 | Some(nth) |
556 | } |
557 | } |
558 | |
559 | fn size_hint(&self) -> (usize, Option<usize>) { |
560 | let count = self.count_u64(); |
561 | if count > core::usize::MAX as u64 { |
562 | (core::usize::MAX, None) |
563 | } else { |
564 | let count = count as usize; |
565 | (count, Some(count)) |
566 | } |
567 | } |
568 | } |
569 | |
570 | impl Iterator for Ipv6AddrRange { |
571 | type Item = Ipv6Addr; |
572 | |
573 | fn next(&mut self) -> Option<Self::Item> { |
574 | match self.start.partial_cmp(&self.end) { |
575 | Some(Less) => { |
576 | let next = self.start.add_one(); |
577 | Some(mem::replace(&mut self.start, next)) |
578 | }, |
579 | Some(Equal) => { |
580 | self.end.replace_zero(); |
581 | Some(self.start.replace_one()) |
582 | }, |
583 | _ => None, |
584 | } |
585 | } |
586 | |
587 | #[allow (arithmetic_overflow)] |
588 | fn count(self) -> usize { |
589 | let count = self.count_u128(); |
590 | // count fits in usize |
591 | if count <= core::usize::MAX as u128 { |
592 | count as usize |
593 | // count does not fit in usize |
594 | } else { |
595 | // emulate standard overflow/panic behavior |
596 | core::usize::MAX + 1 + count as usize |
597 | } |
598 | } |
599 | |
600 | fn last(self) -> Option<Self::Item> { |
601 | match self.start.partial_cmp(&self.end) { |
602 | Some(Less) | Some(Equal) => Some(self.end), |
603 | _ => None, |
604 | } |
605 | } |
606 | |
607 | fn max(self) -> Option<Self::Item> { |
608 | self.last() |
609 | } |
610 | |
611 | fn min(self) -> Option<Self::Item> { |
612 | match self.start.partial_cmp(&self.end) { |
613 | Some(Less) | Some(Equal) => Some(self.start), |
614 | _ => None |
615 | } |
616 | } |
617 | |
618 | fn nth(&mut self, n: usize) -> Option<Self::Item> { |
619 | let n = n as u128; |
620 | if self.can_count_u128() { |
621 | let count = self.count_u128(); |
622 | if n >= count { |
623 | self.end.replace_zero(); |
624 | self.start.replace_one(); |
625 | None |
626 | } else if n == count - 1 { |
627 | self.start.replace_one(); |
628 | Some(self.end.replace_zero()) |
629 | } else { |
630 | let nth = self.start.saturating_add(n); |
631 | self.start = nth.add_one(); |
632 | Some(nth) |
633 | } |
634 | // count overflows u128; n is 64-bits at most. |
635 | // therefore, n can never exceed count |
636 | } else { |
637 | let nth = self.start.saturating_add(n); |
638 | self.start = nth.add_one(); |
639 | Some(nth) |
640 | } |
641 | } |
642 | |
643 | fn size_hint(&self) -> (usize, Option<usize>) { |
644 | if self.can_count_u128() { |
645 | let count = self.count_u128(); |
646 | if count > core::usize::MAX as u128 { |
647 | (core::usize::MAX, None) |
648 | } else { |
649 | let count = count as usize; |
650 | (count, Some(count)) |
651 | } |
652 | } else { |
653 | (core::usize::MAX, None) |
654 | } |
655 | } |
656 | } |
657 | |
658 | impl DoubleEndedIterator for IpAddrRange { |
659 | fn next_back(&mut self) -> Option<Self::Item> { |
660 | match *self { |
661 | IpAddrRange::V4(ref mut a: &mut Ipv4AddrRange) => a.next_back().map(IpAddr::V4), |
662 | IpAddrRange::V6(ref mut a: &mut Ipv6AddrRange) => a.next_back().map(IpAddr::V6), |
663 | } |
664 | } |
665 | fn nth_back(&mut self, n: usize) -> Option<Self::Item> { |
666 | match *self { |
667 | IpAddrRange::V4(ref mut a: &mut Ipv4AddrRange) => a.nth_back(n).map(IpAddr::V4), |
668 | IpAddrRange::V6(ref mut a: &mut Ipv6AddrRange) => a.nth_back(n).map(IpAddr::V6), |
669 | } |
670 | } |
671 | } |
672 | |
673 | impl DoubleEndedIterator for Ipv4AddrRange { |
674 | fn next_back(&mut self) -> Option<Self::Item> { |
675 | match self.start.partial_cmp(&self.end) { |
676 | Some(Less) => { |
677 | let next_back = self.end.sub_one(); |
678 | Some(mem::replace(&mut self.end, next_back)) |
679 | }, |
680 | Some(Equal) => { |
681 | self.end.replace_zero(); |
682 | Some(self.start.replace_one()) |
683 | }, |
684 | _ => None |
685 | } |
686 | } |
687 | fn nth_back(&mut self, n: usize) -> Option<Self::Item> { |
688 | let n = n as u64; |
689 | let count = self.count_u64(); |
690 | if n >= count { |
691 | self.end.replace_zero(); |
692 | self.start.replace_one(); |
693 | None |
694 | } else if n == count - 1 { |
695 | self.end.replace_zero(); |
696 | Some(self.start.replace_one()) |
697 | } else { |
698 | let nth_back = self.end.saturating_sub(n as u32); |
699 | self.end = nth_back.sub_one(); |
700 | Some(nth_back) |
701 | } |
702 | } |
703 | } |
704 | |
705 | impl DoubleEndedIterator for Ipv6AddrRange { |
706 | fn next_back(&mut self) -> Option<Self::Item> { |
707 | match self.start.partial_cmp(&self.end) { |
708 | Some(Less) => { |
709 | let next_back = self.end.sub_one(); |
710 | Some(mem::replace(&mut self.end, next_back)) |
711 | }, |
712 | Some(Equal) => { |
713 | self.end.replace_zero(); |
714 | Some(self.start.replace_one()) |
715 | }, |
716 | _ => None |
717 | } |
718 | } |
719 | fn nth_back(&mut self, n: usize) -> Option<Self::Item> { |
720 | let n = n as u128; |
721 | if self.can_count_u128() { |
722 | let count = self.count_u128(); |
723 | if n >= count { |
724 | self.end.replace_zero(); |
725 | self.start.replace_one(); |
726 | None |
727 | } |
728 | else if n == count - 1 { |
729 | self.end.replace_zero(); |
730 | Some(self.start.replace_one()) |
731 | } else { |
732 | let nth_back = self.end.saturating_sub(n); |
733 | self.end = nth_back.sub_one(); |
734 | Some(nth_back) |
735 | } |
736 | // count overflows u128; n is 64-bits at most. |
737 | // therefore, n can never exceed count |
738 | } else { |
739 | let nth_back = self.end.saturating_sub(n); |
740 | self.end = nth_back.sub_one(); |
741 | Some(nth_back) |
742 | } |
743 | } |
744 | } |
745 | |
746 | impl FusedIterator for IpAddrRange {} |
747 | impl FusedIterator for Ipv4AddrRange {} |
748 | impl FusedIterator for Ipv6AddrRange {} |
749 | |
750 | #[cfg (test)] |
751 | mod tests { |
752 | use alloc::vec::Vec; |
753 | use core::str::FromStr; |
754 | #[cfg (not(feature = "std" ))] |
755 | use core::net::{IpAddr, Ipv4Addr, Ipv6Addr}; |
756 | #[cfg (feature = "std" )] |
757 | use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; |
758 | use super::*; |
759 | |
760 | #[test ] |
761 | fn test_ipaddrrange() { |
762 | // Next, Next-Back |
763 | let i = Ipv4AddrRange::new( |
764 | Ipv4Addr::from_str("10.0.0.0" ).unwrap(), |
765 | Ipv4Addr::from_str("10.0.0.3" ).unwrap() |
766 | ); |
767 | |
768 | assert_eq!(i.collect::<Vec<Ipv4Addr>>(), vec![ |
769 | Ipv4Addr::from_str("10.0.0.0" ).unwrap(), |
770 | Ipv4Addr::from_str("10.0.0.1" ).unwrap(), |
771 | Ipv4Addr::from_str("10.0.0.2" ).unwrap(), |
772 | Ipv4Addr::from_str("10.0.0.3" ).unwrap(), |
773 | ]); |
774 | |
775 | let mut v = i.collect::<Vec<_>>(); |
776 | v.reverse(); |
777 | assert_eq!(v, i.rev().collect::<Vec<_>>()); |
778 | |
779 | let i = Ipv4AddrRange::new( |
780 | Ipv4Addr::from_str("255.255.255.254" ).unwrap(), |
781 | Ipv4Addr::from_str("255.255.255.255" ).unwrap() |
782 | ); |
783 | |
784 | assert_eq!(i.collect::<Vec<Ipv4Addr>>(), vec![ |
785 | Ipv4Addr::from_str("255.255.255.254" ).unwrap(), |
786 | Ipv4Addr::from_str("255.255.255.255" ).unwrap(), |
787 | ]); |
788 | |
789 | let i = Ipv6AddrRange::new( |
790 | Ipv6Addr::from_str("fd00::" ).unwrap(), |
791 | Ipv6Addr::from_str("fd00::3" ).unwrap(), |
792 | ); |
793 | |
794 | assert_eq!(i.collect::<Vec<Ipv6Addr>>(), vec![ |
795 | Ipv6Addr::from_str("fd00::" ).unwrap(), |
796 | Ipv6Addr::from_str("fd00::1" ).unwrap(), |
797 | Ipv6Addr::from_str("fd00::2" ).unwrap(), |
798 | Ipv6Addr::from_str("fd00::3" ).unwrap(), |
799 | ]); |
800 | |
801 | let mut v = i.collect::<Vec<_>>(); |
802 | v.reverse(); |
803 | assert_eq!(v, i.rev().collect::<Vec<_>>()); |
804 | |
805 | let i = Ipv6AddrRange::new( |
806 | Ipv6Addr::from_str("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe" ).unwrap(), |
807 | Ipv6Addr::from_str("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" ).unwrap(), |
808 | ); |
809 | |
810 | assert_eq!(i.collect::<Vec<Ipv6Addr>>(), vec![ |
811 | Ipv6Addr::from_str("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe" ).unwrap(), |
812 | Ipv6Addr::from_str("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" ).unwrap(), |
813 | ]); |
814 | |
815 | let i = IpAddrRange::from(Ipv4AddrRange::new( |
816 | Ipv4Addr::from_str("10.0.0.0" ).unwrap(), |
817 | Ipv4Addr::from_str("10.0.0.3" ).unwrap(), |
818 | )); |
819 | |
820 | assert_eq!(i.collect::<Vec<IpAddr>>(), vec![ |
821 | IpAddr::from_str("10.0.0.0" ).unwrap(), |
822 | IpAddr::from_str("10.0.0.1" ).unwrap(), |
823 | IpAddr::from_str("10.0.0.2" ).unwrap(), |
824 | IpAddr::from_str("10.0.0.3" ).unwrap(), |
825 | ]); |
826 | |
827 | let mut v = i.collect::<Vec<_>>(); |
828 | v.reverse(); |
829 | assert_eq!(v, i.rev().collect::<Vec<_>>()); |
830 | |
831 | let i = IpAddrRange::from(Ipv4AddrRange::new( |
832 | Ipv4Addr::from_str("255.255.255.254" ).unwrap(), |
833 | Ipv4Addr::from_str("255.255.255.255" ).unwrap() |
834 | )); |
835 | |
836 | assert_eq!(i.collect::<Vec<IpAddr>>(), vec![ |
837 | IpAddr::from_str("255.255.255.254" ).unwrap(), |
838 | IpAddr::from_str("255.255.255.255" ).unwrap(), |
839 | ]); |
840 | |
841 | let i = IpAddrRange::from(Ipv6AddrRange::new( |
842 | Ipv6Addr::from_str("fd00::" ).unwrap(), |
843 | Ipv6Addr::from_str("fd00::3" ).unwrap(), |
844 | )); |
845 | |
846 | assert_eq!(i.collect::<Vec<IpAddr>>(), vec![ |
847 | IpAddr::from_str("fd00::" ).unwrap(), |
848 | IpAddr::from_str("fd00::1" ).unwrap(), |
849 | IpAddr::from_str("fd00::2" ).unwrap(), |
850 | IpAddr::from_str("fd00::3" ).unwrap(), |
851 | ]); |
852 | |
853 | let mut v = i.collect::<Vec<_>>(); |
854 | v.reverse(); |
855 | assert_eq!(v, i.rev().collect::<Vec<_>>()); |
856 | |
857 | let i = IpAddrRange::from(Ipv6AddrRange::new( |
858 | Ipv6Addr::from_str("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe" ).unwrap(), |
859 | Ipv6Addr::from_str("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" ).unwrap(), |
860 | )); |
861 | |
862 | assert_eq!(i.collect::<Vec<IpAddr>>(), vec![ |
863 | IpAddr::from_str("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe" ).unwrap(), |
864 | IpAddr::from_str("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" ).unwrap(), |
865 | ]); |
866 | |
867 | // #11 (infinite iterator when start and stop are 0) |
868 | let zero4 = Ipv4Addr::from_str("0.0.0.0" ).unwrap(); |
869 | let zero6 = Ipv6Addr::from_str("::" ).unwrap(); |
870 | |
871 | let mut i = Ipv4AddrRange::new(zero4, zero4); |
872 | assert_eq!(Some(zero4), i.next()); |
873 | assert_eq!(None, i.next()); |
874 | |
875 | let mut i = Ipv6AddrRange::new(zero6, zero6); |
876 | assert_eq!(Some(zero6), i.next()); |
877 | assert_eq!(None, i.next()); |
878 | |
879 | // Count |
880 | let i = Ipv4AddrRange::new( |
881 | Ipv4Addr::from_str("10.0.0.0" ).unwrap(), |
882 | Ipv4Addr::from_str("10.0.0.3" ).unwrap() |
883 | ); |
884 | assert_eq!(i.count(), 4); |
885 | |
886 | let i = Ipv6AddrRange::new( |
887 | Ipv6Addr::from_str("fd00::" ).unwrap(), |
888 | Ipv6Addr::from_str("fd00::3" ).unwrap(), |
889 | ); |
890 | assert_eq!(i.count(), 4); |
891 | |
892 | // Size Hint |
893 | let i = Ipv4AddrRange::new( |
894 | Ipv4Addr::from_str("10.0.0.0" ).unwrap(), |
895 | Ipv4Addr::from_str("10.0.0.3" ).unwrap() |
896 | ); |
897 | assert_eq!(i.size_hint(), (4, Some(4))); |
898 | |
899 | let i = Ipv6AddrRange::new( |
900 | Ipv6Addr::from_str("fd00::" ).unwrap(), |
901 | Ipv6Addr::from_str("fd00::3" ).unwrap(), |
902 | ); |
903 | assert_eq!(i.size_hint(), (4, Some(4))); |
904 | |
905 | // Size Hint: a range where size clearly overflows usize |
906 | let i = Ipv6AddrRange::new( |
907 | Ipv6Addr::from_str("::" ).unwrap(), |
908 | Ipv6Addr::from_str("8000::" ).unwrap(), |
909 | ); |
910 | assert_eq!(i.size_hint(), (core::usize::MAX, None)); |
911 | |
912 | // Min, Max, Last |
913 | let i = Ipv4AddrRange::new( |
914 | Ipv4Addr::from_str("10.0.0.0" ).unwrap(), |
915 | Ipv4Addr::from_str("10.0.0.3" ).unwrap() |
916 | ); |
917 | assert_eq!(Iterator::min(i), Some(Ipv4Addr::from_str("10.0.0.0" ).unwrap())); |
918 | assert_eq!(Iterator::max(i), Some(Ipv4Addr::from_str("10.0.0.3" ).unwrap())); |
919 | assert_eq!(i.last(), Some(Ipv4Addr::from_str("10.0.0.3" ).unwrap())); |
920 | |
921 | let i = Ipv6AddrRange::new( |
922 | Ipv6Addr::from_str("fd00::" ).unwrap(), |
923 | Ipv6Addr::from_str("fd00::3" ).unwrap(), |
924 | ); |
925 | assert_eq!(Iterator::min(i), Some(Ipv6Addr::from_str("fd00::" ).unwrap())); |
926 | assert_eq!(Iterator::max(i), Some(Ipv6Addr::from_str("fd00::3" ).unwrap())); |
927 | assert_eq!(i.last(), Some(Ipv6Addr::from_str("fd00::3" ).unwrap())); |
928 | |
929 | // Nth |
930 | let i = Ipv4AddrRange::new( |
931 | Ipv4Addr::from_str("10.0.0.0" ).unwrap(), |
932 | Ipv4Addr::from_str("10.0.0.3" ).unwrap() |
933 | ); |
934 | assert_eq!(i.clone().nth(0), Some(Ipv4Addr::from_str("10.0.0.0" ).unwrap())); |
935 | assert_eq!(i.clone().nth(3), Some(Ipv4Addr::from_str("10.0.0.3" ).unwrap())); |
936 | assert_eq!(i.clone().nth(4), None); |
937 | assert_eq!(i.clone().nth(99), None); |
938 | let mut i2 = i.clone(); |
939 | assert_eq!(i2.nth(1), Some(Ipv4Addr::from_str("10.0.0.1" ).unwrap())); |
940 | assert_eq!(i2.nth(1), Some(Ipv4Addr::from_str("10.0.0.3" ).unwrap())); |
941 | assert_eq!(i2.nth(0), None); |
942 | let mut i3 = i.clone(); |
943 | assert_eq!(i3.nth(99), None); |
944 | assert_eq!(i3.next(), None); |
945 | |
946 | let i = Ipv6AddrRange::new( |
947 | Ipv6Addr::from_str("fd00::" ).unwrap(), |
948 | Ipv6Addr::from_str("fd00::3" ).unwrap(), |
949 | ); |
950 | assert_eq!(i.clone().nth(0), Some(Ipv6Addr::from_str("fd00::" ).unwrap())); |
951 | assert_eq!(i.clone().nth(3), Some(Ipv6Addr::from_str("fd00::3" ).unwrap())); |
952 | assert_eq!(i.clone().nth(4), None); |
953 | assert_eq!(i.clone().nth(99), None); |
954 | let mut i2 = i.clone(); |
955 | assert_eq!(i2.nth(1), Some(Ipv6Addr::from_str("fd00::1" ).unwrap())); |
956 | assert_eq!(i2.nth(1), Some(Ipv6Addr::from_str("fd00::3" ).unwrap())); |
957 | assert_eq!(i2.nth(0), None); |
958 | let mut i3 = i.clone(); |
959 | assert_eq!(i3.nth(99), None); |
960 | assert_eq!(i3.next(), None); |
961 | |
962 | // Nth Back |
963 | let i = Ipv4AddrRange::new( |
964 | Ipv4Addr::from_str("10.0.0.0" ).unwrap(), |
965 | Ipv4Addr::from_str("10.0.0.3" ).unwrap() |
966 | ); |
967 | assert_eq!(i.clone().nth_back(0), Some(Ipv4Addr::from_str("10.0.0.3" ).unwrap())); |
968 | assert_eq!(i.clone().nth_back(3), Some(Ipv4Addr::from_str("10.0.0.0" ).unwrap())); |
969 | assert_eq!(i.clone().nth_back(4), None); |
970 | assert_eq!(i.clone().nth_back(99), None); |
971 | let mut i2 = i.clone(); |
972 | assert_eq!(i2.nth_back(1), Some(Ipv4Addr::from_str("10.0.0.2" ).unwrap())); |
973 | assert_eq!(i2.nth_back(1), Some(Ipv4Addr::from_str("10.0.0.0" ).unwrap())); |
974 | assert_eq!(i2.nth_back(0), None); |
975 | let mut i3 = i.clone(); |
976 | assert_eq!(i3.nth_back(99), None); |
977 | assert_eq!(i3.next(), None); |
978 | |
979 | let i = Ipv6AddrRange::new( |
980 | Ipv6Addr::from_str("fd00::" ).unwrap(), |
981 | Ipv6Addr::from_str("fd00::3" ).unwrap(), |
982 | ); |
983 | assert_eq!(i.clone().nth_back(0), Some(Ipv6Addr::from_str("fd00::3" ).unwrap())); |
984 | assert_eq!(i.clone().nth_back(3), Some(Ipv6Addr::from_str("fd00::" ).unwrap())); |
985 | assert_eq!(i.clone().nth_back(4), None); |
986 | assert_eq!(i.clone().nth_back(99), None); |
987 | let mut i2 = i.clone(); |
988 | assert_eq!(i2.nth_back(1), Some(Ipv6Addr::from_str("fd00::2" ).unwrap())); |
989 | assert_eq!(i2.nth_back(1), Some(Ipv6Addr::from_str("fd00::" ).unwrap())); |
990 | assert_eq!(i2.nth_back(0), None); |
991 | let mut i3 = i.clone(); |
992 | assert_eq!(i3.nth_back(99), None); |
993 | assert_eq!(i3.next(), None); |
994 | } |
995 | } |
996 | |