cidr_utils/iterator/
v6.rs

1use std::net::Ipv6Addr;
2
3use cidr::Ipv6Cidr;
4use num_bigint::BigUint;
5use num_traits::{One, ToPrimitive, Zero};
6
7use crate::Ipv6CidrSize;
8
9// TODO: Ipv6CidrU8ArrayIterator
10
11/// To iterate IPv6 CIDRs.
12#[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// TODO: Ipv6CidrU8ArrayIterator
129
130/// To iterate IPv6 CIDRs.
131#[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// TODO: Ipv6CidrIterator
248
249/// To iterate IPv6 CIDRs.
250#[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// TODO: Ipv6CidrIpv6AddrIterator
308
309/// To iterate IPv4 CIDRs.
310#[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}