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::fmt;
3use std::net::AddrParseError;
4use std::net::IpAddr;
5use std::net::Ipv4Addr;
6use std::net::Ipv6Addr;
7use std::num::ParseIntError;
8use std::result;
9use std::str::FromStr;
10use std::u32;
11use thiserror::Error;
12
13const INIT_NEXT_VALUE: u8 = 0;
14const IPV4_PREFIX_MAX_LEN: u8 = 32;
15const IPV6_PREFIX_MAX_LEN: u8 = 128;
16
17pub type Result<T, E = SubnetworkError> = result::Result<T, E>;
18
19#[derive(Error, Debug)]
20pub enum SubnetworkError {
21    #[error("invalid input: {msg}")]
22    InvalidInput { msg: String },
23    #[error("ip addr parse error")]
24    AddrParseError(#[from] AddrParseError),
25    #[error("num parse error")]
26    ParseIntError(#[from] ParseIntError),
27}
28
29#[derive(Debug, Clone, Copy)]
30pub struct CrossIpv4Pool {
31    start: u32,
32    end: u32,
33    next: u32,
34}
35
36impl Iterator for CrossIpv4Pool {
37    type Item = Ipv4Addr;
38    fn next(&mut self) -> Option<Self::Item> {
39        if self.next <= self.end {
40            let ret = self.next;
41            self.next += 1;
42            Some(ret.into())
43        } else {
44            None
45        }
46    }
47}
48
49impl fmt::Display for CrossIpv4Pool {
50    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
51        let start: Ipv4Addr = self.start.into();
52        let end: Ipv4Addr = self.end.into();
53        let now: Ipv4Addr = self.next.into();
54        write!(f, "{}-{}, next {}", start, end, now)
55    }
56}
57
58impl CrossIpv4Pool {
59    /// Returns an Ipv4 iterator over the cross different subnetwork.
60    /// # Example
61    /// ```
62    /// use subnetwork::CrossIpv4Pool;
63    /// use std::net::Ipv4Addr;
64    ///
65    /// fn main() {
66    ///     let start = Ipv4Addr::new(192, 168, 1, 1);
67    ///     let end = Ipv4Addr::new(192, 168, 3, 254);
68    ///     let pool = CrossIpv4Pool::new(start, end).unwrap();
69    ///     for i in pool {
70    ///         println!("{:?}", i);
71    ///     }
72    /// }
73    /// ```
74    pub fn new<T: Into<Ipv4AddrExt>>(
75        start: T,
76        end: Ipv4Addr,
77    ) -> Result<CrossIpv4Pool, SubnetworkError> {
78        let start_ip_ext: Ipv4AddrExt = start.into();
79        let end_ip_ext: Ipv4AddrExt = end.into();
80        let start_u32: u32 = start_ip_ext.addr;
81        let end_u32: u32 = end_ip_ext.addr;
82
83        if start_u32 <= end_u32 {
84            let cip = CrossIpv4Pool {
85                start: start_u32,
86                end: end_u32,
87                next: start_u32,
88            };
89            Ok(cip)
90        } else {
91            let error_range = format!("{}-{}", start_u32, end_u32);
92            Err(SubnetworkError::InvalidInput { msg: error_range })
93        }
94    }
95    /// Extract all IPs.
96    pub fn to_vec(&self) -> Vec<Ipv4Addr> {
97        self.into_iter().collect()
98    }
99    /// Check if ip pool contains this ip.
100    pub fn contain(&self, addr: Ipv4Addr) -> bool {
101        let addr: u32 = addr.into();
102        if addr <= self.end && addr >= self.start {
103            true
104        } else {
105            false
106        }
107    }
108    /// Returns the number of possible host address in this `CrossIpv4Pool`.
109    pub fn len(&self) -> usize {
110        let length = self.end - self.start;
111        length as usize
112    }
113}
114
115#[derive(Debug, Clone, Copy)]
116pub struct Ipv4Pool {
117    prefix: u32,
118    mask: u32,
119    next: u32,
120    stop: u32,
121    addr: u32,
122}
123
124impl Iterator for Ipv4Pool {
125    type Item = Ipv4Addr;
126    fn next(&mut self) -> Option<Self::Item> {
127        if self.next < self.stop {
128            let ret = self.prefix + self.next;
129            self.next += 1;
130            Some(ret.into())
131        } else {
132            None
133        }
134    }
135}
136
137impl fmt::Display for Ipv4Pool {
138    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
139        let prefix_addr: Ipv4Addr = self.prefix.into();
140        let mut prefix = 0;
141        let mut mask = self.mask;
142        while mask != 0 {
143            mask <<= 1;
144            prefix += 1;
145        }
146        write!(f, "{}/{}", prefix_addr, prefix)
147    }
148}
149
150impl FromStr for Ipv4Pool {
151    type Err = SubnetworkError;
152    fn from_str(addr: &str) -> Result<Self, Self::Err> {
153        if addr.contains("/") {
154            let addr_vec: Vec<&str> = addr.split("/").collect();
155            if addr_vec.len() == 2 {
156                let ip_addr = Ipv4Addr::from_str(addr_vec[0])?;
157                let prefix = u8::from_str(addr_vec[1])?;
158                if prefix <= IPV4_PREFIX_MAX_LEN {
159                    let addr: u32 = ip_addr.into();
160                    let mask: u32 = u32::MAX << (IPV4_PREFIX_MAX_LEN - prefix);
161                    let next = INIT_NEXT_VALUE as u32;
162                    let stop = 1 << (IPV4_PREFIX_MAX_LEN - prefix);
163                    let prefix = addr & mask;
164                    return Ok(Ipv4Pool {
165                        prefix,
166                        mask,
167                        next,
168                        stop,
169                        addr,
170                    });
171                }
172            }
173        }
174        // final
175        Err(SubnetworkError::InvalidInput {
176            msg: addr.to_string(),
177        })
178    }
179}
180
181impl Ipv4Pool {
182    /// Returns an Ipv4 iterator over the address contained in the network.
183    /// Include network address and broadcast address.
184    /// # Example
185    /// ```
186    /// use subnetwork::Ipv4Pool;
187    /// use std::net::Ipv4Addr;
188    ///
189    /// fn main() {
190    ///     let ip = Ipv4Addr::new(192, 168, 1, 1);
191    ///     let pool = Ipv4Pool::new(ip, 24).unwrap();
192    ///     for i in pool {
193    ///         println!("{:?}", i);
194    ///     }
195    /// }
196    /// ```
197    pub fn new<T: Into<Ipv4AddrExt>>(addr: T, prefix: u8) -> Result<Ipv4Pool, SubnetworkError> {
198        let addr_ext: Ipv4AddrExt = addr.into();
199        if prefix > IPV4_PREFIX_MAX_LEN {
200            let error_addr = format!("{}/{}", addr_ext, prefix);
201            Err(SubnetworkError::InvalidInput {
202                msg: error_addr.to_string(),
203            })
204        } else {
205            let addr: u32 = addr_ext.addr;
206            let mask: u32 = u32::MAX << (IPV4_PREFIX_MAX_LEN - prefix);
207            let next = INIT_NEXT_VALUE as u32;
208            let stop = 1 << (IPV4_PREFIX_MAX_LEN - prefix);
209            let prefix = addr & mask;
210            return Ok(Ipv4Pool {
211                prefix,
212                mask,
213                next,
214                stop,
215                addr,
216            });
217        }
218    }
219    /// Extract all IPs.
220    pub fn to_vec(&self) -> Vec<Ipv4Addr> {
221        self.into_iter().collect()
222    }
223    /// Check if ip pool contains this ip.
224    /// # Example
225    /// ```
226    /// use std::net::Ipv4Addr;
227    /// use std::str::FromStr;
228    /// use subnetwork::Ipv4Pool;
229    ///
230    /// fn main() {
231    ///     let pool = Ipv4Pool::from_str("192.168.1.0/24").unwrap();
232    ///     let ip = Ipv4Addr::from_str("192.168.1.20").unwrap();
233    ///     let ret = pool.contain(ip);
234    ///     assert_eq!(ret, true);
235    /// }
236    /// ```
237    pub fn contain(&self, addr: Ipv4Addr) -> bool {
238        let addr: u32 = addr.into();
239        if addr & self.mask == self.prefix {
240            true
241        } else {
242            false
243        }
244    }
245    /// Returns the addr of the network denoted by this `Ipv4Pool`.
246    /// This means the lowest possible IP addr inside of the network.
247    pub fn network(&self) -> Ipv4Addr {
248        self.prefix.into()
249    }
250    /// Returns the broadcasting addr of this `Ipv4Pool`.
251    /// This means the highest possible IP addr inside of the network.
252    pub fn broadcast(&self) -> Ipv4Addr {
253        let biggest = !self.mask;
254        let ret = self.prefix + biggest;
255        ret.into()
256    }
257    /// Returns the number of possible address in this `Ipv4Pool` (include 0 and 255).
258    pub fn len(&self) -> usize {
259        let biggest = !self.mask + 1;
260        biggest as usize
261    }
262    /// Represents a network-range address.
263    pub fn addr(&self) -> Ipv4Addr {
264        self.addr.into()
265    }
266}
267
268#[derive(Debug, Clone, Copy)]
269pub struct CrossIpv6Pool {
270    start: u128,
271    end: u128,
272    next: u128,
273}
274
275impl Iterator for CrossIpv6Pool {
276    type Item = Ipv6Addr;
277    fn next(&mut self) -> Option<Self::Item> {
278        if self.next <= self.end {
279            let ret = self.next;
280            self.next += 1;
281            Some(ret.into())
282        } else {
283            None
284        }
285    }
286}
287
288impl fmt::Display for CrossIpv6Pool {
289    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
290        let start: Ipv6Addr = self.start.into();
291        let end: Ipv6Addr = self.end.into();
292        write!(f, "{}-{}", start, end)
293    }
294}
295
296impl CrossIpv6Pool {
297    /// Returns an Ipv4 iterator over the cross different subnetwork address.
298    /// # Example
299    /// ```
300    /// use subnetwork::CrossIpv6Pool;
301    /// use std::net::Ipv6Addr;
302    /// use std::str::FromStr;
303    ///
304    /// fn main() {
305    ///     let start = Ipv6Addr::from_str("fe80::215:5dff:fe20:b393").unwrap();
306    ///     let end = Ipv6Addr::from_str("fe80::215:5dff:fe20:b395").unwrap();
307    ///     let pool = CrossIpv6Pool::new(start, end).unwrap();
308    ///     for i in pool {
309    ///         println!("{:?}", i);
310    ///     }
311    /// }
312    /// ```
313    pub fn new(start: Ipv6Addr, end: Ipv6Addr) -> Result<CrossIpv6Pool, SubnetworkError> {
314        let start_ipv6: Ipv6AddrExt = start.into();
315        let end_ipv6: Ipv6AddrExt = end.into();
316        if start_ipv6.addr <= end_ipv6.addr {
317            let cip = CrossIpv6Pool {
318                start: start_ipv6.addr,
319                end: end_ipv6.addr,
320                next: start_ipv6.addr,
321            };
322            Ok(cip)
323        } else {
324            let msg = format!("{}-{}", start, end);
325            Err(SubnetworkError::InvalidInput { msg })
326        }
327    }
328    /// Extract all IPs.
329    pub fn to_vec(&self) -> Vec<Ipv6Addr> {
330        self.into_iter().collect()
331    }
332    /// Check if ip pool contains this ip.
333    pub fn contain(&self, addr: Ipv6Addr) -> bool {
334        let addr: u128 = addr.into();
335        if addr <= self.end && addr >= self.start {
336            true
337        } else {
338            false
339        }
340    }
341    /// Returns the number of possible host address in this `CrossIpv6Pool`.
342    pub fn len(&self) -> usize {
343        let length = self.end - self.start;
344        length as usize
345    }
346}
347
348#[derive(Debug, Clone, Copy)]
349pub struct Ipv6Pool {
350    prefix: u128,
351    mask: u128,
352    next: u128,
353    stop: u128,
354    addr: u128,
355}
356
357impl Iterator for Ipv6Pool {
358    type Item = Ipv6Addr;
359    fn next(&mut self) -> Option<Self::Item> {
360        if self.next < self.stop {
361            let ret = self.prefix + self.next;
362            self.next += 1;
363            Some(ret.into())
364        } else {
365            None
366        }
367    }
368}
369
370impl fmt::Display for Ipv6Pool {
371    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
372        let prefix_addr: Ipv6Addr = self.prefix.into();
373        let mut prefix = 0;
374        let mut mask = self.mask;
375        while mask != 0 {
376            mask <<= 1;
377            prefix += 1;
378        }
379        write!(f, "{}/{}", prefix_addr, prefix)
380    }
381}
382
383impl FromStr for Ipv6Pool {
384    type Err = SubnetworkError;
385    fn from_str(addr: &str) -> Result<Self, Self::Err> {
386        if addr.contains("/") {
387            let addr_vec: Vec<&str> = addr.split("/").collect();
388            if addr_vec.len() == 2 {
389                let ip_addr = Ipv6Addr::from_str(addr_vec[0])?;
390                let prefix = u8::from_str(addr_vec[1])?;
391                if prefix <= IPV6_PREFIX_MAX_LEN {
392                    let addr: u128 = ip_addr.into();
393                    let mask: u128 = u128::MAX << (IPV6_PREFIX_MAX_LEN - prefix);
394                    let next = INIT_NEXT_VALUE as u128;
395                    let stop = 1 << (IPV6_PREFIX_MAX_LEN - prefix);
396                    let prefix = addr & mask;
397                    return Ok(Ipv6Pool {
398                        prefix,
399                        mask,
400                        next,
401                        stop,
402                        addr,
403                    });
404                }
405            }
406        }
407        // final
408        Err(SubnetworkError::InvalidInput {
409            msg: addr.to_string(),
410        })
411    }
412}
413
414impl Ipv6Pool {
415    /// Returns an Ipv6 iterator over the address contained in the network.
416    /// Include network address and broadcast address.
417    /// # Example
418    /// ```
419    /// use subnetwork::Ipv6Pool;
420    /// use std::net::Ipv6Addr;
421    ///
422    /// fn main() {
423    ///     let ipv6_str = "::ffff:192.10.2.0";
424    ///     let ipv6: Ipv6Addr = ipv6_str.parse().unwrap();
425    ///     let pool = Ipv6Pool::new(ipv6, 120).unwrap();
426    ///     for i in pool {
427    ///         println!("{:?}", i);
428    ///     }
429    /// }
430    /// ```
431    pub fn new(addr: Ipv6Addr, prefix: u8) -> Result<Ipv6Pool, SubnetworkError> {
432        if prefix > IPV6_PREFIX_MAX_LEN {
433            let error_addr = format!("{}/{}", addr, prefix);
434            Err(SubnetworkError::InvalidInput {
435                msg: error_addr.to_string(),
436            })
437        } else {
438            let addr: u128 = addr.into();
439            let mask: u128 = u128::MAX << (IPV6_PREFIX_MAX_LEN - prefix);
440            let next = INIT_NEXT_VALUE as u128;
441            let stop = 1 << (IPV6_PREFIX_MAX_LEN - prefix);
442            let prefix = addr & mask;
443            Ok(Ipv6Pool {
444                prefix,
445                mask,
446                next,
447                stop,
448                addr,
449            })
450        }
451    }
452    /// Extract all IPs.
453    pub fn to_vec(&self) -> Vec<Ipv6Addr> {
454        self.into_iter().collect()
455    }
456    /// Check if ip pool contains this ip.
457    /// # Example
458    /// ```
459    /// use std::net::Ipv6Addr;
460    /// use std::str::FromStr;
461    /// use subnetwork::Ipv6Pool;
462    ///
463    /// fn main() {
464    ///     let pool = Ipv6Pool::from_str("::ffff:192.10.2.0/120").unwrap();
465    ///     let ip = Ipv6Addr::from_str("::ffff:192.10.2.1").unwrap();
466    ///     let ret = pool.contain(ip);
467    ///     assert_eq!(ret, true);
468    /// }
469    /// ```
470    pub fn contain(&self, addr: Ipv6Addr) -> bool {
471        let addr: u128 = addr.into();
472        if addr & self.mask == self.prefix {
473            true
474        } else {
475            false
476        }
477    }
478    /// Returns the addr of the network denoted by this `Ipv6Pool`.
479    /// This means the lowest possible IP addr inside of the network.
480    pub fn network(&self) -> Ipv6Addr {
481        self.prefix.into()
482    }
483    /// Returns the number of possible host address in this `Ipv6Pool`.
484    pub fn len(&self) -> usize {
485        let biggest = !self.mask + 1;
486        biggest as usize
487    }
488    /// Represents a network-range address.
489    pub fn addr(&self) -> Ipv6Addr {
490        self.addr.into()
491    }
492}
493
494#[derive(Debug, Clone, Copy)]
495pub enum IpPool {
496    V4(Ipv4Pool),
497    V6(Ipv6Pool),
498}
499
500impl fmt::Display for IpPool {
501    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
502        let output = match self {
503            Self::V4(x) => format!("{}", x),
504            Self::V6(x) => format!("{}", x),
505        };
506        write!(f, "{}", output)
507    }
508}
509
510impl Iterator for IpPool {
511    type Item = IpAddr;
512    fn next(&mut self) -> Option<Self::Item> {
513        match self {
514            IpPool::V4(iter) => iter.next().map(IpAddr::V4),
515            IpPool::V6(iter) => iter.next().map(IpAddr::V6),
516        }
517    }
518}
519
520/* Single Addr Struct */
521
522#[derive(Debug, Clone, Copy)]
523pub struct Ipv4AddrExt {
524    addr: u32,
525}
526
527impl fmt::Display for Ipv4AddrExt {
528    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
529        let addr: Ipv4Addr = self.addr.into();
530        write!(f, "{}", addr)
531    }
532}
533
534impl From<Ipv4Addr> for Ipv4AddrExt {
535    fn from(addr: Ipv4Addr) -> Self {
536        let addr: u32 = addr.into();
537        Ipv4AddrExt { addr }
538    }
539}
540
541impl From<Ipv4AddrExt> for Ipv4Addr {
542    fn from(addr: Ipv4AddrExt) -> Self {
543        let new_addr: u32 = addr.addr;
544        new_addr.into()
545    }
546}
547
548impl FromStr for Ipv4AddrExt {
549    type Err = SubnetworkError;
550    fn from_str(addr: &str) -> Result<Self, Self::Err> {
551        let new_addr = Ipv4Addr::from_str(addr)?;
552        let addr: u32 = new_addr.into();
553        Ok(Ipv4AddrExt { addr })
554    }
555}
556
557impl Ipv4AddrExt {
558    /// Creates a new IPv4AddrExt from four eight-bit octets.
559    pub fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4AddrExt {
560        let a_fix = (a as u32) << 24;
561        let b_fix = (b as u32) << 16;
562        let c_fix = (c as u32) << 8;
563        let d_fix = d as u32;
564        let addr = a_fix + b_fix + c_fix + d_fix;
565        Ipv4AddrExt { addr }
566    }
567    /// Returns the largest identical prefix of two IP address.
568    /// # Example
569    /// ```
570    /// use subnetwork::Ipv4AddrExt;
571    /// use subnetwork::Ipv4Pool;
572    /// use std::net::Ipv4Addr;
573    ///
574    /// fn main() {
575    ///     let ipv4_1 = Ipv4Addr::new(192, 168, 1, 136);
576    ///     let ipv4_2 = Ipv4Addr::new(192, 168, 1, 192);
577    ///     let ipv4ext_1: Ipv4AddrExt = ipv4_1.into();
578    ///     let ret = ipv4ext_1.largest_identical_prefix(ipv4_2);
579    ///     assert_eq!(ret, 25);
580    /// }
581    /// ```
582    pub fn largest_identical_prefix<T: Into<Ipv4AddrExt>>(&self, target: T) -> u8 {
583        let a = self.addr;
584        let b = target.into().addr;
585        let init_mask = 2u32.pow(31);
586        let mut mask = init_mask;
587
588        for c in 0..IPV4_PREFIX_MAX_LEN {
589            if a & mask != b & mask {
590                return c;
591            }
592            mask = (mask >> 1) + init_mask;
593        }
594        0
595    }
596}
597
598#[derive(Debug, Clone, Copy)]
599pub struct Ipv6AddrExt {
600    addr: u128,
601}
602
603impl fmt::Display for Ipv6AddrExt {
604    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
605        let addr: Ipv6Addr = self.addr.into();
606        write!(f, "{}", addr)
607    }
608}
609
610impl From<Ipv6Addr> for Ipv6AddrExt {
611    fn from(addr: Ipv6Addr) -> Self {
612        let addr: u128 = addr.into();
613        Ipv6AddrExt { addr }
614    }
615}
616
617impl From<Ipv6AddrExt> for Ipv6Addr {
618    fn from(addr: Ipv6AddrExt) -> Self {
619        let new_addr: u128 = addr.addr;
620        new_addr.into()
621    }
622}
623
624impl FromStr for Ipv6AddrExt {
625    type Err = SubnetworkError;
626    fn from_str(addr: &str) -> Result<Self, Self::Err> {
627        let new_addr = Ipv6Addr::from_str(addr)?;
628        let addr: u128 = new_addr.into();
629        Ok(Ipv6AddrExt { addr })
630    }
631}
632
633impl Ipv6AddrExt {
634    /// Creates a new IPv6 address from eight 16-bit segments.
635    pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6AddrExt {
636        let a_fix = (a as u128) << 112;
637        let b_fix = (b as u128) << 96;
638        let c_fix = (c as u128) << 80;
639        let d_fix = (d as u128) << 64;
640        let e_fix = (e as u128) << 48;
641        let f_fix = (f as u128) << 32;
642        let g_fix = (g as u128) << 16;
643        let h_fix = h as u128;
644        let addr = a_fix + b_fix + c_fix + d_fix + e_fix + f_fix + g_fix + h_fix;
645        Ipv6AddrExt { addr }
646    }
647    /// Returns the node local scope multicast addr of this `Ipv6`.
648    pub fn node_multicast(&self) -> Ipv6Addr {
649        let node = Ipv6Addr::new(
650            0xff01, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0xff00, 0x0000,
651        );
652        let mask = Ipv6Addr::new(
653            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00ff, 0xffff,
654        );
655        let node_u128: u128 = node.into();
656        let mask_u128: u128 = mask.into();
657        (node_u128 + (mask_u128 & self.addr)).into()
658    }
659    /// Returns the link local scope multicast addr of this `Ipv6`.
660    pub fn link_multicast(&self) -> Ipv6Addr {
661        let link = Ipv6Addr::new(
662            0xff02, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0xff00, 0x0000,
663        );
664        let mask = Ipv6Addr::new(
665            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00ff, 0xffff,
666        );
667        let link_u128: u128 = link.into();
668        let mask_u128: u128 = mask.into();
669        (link_u128 + (mask_u128 & self.addr)).into()
670    }
671    /// Returns the site local scope multicast addr of this `Ipv6`.
672    pub fn site_multicast(&self) -> Ipv6Addr {
673        let site = Ipv6Addr::new(
674            0xff05, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0xff00, 0x0000,
675        );
676        let mask = Ipv6Addr::new(
677            0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00ff, 0xffff,
678        );
679        let site_u128: u128 = site.into();
680        let mask_u128: u128 = mask.into();
681        (site_u128 + (mask_u128 & self.addr)).into()
682    }
683    pub fn largest_identical_prefix<T: Into<Ipv6AddrExt>>(&self, target: T) -> u8 {
684        let a = self.addr;
685        let b = target.into().addr;
686        let init_mask = 2u128.pow(127);
687        let mut mask = init_mask;
688
689        for c in 0..IPV6_PREFIX_MAX_LEN {
690            if a & mask != b & mask {
691                return c;
692            }
693            mask = (mask >> 1) + init_mask;
694        }
695        0
696    }
697}
698
699#[derive(Debug, Clone, Copy)]
700pub struct NetmaskExt {
701    prefix: u8,
702}
703
704impl NetmaskExt {
705    /// Constructs a new `NetmaskExt` from a given prefix.
706    /// # Example
707    /// ```
708    /// use subnetwork::NetmaskExt;
709    ///
710    /// fn main() {
711    ///     let netmask = NetmaskExt::new(24);
712    ///     // 255.255.255.0
713    ///     let netmask_ip = netmask.to_ipv4().unwrap();
714    /// }
715    /// ```
716    pub fn new(prefix: u8) -> NetmaskExt {
717        NetmaskExt { prefix }
718    }
719    /// Constructs a new `NetmaskExt` from a given IpAddr (like 255.255.255.0).
720    /// # Example
721    /// ```
722    /// use subnetwork::NetmaskExt;
723    /// use std::net::Ipv4Addr;
724    /// use std::net::IpAddr;
725    ///
726    /// fn main() {
727    ///     let addr = IpAddr::V4(Ipv4Addr::new(255, 255, 255, 0));
728    ///     let netmask = NetmaskExt::from_addr(addr);
729    ///     // 255.255.255.0
730    ///     let prefix = netmask.get_prefix();
731    ///     assert_eq!(prefix, 24)
732    /// }
733    /// ```
734    pub fn from_addr(addr: IpAddr) -> NetmaskExt {
735        // 255.255.255.0, 255.255.192.0 .etc
736        let prefix = match addr {
737            IpAddr::V4(ipv4) => {
738                let mask = u32::from_be_bytes(ipv4.octets());
739                let prefix = mask.count_ones() as u8;
740                prefix
741            }
742            IpAddr::V6(ipv6) => {
743                let mask = u128::from_be_bytes(ipv6.octets());
744                let prefix = mask.count_ones() as u8;
745                prefix
746            }
747        };
748        NetmaskExt { prefix }
749    }
750    /// Return netmask address's prefix length.
751    pub fn get_prefix(&self) -> u8 {
752        self.prefix
753    }
754    /// Convert to Ipv4Addr address.
755    pub fn to_ipv4(&self) -> Result<Ipv4Addr, SubnetworkError> {
756        if self.prefix == 0 {
757            Ok((0 as u32).into())
758        } else {
759            if self.prefix > IPV4_PREFIX_MAX_LEN {
760                let msg = format!("prefix: {}", self.prefix);
761                Err(SubnetworkError::InvalidInput { msg })
762            } else {
763                Ok((u32::MAX << (IPV4_PREFIX_MAX_LEN - self.prefix)).into())
764            }
765        }
766    }
767    /// Convert to Ipv6Addr address.
768    pub fn to_ipv6(&self) -> Result<Ipv6Addr, SubnetworkError> {
769        if self.prefix == 0 {
770            Ok((0 as u128).into())
771        } else {
772            if self.prefix > IPV6_PREFIX_MAX_LEN {
773                let msg = format!("prefix: {}", self.prefix);
774                Err(SubnetworkError::InvalidInput { msg })
775            } else {
776                Ok((u128::MAX << (IPV6_PREFIX_MAX_LEN - self.prefix)).into())
777            }
778        }
779    }
780}
781
782#[cfg(test)]
783mod tests {
784    use super::*;
785    /* README.md examples */
786    #[test]
787    fn readme_example_1() {
788        let pool = Ipv4Pool::new(Ipv4Addr::new(192, 168, 1, 1), 24).unwrap();
789        // from 192.168.1.0 to 192.168.1.255
790        for ipv4 in pool {
791            println!("{}", ipv4);
792        }
793
794        let pool = Ipv4Pool::from_str("192.168.1.0/24").unwrap();
795        for ipv4 in pool {
796            println!("{}", ipv4);
797        }
798
799        let pool: Ipv4Pool = "192.168.1.0/24".parse().unwrap();
800        for ipv4 in pool {
801            println!("{}", ipv4);
802        }
803
804        let test_ipv4 = Ipv4Addr::new(192, 168, 1, 233);
805        assert_eq!(pool.contain(test_ipv4), true);
806
807        let broadcast = Ipv4Addr::new(192, 168, 1, 255);
808        assert_eq!(pool.broadcast(), broadcast);
809
810        let network = Ipv4Addr::new(192, 168, 1, 0);
811        assert_eq!(pool.network(), network);
812
813        assert_eq!(pool.len(), 256);
814        // pool is copied.
815        assert_eq!(pool.to_string(), "192.168.1.0/24");
816    }
817    #[test]
818    fn readme_example_2() {
819        let start = Ipv4Addr::new(192, 168, 1, 16);
820        let end = Ipv4Addr::new(192, 168, 3, 200);
821        let pool = CrossIpv4Pool::new(start, end).unwrap();
822        // include 192.168.1.16 and 192.168.3.200
823        for i in pool {
824            println!("{:?}", i);
825        }
826
827        let test_ipv4 = Ipv4Addr::new(192, 168, 1, 233);
828        assert_eq!(pool.contain(test_ipv4), true);
829        let test_ipv4 = Ipv4Addr::new(192, 168, 2, 0);
830        assert_eq!(pool.contain(test_ipv4), true);
831        let test_ipv4 = Ipv4Addr::new(192, 168, 3, 255);
832        assert_eq!(pool.contain(test_ipv4), false);
833        let test_ipv4 = Ipv4Addr::new(192, 168, 3, 200);
834        assert_eq!(pool.contain(test_ipv4), true);
835    }
836    #[test]
837    fn readme_example_3() {
838        // test1
839        let ip1 = Ipv4Addr::new(192, 168, 1, 0);
840        let ip2 = Ipv4Addr::new(192, 168, 1, 255);
841
842        let ip1ext: Ipv4AddrExt = ip1.into();
843        assert_eq!(ip1ext.largest_identical_prefix(ip2), 24);
844
845        // test 2
846        let ip1 = Ipv4Addr::new(192, 168, 1, 136);
847        let ip2 = Ipv4Addr::new(192, 168, 1, 192);
848
849        let ip1ext: Ipv4AddrExt = ip1.into();
850        assert_eq!(ip1ext.largest_identical_prefix(ip2), 25);
851    }
852    #[test]
853    fn readme_example_4() {
854        let ipv6 = Ipv6Addr::from_str("::ffff:192.10.2.255").unwrap();
855        let ipv6_ext: Ipv6AddrExt = ipv6.into();
856
857        let ipv6_node_multicast = Ipv6Addr::from_str("ff01::1:ff0a:2ff").unwrap();
858        assert_eq!(ipv6_ext.node_multicast(), ipv6_node_multicast);
859
860        let ipv6_link_multicast = Ipv6Addr::from_str("ff02::1:ff0a:2ff").unwrap();
861        assert_eq!(ipv6_ext.link_multicast(), ipv6_link_multicast);
862
863        let ipv6_site_multicast = Ipv6Addr::from_str("ff05::1:ff0a:2ff").unwrap();
864        assert_eq!(ipv6_ext.site_multicast(), ipv6_site_multicast);
865    }
866    #[test]
867    fn readme_example_5() {
868        let netmask = NetmaskExt::new(24);
869        let netmask_addr = netmask.to_ipv4().unwrap();
870        assert_eq!(netmask_addr, Ipv4Addr::new(255, 255, 255, 0));
871
872        let netmask = NetmaskExt::new(26);
873        let netmask_addr = netmask.to_ipv4().unwrap();
874        assert_eq!(netmask_addr, Ipv4Addr::new(255, 255, 255, 192));
875    }
876    #[test]
877    fn netmask_ext() {
878        let addr = IpAddr::V4(Ipv4Addr::new(255, 255, 255, 0));
879        let netmask = NetmaskExt::from_addr(addr);
880        // 255.255.255.0
881        let prefix = netmask.get_prefix();
882        assert_eq!(prefix, 24);
883
884        let addr = IpAddr::V4(Ipv4Addr::new(255, 255, 255, 192));
885        let netmask = NetmaskExt::from_addr(addr);
886        // 255.255.255.0
887        let prefix = netmask.get_prefix();
888        assert_eq!(prefix, 26);
889
890        let addr = IpAddr::V4(Ipv4Addr::new(255, 255, 0, 0));
891        let netmask = NetmaskExt::from_addr(addr);
892        // 255.255.255.0
893        let prefix = netmask.get_prefix();
894        assert_eq!(prefix, 16);
895
896        let addr = IpAddr::V4(Ipv4Addr::new(255, 255, 192, 0));
897        let netmask = NetmaskExt::from_addr(addr);
898        // 255.255.255.0
899        let prefix = netmask.get_prefix();
900        assert_eq!(prefix, 18);
901    }
902    /* Others */
903    #[test]
904    fn ipv4_methods() {
905        let ipv4 = Ipv4Addr::new(192, 168, 1, 1);
906        if ipv4.is_private() {
907            println!("{} is private", ipv4);
908        } else {
909            println!("{} is not private", ipv4);
910        }
911        let ipv6 = Ipv6Addr::new(0xfe80, 0, 0, 0, 0x20c, 0x29ff, 0xfedd, 0xf57);
912        if ipv6.is_multicast() {
913            println!("{} is multicast", ipv6);
914        } else {
915            println!("{} is not multicast", ipv6);
916        }
917    }
918    /* Ipv4 */
919    #[test]
920    fn ipv4_pool_print() {
921        let test_str = "192.168.1.0/24";
922        let ipv4_pool = Ipv4Pool::from_str(test_str).unwrap();
923        let ipv4_pool_str = format!("{}", ipv4_pool);
924        println!("{}", ipv4_pool_str);
925    }
926    #[test]
927    fn ipv4_print() {
928        let test_str = "192.168.1.1";
929        let ipv4 = Ipv4AddrExt::from_str(test_str).unwrap();
930        let ipv4_str = format!("{}", ipv4);
931        assert_eq!(ipv4_str, test_str);
932    }
933    #[test]
934    fn ipv4() {
935        let ipv4 = Ipv4AddrExt::from_str("192.168.1.1").unwrap();
936        println!("{:8b}", ipv4.addr);
937        assert_eq!(ipv4.addr, 3232235777);
938    }
939    /* Ipv6 */
940    #[test]
941    fn ipv6() {
942        let ipv6 = Ipv6AddrExt::from_str("::ffff:192.10.2.255").unwrap();
943        println!("{:?}", ipv6);
944        assert_eq!(ipv6.addr, 281473903624959);
945    }
946    #[test]
947    fn test_github_issues_1() {
948        // return error instead of panic
949        let _pool1 = Ipv4Pool::from_str("1.2.3.4/33");
950        let _pool2 = Ipv4Pool::from_str("1.2.3.4/");
951        let _pool3 = Ipv4Pool::from_str("nonip/24");
952    }
953}