1use 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#[derive(Clone, PartialEq, Eq)]
86pub struct IpRange<N: IpNet> {
87 trie: IpTrie<N>,
89 phantom_net: PhantomData<N>,
90}
91
92impl<N: IpNet> IpRange<N> {
93 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 pub fn add(&mut self, network: N) -> &mut Self {
133 self.trie.insert(network);
134 self
135 }
136
137 pub fn remove(&mut self, network: N) -> &mut Self {
161 self.trie.remove(network);
162 self
163 }
164
165 pub fn is_empty(&self) -> bool {
180 self.trie.root.is_none()
181 }
182
183 pub fn simplify(&mut self) {
207 self.trie.simplify();
208 }
209
210 pub fn merge(&self, other: &IpRange<N>) -> Self {
215 self.into_iter().chain(other.into_iter()).collect()
216 }
217
218 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 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 pub fn contains<T: ToNetwork<N>>(&self, network: &T) -> bool {
245 self.supernet(&network.to_network()).is_some()
246 }
247
248 pub fn supernet<T: ToNetwork<N>>(&self, network: &T) -> Option<N> {
252 self.trie.search(network.to_network())
253 }
254
255 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
342pub trait IpNet: ToNetwork<Self> + fmt::Debug + Ord + Copy
344where
345 Self: Sized,
346{
347 type S: TraverseState<Net = Self>;
349 type I: Iterator<Item = bool>;
351
352 fn prefix_bits(&self) -> Self::I;
354
355 fn prefix_len(&self) -> u8;
357
358 fn with_new_prefix(&self, len: u8) -> Self;
360}
361
362pub trait ToNetwork<N: IpNet> {
368 fn to_network(&self) -> N;
369}
370
371pub struct IpRangeIter<'a, N>
377where
378 N: IpNet,
379{
380 queue: VecDeque<N::S>,
381 _phantom: PhantomData<&'a N>,
382}
383
384#[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 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 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 let mut node = if let Some(root) = &mut self.root {
471 if root.is_leaf() {
472 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 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 }
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.is_leaf() {
549 return;
550 }
551 }
552 }
553 self.root = None }
555
556 fn simplify(&mut self) {
557 if let Some(root) = self.root.as_mut() {
558 root.simplify();
559 }
560 }
561}
562
563#[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 #[inline]
586 fn is_leaf(&self) -> bool {
587 self.children[0].is_none() && self.children[1].is_none()
588 }
589
590 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 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 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 child.remove(bits, next_bit);
650 child.is_leaf()
651 } else {
652 false
653 };
654 if is_leaf {
661 self.children[i] = None;
662 }
663 }
664 None => {
665 self.children[i] = None;
667 }
668 }
669 }
670}
671
672const MSO_U128: u128 = 1 << 127; const MSO_U32: u32 = 1 << 31; impl 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}