Skip to main content

subnetwork/
lib.rs

1//! The `subnetwork` crate provides a set of APIs to work with IP CIDRs in Rust.
2use std::cmp::Ordering;
3use std::fmt;
4use std::net::AddrParseError;
5use std::net::IpAddr;
6use std::net::Ipv4Addr;
7use std::net::Ipv6Addr;
8use std::num::ParseIntError;
9use std::result;
10use std::str::FromStr;
11use std::u32;
12use thiserror::Error;
13
14const INIT_NEXT_VALUE: u8 = 0;
15const IPV4_PREFIX_MAX_LEN: u8 = 32;
16const IPV6_PREFIX_MAX_LEN: u8 = 128;
17
18pub type Result<T, E = SubnetworkError> = result::Result<T, E>;
19
20#[derive(Error, Debug)]
21pub enum SubnetworkError {
22    #[error("invalid input: {msg}")]
23    InvalidInput { msg: String },
24    #[error("ip addr parse error")]
25    AddrParseError(#[from] AddrParseError),
26    #[error("num parse error")]
27    ParseIntError(#[from] ParseIntError),
28}
29
30#[derive(Debug, Clone, Copy, Hash)]
31pub struct CrossIpv4Pool {
32    start: u32,
33    end: u32,
34    next: u32,
35}
36
37impl PartialEq for CrossIpv4Pool {
38    fn eq(&self, other: &Self) -> bool {
39        self.start == other.start && self.end == other.end
40    }
41}
42
43impl Eq for CrossIpv4Pool {}
44
45impl PartialOrd for CrossIpv4Pool {
46    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
47        if self.start < other.start {
48            return Some(Ordering::Less);
49        } else if self.start > other.start {
50            return Some(Ordering::Greater);
51        }
52
53        if self.end < other.end {
54            return Some(Ordering::Less);
55        } else if self.end > other.end {
56            return Some(Ordering::Greater);
57        }
58
59        if self.next > other.next {
60            return Some(Ordering::Greater);
61        } else if self.next < other.next {
62            return Some(Ordering::Less);
63        }
64
65        Some(Ordering::Equal)
66    }
67}
68
69impl Ord for CrossIpv4Pool {
70    fn cmp(&self, other: &Self) -> Ordering {
71        if self.start < other.start {
72            return Ordering::Less;
73        } else if self.start > other.start {
74            return Ordering::Greater;
75        }
76
77        if self.end < other.end {
78            return Ordering::Less;
79        } else if self.end > other.end {
80            return Ordering::Greater;
81        }
82
83        if self.next > other.next {
84            return Ordering::Greater;
85        } else if self.next < other.next {
86            return Ordering::Less;
87        }
88
89        Ordering::Equal
90    }
91}
92
93impl Iterator for CrossIpv4Pool {
94    type Item = Ipv4Addr;
95    fn next(&mut self) -> Option<Self::Item> {
96        if self.next <= self.end {
97            let ret = self.next;
98            self.next += 1;
99            Some(ret.into())
100        } else {
101            None
102        }
103    }
104}
105
106impl fmt::Display for CrossIpv4Pool {
107    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
108        let start: Ipv4Addr = self.start.into();
109        let end: Ipv4Addr = self.end.into();
110        let now: Ipv4Addr = self.next.into();
111        write!(f, "{}-{}, next {}", start, end, now)
112    }
113}
114
115impl CrossIpv4Pool {
116    /// Returns an Ipv4 iterator over the cross different subnetwork.
117    /// # Example
118    /// ```
119    /// use subnetwork::CrossIpv4Pool;
120    /// use std::net::Ipv4Addr;
121    ///
122    /// fn main() {
123    ///     let start = Ipv4Addr::new(192, 168, 1, 1);
124    ///     let end = Ipv4Addr::new(192, 168, 3, 254);
125    ///     let pool = CrossIpv4Pool::new(start, end).unwrap();
126    ///     for i in pool {
127    ///         println!("{:?}", i);
128    ///     }
129    /// }
130    /// ```
131    pub fn new<T: Into<Ipv4AddrExt>>(
132        start: T,
133        end: Ipv4Addr,
134    ) -> Result<CrossIpv4Pool, SubnetworkError> {
135        let start_ip_ext: Ipv4AddrExt = start.into();
136        let end_ip_ext: Ipv4AddrExt = end.into();
137        let start_u32: u32 = start_ip_ext.addr;
138        let end_u32: u32 = end_ip_ext.addr;
139
140        if start_u32 <= end_u32 {
141            let cip = CrossIpv4Pool {
142                start: start_u32,
143                end: end_u32,
144                next: start_u32,
145            };
146            Ok(cip)
147        } else {
148            let error_range = format!("{}-{}", start_u32, end_u32);
149            Err(SubnetworkError::InvalidInput { msg: error_range })
150        }
151    }
152    /// Extract all IPs.
153    pub fn to_vec(&self) -> Vec<Ipv4Addr> {
154        self.into_iter().collect()
155    }
156    /// Check if ip pool containss this ip.
157    pub fn contains(&self, addr: Ipv4Addr) -> bool {
158        let addr: u32 = addr.into();
159        if addr <= self.end && addr >= self.start {
160            true
161        } else {
162            false
163        }
164    }
165    /// Returns the number of possible host address in this `CrossIpv4Pool`.
166    pub fn len(&self) -> usize {
167        let length = self.end - self.start;
168        length as usize
169    }
170}
171
172#[derive(Debug, Clone, Copy, Hash)]
173pub struct Ipv4Pool {
174    prefix: u32,
175    mask: u32,
176    next: u32,
177    stop: u32,
178    addr: u32,
179}
180
181impl PartialEq for Ipv4Pool {
182    fn eq(&self, other: &Self) -> bool {
183        self.prefix == other.prefix
184            && self.mask == other.mask
185            && self.stop == other.stop
186            && self.addr == other.addr
187    }
188}
189
190impl Eq for Ipv4Pool {}
191
192impl PartialOrd for Ipv4Pool {
193    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
194        if self.prefix < other.prefix {
195            return Some(Ordering::Less);
196        } else if self.prefix > other.prefix {
197            return Some(Ordering::Greater);
198        }
199
200        if self.mask < other.mask {
201            return Some(Ordering::Less);
202        } else if self.mask > other.mask {
203            return Some(Ordering::Greater);
204        }
205
206        if self.stop < other.stop {
207            return Some(Ordering::Less);
208        } else if self.stop > other.stop {
209            return Some(Ordering::Greater);
210        }
211
212        if self.addr < other.addr {
213            return Some(Ordering::Less);
214        } else if self.addr > other.addr {
215            return Some(Ordering::Greater);
216        }
217
218        if self.next < other.next {
219            return Some(Ordering::Less);
220        } else if self.next > other.next {
221            return Some(Ordering::Greater);
222        }
223
224        Some(Ordering::Equal)
225    }
226}
227
228impl Ord for Ipv4Pool {
229    fn cmp(&self, other: &Self) -> Ordering {
230        if self.prefix < other.prefix {
231            return Ordering::Less;
232        } else if self.prefix > other.prefix {
233            return Ordering::Greater;
234        }
235
236        if self.mask < other.mask {
237            return Ordering::Less;
238        } else if self.mask > other.mask {
239            return Ordering::Greater;
240        }
241
242        if self.stop < other.stop {
243            return Ordering::Less;
244        } else if self.stop > other.stop {
245            return Ordering::Greater;
246        }
247
248        if self.addr < other.addr {
249            return Ordering::Less;
250        } else if self.addr > other.addr {
251            return Ordering::Greater;
252        }
253
254        if self.next < other.next {
255            return Ordering::Less;
256        } else if self.next > other.next {
257            return Ordering::Greater;
258        }
259
260        Ordering::Equal
261    }
262}
263
264impl Iterator for Ipv4Pool {
265    type Item = Ipv4Addr;
266    fn next(&mut self) -> Option<Self::Item> {
267        if self.next < self.stop {
268            let ret = self.prefix + self.next;
269            self.next += 1;
270            Some(ret.into())
271        } else {
272            None
273        }
274    }
275}
276
277impl fmt::Display for Ipv4Pool {
278    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
279        let prefix_addr: Ipv4Addr = self.prefix.into();
280        let mut prefix = 0;
281        let mut mask = self.mask;
282        while mask != 0 {
283            mask <<= 1;
284            prefix += 1;
285        }
286        write!(f, "{}/{}", prefix_addr, prefix)
287    }
288}
289
290impl FromStr for Ipv4Pool {
291    type Err = SubnetworkError;
292    fn from_str(addr: &str) -> Result<Self, Self::Err> {
293        if addr.contains("/") {
294            let addr_vec: Vec<&str> = addr.split("/").collect();
295            if addr_vec.len() == 2 {
296                let ip_addr = Ipv4Addr::from_str(addr_vec[0])?;
297                let prefix = u8::from_str(addr_vec[1])?;
298                if prefix <= IPV4_PREFIX_MAX_LEN {
299                    let addr: u32 = ip_addr.into();
300                    let mask: u32 = u32::MAX << (IPV4_PREFIX_MAX_LEN - prefix);
301                    let next = INIT_NEXT_VALUE as u32;
302                    let stop = 1 << (IPV4_PREFIX_MAX_LEN - prefix);
303                    let prefix = addr & mask;
304                    return Ok(Ipv4Pool {
305                        prefix,
306                        mask,
307                        next,
308                        stop,
309                        addr,
310                    });
311                }
312            }
313        }
314        // final
315        Err(SubnetworkError::InvalidInput {
316            msg: addr.to_string(),
317        })
318    }
319}
320
321impl Ipv4Pool {
322    /// Returns an Ipv4 iterator over the address containsed in the network.
323    /// Include network address and broadcast address.
324    /// # Example
325    /// ```
326    /// use subnetwork::Ipv4Pool;
327    /// use std::net::Ipv4Addr;
328    ///
329    /// fn main() {
330    ///     let ip = Ipv4Addr::new(192, 168, 1, 1);
331    ///     let pool = Ipv4Pool::new(ip, 24).unwrap();
332    ///     for i in pool {
333    ///         println!("{:?}", i);
334    ///     }
335    /// }
336    /// ```
337    pub fn new<T: Into<Ipv4AddrExt>>(addr: T, prefix: u8) -> Result<Ipv4Pool, SubnetworkError> {
338        let addr_ext: Ipv4AddrExt = addr.into();
339        if prefix > IPV4_PREFIX_MAX_LEN {
340            let error_addr = format!("{}/{}", addr_ext, prefix);
341            Err(SubnetworkError::InvalidInput {
342                msg: error_addr.to_string(),
343            })
344        } else {
345            let addr: u32 = addr_ext.addr;
346            let mask: u32 = u32::MAX << (IPV4_PREFIX_MAX_LEN - prefix);
347            let next = INIT_NEXT_VALUE as u32;
348            let stop = 1 << (IPV4_PREFIX_MAX_LEN - prefix);
349            let prefix = addr & mask;
350            return Ok(Ipv4Pool {
351                prefix,
352                mask,
353                next,
354                stop,
355                addr,
356            });
357        }
358    }
359    /// Extract all IPs.
360    pub fn to_vec(&self) -> Vec<Ipv4Addr> {
361        self.into_iter().collect()
362    }
363    /// Check if ip pool containss this ip.
364    /// # Example
365    /// ```
366    /// use std::net::Ipv4Addr;
367    /// use std::str::FromStr;
368    /// use subnetwork::Ipv4Pool;
369    ///
370    /// fn main() {
371    ///     let pool = Ipv4Pool::from_str("192.168.1.0/24").unwrap();
372    ///     let ip = Ipv4Addr::from_str("192.168.1.20").unwrap();
373    ///     let ret = pool.contains(ip);
374    ///     assert_eq!(ret, true);
375    /// }
376    /// ```
377    pub fn contains(&self, addr: Ipv4Addr) -> bool {
378        let addr: u32 = addr.into();
379        if addr & self.mask == self.prefix {
380            true
381        } else {
382            false
383        }
384    }
385    /// Returns the addr of the network denoted by this `Ipv4Pool`.
386    /// This means the lowest possible IP addr inside of the network.
387    pub fn network(&self) -> Ipv4Addr {
388        self.prefix.into()
389    }
390    /// Returns the broadcasting addr of this `Ipv4Pool`.
391    /// This means the highest possible IP addr inside of the network.
392    pub fn broadcast(&self) -> Ipv4Addr {
393        let biggest = !self.mask;
394        let ret = self.prefix + biggest;
395        ret.into()
396    }
397    /// Returns the number of possible address in this `Ipv4Pool` (include 0 and 255).
398    pub fn len(&self) -> usize {
399        let biggest = !self.mask + 1;
400        biggest as usize
401    }
402    /// Represents a network-range address.
403    pub fn addr(&self) -> Ipv4Addr {
404        self.addr.into()
405    }
406}
407
408#[derive(Debug, Clone, Copy, Hash)]
409pub struct CrossIpv6Pool {
410    start: u128,
411    end: u128,
412    next: u128,
413}
414
415impl PartialEq for CrossIpv6Pool {
416    fn eq(&self, other: &Self) -> bool {
417        self.start == other.start && self.end == other.end
418    }
419}
420
421impl Eq for CrossIpv6Pool {}
422
423impl PartialOrd for CrossIpv6Pool {
424    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
425        if self.start < other.start {
426            return Some(Ordering::Less);
427        } else if self.start > other.start {
428            return Some(Ordering::Greater);
429        }
430
431        if self.end < other.end {
432            return Some(Ordering::Less);
433        } else if self.end > other.end {
434            return Some(Ordering::Greater);
435        }
436
437        if self.next < other.next {
438            return Some(Ordering::Less);
439        } else if self.next > other.next {
440            return Some(Ordering::Greater);
441        }
442
443        Some(Ordering::Equal)
444    }
445}
446
447impl Ord for CrossIpv6Pool {
448    fn cmp(&self, other: &Self) -> Ordering {
449        if self.start < other.start {
450            return Ordering::Less;
451        } else if self.start > other.start {
452            return Ordering::Greater;
453        }
454
455        if self.end < other.end {
456            return Ordering::Less;
457        } else if self.end > other.end {
458            return Ordering::Greater;
459        }
460
461        if self.next < other.next {
462            return Ordering::Less;
463        } else if self.next > other.next {
464            return Ordering::Greater;
465        }
466
467        Ordering::Equal
468    }
469}
470
471impl Iterator for CrossIpv6Pool {
472    type Item = Ipv6Addr;
473    fn next(&mut self) -> Option<Self::Item> {
474        if self.next <= self.end {
475            let ret = self.next;
476            self.next += 1;
477            Some(ret.into())
478        } else {
479            None
480        }
481    }
482}
483
484impl fmt::Display for CrossIpv6Pool {
485    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
486        let start: Ipv6Addr = self.start.into();
487        let end: Ipv6Addr = self.end.into();
488        write!(f, "{}-{}", start, end)
489    }
490}
491
492impl CrossIpv6Pool {
493    /// Returns an Ipv4 iterator over the cross different subnetwork address.
494    /// # Example
495    /// ```
496    /// use subnetwork::CrossIpv6Pool;
497    /// use std::net::Ipv6Addr;
498    /// use std::str::FromStr;
499    ///
500    /// fn main() {
501    ///     let start = Ipv6Addr::from_str("fe80::215:5dff:fe20:b393").unwrap();
502    ///     let end = Ipv6Addr::from_str("fe80::215:5dff:fe20:b395").unwrap();
503    ///     let pool = CrossIpv6Pool::new(start, end).unwrap();
504    ///     for i in pool {
505    ///         println!("{:?}", i);
506    ///     }
507    /// }
508    /// ```
509    pub fn new(start: Ipv6Addr, end: Ipv6Addr) -> Result<CrossIpv6Pool, SubnetworkError> {
510        let start_ipv6: Ipv6AddrExt = start.into();
511        let end_ipv6: Ipv6AddrExt = end.into();
512        if start_ipv6.addr <= end_ipv6.addr {
513            let cip = CrossIpv6Pool {
514                start: start_ipv6.addr,
515                end: end_ipv6.addr,
516                next: start_ipv6.addr,
517            };
518            Ok(cip)
519        } else {
520            let msg = format!("{}-{}", start, end);
521            Err(SubnetworkError::InvalidInput { msg })
522        }
523    }
524    /// Extract all IPs.
525    pub fn to_vec(&self) -> Vec<Ipv6Addr> {
526        self.into_iter().collect()
527    }
528    /// Check if ip pool containss this ip.
529    pub fn contains(&self, addr: Ipv6Addr) -> bool {
530        let addr: u128 = addr.into();
531        if addr <= self.end && addr >= self.start {
532            true
533        } else {
534            false
535        }
536    }
537    /// Returns the number of possible host address in this `CrossIpv6Pool`.
538    pub fn len(&self) -> usize {
539        let length = self.end - self.start;
540        length as usize
541    }
542}
543
544#[derive(Debug, Clone, Copy, Hash)]
545pub struct Ipv6Pool {
546    prefix: u128,
547    mask: u128,
548    next: u128,
549    stop: u128,
550    addr: u128,
551}
552
553impl PartialEq for Ipv6Pool {
554    fn eq(&self, other: &Self) -> bool {
555        self.prefix == other.prefix
556            && self.mask == other.mask
557            && self.stop == other.stop
558            && self.addr == other.addr
559    }
560}
561
562impl Eq for Ipv6Pool {}
563
564impl PartialOrd for Ipv6Pool {
565    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
566        if self.prefix < other.prefix {
567            return Some(Ordering::Less);
568        } else if self.prefix > other.prefix {
569            return Some(Ordering::Greater);
570        }
571
572        if self.mask < other.mask {
573            return Some(Ordering::Less);
574        } else if self.mask > other.mask {
575            return Some(Ordering::Greater);
576        }
577
578        if self.stop < other.stop {
579            return Some(Ordering::Less);
580        } else if self.stop > other.stop {
581            return Some(Ordering::Greater);
582        }
583
584        if self.addr < other.addr {
585            return Some(Ordering::Less);
586        } else if self.addr > other.addr {
587            return Some(Ordering::Greater);
588        }
589
590        if self.next < other.next {
591            return Some(Ordering::Less);
592        } else if self.next > other.next {
593            return Some(Ordering::Greater);
594        }
595
596        Some(Ordering::Equal)
597    }
598}
599
600impl Ord for Ipv6Pool {
601    fn cmp(&self, other: &Self) -> Ordering {
602        if self.prefix < other.prefix {
603            return Ordering::Less;
604        } else if self.prefix > other.prefix {
605            return Ordering::Greater;
606        }
607
608        if self.mask < other.mask {
609            return Ordering::Less;
610        } else if self.mask > other.mask {
611            return Ordering::Greater;
612        }
613
614        if self.stop < other.stop {
615            return Ordering::Less;
616        } else if self.stop > other.stop {
617            return Ordering::Greater;
618        }
619
620        if self.addr < other.addr {
621            return Ordering::Less;
622        } else if self.addr > other.addr {
623            return Ordering::Greater;
624        }
625
626        if self.next < other.next {
627            return Ordering::Less;
628        } else if self.next > other.next {
629            return Ordering::Greater;
630        }
631
632        Ordering::Equal
633    }
634}
635
636impl Iterator for Ipv6Pool {
637    type Item = Ipv6Addr;
638    fn next(&mut self) -> Option<Self::Item> {
639        if self.next < self.stop {
640            let ret = self.prefix + self.next;
641            self.next += 1;
642            Some(ret.into())
643        } else {
644            None
645        }
646    }
647}
648
649impl fmt::Display for Ipv6Pool {
650    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
651        let prefix_addr: Ipv6Addr = self.prefix.into();
652        let mut prefix = 0;
653        let mut mask = self.mask;
654        while mask != 0 {
655            mask <<= 1;
656            prefix += 1;
657        }
658        write!(f, "{}/{}", prefix_addr, prefix)
659    }
660}
661
662impl FromStr for Ipv6Pool {
663    type Err = SubnetworkError;
664    fn from_str(addr: &str) -> Result<Self, Self::Err> {
665        if addr.contains("/") {
666            let addr_vec: Vec<&str> = addr.split("/").collect();
667            if addr_vec.len() == 2 {
668                let ip_addr = Ipv6Addr::from_str(addr_vec[0])?;
669                let prefix = u8::from_str(addr_vec[1])?;
670                if prefix <= IPV6_PREFIX_MAX_LEN {
671                    let addr: u128 = ip_addr.into();
672                    let mask: u128 = u128::MAX << (IPV6_PREFIX_MAX_LEN - prefix);
673                    let next = INIT_NEXT_VALUE as u128;
674                    let stop = 1 << (IPV6_PREFIX_MAX_LEN - prefix);
675                    let prefix = addr & mask;
676                    return Ok(Ipv6Pool {
677                        prefix,
678                        mask,
679                        next,
680                        stop,
681                        addr,
682                    });
683                }
684            }
685        }
686        // final
687        Err(SubnetworkError::InvalidInput {
688            msg: addr.to_string(),
689        })
690    }
691}
692
693impl Ipv6Pool {
694    /// Returns an Ipv6 iterator over the address containsed in the network.
695    /// Include network address and broadcast address.
696    /// # Example
697    /// ```
698    /// use subnetwork::Ipv6Pool;
699    /// use std::net::Ipv6Addr;
700    ///
701    /// fn main() {
702    ///     let ipv6_str = "::ffff:192.10.2.0";
703    ///     let ipv6: Ipv6Addr = ipv6_str.parse().unwrap();
704    ///     let pool = Ipv6Pool::new(ipv6, 120).unwrap();
705    ///     for i in pool {
706    ///         println!("{:?}", i);
707    ///     }
708    /// }
709    /// ```
710    pub fn new(addr: Ipv6Addr, prefix: u8) -> Result<Ipv6Pool, SubnetworkError> {
711        if prefix > IPV6_PREFIX_MAX_LEN {
712            let error_addr = format!("{}/{}", addr, prefix);
713            Err(SubnetworkError::InvalidInput {
714                msg: error_addr.to_string(),
715            })
716        } else {
717            let addr: u128 = addr.into();
718            let mask: u128 = u128::MAX << (IPV6_PREFIX_MAX_LEN - prefix);
719            let next = INIT_NEXT_VALUE as u128;
720            let stop = 1 << (IPV6_PREFIX_MAX_LEN - prefix);
721            let prefix = addr & mask;
722            Ok(Ipv6Pool {
723                prefix,
724                mask,
725                next,
726                stop,
727                addr,
728            })
729        }
730    }
731    /// Extract all IPs.
732    pub fn to_vec(&self) -> Vec<Ipv6Addr> {
733        self.into_iter().collect()
734    }
735    /// Check if ip pool containss this ip.
736    /// # Example
737    /// ```
738    /// use std::net::Ipv6Addr;
739    /// use std::str::FromStr;
740    /// use subnetwork::Ipv6Pool;
741    ///
742    /// fn main() {
743    ///     let pool = Ipv6Pool::from_str("::ffff:192.10.2.0/120").unwrap();
744    ///     let ip = Ipv6Addr::from_str("::ffff:192.10.2.1").unwrap();
745    ///     let ret = pool.contains(ip);
746    ///     assert_eq!(ret, true);
747    /// }
748    /// ```
749    pub fn contains(&self, addr: Ipv6Addr) -> bool {
750        let addr: u128 = addr.into();
751        if addr & self.mask == self.prefix {
752            true
753        } else {
754            false
755        }
756    }
757    /// Returns the addr of the network denoted by this `Ipv6Pool`.
758    /// This means the lowest possible IP addr inside of the network.
759    pub fn network(&self) -> Ipv6Addr {
760        self.prefix.into()
761    }
762    /// Returns the number of possible host address in this `Ipv6Pool`.
763    pub fn len(&self) -> usize {
764        let biggest = !self.mask + 1;
765        biggest as usize
766    }
767    /// Represents a network-range address.
768    pub fn addr(&self) -> Ipv6Addr {
769        self.addr.into()
770    }
771}
772
773#[derive(Debug, Clone, Copy, Hash)]
774pub enum IpPool {
775    V4(Ipv4Pool),
776    V6(Ipv6Pool),
777}
778
779impl PartialEq for IpPool {
780    fn eq(&self, other: &Self) -> bool {
781        match (self, other) {
782            (Self::V4(x), Self::V4(y)) => x == y,
783            (Self::V6(x), Self::V6(y)) => x == y,
784            _ => false,
785        }
786    }
787}
788
789impl Eq for IpPool {}
790
791impl PartialOrd for IpPool {
792    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
793        match (self, other) {
794            (Self::V4(x), Self::V4(y)) => x.partial_cmp(y),
795            (Self::V6(x), Self::V6(y)) => x.partial_cmp(y),
796            _ => None,
797        }
798    }
799}
800
801impl Ord for IpPool {
802    fn cmp(&self, other: &Self) -> Ordering {
803        match (self, other) {
804            (Self::V4(x), Self::V4(y)) => x.cmp(y),
805            (Self::V6(x), Self::V6(y)) => x.cmp(y),
806            _ => Ordering::Equal,
807        }
808    }
809}
810
811impl fmt::Display for IpPool {
812    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
813        let output = match self {
814            Self::V4(x) => format!("{}", x),
815            Self::V6(x) => format!("{}", x),
816        };
817        write!(f, "{}", output)
818    }
819}
820
821impl Iterator for IpPool {
822    type Item = IpAddr;
823    fn next(&mut self) -> Option<Self::Item> {
824        match self {
825            IpPool::V4(iter) => iter.next().map(IpAddr::V4),
826            IpPool::V6(iter) => iter.next().map(IpAddr::V6),
827        }
828    }
829}
830
831impl IpPool {
832    pub fn new(addr: IpAddr, prefix: u8) -> Result<Self, SubnetworkError> {
833        match addr {
834            IpAddr::V4(ipv4) => {
835                let pool = Ipv4Pool::new(ipv4, prefix)?;
836                Ok(IpPool::V4(pool))
837            }
838            IpAddr::V6(ipv6) => {
839                let pool = Ipv6Pool::new(ipv6, prefix)?;
840                Ok(IpPool::V6(pool))
841            }
842        }
843    }
844    pub fn contains(&self, addr: IpAddr) -> bool {
845        match (self, addr) {
846            (Self::V4(pool), IpAddr::V4(ip)) => pool.contains(ip),
847            (Self::V6(pool), IpAddr::V6(ip)) => pool.contains(ip),
848            _ => false,
849        }
850    }
851    pub fn to_vec(&self) -> Vec<IpAddr> {
852        match self {
853            Self::V4(pool) => pool.to_vec().into_iter().map(IpAddr::V4).collect(),
854            Self::V6(pool) => pool.to_vec().into_iter().map(IpAddr::V6).collect(),
855        }
856    }
857    pub fn len(&self) -> usize {
858        match self {
859            Self::V4(pool) => pool.len(),
860            Self::V6(pool) => pool.len(),
861        }
862    }
863    pub fn network(&self) -> IpAddr {
864        match self {
865            Self::V4(pool) => pool.network().into(),
866            Self::V6(pool) => pool.network().into(),
867        }
868    }
869    pub fn addr(&self) -> IpAddr {
870        match self {
871            Self::V4(pool) => pool.addr().into(),
872            Self::V6(pool) => pool.addr().into(),
873        }
874    }
875}
876
877/* Single Addr Struct */
878
879#[derive(Debug, Clone, Copy, Hash)]
880pub struct Ipv4AddrExt {
881    addr: u32,
882}
883
884impl PartialEq for Ipv4AddrExt {
885    fn eq(&self, other: &Self) -> bool {
886        self.addr == other.addr
887    }
888}
889
890impl Eq for Ipv4AddrExt {}
891
892impl PartialOrd for Ipv4AddrExt {
893    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
894        self.addr.partial_cmp(&other.addr)
895    }
896}
897
898impl Ord for Ipv4AddrExt {
899    fn cmp(&self, other: &Self) -> Ordering {
900        self.addr.cmp(&other.addr)
901    }
902}
903
904impl fmt::Display for Ipv4AddrExt {
905    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
906        let addr: Ipv4Addr = self.addr.into();
907        write!(f, "{}", addr)
908    }
909}
910
911impl From<Ipv4Addr> for Ipv4AddrExt {
912    fn from(addr: Ipv4Addr) -> Self {
913        let addr: u32 = addr.into();
914        Ipv4AddrExt { addr }
915    }
916}
917
918impl From<Ipv4AddrExt> for Ipv4Addr {
919    fn from(addr: Ipv4AddrExt) -> Self {
920        let new_addr: u32 = addr.addr;
921        new_addr.into()
922    }
923}
924
925impl FromStr for Ipv4AddrExt {
926    type Err = SubnetworkError;
927    fn from_str(addr: &str) -> Result<Self, Self::Err> {
928        let new_addr = Ipv4Addr::from_str(addr)?;
929        let addr: u32 = new_addr.into();
930        Ok(Ipv4AddrExt { addr })
931    }
932}
933
934impl Ipv4AddrExt {
935    /// Creates a new IPv4AddrExt from four eight-bit octets.
936    pub fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4AddrExt {
937        let a_fix = (a as u32) << 24;
938        let b_fix = (b as u32) << 16;
939        let c_fix = (c as u32) << 8;
940        let d_fix = d as u32;
941        let addr = a_fix + b_fix + c_fix + d_fix;
942        Ipv4AddrExt { addr }
943    }
944    /// Returns the largest identical prefix of two IP address.
945    /// # Example
946    /// ```
947    /// use subnetwork::Ipv4AddrExt;
948    /// use subnetwork::Ipv4Pool;
949    /// use std::net::Ipv4Addr;
950    ///
951    /// fn main() {
952    ///     let ipv4_1 = Ipv4Addr::new(192, 168, 1, 136);
953    ///     let ipv4_2 = Ipv4Addr::new(192, 168, 1, 192);
954    ///     let ipv4ext_1: Ipv4AddrExt = ipv4_1.into();
955    ///     let ret = ipv4ext_1.largest_identical_prefix(ipv4_2);
956    ///     assert_eq!(ret, 25);
957    /// }
958    /// ```
959    pub fn largest_identical_prefix<T: Into<Ipv4AddrExt>>(&self, target: T) -> u8 {
960        let a = self.addr;
961        let b = target.into().addr;
962        let init_mask = 2u32.pow(31);
963        let mut mask = init_mask;
964
965        for c in 0..IPV4_PREFIX_MAX_LEN {
966            if a & mask != b & mask {
967                return c;
968            }
969            mask = (mask >> 1) + init_mask;
970        }
971        0
972    }
973}
974
975#[derive(Debug, Clone, Copy, Hash)]
976pub struct Ipv6AddrExt {
977    addr: u128,
978}
979
980impl PartialEq for Ipv6AddrExt {
981    fn eq(&self, other: &Self) -> bool {
982        self.addr == other.addr
983    }
984}
985
986impl Eq for Ipv6AddrExt {}
987
988impl PartialOrd for Ipv6AddrExt {
989    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
990        self.addr.partial_cmp(&other.addr)
991    }
992}
993
994impl Ord for Ipv6AddrExt {
995    fn cmp(&self, other: &Self) -> Ordering {
996        self.addr.cmp(&other.addr)
997    }
998}
999
1000impl fmt::Display for Ipv6AddrExt {
1001    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1002        let addr: Ipv6Addr = self.addr.into();
1003        write!(f, "{}", addr)
1004    }
1005}
1006
1007impl From<Ipv6Addr> for Ipv6AddrExt {
1008    fn from(addr: Ipv6Addr) -> Self {
1009        let addr: u128 = addr.into();
1010        Ipv6AddrExt { addr }
1011    }
1012}
1013
1014impl From<Ipv6AddrExt> for Ipv6Addr {
1015    fn from(addr: Ipv6AddrExt) -> Self {
1016        let new_addr: u128 = addr.addr;
1017        new_addr.into()
1018    }
1019}
1020
1021impl FromStr for Ipv6AddrExt {
1022    type Err = SubnetworkError;
1023    fn from_str(addr: &str) -> Result<Self, Self::Err> {
1024        let new_addr = Ipv6Addr::from_str(addr)?;
1025        let addr: u128 = new_addr.into();
1026        Ok(Ipv6AddrExt { addr })
1027    }
1028}
1029
1030impl Ipv6AddrExt {
1031    /// Creates a new IPv6 address from eight 16-bit segments.
1032    pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6AddrExt {
1033        let a_fix = (a as u128) << 112;
1034        let b_fix = (b as u128) << 96;
1035        let c_fix = (c as u128) << 80;
1036        let d_fix = (d as u128) << 64;
1037        let e_fix = (e as u128) << 48;
1038        let f_fix = (f as u128) << 32;
1039        let g_fix = (g as u128) << 16;
1040        let h_fix = h as u128;
1041        let addr = a_fix + b_fix + c_fix + d_fix + e_fix + f_fix + g_fix + h_fix;
1042        Ipv6AddrExt { addr }
1043    }
1044    /// Returns the node local scope multicast addr of this `Ipv6`.
1045    pub fn node_multicast(&self) -> Ipv6Addr {
1046        let node = Ipv6Addr::new(
1047            0xff01, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0xff00, 0x0000,
1048        );
1049        let mask = Ipv6Addr::new(
1050            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00ff, 0xffff,
1051        );
1052        let node_u128: u128 = node.into();
1053        let mask_u128: u128 = mask.into();
1054        (node_u128 + (mask_u128 & self.addr)).into()
1055    }
1056    /// Returns the link local scope multicast addr of this `Ipv6`.
1057    pub fn link_multicast(&self) -> Ipv6Addr {
1058        let link = Ipv6Addr::new(
1059            0xff02, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0xff00, 0x0000,
1060        );
1061        let mask = Ipv6Addr::new(
1062            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00ff, 0xffff,
1063        );
1064        let link_u128: u128 = link.into();
1065        let mask_u128: u128 = mask.into();
1066        (link_u128 + (mask_u128 & self.addr)).into()
1067    }
1068    /// Returns the site local scope multicast addr of this `Ipv6`.
1069    pub fn site_multicast(&self) -> Ipv6Addr {
1070        let site = Ipv6Addr::new(
1071            0xff05, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0xff00, 0x0000,
1072        );
1073        let mask = Ipv6Addr::new(
1074            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00ff, 0xffff,
1075        );
1076        let site_u128: u128 = site.into();
1077        let mask_u128: u128 = mask.into();
1078        (site_u128 + (mask_u128 & self.addr)).into()
1079    }
1080    pub fn largest_identical_prefix<T: Into<Ipv6AddrExt>>(&self, target: T) -> u8 {
1081        let a = self.addr;
1082        let b = target.into().addr;
1083        let init_mask = 2u128.pow(127);
1084        let mut mask = init_mask;
1085
1086        for c in 0..IPV6_PREFIX_MAX_LEN {
1087            if a & mask != b & mask {
1088                return c;
1089            }
1090            mask = (mask >> 1) + init_mask;
1091        }
1092        0
1093    }
1094}
1095
1096#[derive(Debug, Clone, Copy)]
1097pub struct NetmaskExt {
1098    prefix: u8,
1099}
1100
1101impl NetmaskExt {
1102    /// Constructs a new `NetmaskExt` from a given prefix.
1103    /// # Example
1104    /// ```
1105    /// use subnetwork::NetmaskExt;
1106    ///
1107    /// fn main() {
1108    ///     let netmask = NetmaskExt::new(24);
1109    ///     // 255.255.255.0
1110    ///     let netmask_ip = netmask.to_ipv4().unwrap();
1111    /// }
1112    /// ```
1113    pub fn new(prefix: u8) -> NetmaskExt {
1114        NetmaskExt { prefix }
1115    }
1116    /// Constructs a new `NetmaskExt` from a given IpAddr (like 255.255.255.0).
1117    /// # Example
1118    /// ```
1119    /// use subnetwork::NetmaskExt;
1120    /// use std::net::Ipv4Addr;
1121    /// use std::net::IpAddr;
1122    ///
1123    /// fn main() {
1124    ///     let addr = IpAddr::V4(Ipv4Addr::new(255, 255, 255, 0));
1125    ///     let netmask = NetmaskExt::from_addr(addr);
1126    ///     // 255.255.255.0
1127    ///     let prefix = netmask.get_prefix();
1128    ///     assert_eq!(prefix, 24)
1129    /// }
1130    /// ```
1131    pub fn from_addr(addr: IpAddr) -> NetmaskExt {
1132        // 255.255.255.0, 255.255.192.0 .etc
1133        let prefix = match addr {
1134            IpAddr::V4(ipv4) => {
1135                let mask = u32::from_be_bytes(ipv4.octets());
1136                let prefix = mask.count_ones() as u8;
1137                prefix
1138            }
1139            IpAddr::V6(ipv6) => {
1140                let mask = u128::from_be_bytes(ipv6.octets());
1141                let prefix = mask.count_ones() as u8;
1142                prefix
1143            }
1144        };
1145        NetmaskExt { prefix }
1146    }
1147    /// Return netmask address's prefix length.
1148    pub fn get_prefix(&self) -> u8 {
1149        self.prefix
1150    }
1151    /// Convert to Ipv4Addr address.
1152    pub fn to_ipv4(&self) -> Result<Ipv4Addr, SubnetworkError> {
1153        if self.prefix == 0 {
1154            Ok((0 as u32).into())
1155        } else {
1156            if self.prefix > IPV4_PREFIX_MAX_LEN {
1157                let msg = format!("prefix: {}", self.prefix);
1158                Err(SubnetworkError::InvalidInput { msg })
1159            } else {
1160                Ok((u32::MAX << (IPV4_PREFIX_MAX_LEN - self.prefix)).into())
1161            }
1162        }
1163    }
1164    /// Convert to Ipv6Addr address.
1165    pub fn to_ipv6(&self) -> Result<Ipv6Addr, SubnetworkError> {
1166        if self.prefix == 0 {
1167            Ok((0 as u128).into())
1168        } else {
1169            if self.prefix > IPV6_PREFIX_MAX_LEN {
1170                let msg = format!("prefix: {}", self.prefix);
1171                Err(SubnetworkError::InvalidInput { msg })
1172            } else {
1173                Ok((u128::MAX << (IPV6_PREFIX_MAX_LEN - self.prefix)).into())
1174            }
1175        }
1176    }
1177}
1178
1179#[cfg(test)]
1180mod tests {
1181    use super::*;
1182    /* README.md examples */
1183    #[test]
1184    fn readme_example_1() {
1185        let pool = Ipv4Pool::new(Ipv4Addr::new(192, 168, 1, 1), 24).unwrap();
1186        // from 192.168.1.0 to 192.168.1.255
1187        for ipv4 in pool {
1188            println!("{}", ipv4);
1189        }
1190
1191        let pool = Ipv4Pool::from_str("192.168.1.0/24").unwrap();
1192        for ipv4 in pool {
1193            println!("{}", ipv4);
1194        }
1195
1196        let pool: Ipv4Pool = "192.168.1.0/24".parse().unwrap();
1197        for ipv4 in pool {
1198            println!("{}", ipv4);
1199        }
1200
1201        let test_ipv4 = Ipv4Addr::new(192, 168, 1, 233);
1202        assert_eq!(pool.contains(test_ipv4), true);
1203
1204        let broadcast = Ipv4Addr::new(192, 168, 1, 255);
1205        assert_eq!(pool.broadcast(), broadcast);
1206
1207        let network = Ipv4Addr::new(192, 168, 1, 0);
1208        assert_eq!(pool.network(), network);
1209
1210        assert_eq!(pool.len(), 256);
1211        // pool is copied.
1212        assert_eq!(pool.to_string(), "192.168.1.0/24");
1213    }
1214    #[test]
1215    fn readme_example_2() {
1216        let start = Ipv4Addr::new(192, 168, 1, 16);
1217        let end = Ipv4Addr::new(192, 168, 3, 200);
1218        let pool = CrossIpv4Pool::new(start, end).unwrap();
1219        // include 192.168.1.16 and 192.168.3.200
1220        for i in pool {
1221            println!("{:?}", i);
1222        }
1223
1224        let test_ipv4 = Ipv4Addr::new(192, 168, 1, 233);
1225        assert_eq!(pool.contains(test_ipv4), true);
1226        let test_ipv4 = Ipv4Addr::new(192, 168, 2, 0);
1227        assert_eq!(pool.contains(test_ipv4), true);
1228        let test_ipv4 = Ipv4Addr::new(192, 168, 3, 255);
1229        assert_eq!(pool.contains(test_ipv4), false);
1230        let test_ipv4 = Ipv4Addr::new(192, 168, 3, 200);
1231        assert_eq!(pool.contains(test_ipv4), true);
1232    }
1233    #[test]
1234    fn readme_example_3() {
1235        // test1
1236        let ip1 = Ipv4Addr::new(192, 168, 1, 0);
1237        let ip2 = Ipv4Addr::new(192, 168, 1, 255);
1238
1239        let ip1ext: Ipv4AddrExt = ip1.into();
1240        assert_eq!(ip1ext.largest_identical_prefix(ip2), 24);
1241
1242        // test 2
1243        let ip1 = Ipv4Addr::new(192, 168, 1, 136);
1244        let ip2 = Ipv4Addr::new(192, 168, 1, 192);
1245
1246        let ip1ext: Ipv4AddrExt = ip1.into();
1247        assert_eq!(ip1ext.largest_identical_prefix(ip2), 25);
1248    }
1249    #[test]
1250    fn readme_example_4() {
1251        let ipv6 = Ipv6Addr::from_str("::ffff:192.10.2.255").unwrap();
1252        let ipv6_ext: Ipv6AddrExt = ipv6.into();
1253
1254        let ipv6_node_multicast = Ipv6Addr::from_str("ff01::1:ff0a:2ff").unwrap();
1255        assert_eq!(ipv6_ext.node_multicast(), ipv6_node_multicast);
1256
1257        let ipv6_link_multicast = Ipv6Addr::from_str("ff02::1:ff0a:2ff").unwrap();
1258        assert_eq!(ipv6_ext.link_multicast(), ipv6_link_multicast);
1259
1260        let ipv6_site_multicast = Ipv6Addr::from_str("ff05::1:ff0a:2ff").unwrap();
1261        assert_eq!(ipv6_ext.site_multicast(), ipv6_site_multicast);
1262    }
1263    #[test]
1264    fn readme_example_5() {
1265        let netmask = NetmaskExt::new(24);
1266        let netmask_addr = netmask.to_ipv4().unwrap();
1267        assert_eq!(netmask_addr, Ipv4Addr::new(255, 255, 255, 0));
1268
1269        let netmask = NetmaskExt::new(26);
1270        let netmask_addr = netmask.to_ipv4().unwrap();
1271        assert_eq!(netmask_addr, Ipv4Addr::new(255, 255, 255, 192));
1272    }
1273    #[test]
1274    fn netmask_ext() {
1275        let addr = IpAddr::V4(Ipv4Addr::new(255, 255, 255, 0));
1276        let netmask = NetmaskExt::from_addr(addr);
1277        // 255.255.255.0
1278        let prefix = netmask.get_prefix();
1279        assert_eq!(prefix, 24);
1280
1281        let addr = IpAddr::V4(Ipv4Addr::new(255, 255, 255, 192));
1282        let netmask = NetmaskExt::from_addr(addr);
1283        // 255.255.255.0
1284        let prefix = netmask.get_prefix();
1285        assert_eq!(prefix, 26);
1286
1287        let addr = IpAddr::V4(Ipv4Addr::new(255, 255, 0, 0));
1288        let netmask = NetmaskExt::from_addr(addr);
1289        // 255.255.255.0
1290        let prefix = netmask.get_prefix();
1291        assert_eq!(prefix, 16);
1292
1293        let addr = IpAddr::V4(Ipv4Addr::new(255, 255, 192, 0));
1294        let netmask = NetmaskExt::from_addr(addr);
1295        // 255.255.255.0
1296        let prefix = netmask.get_prefix();
1297        assert_eq!(prefix, 18);
1298    }
1299    /* Others */
1300    #[test]
1301    fn ipv4_methods() {
1302        let ipv4 = Ipv4Addr::new(192, 168, 1, 1);
1303        if ipv4.is_private() {
1304            println!("{} is private", ipv4);
1305        } else {
1306            println!("{} is not private", ipv4);
1307        }
1308        let ipv6 = Ipv6Addr::new(0xfe80, 0, 0, 0, 0x20c, 0x29ff, 0xfedd, 0xf57);
1309        if ipv6.is_multicast() {
1310            println!("{} is multicast", ipv6);
1311        } else {
1312            println!("{} is not multicast", ipv6);
1313        }
1314    }
1315    /* Ipv4 */
1316    #[test]
1317    fn ipv4_pool_print() {
1318        let test_str = "192.168.1.0/24";
1319        let ipv4_pool = Ipv4Pool::from_str(test_str).unwrap();
1320        let ipv4_pool_str = format!("{}", ipv4_pool);
1321        println!("{}", ipv4_pool_str);
1322    }
1323    #[test]
1324    fn ipv4_print() {
1325        let test_str = "192.168.1.1";
1326        let ipv4 = Ipv4AddrExt::from_str(test_str).unwrap();
1327        let ipv4_str = format!("{}", ipv4);
1328        assert_eq!(ipv4_str, test_str);
1329    }
1330    #[test]
1331    fn ipv4() {
1332        let ipv4 = Ipv4AddrExt::from_str("192.168.1.1").unwrap();
1333        println!("{:8b}", ipv4.addr);
1334        assert_eq!(ipv4.addr, 3232235777);
1335    }
1336    /* Ipv6 */
1337    #[test]
1338    fn ipv6() {
1339        let ipv6 = Ipv6AddrExt::from_str("::ffff:192.10.2.255").unwrap();
1340        println!("{:?}", ipv6);
1341        assert_eq!(ipv6.addr, 281473903624959);
1342    }
1343    #[test]
1344    fn test_github_issues_1() {
1345        // return error instead of panic
1346        let _pool1 = Ipv4Pool::from_str("1.2.3.4/33");
1347        let _pool2 = Ipv4Pool::from_str("1.2.3.4/");
1348        let _pool3 = Ipv4Pool::from_str("nonip/24");
1349    }
1350}