1extern crate ipnet;
44#[cfg(feature = "serde")]
45#[macro_use]
46extern crate serde;
47
48use ipnet::{Ipv4Net, Ipv6Net};
49use std::collections::VecDeque;
50use std::fmt;
51use std::iter::FromIterator;
52use std::marker::PhantomData;
53use std::net::{Ipv4Addr, Ipv6Addr};
54
55#[derive(Clone, PartialEq, Eq)]
93pub struct IpRange<N: IpNet> {
94 trie: IpTrie<N>,
96 phantom_net: PhantomData<N>,
97}
98
99impl<N: IpNet> IpRange<N> {
100 pub fn new() -> IpRange<N> {
102 IpRange {
103 trie: IpTrie::new(),
104 phantom_net: PhantomData,
105 }
106 }
107
108 pub fn add(&mut self, network: N) -> &mut Self {
136 self.trie.insert(network);
137 self
138 }
139
140 pub fn remove(&mut self, network: N) -> &mut Self {
164 self.trie.remove(network);
165 self
166 }
167
168 pub fn is_empty(&self) -> bool {
183 self.trie.root.is_none()
184 }
185
186 pub fn simplify(&mut self) {
210 self.trie.simplify();
211 }
212
213 pub fn merge(&self, other: &IpRange<N>) -> Self {
218 self.into_iter().chain(other.into_iter()).collect()
219 }
220
221 pub fn intersect(&self, other: &IpRange<N>) -> Self {
226 let range1 = self.into_iter().filter(|network| other.contains(network));
227 let range2 = other.into_iter().filter(|network| self.contains(network));
228 range1.chain(range2).collect()
229 }
230
231 pub fn exclude(&self, other: &IpRange<N>) -> IpRange<N> {
236 let mut new = (*self).clone();
237 for network in other {
238 new.remove(network);
239 }
240 new
241 }
242
243 pub fn contains<T: ToNetwork<N>>(&self, network: &T) -> bool {
248 self.supernet(&network.to_network()).is_some()
249 }
250
251 pub fn supernet<T: ToNetwork<N>>(&self, network: &T) -> Option<N> {
255 self.trie.search(network.to_network())
256 }
257
258 pub fn iter(&self) -> IpRangeIter<N> {
260 self.into_iter()
261 }
262}
263
264impl<N> Default for IpRange<N>
265where
266 N: IpNet + ToNetwork<N> + Clone,
267{
268 fn default() -> Self {
269 Self::new()
270 }
271}
272
273impl<N: IpNet> fmt::Debug for IpRange<N> {
274 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
275 let mut networks: Vec<_> = self
276 .iter()
277 .take(4)
278 .map(|net| format!("{:?}", net))
279 .collect();
280 if networks.len() == 4 {
281 networks[3] = "...".to_string();
282 }
283 write!(f, "IpRange [{}]", networks.join(", "))
284 }
285}
286
287impl<'a, N> IntoIterator for &'a IpRange<N>
288where
289 N: IpNet + ToNetwork<N> + Clone,
290{
291 type Item = N;
292 type IntoIter = IpRangeIter<'a, N>;
293
294 fn into_iter(self) -> Self::IntoIter {
295 let mut queue = VecDeque::new();
296 if let Some(root) = self.trie.root.as_ref() {
297 let state: N::S = root.init_traverse_state();
298 queue.push_back(state);
299 }
300 IpRangeIter {
301 queue,
302 _phantom: PhantomData,
303 }
304 }
305}
306
307#[cfg(feature = "serde")]
308impl<N: IpNet> serde::Serialize for IpRange<N> {
309 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
310 where
311 S: serde::Serializer,
312 {
313 serde::Serialize::serialize(&self.trie.root, serializer)
314 }
315}
316
317#[cfg(feature = "serde")]
318impl<'de, N: IpNet> serde::Deserialize<'de> for IpRange<N> {
319 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
320 where
321 D: serde::Deserializer<'de>,
322 {
323 Ok(IpRange {
324 trie: IpTrie {
325 root: serde::Deserialize::deserialize(deserializer)?,
326 phantom_net: PhantomData,
327 },
328 phantom_net: PhantomData,
329 })
330 }
331}
332
333pub trait IpNet: ToNetwork<Self> + fmt::Debug + Ord + Copy
335where
336 Self: Sized,
337{
338 type S: TraverseState<Net = Self>;
340 type I: Iterator<Item = bool>;
342
343 fn prefix_bits(&self) -> Self::I;
345
346 fn prefix_len(&self) -> u8;
348
349 fn with_new_prefix(&self, len: u8) -> Self;
351}
352
353pub trait ToNetwork<N: IpNet> {
359 fn to_network(&self) -> N;
360}
361
362pub struct IpRangeIter<'a, N>
368where
369 N: IpNet,
370{
371 queue: VecDeque<N::S>,
372 _phantom: PhantomData<&'a N>,
373}
374
375#[doc(hidden)]
379pub trait TraverseState {
380 type Net: IpNet;
381
382 fn node(&self) -> *const IpTrieNode;
383
384 fn init(root: &IpTrieNode) -> Self;
385
386 fn transit(&self, next_node: &IpTrieNode, current_bit: bool) -> Self;
387
388 fn build(&self) -> Self::Net;
389}
390
391impl<'a, N> Iterator for IpRangeIter<'a, N>
392where
393 N: IpNet,
394{
395 type Item = N;
396
397 fn next(&mut self) -> Option<Self::Item> {
398 while let Some(elem) = self.queue.pop_front() {
399 let node = unsafe { &*elem.node() };
404 if node.is_leaf() {
405 return Some(elem.build());
406 }
407 for &i in &[0, 1] {
408 if let Some(child) = node.children[i as usize].as_ref() {
409 self.queue.push_back(elem.transit(child, i != 0));
411 }
412 }
413 }
414 None
415 }
416}
417
418impl<N> FromIterator<N> for IpRange<N>
419where
420 N: IpNet + ToNetwork<N> + Clone,
421{
422 fn from_iter<T>(iter: T) -> Self
423 where
424 T: IntoIterator<Item = N>,
425 {
426 let mut ip_range = IpRange::new();
427 for network in iter {
428 ip_range.add(network);
429 }
430 ip_range.simplify();
431 ip_range
432 }
433}
434
435#[derive(Clone, Debug, PartialEq, Eq, Default)]
436struct IpTrie<N>
437where
438 N: IpNet,
439{
440 root: Option<IpTrieNode>,
441 phantom_net: PhantomData<N>,
442}
443
444impl<N> IpTrie<N>
445where
446 N: IpNet,
447{
448 fn new() -> IpTrie<N> {
449 IpTrie {
450 root: None,
451 phantom_net: PhantomData,
452 }
453 }
454
455 fn insert(&mut self, network: N) {
456 let mut node = if let Some(root) = &mut self.root {
458 if root.is_leaf() {
459 return;
461 }
462 root as *mut IpTrieNode
463 } else {
464 self.root = Some(IpTrieNode::new());
465 self.root.as_mut().unwrap() as *mut IpTrieNode
466 };
467
468 unsafe {
469 let bits = network.prefix_bits();
470 for bit in bits {
471 let i = bit as usize;
472 let child = &mut (*node).children[i];
473 match child {
474 Some(child) => {
475 if child.is_leaf() {
476 return;
479 }
480 node = &mut **child as *mut IpTrieNode;
481 }
482 None => {
483 (*node).children[i] = Some(Box::new(IpTrieNode::new()));
484 node = (*node).children[i].as_mut().unwrap().as_mut() as *mut IpTrieNode;
485 }
486 }
487 }
488 (*node).children = [None, None];
489 }
490 }
491
492 fn search(&self, network: N) -> Option<N> {
493 let mut node = self.root.as_ref()?;
494
495 let bits = network.prefix_bits();
496 for (j, bit) in bits.enumerate() {
497 if node.is_leaf() {
498 return Some(network.with_new_prefix(j as u8));
499 }
500
501 let i = bit as usize;
502 let child = node.children[i].as_ref();
503 match child {
504 Some(child) => node = child,
505 None => return None,
506 }
507 }
508
509 if node.is_leaf() {
510 Some(network)
511 } else {
512 None
513 }
514
515 }
529
530 fn remove(&mut self, network: N) {
531 if let Some(root) = self.root.as_mut() {
532 let mut bits = network.prefix_bits();
533 if let Some(next_bit) = bits.next() {
534 root.remove(bits, next_bit);
535 if !root.is_leaf() {
538 return;
539 }
540 }
541 }
542 self.root = None }
544
545 fn simplify(&mut self) {
546 if let Some(root) = self.root.as_mut() {
547 root.simplify();
548 }
549 }
550}
551
552#[derive(Clone, Debug, PartialEq, Eq)]
554#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(transparent))]
555pub struct IpTrieNode {
556 children: [Option<Box<IpTrieNode>>; 2],
557}
558
559impl IpTrieNode {
560 fn new() -> IpTrieNode {
561 IpTrieNode {
562 children: [None, None],
563 }
564 }
565
566 #[inline]
567 fn init_traverse_state<S: TraverseState>(&self) -> S {
568 S::init(self)
569 }
570
571 #[inline]
575 fn is_leaf(&self) -> bool {
576 self.children[0].is_none() && self.children[1].is_none()
577 }
578
579 fn simplify(&mut self) {
582 let leaf_count: u32 = self
583 .children
584 .iter_mut()
585 .map(|child| {
586 child
587 .as_mut()
588 .map(|child| {
589 child.simplify();
590 child.is_leaf() as u32
591 })
592 .unwrap_or_default()
593 })
594 .sum();
595 if leaf_count == 2 {
596 self.children = [None, None];
597 }
598 }
599
600 fn remove<I>(&mut self, mut bits: I, current_bit: bool)
619 where
620 I: Iterator<Item = bool>,
621 {
622 let i = current_bit as usize;
623 let next_bit = bits.next();
624
625 if self.is_leaf() {
628 self.children = [
629 Some(Box::new(IpTrieNode::new())),
630 Some(Box::new(IpTrieNode::new())),
631 ];
632 }
633
634 match next_bit {
635 Some(next_bit) => {
636 let is_leaf = if let Some(child) = self.children[i].as_mut() {
637 child.remove(bits, next_bit);
639 child.is_leaf()
640 } else {
641 false
642 };
643 if is_leaf {
650 self.children[i] = None;
651 }
652 }
653 None => {
654 self.children[i] = None;
656 }
657 }
658 }
659}
660
661const MSO_U128: u128 = 1 << 127; const MSO_U32: u32 = 1 << 31; impl IpNet for Ipv4Net {
665 type S = Ipv4TraverseState;
666 type I = Ipv4PrefixBitIterator;
667
668 #[inline]
669 fn prefix_bits(&self) -> Self::I {
670 let prefix: u32 = self.addr().into();
671 Ipv4PrefixBitIterator {
672 prefix,
673 prefix_len: self.prefix_len(),
674 }
675 }
676
677 #[inline]
678 fn prefix_len(&self) -> u8 {
679 self.prefix_len()
680 }
681
682 #[inline]
683 fn with_new_prefix(&self, len: u8) -> Self {
684 Ipv4Net::new(self.addr(), len).unwrap().trunc()
685 }
686}
687
688impl ToNetwork<Ipv4Net> for Ipv4Net {
689 #[inline]
690 fn to_network(&self) -> Ipv4Net {
691 self.trunc()
692 }
693}
694
695impl ToNetwork<Ipv4Net> for Ipv4Addr {
696 #[inline]
697 fn to_network(&self) -> Ipv4Net {
698 Ipv4Net::new(*self, 32).unwrap()
699 }
700}
701
702impl ToNetwork<Ipv4Net> for u32 {
703 #[inline]
704 fn to_network(&self) -> Ipv4Net {
705 Ipv4Net::new((*self).into(), 32).unwrap()
706 }
707}
708
709impl ToNetwork<Ipv4Net> for [u8; 4] {
710 #[inline]
711 fn to_network(&self) -> Ipv4Net {
712 Ipv4Net::new((*self).into(), 32).unwrap()
713 }
714}
715
716#[doc(hidden)]
717pub struct Ipv4TraverseState {
718 node: *const IpTrieNode,
719 prefix: u32,
720 prefix_len: u8,
721}
722
723impl TraverseState for Ipv4TraverseState {
724 type Net = Ipv4Net;
725
726 #[inline]
727 fn node(&self) -> *const IpTrieNode {
728 self.node
729 }
730
731 #[inline]
732 fn init(root: &IpTrieNode) -> Self {
733 Ipv4TraverseState {
734 node: root,
735 prefix: 0,
736 prefix_len: 0,
737 }
738 }
739
740 #[inline]
741 fn transit(&self, next_node: &IpTrieNode, current_bit: bool) -> Self {
742 let mask = if current_bit {
743 MSO_U32 >> self.prefix_len
744 } else {
745 0
746 };
747 Ipv4TraverseState {
748 node: next_node,
749 prefix: self.prefix | mask,
750 prefix_len: self.prefix_len + 1,
751 }
752 }
753
754 #[inline]
755 fn build(&self) -> Self::Net {
756 Ipv4Net::new(self.prefix.into(), self.prefix_len as u8).unwrap()
757 }
758}
759
760#[doc(hidden)]
761pub struct Ipv4PrefixBitIterator {
762 prefix: u32,
763 prefix_len: u8,
764}
765
766impl Iterator for Ipv4PrefixBitIterator {
767 type Item = bool;
768
769 #[inline]
770 fn next(&mut self) -> Option<Self::Item> {
771 if self.prefix_len > 0 {
772 let prefix = self.prefix;
773 self.prefix <<= 1;
774 self.prefix_len -= 1;
775 Some(prefix & MSO_U32 != 0)
776 } else {
777 None
778 }
779 }
780}
781
782impl IpNet for Ipv6Net {
783 type S = Ipv6TraverseState;
784 type I = Ipv6PrefixBitIterator;
785
786 #[inline]
787 fn prefix_bits(&self) -> Self::I {
788 Ipv6PrefixBitIterator {
789 prefix: self.addr().into(),
790 prefix_len: self.prefix_len(),
791 }
792 }
793
794 #[inline]
795 fn prefix_len(&self) -> u8 {
796 self.prefix_len()
797 }
798
799 #[inline]
800 fn with_new_prefix(&self, len: u8) -> Self {
801 Ipv6Net::new(self.addr(), len).unwrap().trunc()
802 }
803}
804
805impl ToNetwork<Ipv6Net> for Ipv6Net {
806 #[inline]
807 fn to_network(&self) -> Ipv6Net {
808 self.trunc()
809 }
810}
811
812impl ToNetwork<Ipv6Net> for Ipv6Addr {
813 #[inline]
814 fn to_network(&self) -> Ipv6Net {
815 Ipv6Net::new(*self, 128).unwrap()
816 }
817}
818
819impl ToNetwork<Ipv6Net> for u128 {
820 #[inline]
821 fn to_network(&self) -> Ipv6Net {
822 Ipv6Net::new((*self).into(), 128).unwrap()
823 }
824}
825
826impl ToNetwork<Ipv6Net> for [u8; 16] {
827 #[inline]
828 fn to_network(&self) -> Ipv6Net {
829 Ipv6Net::new((*self).into(), 128).unwrap()
830 }
831}
832
833impl ToNetwork<Ipv6Net> for [u16; 8] {
834 #[inline]
835 fn to_network(&self) -> Ipv6Net {
836 Ipv6Net::new((*self).into(), 128).unwrap()
837 }
838}
839
840#[doc(hidden)]
841pub struct Ipv6TraverseState {
842 node: *const IpTrieNode,
843 prefix: u128,
844 prefix_len: u8,
845}
846
847impl TraverseState for Ipv6TraverseState {
848 type Net = Ipv6Net;
849
850 #[inline]
851 fn node(&self) -> *const IpTrieNode {
852 self.node
853 }
854
855 #[inline]
856 fn init(root: &IpTrieNode) -> Self {
857 Ipv6TraverseState {
858 node: root,
859 prefix: 0,
860 prefix_len: 0,
861 }
862 }
863
864 #[inline]
865 fn transit(&self, next_node: &IpTrieNode, current_bit: bool) -> Self {
866 let mask = if current_bit {
867 MSO_U128 >> self.prefix_len
868 } else {
869 0
870 };
871 Ipv6TraverseState {
872 node: next_node,
873 prefix: self.prefix | mask,
874 prefix_len: self.prefix_len + 1,
875 }
876 }
877
878 #[inline]
879 fn build(&self) -> Self::Net {
880 Ipv6Net::new(self.prefix.into(), self.prefix_len as u8).unwrap()
881 }
882}
883
884#[doc(hidden)]
885pub struct Ipv6PrefixBitIterator {
886 prefix: u128,
887 prefix_len: u8,
888}
889
890impl Iterator for Ipv6PrefixBitIterator {
891 type Item = bool;
892
893 #[inline]
894 fn next(&mut self) -> Option<Self::Item> {
895 if self.prefix_len > 0 {
896 let prefix = self.prefix;
897 self.prefix <<= 1;
898 self.prefix_len -= 1;
899 Some(prefix & MSO_U128 != 0)
900 } else {
901 None
902 }
903 }
904}
905
906#[cfg(test)]
907mod tests {
908 use super::*;
909
910 #[test]
911 fn parse_invalid_networks() {
912 assert!("192.168.256.130/5".parse::<Ipv4Net>().is_err());
913 assert!("192.168.5.130/-1".parse::<Ipv4Net>().is_err());
914 assert!("192.168.5.130/33".parse::<Ipv4Net>().is_err());
915 assert!("192.168.5.33".parse::<Ipv4Net>().is_err());
916 assert!("192.168.5.130/0.0.0".parse::<Ipv4Net>().is_err());
917 assert!("192.168.5.130/0.0.0.256".parse::<Ipv4Net>().is_err());
918 }
919
920 impl IpRange<Ipv4Net> {
921 fn get_network(&self, prefix_size: usize, prefix: &str) -> Option<Ipv4Net> {
922 self.trie
923 .search(format!("{}/{}", prefix, prefix_size).parse().unwrap())
924 }
925 }
926
927 #[test]
928 fn add_single_network() {
929 let mut ip_range = IpRange::new();
930 let network = "192.168.5.0/24".parse().unwrap();
931 ip_range.add(network);
932 assert_eq!(ip_range.into_iter().count(), 1);
933 assert_eq!(Some(network), ip_range.get_network(24, "192.168.5.0"));
934 }
935
936 #[test]
937 fn add_multiple_networks_disjoint() {
938 let mut ip_range = IpRange::new();
939 let network1 = "10.0.0.0/8".parse().unwrap();
940 let network2 = "172.16.0.0/16".parse().unwrap();
941 let network3 = "192.168.1.0/24".parse().unwrap();
942 let network4 = "254.254.254.254/32".parse().unwrap();
943 ip_range
944 .add(network1)
945 .add(network2)
946 .add(network3)
947 .add(network4)
948 .simplify();
949
950 assert_eq!(ip_range.into_iter().count(), 4);
951 assert_eq!(Some(network1), ip_range.get_network(8, "10.0.0.0"));
952 assert_eq!(Some(network2), ip_range.get_network(16, "172.16.0.0"));
953 assert_eq!(Some(network3), ip_range.get_network(24, "192.168.1.0"));
954 assert_eq!(Some(network4), ip_range.get_network(32, "254.254.254.254"));
955 }
956
957 #[test]
958 fn simplify() {
959 let mut ip_range = IpRange::new();
960 ip_range
961 .add("192.168.0.0/20".parse().unwrap())
962 .add("192.168.16.0/22".parse().unwrap())
963 .add("192.168.20.0/24".parse().unwrap())
964 .add("192.168.21.0/24".parse().unwrap())
965 .add("192.168.22.0/24".parse().unwrap())
966 .add("192.168.23.0/24".parse().unwrap())
967 .add("192.168.24.0/21".parse().unwrap())
968 .simplify();
969
970 assert_eq!(ip_range.into_iter().count(), 1);
971 assert_eq!(
972 "192.168.0.0/19".parse().ok(),
973 ip_range.get_network(19, "192.168.0.0")
974 );
975 }
976
977 #[test]
978 fn add_multiple_networks_joint1() {
979 let mut ip_range = IpRange::new();
980 let network1 = "172.16.4.0/24".parse().unwrap();
981 let network2 = "172.16.4.0/22".parse().unwrap();
982 ip_range.add(network1).add(network2).simplify();
983
984 assert_eq!(ip_range.into_iter().count(), 1);
985 assert_eq!(Some(network2), ip_range.get_network(22, "172.16.4.0"));
986 }
987
988 #[test]
989 fn add_multiple_networks_joint2() {
990 let mut ip_range = IpRange::new();
991 let network1 = "172.16.5.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_joint3() {
1001 let mut ip_range = IpRange::new();
1002 let network1 = "172.16.4.0/24".parse().unwrap();
1003 let network2 = "172.16.4.0/22".parse().unwrap();
1004 ip_range.add(network2).add(network1).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_joint4() {
1012 let mut ip_range = IpRange::new();
1013 let network1 = "172.16.5.0/24".parse().unwrap();
1014 let network2 = "172.16.5.0/24".parse().unwrap();
1015 ip_range.add(network1).add(network2).simplify();
1016
1017 assert_eq!(ip_range.into_iter().count(), 1);
1018 assert_eq!(Some(network2), ip_range.get_network(24, "172.16.5.0"));
1019 }
1020
1021 #[test]
1022 fn add_multiple_networks_joint5() {
1023 let mut ip_range = IpRange::new();
1024 let network1 = "172.16.5.0/24".parse().unwrap();
1025 let network2 = "172.16.0.0/16".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(16, "172.16.0.0"));
1030 }
1031
1032 #[test]
1033 fn add_multiple_networks_joint6() {
1034 let mut ip_range = IpRange::new();
1035 let network1 = "172.16.5.0/24".parse().unwrap();
1036 let network2 = "0.0.0.0/0".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(0, "0.0.0.0"));
1041 }
1042
1043 #[test]
1044 fn remove_networks_no_split() {
1045 let mut ip_range = IpRange::new();
1046 let network1 = "192.168.0.0/24".parse().unwrap();
1047 let network2 = "172.16.0.0/16".parse().unwrap();
1048 ip_range.add(network1).add(network2).simplify();
1049
1050 ip_range.remove(network1);
1051 assert_eq!(ip_range.into_iter().count(), 1);
1052 assert_eq!(Some(network2), ip_range.get_network(16, "172.16.0.0"));
1053 }
1054
1055 #[test]
1056 fn remove_networks_split1() {
1057 let mut ip_range = IpRange::new();
1058 ip_range.add("192.168.0.0/22".parse().unwrap());
1059 ip_range
1060 .remove("192.168.2.0/23".parse().unwrap())
1061 .simplify();
1062
1063 assert_eq!(ip_range.into_iter().count(), 1);
1064 assert_eq!(
1065 Some("192.168.0.0/23".parse().unwrap()),
1066 ip_range.get_network(23, "192.168.0.0")
1067 );
1068 }
1069
1070 #[test]
1071 fn remove_networks_split2() {
1072 let mut ip_range = IpRange::new();
1073 ip_range.add("192.168.0.0/22".parse().unwrap());
1074 ip_range
1075 .remove("192.168.0.0/23".parse().unwrap())
1076 .simplify();
1077
1078 assert_eq!(ip_range.into_iter().count(), 1);
1079 assert_eq!(
1080 Some("192.168.2.0/23".parse().unwrap()),
1081 ip_range.get_network(23, "192.168.2.0")
1082 );
1083 }
1084
1085 #[test]
1086 fn remove_networks_split3() {
1087 let mut ip_range = IpRange::new();
1088 ip_range.add("192.168.0.0/22".parse().unwrap());
1089 ip_range
1090 .remove("192.168.2.0/25".parse().unwrap())
1091 .simplify();
1092
1093 assert_eq!(ip_range.into_iter().count(), 3);
1094 assert_eq!(
1095 Some("192.168.0.0/23".parse().unwrap()),
1096 ip_range.get_network(23, "192.168.0.0")
1097 );
1098 assert_eq!(
1099 Some("192.168.2.128/25".parse().unwrap()),
1100 ip_range.get_network(25, "192.168.2.128")
1101 );
1102 assert_eq!(
1103 Some("192.168.3.0/24".parse().unwrap()),
1104 ip_range.get_network(24, "192.168.3.0")
1105 );
1106 }
1107
1108 impl IpRange<Ipv4Net> {
1109 fn contains_ip(&self, ip: &str) -> bool {
1110 self.contains(&ip.parse::<Ipv4Addr>().unwrap())
1111 }
1112
1113 fn find_network_by_ip(&self, ip: &str) -> Option<Ipv4Net> {
1114 self.supernet(&ip.parse::<Ipv4Addr>().unwrap())
1115 }
1116
1117 fn contains_network(&self, network: &str) -> bool {
1118 self.contains(&network.parse::<Ipv4Net>().unwrap())
1119 }
1120
1121 fn super_network_by_network(&self, network: &str) -> Option<Ipv4Net> {
1122 self.supernet(&network.parse::<Ipv4Net>().unwrap())
1123 }
1124 }
1125
1126 #[test]
1127 fn contains_ip_with_one_network() {
1128 let mut ip_range = IpRange::new();
1129 ip_range.add("192.168.0.0/24".parse().unwrap());
1130
1131 assert!(ip_range.contains_ip("192.168.0.0"));
1132 assert!(ip_range.contains_ip("192.168.0.128"));
1133 assert!(ip_range.contains_ip("192.168.0.255"));
1134 assert!(!ip_range.contains_ip("192.167.255.255"));
1135 assert!(!ip_range.contains_ip("192.168.1.0"));
1136 }
1137
1138 #[test]
1139 fn contains_ip_with_many_networks() {
1140 let mut ip_range = IpRange::new();
1141 ip_range
1142 .add("192.168.0.0/24".parse().unwrap())
1143 .add("172.16.0.0/16".parse().unwrap())
1144 .add("10.0.0.0/8".parse().unwrap())
1145 .simplify();
1146
1147 assert!(ip_range.contains_ip("192.168.0.128"));
1148 assert!(ip_range.contains_ip("172.16.32.1"));
1149 assert!(ip_range.contains_ip("10.10.10.10"));
1150 assert!(!ip_range.contains_ip("0.0.0.0"));
1151 assert!(!ip_range.contains_ip("8.8.8.8"));
1152 assert!(!ip_range.contains_ip("11.0.0.0"));
1153 assert!(!ip_range.contains_ip("192.167.255.255"));
1154 assert!(!ip_range.contains_ip("255.255.255.255"));
1155 }
1156
1157 #[test]
1158 fn contains_ip_boundary1() {
1159 let mut ip_range = IpRange::new();
1160 ip_range.add("0.0.0.0/0".parse().unwrap());
1161
1162 assert!(ip_range.contains_ip("0.0.0.0"));
1163 assert!(ip_range.contains_ip("8.8.8.8"));
1164 assert!(ip_range.contains_ip("192.168.0.0"));
1165 assert!(ip_range.contains_ip("192.168.1.1"));
1166 }
1167
1168 #[test]
1169 fn contains_ip_boundary2() {
1170 let mut ip_range = IpRange::new();
1171 ip_range.add("254.254.254.254/32".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("254.254.254.254"));
1177 }
1178
1179 #[test]
1180 fn find_network_with_one_network() {
1181 let mut ip_range = IpRange::new();
1182 let network = "192.168.0.0/24".parse().unwrap();
1183 ip_range.add(network);
1184
1185 assert_eq!(Some(network), ip_range.find_network_by_ip("192.168.0.0"));
1186 assert_eq!(Some(network), ip_range.find_network_by_ip("192.168.0.128"));
1187 assert_eq!(Some(network), ip_range.find_network_by_ip("192.168.0.255"));
1188 assert_eq!(None, ip_range.find_network_by_ip("192.167.255.255"));
1189 assert_eq!(None, ip_range.find_network_by_ip("192.168.1.0"));
1190 }
1191
1192 #[test]
1193 fn find_network_with_many_networks() {
1194 let mut ip_range = IpRange::new();
1195 let network1 = "192.168.0.0/24".parse().unwrap();
1196 let network2 = "172.16.0.0/16".parse().unwrap();
1197 let network3 = "10.0.0.0/8".parse().unwrap();
1198 ip_range
1199 .add(network1)
1200 .add(network2)
1201 .add(network3)
1202 .simplify();
1203
1204 assert_eq!(Some(network1), ip_range.find_network_by_ip("192.168.0.128"));
1205 assert_eq!(Some(network2), ip_range.find_network_by_ip("172.16.32.1"));
1206 assert_eq!(Some(network3), ip_range.find_network_by_ip("10.10.10.10"));
1207 assert_eq!(None, ip_range.find_network_by_ip("0.0.0.0"));
1208 assert_eq!(None, ip_range.find_network_by_ip("8.8.8.8"));
1209 assert_eq!(None, ip_range.find_network_by_ip("11.0.0.0"));
1210 assert_eq!(None, ip_range.find_network_by_ip("192.167.255.255"));
1211 assert_eq!(None, ip_range.find_network_by_ip("255.255.255.255"));
1212 }
1213
1214 #[test]
1215 fn find_network_boundary1() {
1216 let mut ip_range = IpRange::new();
1217 let network = "0.0.0.0/0".parse().unwrap();
1218 ip_range.add(network);
1219
1220 assert_eq!(Some(network), ip_range.find_network_by_ip("0.0.0.0"));
1221 assert_eq!(Some(network), ip_range.find_network_by_ip("8.8.8.8"));
1222 assert_eq!(Some(network), ip_range.find_network_by_ip("192.168.0.0"));
1223 assert_eq!(Some(network), ip_range.find_network_by_ip("192.168.1.1"));
1224 }
1225
1226 #[test]
1227 fn find_network_boundary2() {
1228 let mut ip_range = IpRange::new();
1229 let network = "254.254.254.254/32".parse().unwrap();
1230 ip_range.add(network);
1231
1232 assert_eq!(None, ip_range.find_network_by_ip("0.0.0.0"));
1233 assert_eq!(None, ip_range.find_network_by_ip("8.8.8.8"));
1234 assert_eq!(None, ip_range.find_network_by_ip("192.168.0.0"));
1235 assert_eq!(
1236 Some(network),
1237 ip_range.find_network_by_ip("254.254.254.254")
1238 );
1239 }
1240
1241 #[test]
1242 fn contains_network_with_one_network() {
1243 let mut ip_range = IpRange::new();
1244 ip_range.add("192.168.0.0/24".parse().unwrap());
1245
1246 assert!(ip_range.contains_network("192.168.0.0/24"));
1247 assert!(ip_range.contains_network("192.168.0.128/25"));
1248 assert!(!ip_range.contains_network("192.168.0.0/23"));
1249 assert!(!ip_range.contains_network("192.168.1.0/24"));
1250 assert!(!ip_range.contains_network("192.167.0.0/24"));
1251 }
1252
1253 #[test]
1254 fn contains_network_with_many_networks() {
1255 let mut ip_range = IpRange::new();
1256 ip_range
1257 .add("192.168.0.0/24".parse().unwrap())
1258 .add("172.16.0.0/16".parse().unwrap())
1259 .add("10.0.0.0/8".parse().unwrap())
1260 .simplify();
1261
1262 assert!(ip_range.contains_network("192.168.0.128/25"));
1263 assert!(ip_range.contains_network("172.16.32.0/20"));
1264 assert!(ip_range.contains_network("10.10.0.0/16"));
1265 assert!(!ip_range.contains_network("0.0.0.0/0"));
1266 assert!(!ip_range.contains_network("8.0.0.0/6"));
1267 assert!(!ip_range.contains_network("8.0.0.0/7"));
1268 assert!(!ip_range.contains_network("11.0.0.0/9"));
1269 assert!(!ip_range.contains_network("192.167.255.255/32"));
1270 assert!(!ip_range.contains_network("255.0.0.0/8"));
1271 }
1272
1273 #[test]
1274 fn contains_network_boundary1() {
1275 let mut ip_range = IpRange::new();
1276 ip_range.add("0.0.0.0/0".parse().unwrap());
1277
1278 assert!(ip_range.contains_network("0.0.0.0/0"));
1279 assert!(ip_range.contains_network("8.0.0.0/6"));
1280 assert!(ip_range.contains_network("11.0.0.0/9"));
1281 assert!(ip_range.contains_network("192.168.0.128/25"));
1282 assert!(ip_range.contains_network("255.255.255.255/32"));
1283 }
1284
1285 #[test]
1286 fn contains_network_boundary2() {
1287 let mut ip_range = IpRange::new();
1288 ip_range.add("254.254.254.254/32".parse().unwrap());
1289
1290 assert!(!ip_range.contains_network("0.0.0.0/0"));
1291 assert!(!ip_range.contains_network("8.0.0.0/6"));
1292 assert!(!ip_range.contains_network("254.254.0.0/16"));
1293 assert!(ip_range.contains_network("254.254.254.254/32"));
1294 assert!(!ip_range.contains_network("255.255.255.255/32"));
1295 }
1296
1297 #[test]
1298 fn super_network_with_one_network() {
1299 let mut ip_range = IpRange::new();
1300 let network = "192.168.0.0/24".parse().unwrap();
1301 ip_range.add(network);
1302
1303 assert_eq!(
1304 Some(network),
1305 ip_range.super_network_by_network("192.168.0.0/24")
1306 );
1307 assert_eq!(
1308 Some(network),
1309 ip_range.super_network_by_network("192.168.0.128/25")
1310 );
1311 assert_eq!(None, ip_range.super_network_by_network("192.168.0.0/23"));
1312 assert_eq!(None, ip_range.super_network_by_network("192.168.1.0/24"));
1313 assert_eq!(None, ip_range.super_network_by_network("192.167.0.0/24"));
1314 }
1315
1316 #[test]
1317 fn super_network_with_many_networks() {
1318 let mut ip_range = IpRange::new();
1319 let network1 = "192.168.0.0/24".parse().unwrap();
1320 let network2 = "172.16.0.0/16".parse().unwrap();
1321 let network3 = "10.0.0.0/8".parse().unwrap();
1322 ip_range
1323 .add(network1)
1324 .add(network2)
1325 .add(network3)
1326 .simplify();
1327
1328 assert_eq!(
1329 Some(network1),
1330 ip_range.super_network_by_network("192.168.0.128/25")
1331 );
1332 assert_eq!(
1333 Some(network2),
1334 ip_range.super_network_by_network("172.16.32.0/20")
1335 );
1336 assert_eq!(
1337 Some(network3),
1338 ip_range.super_network_by_network("10.10.0.0/16")
1339 );
1340 assert_eq!(None, ip_range.super_network_by_network("0.0.0.0/0"));
1341 assert_eq!(None, ip_range.super_network_by_network("8.0.0.0/6"));
1342 assert_eq!(None, ip_range.super_network_by_network("8.0.0.0/7"));
1343 assert_eq!(None, ip_range.super_network_by_network("11.0.0.0/9"));
1344 assert_eq!(
1345 None,
1346 ip_range.super_network_by_network("192.167.255.255/32")
1347 );
1348 assert_eq!(None, ip_range.super_network_by_network("255.0.0.0/8"));
1349 }
1350
1351 #[test]
1352 fn super_network_boundary1() {
1353 let mut ip_range = IpRange::new();
1354 let network = "0.0.0.0/0".parse().unwrap();
1355 ip_range.add(network);
1356
1357 assert_eq!(
1358 Some(network),
1359 ip_range.super_network_by_network("0.0.0.0/0")
1360 );
1361 assert_eq!(
1362 Some(network),
1363 ip_range.super_network_by_network("8.0.0.0/6")
1364 );
1365 assert_eq!(
1366 Some(network),
1367 ip_range.super_network_by_network("11.0.0.0/9")
1368 );
1369 assert_eq!(
1370 Some(network),
1371 ip_range.super_network_by_network("192.168.0.128/25")
1372 );
1373 assert_eq!(
1374 Some(network),
1375 ip_range.super_network_by_network("255.255.255.255/32")
1376 );
1377 }
1378
1379 #[test]
1380 fn super_network_boundary2() {
1381 let mut ip_range = IpRange::new();
1382 let network = "254.254.254.254/32".parse().unwrap();
1383 ip_range.add(network);
1384
1385 assert_eq!(None, ip_range.super_network_by_network("0.0.0.0/0"));
1386 assert_eq!(None, ip_range.super_network_by_network("8.0.0.0/6"));
1387 assert_eq!(None, ip_range.super_network_by_network("254.254.0.0/16"));
1388 assert_eq!(
1389 Some(network),
1390 ip_range.super_network_by_network("254.254.254.254/32")
1391 );
1392 assert_eq!(
1393 None,
1394 ip_range.super_network_by_network("255.255.255.255/32")
1395 );
1396 }
1397
1398 #[test]
1399 fn merge_empty1() {
1400 let ip_range1 = IpRange::new();
1401 let mut ip_range2 = IpRange::new();
1402 let network1 = "10.0.0.0/8".parse().unwrap();
1403 let network2 = "172.16.0.0/16".parse().unwrap();
1404 let network3 = "192.168.1.0/24".parse().unwrap();
1405 let network4 = "254.254.254.254/32".parse().unwrap();
1406 ip_range2
1407 .add(network1)
1408 .add(network2)
1409 .add(network3)
1410 .add(network4)
1411 .simplify();
1412
1413 let ip_range = ip_range1.merge(&ip_range2);
1414 assert_eq!(ip_range.into_iter().count(), 4);
1415 assert_eq!(Some(network1), ip_range.get_network(8, "10.0.0.0"));
1416 assert_eq!(Some(network2), ip_range.get_network(16, "172.16.0.0"));
1417 assert_eq!(Some(network3), ip_range.get_network(24, "192.168.1.0"));
1418 assert_eq!(Some(network4), ip_range.get_network(32, "254.254.254.254"));
1419 }
1420
1421 #[test]
1422 fn merge_empty2() {
1423 let mut ip_range1 = IpRange::new();
1424 let ip_range2 = IpRange::new();
1425 let network1 = "10.0.0.0/8".parse().unwrap();
1426 let network2 = "172.16.0.0/16".parse().unwrap();
1427 let network3 = "192.168.1.0/24".parse().unwrap();
1428 let network4 = "254.254.254.254/32".parse().unwrap();
1429 ip_range1
1430 .add(network1)
1431 .add(network2)
1432 .add(network3)
1433 .add(network4)
1434 .simplify();
1435
1436 let ip_range = ip_range1.merge(&ip_range2);
1437 assert_eq!(ip_range.into_iter().count(), 4);
1438 assert_eq!(Some(network1), ip_range.get_network(8, "10.0.0.0"));
1439 assert_eq!(Some(network2), ip_range.get_network(16, "172.16.0.0"));
1440 assert_eq!(Some(network3), ip_range.get_network(24, "192.168.1.0"));
1441 assert_eq!(Some(network4), ip_range.get_network(32, "254.254.254.254"));
1442 }
1443
1444 #[test]
1445 fn merge_disjoint() {
1446 let mut ip_range1 = IpRange::new();
1447 let mut ip_range2 = IpRange::new();
1448 let network1 = "10.0.0.0/8".parse().unwrap();
1449 let network2 = "172.16.0.0/16".parse().unwrap();
1450 let network3 = "192.168.1.0/24".parse().unwrap();
1451 let network4 = "254.254.254.254/32".parse().unwrap();
1452 ip_range1.add(network1).add(network2);
1453 ip_range2.add(network3).add(network4);
1454
1455 let ip_range = ip_range1.merge(&ip_range2);
1456 assert_eq!(ip_range.into_iter().count(), 4);
1457 assert_eq!(Some(network1), ip_range.get_network(8, "10.0.0.0"));
1458 assert_eq!(Some(network2), ip_range.get_network(16, "172.16.0.0"));
1459 assert_eq!(Some(network3), ip_range.get_network(24, "192.168.1.0"));
1460 assert_eq!(Some(network4), ip_range.get_network(32, "254.254.254.254"));
1461 }
1462
1463 #[test]
1464 fn merge_joint1() {
1465 let mut ip_range1 = IpRange::new();
1466 let mut ip_range2 = IpRange::new();
1467 let network1 = "172.16.4.0/24".parse().unwrap();
1468 let network2 = "172.16.4.0/22".parse().unwrap();
1469 ip_range1.add(network1);
1470 ip_range2.add(network2);
1471
1472 let ip_range = ip_range1.merge(&ip_range2);
1473 assert_eq!(ip_range.into_iter().count(), 1);
1474 assert_eq!(Some(network2), ip_range.get_network(22, "172.16.4.0"));
1475 }
1476
1477 #[test]
1478 fn merge_joint2() {
1479 let mut ip_range1 = IpRange::new();
1480 let mut ip_range2 = IpRange::new();
1481 let network1 = "172.16.5.0/24".parse().unwrap();
1482 let network2 = "172.16.4.0/22".parse().unwrap();
1483 ip_range1.add(network1);
1484 ip_range2.add(network2);
1485
1486 let ip_range = ip_range1.merge(&ip_range2);
1487 assert_eq!(ip_range.into_iter().count(), 1);
1488 assert_eq!(Some(network2), ip_range.get_network(22, "172.16.4.0"));
1489 }
1490
1491 #[test]
1492 fn merge_sequent1() {
1493 let mut ip_range1 = IpRange::new();
1494 let mut ip_range2 = IpRange::new();
1495 let network1 = "172.16.4.0/24".parse().unwrap();
1496 let network2 = "172.16.5.0/24".parse().unwrap();
1497 let network3 = "172.16.6.0/24".parse().unwrap();
1498 ip_range1.add(network1);
1499 ip_range2.add(network2);
1500 ip_range2.add(network3);
1501
1502 let ip_range = ip_range1.merge(&ip_range2);
1503 assert_eq!(ip_range.into_iter().count(), 2);
1504 assert_eq!(
1505 "172.16.4.0/23".parse().ok(),
1506 ip_range.get_network(23, "172.16.4.0")
1507 );
1508 assert_eq!(
1509 "172.16.6.0/24".parse().ok(),
1510 ip_range.get_network(24, "172.16.6.0")
1511 );
1512 }
1513
1514 #[test]
1515 fn merge_sequent2() {
1516 let mut ip_range1 = IpRange::new();
1517 let mut ip_range2 = IpRange::new();
1518 let mut ip_range3 = IpRange::new();
1519 ip_range1
1520 .add("192.168.0.0/20".parse().unwrap())
1521 .add("192.168.24.0/21".parse().unwrap());
1522 ip_range2
1523 .add("192.168.16.0/22".parse().unwrap())
1524 .add("192.168.23.0/24".parse().unwrap());
1525 ip_range3
1526 .add("192.168.20.0/24".parse().unwrap())
1527 .add("192.168.21.0/24".parse().unwrap())
1528 .add("192.168.22.0/24".parse().unwrap());
1529
1530 let ip_range = ip_range1.merge(&ip_range2);
1531 let ip_range = ip_range.merge(&ip_range3);
1532 assert_eq!(ip_range.into_iter().count(), 1);
1533 assert_eq!(
1534 "192.168.0.0/19".parse().ok(),
1535 ip_range.get_network(19, "192.168.0.0")
1536 );
1537 }
1538
1539 #[test]
1540 fn intersect_disjoint() {
1541 let mut ip_range1 = IpRange::new();
1542 let mut ip_range2 = IpRange::new();
1543 let network1: Ipv4Net = "10.0.0.0/8".parse().unwrap();
1544 let network2 = "172.16.0.0/16".parse().unwrap();
1545 let network3 = "192.168.1.0/24".parse().unwrap();
1546 let network4 = "254.254.254.254/32".parse().unwrap();
1547 ip_range1.add(network1).add(network2);
1548 ip_range2.add(network3).add(network4);
1549
1550 let ip_range = ip_range1.intersect(&ip_range2);
1551 assert_eq!(ip_range.into_iter().count(), 0);
1552 }
1553
1554 #[test]
1555 fn intersect_joint1() {
1556 let mut ip_range1 = IpRange::new();
1557 let mut ip_range2 = IpRange::new();
1558 let network1 = "172.16.4.0/24".parse().unwrap();
1559 let network2 = "172.16.4.0/22".parse().unwrap();
1560 ip_range1.add(network1);
1561 ip_range2.add(network2);
1562
1563 let ip_range = ip_range1.intersect(&ip_range2);
1564 assert_eq!(ip_range.into_iter().count(), 1);
1565 assert_eq!(Some(network1), ip_range.get_network(24, "172.16.4.0"));
1566 }
1567
1568 #[test]
1569 fn intersect_joint2() {
1570 let mut ip_range1 = IpRange::new();
1571 let mut ip_range2 = IpRange::new();
1572 let network1 = "172.16.5.0/24".parse().unwrap();
1573 let network2 = "172.16.4.0/22".parse().unwrap();
1574 ip_range1.add(network1);
1575 ip_range2.add(network2);
1576
1577 let ip_range = ip_range1.intersect(&ip_range2);
1578 assert_eq!(ip_range.into_iter().count(), 1);
1579 assert_eq!(Some(network1), ip_range.get_network(24, "172.16.5.0"));
1580 }
1581
1582 #[test]
1583 fn intersect_joint3() {
1584 let mut ip_range1 = IpRange::new();
1585 let mut ip_range2 = IpRange::new();
1586 let network1 = "172.16.5.0/24".parse().unwrap();
1587 let network2 = "172.16.5.0/24".parse().unwrap();
1588 ip_range1.add(network1);
1589 ip_range2.add(network2);
1590
1591 let ip_range = ip_range1.intersect(&ip_range2);
1592 assert_eq!(ip_range.into_iter().count(), 1);
1593 assert_eq!(Some(network1), ip_range.get_network(24, "172.16.5.0"));
1594 }
1595
1596 #[test]
1597 fn intersect_joint4() {
1598 let mut ip_range1 = IpRange::new();
1599 let mut ip_range2 = IpRange::new();
1600 let network1 = "10.0.0.0/8".parse().unwrap();
1601 let network2 = "192.168.0.0/24".parse().unwrap();
1602 let network3 = "10.10.0.0/16".parse().unwrap();
1603 let network4 = "10.254.0.0/17".parse().unwrap();
1604 let network5 = "192.168.0.0/16".parse().unwrap();
1605 ip_range1.add(network1).add(network2);
1606 ip_range2.add(network3).add(network4).add(network5);
1607
1608 let ip_range = ip_range1.intersect(&ip_range2);
1609 assert_eq!(ip_range.into_iter().count(), 3);
1610 assert_eq!(Some(network3), ip_range.get_network(16, "10.10.0.0"));
1611 assert_eq!(Some(network4), ip_range.get_network(17, "10.254.0.0"));
1612 assert_eq!(Some(network2), ip_range.get_network(24, "192.168.0.0"));
1613 }
1614
1615 #[test]
1616 fn exclude_disjoint() {
1617 let mut ip_range1 = IpRange::new();
1618 let mut ip_range2 = IpRange::new();
1619 let network1: Ipv4Net = "10.0.0.0/8".parse().unwrap();
1620 let network2 = "172.16.0.0/16".parse().unwrap();
1621 let network3 = "192.168.1.0/24".parse().unwrap();
1622 let network4 = "254.254.254.254/32".parse().unwrap();
1623 ip_range1.add(network1).add(network2);
1624 ip_range2.add(network3).add(network4);
1625
1626 let ip_range = ip_range1.exclude(&ip_range2);
1627 assert_eq!(ip_range1, ip_range);
1628 }
1629
1630 #[test]
1631 fn exclude_larger() {
1632 let mut ip_range1 = IpRange::new();
1633 let mut ip_range2 = IpRange::new();
1634 let network1: Ipv4Net = "172.16.4.0/24".parse().unwrap();
1635 let network2 = "192.168.1.0/24".parse().unwrap();
1636 let network3 = "172.16.4.0/22".parse().unwrap();
1637 ip_range1.add(network1).add(network2);
1638 ip_range2.add(network3);
1639
1640 let ip_range = ip_range1.exclude(&ip_range2);
1641 assert_eq!(ip_range.into_iter().count(), 1);
1642 assert_eq!(Some(network2), ip_range.get_network(24, "192.168.1.0"));
1643 }
1644
1645 #[test]
1646 fn exclude_identical() {
1647 let mut ip_range1 = IpRange::new();
1648 let mut ip_range2 = IpRange::new();
1649 let network1: Ipv4Net = "172.16.5.0/24".parse().unwrap();
1650 let network2 = "192.168.1.0/24".parse().unwrap();
1651 let network3 = "172.16.4.0/22".parse().unwrap();
1652 let network4 = "10.0.0.0/8".parse().unwrap();
1653
1654 ip_range1.add(network1).add(network2);
1655 ip_range2.add(network3).add(network4);
1656
1657 let ip_range = ip_range1.exclude(&ip_range2);
1658 assert_eq!(ip_range.into_iter().count(), 1);
1659 assert_eq!(Some(network2), ip_range.get_network(24, "192.168.1.0"));
1660 }
1661
1662 #[test]
1663 fn exclude_split1() {
1664 let mut ip_range1 = IpRange::new();
1665 let mut ip_range2 = IpRange::new();
1666 let network1: Ipv4Net = "172.16.4.0/22".parse().unwrap();
1667 let network2 = "192.168.1.0/24".parse().unwrap();
1668 let network3 = "172.16.5.0/24".parse().unwrap();
1669 let network4 = "10.0.0.0/8".parse().unwrap();
1670
1671 ip_range1.add(network1).add(network2);
1672 ip_range2.add(network3).add(network4);
1673
1674 let ip_range = ip_range1.exclude(&ip_range2);
1675 assert_eq!(ip_range.into_iter().count(), 3);
1676 assert_eq!(Some(network2), ip_range.get_network(24, "192.168.1.0"));
1677 assert_eq!(
1678 "172.16.4.0/24".parse().ok(),
1679 ip_range.get_network(24, "172.16.4.0")
1680 );
1681 assert_eq!(
1682 "172.16.6.0/23".parse().ok(),
1683 ip_range.get_network(23, "172.16.6.0")
1684 );
1685 }
1686
1687 #[test]
1688 fn exclude_split2() {
1689 let mut ip_range1 = IpRange::new();
1690 let mut ip_range2 = IpRange::new();
1691 let network1: Ipv4Net = "172.16.4.0/22".parse().unwrap();
1692 let network2 = "192.168.1.0/24".parse().unwrap();
1693 let network3 = "172.16.4.0/24".parse().unwrap();
1694 let network4 = "10.0.0.0/8".parse().unwrap();
1695
1696 ip_range1.add(network1).add(network2);
1697 ip_range2.add(network3).add(network4);
1698
1699 let ip_range = ip_range1.exclude(&ip_range2);
1700 assert_eq!(ip_range.into_iter().count(), 3);
1701 assert_eq!(Some(network2), ip_range.get_network(24, "192.168.1.0"));
1702 assert_eq!(
1703 "172.16.5.0/24".parse().ok(),
1704 ip_range.get_network(24, "172.16.5.0")
1705 );
1706 assert_eq!(
1707 "172.16.6.0/23".parse().ok(),
1708 ip_range.get_network(23, "172.16.6.0")
1709 );
1710 }
1711
1712 #[test]
1713 fn iter_ipv4() {
1714 let mut data = vec!["1.0.1.0/24", "1.0.2.0/23", "1.0.8.0/21"];
1715 let ip_range: IpRange<Ipv4Net> = data.iter().map(|net| net.parse().unwrap()).collect();
1716 let mut nets: Vec<String> = ip_range.iter().map(|net| format!("{}", net)).collect();
1717 data.sort_unstable();
1718 nets.sort_unstable();
1719 assert_eq!(nets, data);
1720 }
1721
1722 #[test]
1723 fn iter_ipv6() {
1724 let mut data = vec![
1725 "2400:9a40::/32",
1726 "2400:9dc0::/32",
1727 "2400:9e00::/32",
1728 "2400:a040::/32",
1729 ];
1730 let ip_range: IpRange<Ipv6Net> = data.iter().map(|net| net.parse().unwrap()).collect();
1731 let mut nets: Vec<String> = ip_range.iter().map(|net| format!("{}", net)).collect();
1732 data.sort_unstable();
1733 nets.sort_unstable();
1734 assert_eq!(nets, data);
1735 }
1736
1737 #[test]
1738 fn debug_fmt() {
1739 let ip_range: IpRange<Ipv4Net> = IpRange::default();
1740 assert_eq!(format!("{:?}", ip_range), "IpRange []");
1741
1742 let ip_range: IpRange<Ipv4Net> = ["1.0.1.0/24", "1.0.2.0/23", "1.0.8.0/21"]
1743 .iter()
1744 .map(|net| net.parse().unwrap())
1745 .collect();
1746 assert_eq!(
1747 format!("{:?}", ip_range),
1748 "IpRange [1.0.8.0/21, 1.0.2.0/23, 1.0.1.0/24]"
1749 );
1750
1751 let ip_range: IpRange<Ipv4Net> = [
1752 "192.168.0.0/16",
1753 "1.0.2.0/23",
1754 "1.0.8.0/21",
1755 "127.0.0.0/8",
1756 "172.16.0.0/12",
1757 ]
1758 .iter()
1759 .map(|net| net.parse().unwrap())
1760 .collect();
1761 assert_eq!(
1762 format!("{:?}", ip_range),
1763 "IpRange [127.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, ...]"
1764 );
1765
1766 let ip_range: IpRange<Ipv6Net> = [
1767 "2001:4438::/32",
1768 "2001:4510::/29",
1769 "2400:1040::/32",
1770 "2400:12c0::/32",
1771 "2400:1340::/32",
1772 "2400:1380::/32",
1773 "2400:15c0::/32",
1774 ]
1775 .iter()
1776 .map(|net| net.parse().unwrap())
1777 .collect();
1778 assert_eq!(
1779 format!("{:?}", ip_range),
1780 "IpRange [2001:4510::/29, 2001:4438::/32, 2400:1040::/32, ...]"
1781 );
1782 }
1783
1784 #[test]
1785 fn remove_all() {
1786 let mut ip_range = IpRange::new();
1787 let network: Ipv4Net = "1.0.1.0/24".parse().unwrap();
1788 ip_range.add(network);
1789 ip_range.remove(network);
1790 assert!(ip_range.iter().next().is_none());
1791 }
1792
1793 #[test]
1794 fn add_to_all_zeros() {
1795 let mut ip_range: IpRange<Ipv4Net> = IpRange::new();
1796 ip_range.add("0.0.0.0/0".parse().unwrap());
1797 ip_range.add("127.0.0.1/32".parse().unwrap());
1798 assert!(ip_range.contains_network("0.0.0.0/0"));
1799 }
1800
1801 #[test]
1802 #[cfg(feature = "serde")]
1803 fn serialize_ipv4_as_binary() {
1804 let mut ip_range: IpRange<Ipv4Net> = IpRange::new();
1805 ip_range.add("0.0.0.0/0".parse().unwrap());
1806 ip_range.add("127.0.0.1/32".parse().unwrap());
1807 ip_range.add("254.254.254.254/32".parse().unwrap());
1808 let encoded: Vec<u8> = bincode::serialize(&ip_range).unwrap();
1809 let decoded_ip_range: IpRange<Ipv4Net> = bincode::deserialize(&encoded[..]).unwrap();
1810 assert_eq!(ip_range, decoded_ip_range);
1811 }
1812
1813 #[test]
1814 #[cfg(feature = "serde")]
1815 fn serialize_ipv6_as_binary() {
1816 let mut ip_range: IpRange<Ipv6Net> = IpRange::new();
1817 ip_range.add("2001:4438::/32".parse().unwrap());
1818 ip_range.add("2400:1040::/32".parse().unwrap());
1819 ip_range.add("2400:1340::/32".parse().unwrap());
1820 let encoded: Vec<u8> = bincode::serialize(&ip_range).unwrap();
1821 let decoded_ip_range: IpRange<Ipv6Net> = bincode::deserialize(&encoded[..]).unwrap();
1822 assert_eq!(ip_range, decoded_ip_range);
1823 }
1824}