1use std::net::Ipv6Addr;
2
3use cidr::Ipv6Cidr;
4use num_bigint::BigUint;
5use num_traits::{One, ToPrimitive, Zero};
6
7use crate::Ipv6CidrSize;
8
9#[derive(Debug)]
13pub struct Ipv6CidrU8ArrayIterator {
14 from: u128,
15 size: BigUint,
16 next: BigUint,
17 back: BigUint,
18}
19
20impl Ipv6CidrU8ArrayIterator {
21 #[inline]
22 pub fn new(cidr: &Ipv6Cidr) -> Self {
23 let from: u128 = cidr.first_address().into();
24 let size = cidr.size();
25
26 Self {
27 from,
28 size: size.clone(),
29 next: BigUint::zero(),
30 back: size,
31 }
32 }
33}
34
35impl Ipv6CidrU8ArrayIterator {
36 #[inline]
37 unsafe fn next_unchecked(&mut self) -> [u8; 16] {
38 let p = self.from + self.next.to_u128().unwrap();
39
40 self.next += BigUint::one();
41
42 p.to_be_bytes()
43 }
44
45 #[inline]
46 unsafe fn next_back_unchecked(&mut self) -> [u8; 16] {
47 self.back -= BigUint::one();
48
49 let p = self.from + self.back.to_u128().unwrap();
50
51 p.to_be_bytes()
52 }
53
54 #[inline]
55 pub fn nth_big_uint(&mut self, n: BigUint) -> Option<[u8; 16]> {
56 self.next += n;
57
58 if self.next < self.back {
59 Some(unsafe { self.next_unchecked() })
60 } else {
61 self.next = self.size.clone();
62
63 None
64 }
65 }
66
67 #[inline]
68 pub fn nth_back_big_uint(&mut self, n: BigUint) -> Option<[u8; 16]> {
69 if self.back > n {
70 self.back -= n;
71
72 if self.next < self.back {
73 return Some(unsafe { self.next_back_unchecked() });
74 }
75 }
76
77 self.next = self.size.clone();
78
79 None
80 }
81}
82
83impl Iterator for Ipv6CidrU8ArrayIterator {
84 type Item = [u8; 16];
85
86 #[inline]
87 fn next(&mut self) -> Option<Self::Item> {
88 if self.next < self.back {
89 Some(unsafe { self.next_unchecked() })
90 } else {
91 None
92 }
93 }
94
95 #[inline]
96 fn last(mut self) -> Option<Self::Item> {
97 if self.next < self.back {
98 self.next = self.back.clone() - BigUint::one();
99
100 Some(unsafe { self.next_unchecked() })
101 } else {
102 None
103 }
104 }
105
106 #[inline]
107 fn nth(&mut self, n: usize) -> Option<Self::Item> {
108 self.nth_big_uint(BigUint::from(n))
109 }
110}
111
112impl DoubleEndedIterator for Ipv6CidrU8ArrayIterator {
113 #[inline]
114 fn next_back(&mut self) -> Option<Self::Item> {
115 if self.next < self.back {
116 Some(unsafe { self.next_back_unchecked() })
117 } else {
118 None
119 }
120 }
121
122 #[inline]
123 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
124 self.nth_back_big_uint(BigUint::from(n))
125 }
126}
127
128#[derive(Debug)]
132pub struct Ipv6CidrU16ArrayIterator {
133 from: u128,
134 next: BigUint,
135 back: BigUint,
136 size: BigUint,
137}
138
139impl Ipv6CidrU16ArrayIterator {
140 #[inline]
141 pub fn new(cidr: &Ipv6Cidr) -> Self {
142 let from: u128 = cidr.first_address().into();
143 let size = cidr.size();
144
145 Self {
146 from,
147 size: size.clone(),
148 next: BigUint::zero(),
149 back: size,
150 }
151 }
152}
153
154impl Ipv6CidrU16ArrayIterator {
155 #[inline]
156 unsafe fn next_unchecked(&mut self) -> [u16; 8] {
157 let p = self.from + self.next.to_u128().unwrap();
158
159 self.next += BigUint::one();
160
161 u128_to_u16_array(p)
162 }
163
164 #[inline]
165 unsafe fn next_back_unchecked(&mut self) -> [u16; 8] {
166 self.back -= BigUint::one();
167
168 let p = self.from + self.back.to_u128().unwrap();
169
170 u128_to_u16_array(p)
171 }
172
173 #[inline]
174 pub fn nth_big_uint(&mut self, n: BigUint) -> Option<[u16; 8]> {
175 self.next += n;
176
177 if self.next < self.back {
178 Some(unsafe { self.next_unchecked() })
179 } else {
180 self.next = self.size.clone();
181
182 None
183 }
184 }
185
186 #[inline]
187 pub fn nth_back_big_uint(&mut self, n: BigUint) -> Option<[u16; 8]> {
188 if self.back > n {
189 self.back -= n;
190
191 if self.next < self.back {
192 return Some(unsafe { self.next_back_unchecked() });
193 }
194 }
195
196 self.next = self.size.clone();
197
198 None
199 }
200}
201
202impl Iterator for Ipv6CidrU16ArrayIterator {
203 type Item = [u16; 8];
204
205 #[inline]
206 fn next(&mut self) -> Option<Self::Item> {
207 if self.next < self.back {
208 Some(unsafe { self.next_unchecked() })
209 } else {
210 None
211 }
212 }
213
214 #[inline]
215 fn last(mut self) -> Option<Self::Item> {
216 if self.next < self.back {
217 self.next = self.back.clone() - BigUint::one();
218
219 Some(unsafe { self.next_unchecked() })
220 } else {
221 None
222 }
223 }
224
225 #[inline]
226 fn nth(&mut self, n: usize) -> Option<Self::Item> {
227 self.nth_big_uint(BigUint::from(n))
228 }
229}
230
231impl DoubleEndedIterator for Ipv6CidrU16ArrayIterator {
232 #[inline]
233 fn next_back(&mut self) -> Option<Self::Item> {
234 if self.next < self.back {
235 Some(unsafe { self.next_back_unchecked() })
236 } else {
237 None
238 }
239 }
240
241 #[inline]
242 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
243 self.nth_back_big_uint(BigUint::from(n))
244 }
245}
246
247#[derive(Debug)]
251pub struct Ipv6CidrIterator {
252 iter: Ipv6CidrU8ArrayIterator,
253}
254
255impl Ipv6CidrIterator {
256 #[inline]
257 pub fn new(cidr: &Ipv6Cidr) -> Self {
258 Self {
259 iter: Ipv6CidrU8ArrayIterator::new(cidr)
260 }
261 }
262}
263
264impl Ipv6CidrIterator {
265 #[inline]
266 pub fn nth_big_uint(&mut self, n: BigUint) -> Option<u128> {
267 self.iter.nth_big_uint(n).map(u128::from_be_bytes)
268 }
269
270 #[inline]
271 pub fn nth_back_big_uint(&mut self, n: BigUint) -> Option<u128> {
272 self.iter.nth_back_big_uint(n).map(u128::from_be_bytes)
273 }
274}
275
276impl Iterator for Ipv6CidrIterator {
277 type Item = u128;
278
279 #[inline]
280 fn next(&mut self) -> Option<u128> {
281 self.iter.next().map(u128::from_be_bytes)
282 }
283
284 #[inline]
285 fn last(self) -> Option<u128> {
286 self.iter.last().map(u128::from_be_bytes)
287 }
288
289 #[inline]
290 fn nth(&mut self, n: usize) -> Option<u128> {
291 self.iter.nth(n).map(u128::from_be_bytes)
292 }
293}
294
295impl DoubleEndedIterator for Ipv6CidrIterator {
296 #[inline]
297 fn next_back(&mut self) -> Option<Self::Item> {
298 self.iter.next_back().map(u128::from_be_bytes)
299 }
300
301 #[inline]
302 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
303 self.iter.nth_back(n).map(u128::from_be_bytes)
304 }
305}
306
307#[derive(Debug)]
311pub struct Ipv6CidrIpv6AddrIterator {
312 iter: Ipv6CidrU16ArrayIterator,
313}
314
315impl Ipv6CidrIpv6AddrIterator {
316 #[inline]
317 pub fn new(cidr: &Ipv6Cidr) -> Self {
318 Self {
319 iter: Ipv6CidrU16ArrayIterator::new(cidr)
320 }
321 }
322}
323
324impl Ipv6CidrIpv6AddrIterator {
325 #[inline]
326 pub fn nth_big_uint(&mut self, n: BigUint) -> Option<Ipv6Addr> {
327 self.iter
328 .nth_big_uint(n)
329 .map(|a| Ipv6Addr::new(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]))
330 }
331
332 #[inline]
333 pub fn nth_back_big_int(&mut self, n: BigUint) -> Option<Ipv6Addr> {
334 self.iter
335 .nth_back_big_uint(n)
336 .map(|a| Ipv6Addr::new(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]))
337 }
338}
339
340impl Iterator for Ipv6CidrIpv6AddrIterator {
341 type Item = Ipv6Addr;
342
343 #[inline]
344 fn next(&mut self) -> Option<Ipv6Addr> {
345 self.iter.next().map(|a| Ipv6Addr::new(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]))
346 }
347
348 #[inline]
349 fn last(self) -> Option<Ipv6Addr> {
350 self.iter.last().map(|a| Ipv6Addr::new(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]))
351 }
352
353 #[inline]
354 fn nth(&mut self, n: usize) -> Option<Ipv6Addr> {
355 self.iter.nth(n).map(|a| Ipv6Addr::new(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]))
356 }
357}
358
359impl DoubleEndedIterator for Ipv6CidrIpv6AddrIterator {
360 #[inline]
361 fn next_back(&mut self) -> Option<Self::Item> {
362 self.iter.next_back().map(|a| Ipv6Addr::new(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]))
363 }
364
365 #[inline]
366 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
367 self.iter.nth_back(n).map(|a| Ipv6Addr::new(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]))
368 }
369}
370
371fn u128_to_u16_array(uint128: u128) -> [u16; 8] {
372 let a = uint128.to_be_bytes();
373
374 let mut o = [0; 8];
375
376 for (i, e) in o.iter_mut().enumerate() {
377 let ii = i * 2;
378
379 *e = a[ii] as u16 * 256 + a[ii + 1] as u16;
380 }
381
382 o
383}