cidr_utils/combiner/
v6.rs1use core::ops::Deref;
2use std::net::Ipv6Addr;
3
4use cidr::Ipv6Cidr;
5use num_bigint::BigUint;
6use num_traits::Zero;
7
8use crate::Ipv6CidrSize;
9
10#[derive(Debug, Clone)]
12pub struct Ipv6CidrCombiner(Vec<Ipv6Cidr>);
13
14impl Default for Ipv6CidrCombiner {
15 #[inline]
16 fn default() -> Self {
17 Ipv6CidrCombiner::new()
18 }
19}
20
21impl Deref for Ipv6CidrCombiner {
22 type Target = Vec<Ipv6Cidr>;
23
24 #[inline]
25 fn deref(&self) -> &Vec<Ipv6Cidr> {
26 &self.0
27 }
28}
29
30impl Ipv6CidrCombiner {
31 #[inline]
33 pub const fn new() -> Ipv6CidrCombiner {
34 Ipv6CidrCombiner(Vec::new())
35 }
36
37 #[inline]
39 pub fn with_capacity(capacity: usize) -> Ipv6CidrCombiner {
40 Ipv6CidrCombiner(Vec::with_capacity(capacity))
41 }
42
43 #[inline]
49 pub const unsafe fn from_ipv6_cidr_vec_unchecked(cidr_vec: Vec<Ipv6Cidr>) -> Ipv6CidrCombiner {
50 Ipv6CidrCombiner(cidr_vec)
51 }
52
53 #[inline]
54 pub fn into_ipv6_cidr_vec(self) -> Vec<Ipv6Cidr> {
55 self.0
56 }
57}
58
59impl Ipv6CidrCombiner {
60 pub fn push(&mut self, mut cidr: Ipv6Cidr) {
62 if let Err(mut index) = self.0.binary_search(&cidr) {
63 if self.0.is_empty() {
64 self.0.push(cidr);
65 } else {
66 let pushable = if index == 0 {
67 true
68 } else {
69 let previous_cidr = self.0.get(index - 1).unwrap();
70
71 !previous_cidr.contains(&cidr.first_address())
72 };
73
74 if pushable {
75 loop {
76 if index == self.0.len() {
77 break;
78 }
79
80 let next = self.0.get(index).unwrap();
81
82 if cidr.contains(&next.first_address()) {
83 self.0.remove(index);
84 } else {
85 break;
86 }
87 }
88
89 let mut merging = true;
90
91 while merging {
92 merging = false;
93
94 if index < self.0.len() {
95 let next_cidr = self.0.get(index).unwrap();
96
97 let next_bits = next_cidr.network_length();
98 let bits = cidr.network_length();
99
100 if bits == next_bits {
101 let next_prefix: u128 = next_cidr.first_address().into();
102 let prefix: u128 = cidr.first_address().into();
103
104 let d = next_prefix ^ prefix;
105
106 if d == 1 << (128 - bits) as u128 {
107 cidr = Ipv6Cidr::new(prefix.into(), bits - 1).unwrap();
108
109 self.0.remove(index);
110
111 merging = true;
112 }
113 }
114 }
115
116 if index > 0 {
117 let index_dec = index - 1;
118
119 let previous_cidr = self.0.get_mut(index_dec).unwrap();
120
121 let previous_bits = previous_cidr.network_length();
122 let bits = cidr.network_length();
123
124 if bits == previous_bits {
125 let previous_prefix: u128 = previous_cidr.first_address().into();
126 let prefix: u128 = cidr.first_address().into();
127
128 let d = prefix ^ previous_prefix;
129
130 if d == 1 << (128 - bits) as u128 {
131 self.0.remove(index_dec);
132
133 index = index_dec;
134
135 cidr = Ipv6Cidr::new(previous_prefix.into(), previous_bits - 1)
136 .unwrap();
137
138 merging = true;
139 }
140 }
141 }
142 }
143
144 self.0.insert(index, cidr);
145 }
146 }
147 }
148 }
149
150 #[inline]
152 pub fn contains(&self, ipv6: &Ipv6Addr) -> bool {
153 for cidr in self.0.iter() {
154 if cidr.contains(ipv6) {
155 return true;
156 }
157 }
158
159 false
160 }
161
162 #[inline]
164 pub fn size(&self) -> BigUint {
165 let mut sum = BigUint::zero();
166
167 for cidr in self.0.iter() {
168 sum += cidr.size();
169 }
170
171 sum
172 }
173}