ipcheck_rs/
lib.rs

1//! `iprange` is a library for managing IP ranges.
2//!
3//! An [`IpRange`] is a set of networks.
4//! The type of the networks it holds is specified by the generics type of [`IpRange`].
5//!
6//! You can add or remove an [`IpNet`] from an [`IpRange`].
7//! An [`IpNet`] can be either an `Ipv4Net` or an `Ipv6Net`.
8//!
9//! It also supports these useful operations:
10//!
11//! * [`merge`]
12//! * [`intersect`]
13//! * [`exclude`]
14//!
15//! Here is a simple example:
16//!
17//! ```
18//! extern crate iprange;
19//! extern crate ipnet;
20//!
21//! use std::net::Ipv4Addr;
22//! use iprange::IpRange;
23//! use ipnet::Ipv4Net;
24//!
25//! fn main() {
26//!     let ip_range: IpRange<Ipv4Net> = ["10.0.0.0/8", "172.16.0.0/16", "192.168.1.0/24"]
27//!         .iter()
28//!         .map(|s| s.parse().unwrap())
29//!         .collect();
30//!
31//!     assert!(ip_range.contains(&"172.16.32.1".parse::<Ipv4Addr>().unwrap()));
32//!     assert!(ip_range.contains(&"192.168.1.1".parse::<Ipv4Addr>().unwrap()));
33//! }
34//! ```
35//!
36//! [`IpRange`]: struct.IpRange.html
37//! [`IpNet`]: trait.IpNet.html
38//! [`Ipv4Net`]: https://docs.rs/ipnet/1.0.0/ipnet/struct.Ipv4Net.html
39//! [`merge`]: struct.IpRange.html#method.merge
40//! [`intersect`]: struct.IpRange.html#method.intersect
41//! [`exclude`]: struct.IpRange.html#method.exclude
42
43use ipnet::{Ipv4Net, Ipv6Net};
44use std::collections::VecDeque;
45use std::fmt;
46use std::iter::FromIterator;
47use std::marker::PhantomData;
48use std::net::{Ipv4Addr, Ipv6Addr};
49
50/// A set of networks that supports various operations:
51///
52/// * [`add`]
53/// * [`remove`]
54/// * [`contains`]
55/// * [`merge`]
56/// * [`intersect`]
57/// * [`exclude`]
58///
59/// `IntoIter` is implemented for `&IpRange`. So, you can use `for`
60/// to iterate over the networks in an `IpRange`:
61///
62/// ```
63///
64/// use iprange::IpRange;
65/// use ipnet::Ipv4Net;
66///
67/// fn main() {
68///     let ip_range: IpRange<Ipv4Net> = ["172.16.0.0/16", "192.168.1.0/24"]
69///         .iter()
70///         .map(|s| s.parse().unwrap())
71///         .collect();
72///
73///     for network in &ip_range {
74///         println!("{:?}", network);
75///     }
76/// }
77/// ```
78///
79/// [`add`]: struct.IpRange.html#method.add
80/// [`remove`]: struct.IpRange.html#method.remove
81/// [`contains`]: struct.IpRange.html#method.contains
82/// [`merge`]: struct.IpRange.html#method.merge
83/// [`intersect`]: struct.IpRange.html#method.intersect
84/// [`exclude`]: struct.IpRange.html#method.exclude
85#[derive(Clone, PartialEq, Eq)]
86pub struct IpRange<N: IpNet> {
87    // IpRange uses a radix trie to store networks
88    trie: IpTrie<N>,
89    phantom_net: PhantomData<N>,
90}
91
92impl<N: IpNet> IpRange<N> {
93    /// Creates an empty `IpRange`.
94    pub fn new() -> IpRange<N> {
95        IpRange {
96            trie: IpTrie::new(),
97            phantom_net: PhantomData,
98        }
99    }
100
101    pub fn into_trie(self) -> IpTrie<N> {
102        self.trie
103    }
104
105    /// Add a network to `self`.
106    ///
107    /// Returns `&mut self` in order to enable method chaining.
108    ///
109    /// Pay attention that this operation will not combine two
110    /// networks automatically. To do this, call [`simplify`] method
111    /// explicitly. For example:
112    ///
113    /// ```
114    /// extern crate iprange;
115    /// extern crate ipnet;
116    ///
117    /// use iprange::IpRange;
118    /// use ipnet::Ipv4Net;
119    ///
120    /// fn main() {
121    ///     let mut ip_range: IpRange<Ipv4Net> = IpRange::new();
122    ///     ip_range.add("192.168.0.0/24".parse().unwrap())
123    ///            .add("192.168.1.0/24".parse().unwrap());
124    ///     assert_eq!(ip_range.into_iter().count(), 2);
125    ///
126    ///     ip_range.simplify();
127    ///     assert_eq!(ip_range.into_iter().count(), 1);
128    /// }
129    /// ```
130    ///
131    /// [`simplify`]: struct.IpRange.html#method.simplify
132    pub fn add(&mut self, network: N) -> &mut Self {
133        self.trie.insert(network);
134        self
135    }
136
137    /// Remove a network from `self`.
138    ///
139    /// Returns `&mut self` in order to enable method chaining.
140    ///
141    /// `self` does not necessarily has exactly the network to be removed.
142    /// The network can be a networkwork of a network in `self`.
143    /// This method will do splitting and remove the corresponding network.
144    /// For example:
145    ///
146    /// ```
147    /// extern crate iprange;
148    /// extern crate ipnet;
149    ///
150    /// use iprange::IpRange;
151    /// use ipnet::Ipv4Net;
152    ///
153    /// fn main() {
154    ///     let mut ip_range: IpRange<Ipv4Net> = IpRange::new();
155    ///     ip_range.add("192.168.0.0/23".parse().unwrap())
156    ///             .remove("192.168.0.0/24".parse().unwrap());
157    ///     // Now, ip_range has only one network: "192.168.1.0/24".
158    /// }
159    /// ```
160    pub fn remove(&mut self, network: N) -> &mut Self {
161        self.trie.remove(network);
162        self
163    }
164
165    /// Returns `true` if the `self` has no network.
166    ///
167    /// # Examples
168    /// ```
169    /// # extern crate ipnet;
170    /// #
171    /// # use iprange::IpRange;
172    /// # use ipnet::Ipv4Net;
173    /// let mut ip_range = IpRange::new();
174    /// let network: Ipv4Net = "1.0.1.0/24".parse().unwrap();
175    /// ip_range.add(network.clone());
176    /// ip_range.remove(network);
177    /// assert!(ip_range.is_empty());
178    /// ```
179    pub fn is_empty(&self) -> bool {
180        self.trie.root.is_none()
181    }
182
183    /// Simplify `self` by combining networks. For example:
184    ///
185    /// ```
186    /// extern crate iprange;
187    /// extern crate ipnet;
188    ///
189    /// use iprange::IpRange;
190    /// use ipnet::Ipv4Net;
191    ///
192    /// fn main() {
193    ///     let mut ip_range: IpRange<Ipv4Net> = IpRange::new();
194    ///     ip_range
195    ///         .add("192.168.0.0/20".parse().unwrap())
196    ///         .add("192.168.16.0/22".parse().unwrap())
197    ///         .add("192.168.20.0/24".parse().unwrap())
198    ///         .add("192.168.21.0/24".parse().unwrap())
199    ///         .add("192.168.22.0/24".parse().unwrap())
200    ///         .add("192.168.23.0/24".parse().unwrap())
201    ///         .add("192.168.24.0/21".parse().unwrap())
202    ///         .simplify();
203    ///     // Now, ip_range has only one network: "192.168.0.0/19".
204    /// }
205    /// ```
206    pub fn simplify(&mut self) {
207        self.trie.simplify();
208    }
209
210    /// Returns a new `IpRange` which contains all networks
211    /// that is either in `self` or in `other`.
212    ///
213    /// The returned `IpRange` is simplified.
214    pub fn merge(&self, other: &IpRange<N>) -> Self {
215        self.into_iter().chain(other.into_iter()).collect()
216    }
217
218    /// Returns a new `IpRange` which contains all networks
219    /// that is in both `self` and `other`.
220    ///
221    /// The returned `IpRange` is simplified.
222    pub fn intersect(&self, other: &IpRange<N>) -> Self {
223        let range1 = self.into_iter().filter(|network| other.contains(network));
224        let range2 = other.into_iter().filter(|network| self.contains(network));
225        range1.chain(range2).collect()
226    }
227
228    /// Returns a new `IpRange` which contains all networks
229    /// that is in `self` while not in `other`.
230    ///
231    /// The returned `IpRange` is simplified.
232    pub fn exclude(&self, other: &IpRange<N>) -> IpRange<N> {
233        let mut new = (*self).clone();
234        for network in other {
235            new.remove(network);
236        }
237        new
238    }
239
240    /// Tests if `self` contains `network`.
241    ///
242    /// `network` is anything that can be converted into `N`.
243    /// See `ToNetwork<N>` for detail.
244    pub fn contains<T: ToNetwork<N>>(&self, network: &T) -> bool {
245        self.supernet(&network.to_network()).is_some()
246    }
247
248    /// Returns the network in `self` which is the supernetwork of `network`.
249    ///
250    /// Returns None if no network in `self` contains `network`.
251    pub fn supernet<T: ToNetwork<N>>(&self, network: &T) -> Option<N> {
252        self.trie.search(network.to_network())
253    }
254
255    /// Returns the iterator to `&self`.
256    pub fn iter(&self) -> IpRangeIter<N> {
257        self.into_iter()
258    }
259}
260
261impl<N> Default for IpRange<N>
262where
263    N: IpNet + ToNetwork<N> + Clone,
264{
265    fn default() -> Self {
266        Self::new()
267    }
268}
269
270impl<N: IpNet> fmt::Debug for IpRange<N> {
271    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
272        let mut networks: Vec<_> = self
273            .iter()
274            .take(4)
275            .map(|net| format!("{:?}", net))
276            .collect();
277        if networks.len() == 4 {
278            networks[3] = "...".to_string();
279        }
280        write!(f, "IpRange [{}]", networks.join(", "))
281    }
282}
283
284impl<'a, N> IntoIterator for &'a IpRange<N>
285where
286    N: IpNet + ToNetwork<N> + Clone,
287{
288    type Item = N;
289    type IntoIter = IpRangeIter<'a, N>;
290
291    fn into_iter(self) -> Self::IntoIter {
292        let mut queue = VecDeque::new();
293        if let Some(root) = self.trie.root.as_ref() {
294            let state: N::S = root.init_traverse_state();
295            queue.push_back(state);
296        }
297        IpRangeIter {
298            queue,
299            _phantom: PhantomData,
300        }
301    }
302}
303
304impl<N: IpNet> From<Box<IpTrieNode>> for IpRange<N> {
305    fn from(trie: Box<IpTrieNode>) -> Self {
306        IpRange {
307            trie: IpTrie {
308                root: Some(*trie),
309                phantom_net: PhantomData,
310            },
311            phantom_net: PhantomData,
312        }
313    }
314}
315
316#[cfg(feature = "serde")]
317impl<N: IpNet> serde::Serialize for IpRange<N> {
318    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
319    where
320        S: serde::Serializer,
321    {
322        serde::Serialize::serialize(&self.trie.root, serializer)
323    }
324}
325
326#[cfg(feature = "serde")]
327impl<'de, N: IpNet> serde::Deserialize<'de> for IpRange<N> {
328    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
329    where
330        D: serde::Deserializer<'de>,
331    {
332        Ok(IpRange {
333            trie: IpTrie {
334                root: serde::Deserialize::deserialize(deserializer)?,
335                phantom_net: PhantomData,
336            },
337            phantom_net: PhantomData,
338        })
339    }
340}
341
342/// An abstraction for IP networks.
343pub trait IpNet: ToNetwork<Self> + fmt::Debug + Ord + Copy
344where
345    Self: Sized,
346{
347    /// Used for internal traversing.
348    type S: TraverseState<Net = Self>;
349    ///`I` is an iterator to the prefix bits of the network.
350    type I: Iterator<Item = bool>;
351
352    /// Returns the iterator to the prefix bits of the network.
353    fn prefix_bits(&self) -> Self::I;
354
355    /// Returns the prefix length.
356    fn prefix_len(&self) -> u8;
357
358    /// Returns a copy of the network with the address truncated to the given length.
359    fn with_new_prefix(&self, len: u8) -> Self;
360}
361
362/// Anything that can be converted to `IpNet`.
363///
364/// Due to limitation of Rust's type system,
365/// this trait is only implemented for some
366/// concrete types.
367pub trait ToNetwork<N: IpNet> {
368    fn to_network(&self) -> N;
369}
370
371/// An iterator over the networks in an [`IpRange`].
372///
373/// BFS (Breadth-First-Search) is used for traversing the inner Radix Trie.
374///
375/// [`IpRange`]: struct.IpRange.html
376pub struct IpRangeIter<'a, N>
377where
378    N: IpNet,
379{
380    queue: VecDeque<N::S>,
381    _phantom: PhantomData<&'a N>,
382}
383
384/// Used for internal traversing.
385///
386/// You can simply ignore this trait.
387#[doc(hidden)]
388pub trait TraverseState {
389    type Net: IpNet;
390
391    fn node(&self) -> *const IpTrieNode;
392
393    fn init(root: &IpTrieNode) -> Self;
394
395    fn transit(&self, next_node: &IpTrieNode, current_bit: bool) -> Self;
396
397    fn build(&self) -> Self::Net;
398}
399
400impl<'a, N> Iterator for IpRangeIter<'a, N>
401where
402    N: IpNet,
403{
404    type Item = N;
405
406    fn next(&mut self) -> Option<Self::Item> {
407        while let Some(elem) = self.queue.pop_front() {
408            // Get the front element of the queue.
409            // If it is a leaf, it represents a network.
410            // SAFETY: IpRangeIter has an PhantomData<'a N> so the IpNet must
411            // exist when this iterator exists.
412            let node = unsafe { &*elem.node() };
413            if node.is_leaf() {
414                return Some(elem.build());
415            }
416            for &i in &[0, 1] {
417                if let Some(child) = node.children[i as usize].as_ref() {
418                    // Push the child nodes into the queue
419                    self.queue.push_back(elem.transit(child, i != 0));
420                }
421            }
422        }
423        None
424    }
425}
426
427impl<N> FromIterator<N> for IpRange<N>
428where
429    N: IpNet + ToNetwork<N> + Clone,
430{
431    fn from_iter<T>(iter: T) -> Self
432    where
433        T: IntoIterator<Item = N>,
434    {
435        let mut ip_range = IpRange::new();
436        for network in iter {
437            ip_range.add(network);
438        }
439        ip_range.simplify();
440        ip_range
441    }
442}
443
444#[derive(Clone, Debug, PartialEq, Eq, Default)]
445pub struct IpTrie<N>
446where
447    N: IpNet,
448{
449    root: Option<IpTrieNode>,
450    phantom_net: PhantomData<N>,
451}
452
453impl<N> IpTrie<N>
454where
455    N: IpNet,
456{
457    fn new() -> IpTrie<N> {
458        IpTrie {
459            root: None,
460            phantom_net: PhantomData,
461        }
462    }
463
464    pub fn into_boxed_node(self) -> Option<Box<IpTrieNode>> {
465        self.root.map(|node| Box::new(node))
466    }
467
468    fn insert(&mut self, network: N) {
469        // The current node
470        let mut node = if let Some(root) = &mut self.root {
471            if root.is_leaf() {
472                // Insert into all-zero network has no effect.
473                return;
474            }
475            root
476        } else {
477            self.root = Some(IpTrieNode::new());
478            self.root.as_mut().unwrap()
479        };
480
481        let bits = network.prefix_bits();
482        for bit in bits {
483            let i = bit as usize;
484            let child = &mut node.children[i];
485            match child {
486                Some(child) => {
487                    if child.is_leaf() {
488                        // This means the network to be inserted
489                        // is already in the trie.
490                        return;
491                    }
492                    node = child;
493                }
494                None => {
495                    *child = Some(Box::new(IpTrieNode::new()));
496                    node = child.as_mut().unwrap();
497                }
498            }
499        }
500        node.children = [None, None];
501    }
502
503    fn search(&self, network: N) -> Option<N> {
504        let mut node = self.root.as_ref()?;
505
506        let bits = network.prefix_bits();
507        for (j, bit) in bits.enumerate() {
508            if node.is_leaf() {
509                return Some(network.with_new_prefix(j as u8));
510            }
511
512            let i = bit as usize;
513            let child = node.children[i].as_ref();
514            match child {
515                Some(child) => node = child,
516                None => return None,
517            }
518        }
519
520        if node.is_leaf() {
521            Some(network)
522        } else {
523            None
524        }
525
526        // The commented code below is more clear. However, this uses a
527        // commented method `search` in IpTrieNode, and the performance
528        // is relatively poorer that the implementation above.
529
530        // self.root.as_ref().and_then(|root| {
531        //     let mut bits = network.prefix_bits();
532        //     let first_bit = bits.next();
533        //     root.borrow()
534        //         .search(bits, first_bit, 0)
535        //         .map(|prefix_size| {
536        //             network.with_new_prefix(prefix_size)
537        //         })
538        // })
539    }
540
541    fn remove(&mut self, network: N) {
542        if let Some(root) = self.root.as_mut() {
543            let mut bits = network.prefix_bits();
544            if let Some(next_bit) = bits.next() {
545                root.remove(bits, next_bit);
546                // If root becomes a leaf after removing the network,
547                // we should simply reinitialize the trie.
548                if !root.is_leaf() {
549                    return;
550                }
551            }
552        }
553        self.root = None // Reinitialize the trie
554    }
555
556    fn simplify(&mut self) {
557        if let Some(root) = self.root.as_mut() {
558            root.simplify();
559        }
560    }
561}
562
563/// Node of the inner radix trie.
564#[derive(Clone, Debug, PartialEq, Eq)]
565#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(transparent))]
566pub struct IpTrieNode {
567    pub children: [Option<Box<IpTrieNode>>; 2],
568}
569
570impl IpTrieNode {
571    pub fn new() -> IpTrieNode {
572        IpTrieNode {
573            children: [None, None],
574        }
575    }
576
577    #[inline]
578    fn init_traverse_state<S: TraverseState>(&self) -> S {
579        S::init(self)
580    }
581
582    // If both the zero child and the one child of a node are None,
583    // it is a leaf node, and it represents a network whose
584    // prefix is the path from root to it.
585    #[inline]
586    fn is_leaf(&self) -> bool {
587        self.children[0].is_none() && self.children[1].is_none()
588    }
589
590    // If the two children of a node are all leaf node,
591    // they can be merged into a new leaf node.
592    fn simplify(&mut self) {
593        let leaf_count: u32 = self
594            .children
595            .iter_mut()
596            .map(|child| {
597                child
598                    .as_mut()
599                    .map(|child| {
600                        child.simplify();
601                        child.is_leaf() as u32
602                    })
603                    .unwrap_or_default()
604            })
605            .sum();
606        if leaf_count == 2 {
607            self.children = [None, None];
608        }
609    }
610
611    //    fn search<I>(&self, mut bits: I, current_bit: Option<bool>, acc: u8) -> Option<u8>
612    //        where I: Iterator<Item=bool>
613    //    {
614    //        if self.is_leaf() {
615    //            Some(acc)
616    //        } else {
617    //            if let Some(current_bit) = current_bit {
618    //                if let Some(child) = self.children[current_bit as usize].clone() {
619    //                    let next_bit = bits.next();
620    //                    return child
621    //                        .borrow_mut()
622    //                        .search(bits, next_bit, acc + 1);
623    //                }
624    //            }
625    //            None
626    //        }
627    //    }
628
629    fn remove<I>(&mut self, mut bits: I, current_bit: bool)
630    where
631        I: Iterator<Item = bool>,
632    {
633        let i = current_bit as usize;
634        let next_bit = bits.next();
635
636        // If the current node is a leaf node, and we have a network
637        // to remove, we must split it into two deeper nodes.
638        if self.is_leaf() {
639            self.children = [
640                Some(Box::new(IpTrieNode::new())),
641                Some(Box::new(IpTrieNode::new())),
642            ];
643        }
644
645        match next_bit {
646            Some(next_bit) => {
647                let is_leaf = if let Some(child) = self.children[i].as_mut() {
648                    // Remove the deeper node recursively
649                    child.remove(bits, next_bit);
650                    child.is_leaf()
651                } else {
652                    false
653                };
654                // In general, a leaf node represents a complete
655                // network. However, the child node cannot be a complete
656                // network after removing a network from it.
657                // This occurring indicates the only child of the
658                // child node is removed, and now this child node
659                // should be marked None.
660                if is_leaf {
661                    self.children[i] = None;
662                }
663            }
664            None => {
665                // Remove the node that represents the network.
666                self.children[i] = None;
667            }
668        }
669    }
670}
671
672const MSO_U128: u128 = 1 << 127; // Most significant one for u128
673const MSO_U32: u32 = 1 << 31; // Most significant one for u32
674
675impl IpNet for Ipv4Net {
676    type S = Ipv4TraverseState;
677    type I = Ipv4PrefixBitIterator;
678
679    #[inline]
680    fn prefix_bits(&self) -> Self::I {
681        let prefix: u32 = self.addr().into();
682        Ipv4PrefixBitIterator {
683            prefix,
684            prefix_len: self.prefix_len(),
685        }
686    }
687
688    #[inline]
689    fn prefix_len(&self) -> u8 {
690        self.prefix_len()
691    }
692
693    #[inline]
694    fn with_new_prefix(&self, len: u8) -> Self {
695        Ipv4Net::new(self.addr(), len).unwrap().trunc()
696    }
697}
698
699impl ToNetwork<Ipv4Net> for Ipv4Net {
700    #[inline]
701    fn to_network(&self) -> Ipv4Net {
702        self.trunc()
703    }
704}
705
706impl ToNetwork<Ipv4Net> for Ipv4Addr {
707    #[inline]
708    fn to_network(&self) -> Ipv4Net {
709        Ipv4Net::new(*self, 32).unwrap()
710    }
711}
712
713impl ToNetwork<Ipv4Net> for u32 {
714    #[inline]
715    fn to_network(&self) -> Ipv4Net {
716        Ipv4Net::new((*self).into(), 32).unwrap()
717    }
718}
719
720impl ToNetwork<Ipv4Net> for [u8; 4] {
721    #[inline]
722    fn to_network(&self) -> Ipv4Net {
723        Ipv4Net::new((*self).into(), 32).unwrap()
724    }
725}
726
727#[doc(hidden)]
728pub struct Ipv4TraverseState {
729    node: *const IpTrieNode,
730    prefix: u32,
731    prefix_len: u8,
732}
733
734impl TraverseState for Ipv4TraverseState {
735    type Net = Ipv4Net;
736
737    #[inline]
738    fn node(&self) -> *const IpTrieNode {
739        self.node
740    }
741
742    #[inline]
743    fn init(root: &IpTrieNode) -> Self {
744        Ipv4TraverseState {
745            node: root,
746            prefix: 0,
747            prefix_len: 0,
748        }
749    }
750
751    #[inline]
752    fn transit(&self, next_node: &IpTrieNode, current_bit: bool) -> Self {
753        let mask = if current_bit {
754            MSO_U32 >> self.prefix_len
755        } else {
756            0
757        };
758        Ipv4TraverseState {
759            node: next_node,
760            prefix: self.prefix | mask,
761            prefix_len: self.prefix_len + 1,
762        }
763    }
764
765    #[inline]
766    fn build(&self) -> Self::Net {
767        Ipv4Net::new(self.prefix.into(), self.prefix_len as u8).unwrap()
768    }
769}
770
771#[doc(hidden)]
772pub struct Ipv4PrefixBitIterator {
773    prefix: u32,
774    prefix_len: u8,
775}
776
777impl Iterator for Ipv4PrefixBitIterator {
778    type Item = bool;
779
780    #[inline]
781    fn next(&mut self) -> Option<Self::Item> {
782        if self.prefix_len > 0 {
783            let prefix = self.prefix;
784            self.prefix <<= 1;
785            self.prefix_len -= 1;
786            Some(prefix & MSO_U32 != 0)
787        } else {
788            None
789        }
790    }
791}
792
793impl IpNet for Ipv6Net {
794    type S = Ipv6TraverseState;
795    type I = Ipv6PrefixBitIterator;
796
797    #[inline]
798    fn prefix_bits(&self) -> Self::I {
799        Ipv6PrefixBitIterator {
800            prefix: self.addr().into(),
801            prefix_len: self.prefix_len(),
802        }
803    }
804
805    #[inline]
806    fn prefix_len(&self) -> u8 {
807        self.prefix_len()
808    }
809
810    #[inline]
811    fn with_new_prefix(&self, len: u8) -> Self {
812        Ipv6Net::new(self.addr(), len).unwrap().trunc()
813    }
814}
815
816impl ToNetwork<Ipv6Net> for Ipv6Net {
817    #[inline]
818    fn to_network(&self) -> Ipv6Net {
819        self.trunc()
820    }
821}
822
823impl ToNetwork<Ipv6Net> for Ipv6Addr {
824    #[inline]
825    fn to_network(&self) -> Ipv6Net {
826        Ipv6Net::new(*self, 128).unwrap()
827    }
828}
829
830impl ToNetwork<Ipv6Net> for u128 {
831    #[inline]
832    fn to_network(&self) -> Ipv6Net {
833        Ipv6Net::new((*self).into(), 128).unwrap()
834    }
835}
836
837impl ToNetwork<Ipv6Net> for [u8; 16] {
838    #[inline]
839    fn to_network(&self) -> Ipv6Net {
840        Ipv6Net::new((*self).into(), 128).unwrap()
841    }
842}
843
844impl ToNetwork<Ipv6Net> for [u16; 8] {
845    #[inline]
846    fn to_network(&self) -> Ipv6Net {
847        Ipv6Net::new((*self).into(), 128).unwrap()
848    }
849}
850
851#[doc(hidden)]
852pub struct Ipv6TraverseState {
853    node: *const IpTrieNode,
854    prefix: u128,
855    prefix_len: u8,
856}
857
858impl TraverseState for Ipv6TraverseState {
859    type Net = Ipv6Net;
860
861    #[inline]
862    fn node(&self) -> *const IpTrieNode {
863        self.node
864    }
865
866    #[inline]
867    fn init(root: &IpTrieNode) -> Self {
868        Ipv6TraverseState {
869            node: root,
870            prefix: 0,
871            prefix_len: 0,
872        }
873    }
874
875    #[inline]
876    fn transit(&self, next_node: &IpTrieNode, current_bit: bool) -> Self {
877        let mask = if current_bit {
878            MSO_U128 >> self.prefix_len
879        } else {
880            0
881        };
882        Ipv6TraverseState {
883            node: next_node,
884            prefix: self.prefix | mask,
885            prefix_len: self.prefix_len + 1,
886        }
887    }
888
889    #[inline]
890    fn build(&self) -> Self::Net {
891        Ipv6Net::new(self.prefix.into(), self.prefix_len as u8).unwrap()
892    }
893}
894
895#[doc(hidden)]
896pub struct Ipv6PrefixBitIterator {
897    prefix: u128,
898    prefix_len: u8,
899}
900
901impl Iterator for Ipv6PrefixBitIterator {
902    type Item = bool;
903
904    #[inline]
905    fn next(&mut self) -> Option<Self::Item> {
906        if self.prefix_len > 0 {
907            let prefix = self.prefix;
908            self.prefix <<= 1;
909            self.prefix_len -= 1;
910            Some(prefix & MSO_U128 != 0)
911        } else {
912            None
913        }
914    }
915}
916
917#[cfg(test)]
918mod tests {
919    use super::*;
920
921    #[test]
922    fn parse_invalid_networks() {
923        assert!("192.168.256.130/5".parse::<Ipv4Net>().is_err());
924        assert!("192.168.5.130/-1".parse::<Ipv4Net>().is_err());
925        assert!("192.168.5.130/33".parse::<Ipv4Net>().is_err());
926        assert!("192.168.5.33".parse::<Ipv4Net>().is_err());
927        assert!("192.168.5.130/0.0.0".parse::<Ipv4Net>().is_err());
928        assert!("192.168.5.130/0.0.0.256".parse::<Ipv4Net>().is_err());
929    }
930
931    impl IpRange<Ipv4Net> {
932        fn get_network(&self, prefix_size: usize, prefix: &str) -> Option<Ipv4Net> {
933            self.trie
934                .search(format!("{}/{}", prefix, prefix_size).parse().unwrap())
935        }
936    }
937
938    #[test]
939    fn add_single_network() {
940        let mut ip_range = IpRange::new();
941        let network = "192.168.5.0/24".parse().unwrap();
942        ip_range.add(network);
943        assert_eq!(ip_range.into_iter().count(), 1);
944        assert_eq!(Some(network), ip_range.get_network(24, "192.168.5.0"));
945    }
946
947    #[test]
948    fn add_multiple_networks_disjoint() {
949        let mut ip_range = IpRange::new();
950        let network1 = "10.0.0.0/8".parse().unwrap();
951        let network2 = "172.16.0.0/16".parse().unwrap();
952        let network3 = "192.168.1.0/24".parse().unwrap();
953        let network4 = "254.254.254.254/32".parse().unwrap();
954        ip_range
955            .add(network1)
956            .add(network2)
957            .add(network3)
958            .add(network4)
959            .simplify();
960
961        assert_eq!(ip_range.into_iter().count(), 4);
962        assert_eq!(Some(network1), ip_range.get_network(8, "10.0.0.0"));
963        assert_eq!(Some(network2), ip_range.get_network(16, "172.16.0.0"));
964        assert_eq!(Some(network3), ip_range.get_network(24, "192.168.1.0"));
965        assert_eq!(Some(network4), ip_range.get_network(32, "254.254.254.254"));
966    }
967
968    #[test]
969    fn simplify() {
970        let mut ip_range = IpRange::new();
971        ip_range
972            .add("192.168.0.0/20".parse().unwrap())
973            .add("192.168.16.0/22".parse().unwrap())
974            .add("192.168.20.0/24".parse().unwrap())
975            .add("192.168.21.0/24".parse().unwrap())
976            .add("192.168.22.0/24".parse().unwrap())
977            .add("192.168.23.0/24".parse().unwrap())
978            .add("192.168.24.0/21".parse().unwrap())
979            .simplify();
980
981        assert_eq!(ip_range.into_iter().count(), 1);
982        assert_eq!(
983            "192.168.0.0/19".parse().ok(),
984            ip_range.get_network(19, "192.168.0.0")
985        );
986    }
987
988    #[test]
989    fn add_multiple_networks_joint1() {
990        let mut ip_range = IpRange::new();
991        let network1 = "172.16.4.0/24".parse().unwrap();
992        let network2 = "172.16.4.0/22".parse().unwrap();
993        ip_range.add(network1).add(network2).simplify();
994
995        assert_eq!(ip_range.into_iter().count(), 1);
996        assert_eq!(Some(network2), ip_range.get_network(22, "172.16.4.0"));
997    }
998
999    #[test]
1000    fn add_multiple_networks_joint2() {
1001        let mut ip_range = IpRange::new();
1002        let network1 = "172.16.5.0/24".parse().unwrap();
1003        let network2 = "172.16.4.0/22".parse().unwrap();
1004        ip_range.add(network1).add(network2).simplify();
1005
1006        assert_eq!(ip_range.into_iter().count(), 1);
1007        assert_eq!(Some(network2), ip_range.get_network(22, "172.16.4.0"));
1008    }
1009
1010    #[test]
1011    fn add_multiple_networks_joint3() {
1012        let mut ip_range = IpRange::new();
1013        let network1 = "172.16.4.0/24".parse().unwrap();
1014        let network2 = "172.16.4.0/22".parse().unwrap();
1015        ip_range.add(network2).add(network1).simplify();
1016
1017        assert_eq!(ip_range.into_iter().count(), 1);
1018        assert_eq!(Some(network2), ip_range.get_network(22, "172.16.4.0"));
1019    }
1020
1021    #[test]
1022    fn add_multiple_networks_joint4() {
1023        let mut ip_range = IpRange::new();
1024        let network1 = "172.16.5.0/24".parse().unwrap();
1025        let network2 = "172.16.5.0/24".parse().unwrap();
1026        ip_range.add(network1).add(network2).simplify();
1027
1028        assert_eq!(ip_range.into_iter().count(), 1);
1029        assert_eq!(Some(network2), ip_range.get_network(24, "172.16.5.0"));
1030    }
1031
1032    #[test]
1033    fn add_multiple_networks_joint5() {
1034        let mut ip_range = IpRange::new();
1035        let network1 = "172.16.5.0/24".parse().unwrap();
1036        let network2 = "172.16.0.0/16".parse().unwrap();
1037        ip_range.add(network1).add(network2).simplify();
1038
1039        assert_eq!(ip_range.into_iter().count(), 1);
1040        assert_eq!(Some(network2), ip_range.get_network(16, "172.16.0.0"));
1041    }
1042
1043    #[test]
1044    fn add_multiple_networks_joint6() {
1045        let mut ip_range = IpRange::new();
1046        let network1 = "172.16.5.0/24".parse().unwrap();
1047        let network2 = "0.0.0.0/0".parse().unwrap();
1048        ip_range.add(network1).add(network2).simplify();
1049
1050        assert_eq!(ip_range.into_iter().count(), 1);
1051        assert_eq!(Some(network2), ip_range.get_network(0, "0.0.0.0"));
1052    }
1053
1054    #[test]
1055    fn remove_networks_no_split() {
1056        let mut ip_range = IpRange::new();
1057        let network1 = "192.168.0.0/24".parse().unwrap();
1058        let network2 = "172.16.0.0/16".parse().unwrap();
1059        ip_range.add(network1).add(network2).simplify();
1060
1061        ip_range.remove(network1);
1062        assert_eq!(ip_range.into_iter().count(), 1);
1063        assert_eq!(Some(network2), ip_range.get_network(16, "172.16.0.0"));
1064    }
1065
1066    #[test]
1067    fn remove_networks_split1() {
1068        let mut ip_range = IpRange::new();
1069        ip_range.add("192.168.0.0/22".parse().unwrap());
1070        ip_range
1071            .remove("192.168.2.0/23".parse().unwrap())
1072            .simplify();
1073
1074        assert_eq!(ip_range.into_iter().count(), 1);
1075        assert_eq!(
1076            Some("192.168.0.0/23".parse().unwrap()),
1077            ip_range.get_network(23, "192.168.0.0")
1078        );
1079    }
1080
1081    #[test]
1082    fn remove_networks_split2() {
1083        let mut ip_range = IpRange::new();
1084        ip_range.add("192.168.0.0/22".parse().unwrap());
1085        ip_range
1086            .remove("192.168.0.0/23".parse().unwrap())
1087            .simplify();
1088
1089        assert_eq!(ip_range.into_iter().count(), 1);
1090        assert_eq!(
1091            Some("192.168.2.0/23".parse().unwrap()),
1092            ip_range.get_network(23, "192.168.2.0")
1093        );
1094    }
1095
1096    #[test]
1097    fn remove_networks_split3() {
1098        let mut ip_range = IpRange::new();
1099        ip_range.add("192.168.0.0/22".parse().unwrap());
1100        ip_range
1101            .remove("192.168.2.0/25".parse().unwrap())
1102            .simplify();
1103
1104        assert_eq!(ip_range.into_iter().count(), 3);
1105        assert_eq!(
1106            Some("192.168.0.0/23".parse().unwrap()),
1107            ip_range.get_network(23, "192.168.0.0")
1108        );
1109        assert_eq!(
1110            Some("192.168.2.128/25".parse().unwrap()),
1111            ip_range.get_network(25, "192.168.2.128")
1112        );
1113        assert_eq!(
1114            Some("192.168.3.0/24".parse().unwrap()),
1115            ip_range.get_network(24, "192.168.3.0")
1116        );
1117    }
1118
1119    impl IpRange<Ipv4Net> {
1120        fn contains_ip(&self, ip: &str) -> bool {
1121            self.contains(&ip.parse::<Ipv4Addr>().unwrap())
1122        }
1123
1124        fn find_network_by_ip(&self, ip: &str) -> Option<Ipv4Net> {
1125            self.supernet(&ip.parse::<Ipv4Addr>().unwrap())
1126        }
1127
1128        fn contains_network(&self, network: &str) -> bool {
1129            self.contains(&network.parse::<Ipv4Net>().unwrap())
1130        }
1131
1132        fn super_network_by_network(&self, network: &str) -> Option<Ipv4Net> {
1133            self.supernet(&network.parse::<Ipv4Net>().unwrap())
1134        }
1135    }
1136
1137    #[test]
1138    fn contains_ip_with_one_network() {
1139        let mut ip_range = IpRange::new();
1140        ip_range.add("192.168.0.0/24".parse().unwrap());
1141
1142        assert!(ip_range.contains_ip("192.168.0.0"));
1143        assert!(ip_range.contains_ip("192.168.0.128"));
1144        assert!(ip_range.contains_ip("192.168.0.255"));
1145        assert!(!ip_range.contains_ip("192.167.255.255"));
1146        assert!(!ip_range.contains_ip("192.168.1.0"));
1147    }
1148
1149    #[test]
1150    fn contains_ip_with_many_networks() {
1151        let mut ip_range = IpRange::new();
1152        ip_range
1153            .add("192.168.0.0/24".parse().unwrap())
1154            .add("172.16.0.0/16".parse().unwrap())
1155            .add("10.0.0.0/8".parse().unwrap())
1156            .simplify();
1157
1158        assert!(ip_range.contains_ip("192.168.0.128"));
1159        assert!(ip_range.contains_ip("172.16.32.1"));
1160        assert!(ip_range.contains_ip("10.10.10.10"));
1161        assert!(!ip_range.contains_ip("0.0.0.0"));
1162        assert!(!ip_range.contains_ip("8.8.8.8"));
1163        assert!(!ip_range.contains_ip("11.0.0.0"));
1164        assert!(!ip_range.contains_ip("192.167.255.255"));
1165        assert!(!ip_range.contains_ip("255.255.255.255"));
1166    }
1167
1168    #[test]
1169    fn contains_ip_boundary1() {
1170        let mut ip_range = IpRange::new();
1171        ip_range.add("0.0.0.0/0".parse().unwrap());
1172
1173        assert!(ip_range.contains_ip("0.0.0.0"));
1174        assert!(ip_range.contains_ip("8.8.8.8"));
1175        assert!(ip_range.contains_ip("192.168.0.0"));
1176        assert!(ip_range.contains_ip("192.168.1.1"));
1177    }
1178
1179    #[test]
1180    fn contains_ip_boundary2() {
1181        let mut ip_range = IpRange::new();
1182        ip_range.add("254.254.254.254/32".parse().unwrap());
1183
1184        assert!(!ip_range.contains_ip("0.0.0.0"));
1185        assert!(!ip_range.contains_ip("8.8.8.8"));
1186        assert!(!ip_range.contains_ip("192.168.0.0"));
1187        assert!(ip_range.contains_ip("254.254.254.254"));
1188    }
1189
1190    #[test]
1191    fn find_network_with_one_network() {
1192        let mut ip_range = IpRange::new();
1193        let network = "192.168.0.0/24".parse().unwrap();
1194        ip_range.add(network);
1195
1196        assert_eq!(Some(network), ip_range.find_network_by_ip("192.168.0.0"));
1197        assert_eq!(Some(network), ip_range.find_network_by_ip("192.168.0.128"));
1198        assert_eq!(Some(network), ip_range.find_network_by_ip("192.168.0.255"));
1199        assert_eq!(None, ip_range.find_network_by_ip("192.167.255.255"));
1200        assert_eq!(None, ip_range.find_network_by_ip("192.168.1.0"));
1201    }
1202
1203    #[test]
1204    fn find_network_with_many_networks() {
1205        let mut ip_range = IpRange::new();
1206        let network1 = "192.168.0.0/24".parse().unwrap();
1207        let network2 = "172.16.0.0/16".parse().unwrap();
1208        let network3 = "10.0.0.0/8".parse().unwrap();
1209        ip_range
1210            .add(network1)
1211            .add(network2)
1212            .add(network3)
1213            .simplify();
1214
1215        assert_eq!(Some(network1), ip_range.find_network_by_ip("192.168.0.128"));
1216        assert_eq!(Some(network2), ip_range.find_network_by_ip("172.16.32.1"));
1217        assert_eq!(Some(network3), ip_range.find_network_by_ip("10.10.10.10"));
1218        assert_eq!(None, ip_range.find_network_by_ip("0.0.0.0"));
1219        assert_eq!(None, ip_range.find_network_by_ip("8.8.8.8"));
1220        assert_eq!(None, ip_range.find_network_by_ip("11.0.0.0"));
1221        assert_eq!(None, ip_range.find_network_by_ip("192.167.255.255"));
1222        assert_eq!(None, ip_range.find_network_by_ip("255.255.255.255"));
1223    }
1224
1225    #[test]
1226    fn find_network_boundary1() {
1227        let mut ip_range = IpRange::new();
1228        let network = "0.0.0.0/0".parse().unwrap();
1229        ip_range.add(network);
1230
1231        assert_eq!(Some(network), ip_range.find_network_by_ip("0.0.0.0"));
1232        assert_eq!(Some(network), ip_range.find_network_by_ip("8.8.8.8"));
1233        assert_eq!(Some(network), ip_range.find_network_by_ip("192.168.0.0"));
1234        assert_eq!(Some(network), ip_range.find_network_by_ip("192.168.1.1"));
1235    }
1236
1237    #[test]
1238    fn find_network_boundary2() {
1239        let mut ip_range = IpRange::new();
1240        let network = "254.254.254.254/32".parse().unwrap();
1241        ip_range.add(network);
1242
1243        assert_eq!(None, ip_range.find_network_by_ip("0.0.0.0"));
1244        assert_eq!(None, ip_range.find_network_by_ip("8.8.8.8"));
1245        assert_eq!(None, ip_range.find_network_by_ip("192.168.0.0"));
1246        assert_eq!(
1247            Some(network),
1248            ip_range.find_network_by_ip("254.254.254.254")
1249        );
1250    }
1251
1252    #[test]
1253    fn contains_network_with_one_network() {
1254        let mut ip_range = IpRange::new();
1255        ip_range.add("192.168.0.0/24".parse().unwrap());
1256
1257        assert!(ip_range.contains_network("192.168.0.0/24"));
1258        assert!(ip_range.contains_network("192.168.0.128/25"));
1259        assert!(!ip_range.contains_network("192.168.0.0/23"));
1260        assert!(!ip_range.contains_network("192.168.1.0/24"));
1261        assert!(!ip_range.contains_network("192.167.0.0/24"));
1262    }
1263
1264    #[test]
1265    fn contains_network_with_many_networks() {
1266        let mut ip_range = IpRange::new();
1267        ip_range
1268            .add("192.168.0.0/24".parse().unwrap())
1269            .add("172.16.0.0/16".parse().unwrap())
1270            .add("10.0.0.0/8".parse().unwrap())
1271            .simplify();
1272
1273        assert!(ip_range.contains_network("192.168.0.128/25"));
1274        assert!(ip_range.contains_network("172.16.32.0/20"));
1275        assert!(ip_range.contains_network("10.10.0.0/16"));
1276        assert!(!ip_range.contains_network("0.0.0.0/0"));
1277        assert!(!ip_range.contains_network("8.0.0.0/6"));
1278        assert!(!ip_range.contains_network("8.0.0.0/7"));
1279        assert!(!ip_range.contains_network("11.0.0.0/9"));
1280        assert!(!ip_range.contains_network("192.167.255.255/32"));
1281        assert!(!ip_range.contains_network("255.0.0.0/8"));
1282    }
1283
1284    #[test]
1285    fn contains_network_boundary1() {
1286        let mut ip_range = IpRange::new();
1287        ip_range.add("0.0.0.0/0".parse().unwrap());
1288
1289        assert!(ip_range.contains_network("0.0.0.0/0"));
1290        assert!(ip_range.contains_network("8.0.0.0/6"));
1291        assert!(ip_range.contains_network("11.0.0.0/9"));
1292        assert!(ip_range.contains_network("192.168.0.128/25"));
1293        assert!(ip_range.contains_network("255.255.255.255/32"));
1294    }
1295
1296    #[test]
1297    fn contains_network_boundary2() {
1298        let mut ip_range = IpRange::new();
1299        ip_range.add("254.254.254.254/32".parse().unwrap());
1300
1301        assert!(!ip_range.contains_network("0.0.0.0/0"));
1302        assert!(!ip_range.contains_network("8.0.0.0/6"));
1303        assert!(!ip_range.contains_network("254.254.0.0/16"));
1304        assert!(ip_range.contains_network("254.254.254.254/32"));
1305        assert!(!ip_range.contains_network("255.255.255.255/32"));
1306    }
1307
1308    #[test]
1309    fn super_network_with_one_network() {
1310        let mut ip_range = IpRange::new();
1311        let network = "192.168.0.0/24".parse().unwrap();
1312        ip_range.add(network);
1313
1314        assert_eq!(
1315            Some(network),
1316            ip_range.super_network_by_network("192.168.0.0/24")
1317        );
1318        assert_eq!(
1319            Some(network),
1320            ip_range.super_network_by_network("192.168.0.128/25")
1321        );
1322        assert_eq!(None, ip_range.super_network_by_network("192.168.0.0/23"));
1323        assert_eq!(None, ip_range.super_network_by_network("192.168.1.0/24"));
1324        assert_eq!(None, ip_range.super_network_by_network("192.167.0.0/24"));
1325    }
1326
1327    #[test]
1328    fn super_network_with_many_networks() {
1329        let mut ip_range = IpRange::new();
1330        let network1 = "192.168.0.0/24".parse().unwrap();
1331        let network2 = "172.16.0.0/16".parse().unwrap();
1332        let network3 = "10.0.0.0/8".parse().unwrap();
1333        ip_range
1334            .add(network1)
1335            .add(network2)
1336            .add(network3)
1337            .simplify();
1338
1339        assert_eq!(
1340            Some(network1),
1341            ip_range.super_network_by_network("192.168.0.128/25")
1342        );
1343        assert_eq!(
1344            Some(network2),
1345            ip_range.super_network_by_network("172.16.32.0/20")
1346        );
1347        assert_eq!(
1348            Some(network3),
1349            ip_range.super_network_by_network("10.10.0.0/16")
1350        );
1351        assert_eq!(None, ip_range.super_network_by_network("0.0.0.0/0"));
1352        assert_eq!(None, ip_range.super_network_by_network("8.0.0.0/6"));
1353        assert_eq!(None, ip_range.super_network_by_network("8.0.0.0/7"));
1354        assert_eq!(None, ip_range.super_network_by_network("11.0.0.0/9"));
1355        assert_eq!(
1356            None,
1357            ip_range.super_network_by_network("192.167.255.255/32")
1358        );
1359        assert_eq!(None, ip_range.super_network_by_network("255.0.0.0/8"));
1360    }
1361
1362    #[test]
1363    fn super_network_boundary1() {
1364        let mut ip_range = IpRange::new();
1365        let network = "0.0.0.0/0".parse().unwrap();
1366        ip_range.add(network);
1367
1368        assert_eq!(
1369            Some(network),
1370            ip_range.super_network_by_network("0.0.0.0/0")
1371        );
1372        assert_eq!(
1373            Some(network),
1374            ip_range.super_network_by_network("8.0.0.0/6")
1375        );
1376        assert_eq!(
1377            Some(network),
1378            ip_range.super_network_by_network("11.0.0.0/9")
1379        );
1380        assert_eq!(
1381            Some(network),
1382            ip_range.super_network_by_network("192.168.0.128/25")
1383        );
1384        assert_eq!(
1385            Some(network),
1386            ip_range.super_network_by_network("255.255.255.255/32")
1387        );
1388    }
1389
1390    #[test]
1391    fn super_network_boundary2() {
1392        let mut ip_range = IpRange::new();
1393        let network = "254.254.254.254/32".parse().unwrap();
1394        ip_range.add(network);
1395
1396        assert_eq!(None, ip_range.super_network_by_network("0.0.0.0/0"));
1397        assert_eq!(None, ip_range.super_network_by_network("8.0.0.0/6"));
1398        assert_eq!(None, ip_range.super_network_by_network("254.254.0.0/16"));
1399        assert_eq!(
1400            Some(network),
1401            ip_range.super_network_by_network("254.254.254.254/32")
1402        );
1403        assert_eq!(
1404            None,
1405            ip_range.super_network_by_network("255.255.255.255/32")
1406        );
1407    }
1408
1409    #[test]
1410    fn merge_empty1() {
1411        let ip_range1 = IpRange::new();
1412        let mut ip_range2 = IpRange::new();
1413        let network1 = "10.0.0.0/8".parse().unwrap();
1414        let network2 = "172.16.0.0/16".parse().unwrap();
1415        let network3 = "192.168.1.0/24".parse().unwrap();
1416        let network4 = "254.254.254.254/32".parse().unwrap();
1417        ip_range2
1418            .add(network1)
1419            .add(network2)
1420            .add(network3)
1421            .add(network4)
1422            .simplify();
1423
1424        let ip_range = ip_range1.merge(&ip_range2);
1425        assert_eq!(ip_range.into_iter().count(), 4);
1426        assert_eq!(Some(network1), ip_range.get_network(8, "10.0.0.0"));
1427        assert_eq!(Some(network2), ip_range.get_network(16, "172.16.0.0"));
1428        assert_eq!(Some(network3), ip_range.get_network(24, "192.168.1.0"));
1429        assert_eq!(Some(network4), ip_range.get_network(32, "254.254.254.254"));
1430    }
1431
1432    #[test]
1433    fn merge_empty2() {
1434        let mut ip_range1 = IpRange::new();
1435        let ip_range2 = IpRange::new();
1436        let network1 = "10.0.0.0/8".parse().unwrap();
1437        let network2 = "172.16.0.0/16".parse().unwrap();
1438        let network3 = "192.168.1.0/24".parse().unwrap();
1439        let network4 = "254.254.254.254/32".parse().unwrap();
1440        ip_range1
1441            .add(network1)
1442            .add(network2)
1443            .add(network3)
1444            .add(network4)
1445            .simplify();
1446
1447        let ip_range = ip_range1.merge(&ip_range2);
1448        assert_eq!(ip_range.into_iter().count(), 4);
1449        assert_eq!(Some(network1), ip_range.get_network(8, "10.0.0.0"));
1450        assert_eq!(Some(network2), ip_range.get_network(16, "172.16.0.0"));
1451        assert_eq!(Some(network3), ip_range.get_network(24, "192.168.1.0"));
1452        assert_eq!(Some(network4), ip_range.get_network(32, "254.254.254.254"));
1453    }
1454
1455    #[test]
1456    fn merge_disjoint() {
1457        let mut ip_range1 = IpRange::new();
1458        let mut ip_range2 = IpRange::new();
1459        let network1 = "10.0.0.0/8".parse().unwrap();
1460        let network2 = "172.16.0.0/16".parse().unwrap();
1461        let network3 = "192.168.1.0/24".parse().unwrap();
1462        let network4 = "254.254.254.254/32".parse().unwrap();
1463        ip_range1.add(network1).add(network2);
1464        ip_range2.add(network3).add(network4);
1465
1466        let ip_range = ip_range1.merge(&ip_range2);
1467        assert_eq!(ip_range.into_iter().count(), 4);
1468        assert_eq!(Some(network1), ip_range.get_network(8, "10.0.0.0"));
1469        assert_eq!(Some(network2), ip_range.get_network(16, "172.16.0.0"));
1470        assert_eq!(Some(network3), ip_range.get_network(24, "192.168.1.0"));
1471        assert_eq!(Some(network4), ip_range.get_network(32, "254.254.254.254"));
1472    }
1473
1474    #[test]
1475    fn merge_joint1() {
1476        let mut ip_range1 = IpRange::new();
1477        let mut ip_range2 = IpRange::new();
1478        let network1 = "172.16.4.0/24".parse().unwrap();
1479        let network2 = "172.16.4.0/22".parse().unwrap();
1480        ip_range1.add(network1);
1481        ip_range2.add(network2);
1482
1483        let ip_range = ip_range1.merge(&ip_range2);
1484        assert_eq!(ip_range.into_iter().count(), 1);
1485        assert_eq!(Some(network2), ip_range.get_network(22, "172.16.4.0"));
1486    }
1487
1488    #[test]
1489    fn merge_joint2() {
1490        let mut ip_range1 = IpRange::new();
1491        let mut ip_range2 = IpRange::new();
1492        let network1 = "172.16.5.0/24".parse().unwrap();
1493        let network2 = "172.16.4.0/22".parse().unwrap();
1494        ip_range1.add(network1);
1495        ip_range2.add(network2);
1496
1497        let ip_range = ip_range1.merge(&ip_range2);
1498        assert_eq!(ip_range.into_iter().count(), 1);
1499        assert_eq!(Some(network2), ip_range.get_network(22, "172.16.4.0"));
1500    }
1501
1502    #[test]
1503    fn merge_sequent1() {
1504        let mut ip_range1 = IpRange::new();
1505        let mut ip_range2 = IpRange::new();
1506        let network1 = "172.16.4.0/24".parse().unwrap();
1507        let network2 = "172.16.5.0/24".parse().unwrap();
1508        let network3 = "172.16.6.0/24".parse().unwrap();
1509        ip_range1.add(network1);
1510        ip_range2.add(network2);
1511        ip_range2.add(network3);
1512
1513        let ip_range = ip_range1.merge(&ip_range2);
1514        assert_eq!(ip_range.into_iter().count(), 2);
1515        assert_eq!(
1516            "172.16.4.0/23".parse().ok(),
1517            ip_range.get_network(23, "172.16.4.0")
1518        );
1519        assert_eq!(
1520            "172.16.6.0/24".parse().ok(),
1521            ip_range.get_network(24, "172.16.6.0")
1522        );
1523    }
1524
1525    #[test]
1526    fn merge_sequent2() {
1527        let mut ip_range1 = IpRange::new();
1528        let mut ip_range2 = IpRange::new();
1529        let mut ip_range3 = IpRange::new();
1530        ip_range1
1531            .add("192.168.0.0/20".parse().unwrap())
1532            .add("192.168.24.0/21".parse().unwrap());
1533        ip_range2
1534            .add("192.168.16.0/22".parse().unwrap())
1535            .add("192.168.23.0/24".parse().unwrap());
1536        ip_range3
1537            .add("192.168.20.0/24".parse().unwrap())
1538            .add("192.168.21.0/24".parse().unwrap())
1539            .add("192.168.22.0/24".parse().unwrap());
1540
1541        let ip_range = ip_range1.merge(&ip_range2);
1542        let ip_range = ip_range.merge(&ip_range3);
1543        assert_eq!(ip_range.into_iter().count(), 1);
1544        assert_eq!(
1545            "192.168.0.0/19".parse().ok(),
1546            ip_range.get_network(19, "192.168.0.0")
1547        );
1548    }
1549
1550    #[test]
1551    fn intersect_disjoint() {
1552        let mut ip_range1 = IpRange::new();
1553        let mut ip_range2 = IpRange::new();
1554        let network1: Ipv4Net = "10.0.0.0/8".parse().unwrap();
1555        let network2 = "172.16.0.0/16".parse().unwrap();
1556        let network3 = "192.168.1.0/24".parse().unwrap();
1557        let network4 = "254.254.254.254/32".parse().unwrap();
1558        ip_range1.add(network1).add(network2);
1559        ip_range2.add(network3).add(network4);
1560
1561        let ip_range = ip_range1.intersect(&ip_range2);
1562        assert_eq!(ip_range.into_iter().count(), 0);
1563    }
1564
1565    #[test]
1566    fn intersect_joint1() {
1567        let mut ip_range1 = IpRange::new();
1568        let mut ip_range2 = IpRange::new();
1569        let network1 = "172.16.4.0/24".parse().unwrap();
1570        let network2 = "172.16.4.0/22".parse().unwrap();
1571        ip_range1.add(network1);
1572        ip_range2.add(network2);
1573
1574        let ip_range = ip_range1.intersect(&ip_range2);
1575        assert_eq!(ip_range.into_iter().count(), 1);
1576        assert_eq!(Some(network1), ip_range.get_network(24, "172.16.4.0"));
1577    }
1578
1579    #[test]
1580    fn intersect_joint2() {
1581        let mut ip_range1 = IpRange::new();
1582        let mut ip_range2 = IpRange::new();
1583        let network1 = "172.16.5.0/24".parse().unwrap();
1584        let network2 = "172.16.4.0/22".parse().unwrap();
1585        ip_range1.add(network1);
1586        ip_range2.add(network2);
1587
1588        let ip_range = ip_range1.intersect(&ip_range2);
1589        assert_eq!(ip_range.into_iter().count(), 1);
1590        assert_eq!(Some(network1), ip_range.get_network(24, "172.16.5.0"));
1591    }
1592
1593    #[test]
1594    fn intersect_joint3() {
1595        let mut ip_range1 = IpRange::new();
1596        let mut ip_range2 = IpRange::new();
1597        let network1 = "172.16.5.0/24".parse().unwrap();
1598        let network2 = "172.16.5.0/24".parse().unwrap();
1599        ip_range1.add(network1);
1600        ip_range2.add(network2);
1601
1602        let ip_range = ip_range1.intersect(&ip_range2);
1603        assert_eq!(ip_range.into_iter().count(), 1);
1604        assert_eq!(Some(network1), ip_range.get_network(24, "172.16.5.0"));
1605    }
1606
1607    #[test]
1608    fn intersect_joint4() {
1609        let mut ip_range1 = IpRange::new();
1610        let mut ip_range2 = IpRange::new();
1611        let network1 = "10.0.0.0/8".parse().unwrap();
1612        let network2 = "192.168.0.0/24".parse().unwrap();
1613        let network3 = "10.10.0.0/16".parse().unwrap();
1614        let network4 = "10.254.0.0/17".parse().unwrap();
1615        let network5 = "192.168.0.0/16".parse().unwrap();
1616        ip_range1.add(network1).add(network2);
1617        ip_range2.add(network3).add(network4).add(network5);
1618
1619        let ip_range = ip_range1.intersect(&ip_range2);
1620        assert_eq!(ip_range.into_iter().count(), 3);
1621        assert_eq!(Some(network3), ip_range.get_network(16, "10.10.0.0"));
1622        assert_eq!(Some(network4), ip_range.get_network(17, "10.254.0.0"));
1623        assert_eq!(Some(network2), ip_range.get_network(24, "192.168.0.0"));
1624    }
1625
1626    #[test]
1627    fn exclude_disjoint() {
1628        let mut ip_range1 = IpRange::new();
1629        let mut ip_range2 = IpRange::new();
1630        let network1: Ipv4Net = "10.0.0.0/8".parse().unwrap();
1631        let network2 = "172.16.0.0/16".parse().unwrap();
1632        let network3 = "192.168.1.0/24".parse().unwrap();
1633        let network4 = "254.254.254.254/32".parse().unwrap();
1634        ip_range1.add(network1).add(network2);
1635        ip_range2.add(network3).add(network4);
1636
1637        let ip_range = ip_range1.exclude(&ip_range2);
1638        assert_eq!(ip_range1, ip_range);
1639    }
1640
1641    #[test]
1642    fn exclude_larger() {
1643        let mut ip_range1 = IpRange::new();
1644        let mut ip_range2 = IpRange::new();
1645        let network1: Ipv4Net = "172.16.4.0/24".parse().unwrap();
1646        let network2 = "192.168.1.0/24".parse().unwrap();
1647        let network3 = "172.16.4.0/22".parse().unwrap();
1648        ip_range1.add(network1).add(network2);
1649        ip_range2.add(network3);
1650
1651        let ip_range = ip_range1.exclude(&ip_range2);
1652        assert_eq!(ip_range.into_iter().count(), 1);
1653        assert_eq!(Some(network2), ip_range.get_network(24, "192.168.1.0"));
1654    }
1655
1656    #[test]
1657    fn exclude_identical() {
1658        let mut ip_range1 = IpRange::new();
1659        let mut ip_range2 = IpRange::new();
1660        let network1: Ipv4Net = "172.16.5.0/24".parse().unwrap();
1661        let network2 = "192.168.1.0/24".parse().unwrap();
1662        let network3 = "172.16.4.0/22".parse().unwrap();
1663        let network4 = "10.0.0.0/8".parse().unwrap();
1664
1665        ip_range1.add(network1).add(network2);
1666        ip_range2.add(network3).add(network4);
1667
1668        let ip_range = ip_range1.exclude(&ip_range2);
1669        assert_eq!(ip_range.into_iter().count(), 1);
1670        assert_eq!(Some(network2), ip_range.get_network(24, "192.168.1.0"));
1671    }
1672
1673    #[test]
1674    fn exclude_split1() {
1675        let mut ip_range1 = IpRange::new();
1676        let mut ip_range2 = IpRange::new();
1677        let network1: Ipv4Net = "172.16.4.0/22".parse().unwrap();
1678        let network2 = "192.168.1.0/24".parse().unwrap();
1679        let network3 = "172.16.5.0/24".parse().unwrap();
1680        let network4 = "10.0.0.0/8".parse().unwrap();
1681
1682        ip_range1.add(network1).add(network2);
1683        ip_range2.add(network3).add(network4);
1684
1685        let ip_range = ip_range1.exclude(&ip_range2);
1686        assert_eq!(ip_range.into_iter().count(), 3);
1687        assert_eq!(Some(network2), ip_range.get_network(24, "192.168.1.0"));
1688        assert_eq!(
1689            "172.16.4.0/24".parse().ok(),
1690            ip_range.get_network(24, "172.16.4.0")
1691        );
1692        assert_eq!(
1693            "172.16.6.0/23".parse().ok(),
1694            ip_range.get_network(23, "172.16.6.0")
1695        );
1696    }
1697
1698    #[test]
1699    fn exclude_split2() {
1700        let mut ip_range1 = IpRange::new();
1701        let mut ip_range2 = IpRange::new();
1702        let network1: Ipv4Net = "172.16.4.0/22".parse().unwrap();
1703        let network2 = "192.168.1.0/24".parse().unwrap();
1704        let network3 = "172.16.4.0/24".parse().unwrap();
1705        let network4 = "10.0.0.0/8".parse().unwrap();
1706
1707        ip_range1.add(network1).add(network2);
1708        ip_range2.add(network3).add(network4);
1709
1710        let ip_range = ip_range1.exclude(&ip_range2);
1711        assert_eq!(ip_range.into_iter().count(), 3);
1712        assert_eq!(Some(network2), ip_range.get_network(24, "192.168.1.0"));
1713        assert_eq!(
1714            "172.16.5.0/24".parse().ok(),
1715            ip_range.get_network(24, "172.16.5.0")
1716        );
1717        assert_eq!(
1718            "172.16.6.0/23".parse().ok(),
1719            ip_range.get_network(23, "172.16.6.0")
1720        );
1721    }
1722
1723    #[test]
1724    fn iter_ipv4() {
1725        let mut data = vec!["1.0.1.0/24", "1.0.2.0/23", "1.0.8.0/21"];
1726        let ip_range: IpRange<Ipv4Net> = data.iter().map(|net| net.parse().unwrap()).collect();
1727        let mut nets: Vec<String> = ip_range.iter().map(|net| format!("{}", net)).collect();
1728        data.sort_unstable();
1729        nets.sort_unstable();
1730        assert_eq!(nets, data);
1731    }
1732
1733    #[test]
1734    fn iter_ipv6() {
1735        let mut data = vec![
1736            "2400:9a40::/32",
1737            "2400:9dc0::/32",
1738            "2400:9e00::/32",
1739            "2400:a040::/32",
1740        ];
1741        let ip_range: IpRange<Ipv6Net> = data.iter().map(|net| net.parse().unwrap()).collect();
1742        let mut nets: Vec<String> = ip_range.iter().map(|net| format!("{}", net)).collect();
1743        data.sort_unstable();
1744        nets.sort_unstable();
1745        assert_eq!(nets, data);
1746    }
1747
1748    #[test]
1749    fn debug_fmt() {
1750        let ip_range: IpRange<Ipv4Net> = IpRange::default();
1751        assert_eq!(format!("{:?}", ip_range), "IpRange []");
1752
1753        let ip_range: IpRange<Ipv4Net> = ["1.0.1.0/24", "1.0.2.0/23", "1.0.8.0/21"]
1754            .iter()
1755            .map(|net| net.parse().unwrap())
1756            .collect();
1757        assert_eq!(
1758            format!("{:?}", ip_range),
1759            "IpRange [1.0.8.0/21, 1.0.2.0/23, 1.0.1.0/24]"
1760        );
1761
1762        let ip_range: IpRange<Ipv4Net> = [
1763            "192.168.0.0/16",
1764            "1.0.2.0/23",
1765            "1.0.8.0/21",
1766            "127.0.0.0/8",
1767            "172.16.0.0/12",
1768        ]
1769        .iter()
1770        .map(|net| net.parse().unwrap())
1771        .collect();
1772        assert_eq!(
1773            format!("{:?}", ip_range),
1774            "IpRange [127.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, ...]"
1775        );
1776
1777        let ip_range: IpRange<Ipv6Net> = [
1778            "2001:4438::/32",
1779            "2001:4510::/29",
1780            "2400:1040::/32",
1781            "2400:12c0::/32",
1782            "2400:1340::/32",
1783            "2400:1380::/32",
1784            "2400:15c0::/32",
1785        ]
1786        .iter()
1787        .map(|net| net.parse().unwrap())
1788        .collect();
1789        assert_eq!(
1790            format!("{:?}", ip_range),
1791            "IpRange [2001:4510::/29, 2001:4438::/32, 2400:1040::/32, ...]"
1792        );
1793    }
1794
1795    #[test]
1796    fn remove_all() {
1797        let mut ip_range = IpRange::new();
1798        let network: Ipv4Net = "1.0.1.0/24".parse().unwrap();
1799        ip_range.add(network);
1800        ip_range.remove(network);
1801        assert!(ip_range.iter().next().is_none());
1802    }
1803
1804    #[test]
1805    fn add_to_all_zeros() {
1806        let mut ip_range: IpRange<Ipv4Net> = IpRange::new();
1807        ip_range.add("0.0.0.0/0".parse().unwrap());
1808        ip_range.add("127.0.0.1/32".parse().unwrap());
1809        assert!(ip_range.contains_network("0.0.0.0/0"));
1810    }
1811
1812    #[test]
1813    #[cfg(feature = "serde")]
1814    fn serialize_ipv4_as_binary() {
1815        let mut ip_range: IpRange<Ipv4Net> = IpRange::new();
1816        ip_range.add("0.0.0.0/0".parse().unwrap());
1817        ip_range.add("127.0.0.1/32".parse().unwrap());
1818        ip_range.add("254.254.254.254/32".parse().unwrap());
1819        let encoded: Vec<u8> = bincode::serialize(&ip_range).unwrap();
1820        let decoded_ip_range: IpRange<Ipv4Net> = bincode::deserialize(&encoded[..]).unwrap();
1821        assert_eq!(ip_range, decoded_ip_range);
1822    }
1823
1824    #[test]
1825    #[cfg(feature = "serde")]
1826    fn serialize_ipv6_as_binary() {
1827        let mut ip_range: IpRange<Ipv6Net> = IpRange::new();
1828        ip_range.add("2001:4438::/32".parse().unwrap());
1829        ip_range.add("2400:1040::/32".parse().unwrap());
1830        ip_range.add("2400:1340::/32".parse().unwrap());
1831        let encoded: Vec<u8> = bincode::serialize(&ip_range).unwrap();
1832        let decoded_ip_range: IpRange<Ipv6Net> = bincode::deserialize(&encoded[..]).unwrap();
1833        assert_eq!(ip_range, decoded_ip_range);
1834    }
1835}