cidr_utils/iterator/
v4.rs

1use std::net::Ipv4Addr;
2
3use cidr::Ipv4Cidr;
4
5use crate::Ipv4CidrSize;
6
7// TODO: Ipv4CidrU8ArrayIterator
8
9/// To iterate IPv4 CIDRs.
10#[derive(Debug)]
11pub struct Ipv4CidrU8ArrayIterator {
12    from: u32,
13    size: u64,
14    next: u64,
15    back: u64,
16}
17
18impl Ipv4CidrU8ArrayIterator {
19    #[inline]
20    pub fn new(cidr: &Ipv4Cidr) -> Self {
21        let from: u32 = cidr.first_address().into();
22        let size = cidr.size();
23
24        Self {
25            from,
26            size,
27            next: 0,
28            back: size,
29        }
30    }
31}
32
33impl Ipv4CidrU8ArrayIterator {
34    #[inline]
35    unsafe fn next_unchecked(&mut self) -> [u8; 4] {
36        let p = self.from + self.next as u32;
37
38        self.next += 1;
39
40        p.to_be_bytes()
41    }
42
43    #[inline]
44    unsafe fn next_back_unchecked(&mut self) -> [u8; 4] {
45        self.back -= 1;
46
47        let p = self.from + self.back as u32;
48
49        p.to_be_bytes()
50    }
51
52    #[inline]
53    pub fn nth_u64(&mut self, n: u64) -> Option<[u8; 4]> {
54        self.next += n;
55
56        if self.next < self.back {
57            Some(unsafe { self.next_unchecked() })
58        } else {
59            self.next = self.size;
60
61            None
62        }
63    }
64
65    #[inline]
66    pub fn nth_back_u64(&mut self, n: u64) -> Option<[u8; 4]> {
67        if self.back > n {
68            self.back -= n;
69
70            if self.next < self.back {
71                return Some(unsafe { self.next_back_unchecked() });
72            }
73        }
74
75        self.next = self.size;
76
77        None
78    }
79}
80
81impl Iterator for Ipv4CidrU8ArrayIterator {
82    type Item = [u8; 4];
83
84    #[inline]
85    fn next(&mut self) -> Option<Self::Item> {
86        if self.next < self.back {
87            Some(unsafe { self.next_unchecked() })
88        } else {
89            None
90        }
91    }
92
93    #[cfg(not(any(
94        target_pointer_width = "8",
95        target_pointer_width = "16",
96        target_pointer_width = "32"
97    )))]
98    #[inline]
99    fn size_hint(&self) -> (usize, Option<usize>) {
100        let remaining_ips = (self.back - self.next) as usize;
101
102        (remaining_ips, Some(remaining_ips))
103    }
104
105    #[cfg(not(any(
106        target_pointer_width = "8",
107        target_pointer_width = "16",
108        target_pointer_width = "32"
109    )))]
110    #[inline]
111    fn count(self) -> usize
112    where
113        Self: Sized, {
114        if self.next < self.back {
115            (self.back - self.next) as usize
116        } else {
117            0
118        }
119    }
120
121    #[inline]
122    fn last(mut self) -> Option<Self::Item> {
123        if self.next < self.back {
124            self.next = self.back - 1;
125
126            Some(unsafe { self.next_unchecked() })
127        } else {
128            None
129        }
130    }
131
132    #[inline]
133    fn nth(&mut self, n: usize) -> Option<Self::Item> {
134        self.nth_u64(n as u64)
135    }
136}
137
138impl DoubleEndedIterator for Ipv4CidrU8ArrayIterator {
139    #[inline]
140    fn next_back(&mut self) -> Option<Self::Item> {
141        if self.next < self.back {
142            Some(unsafe { self.next_back_unchecked() })
143        } else {
144            None
145        }
146    }
147
148    #[inline]
149    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
150        self.nth_back_u64(n as u64)
151    }
152}
153
154// TODO: Ipv4CidrIterator
155
156/// To iterate IPv4 CIDRs.
157#[derive(Debug)]
158pub struct Ipv4CidrIterator {
159    iter: Ipv4CidrU8ArrayIterator,
160}
161
162impl Ipv4CidrIterator {
163    #[inline]
164    pub fn new(cidr: &Ipv4Cidr) -> Self {
165        Self {
166            iter: Ipv4CidrU8ArrayIterator::new(cidr)
167        }
168    }
169}
170
171impl Ipv4CidrIterator {
172    #[inline]
173    pub fn nth_u64(&mut self, n: u64) -> Option<u32> {
174        self.iter.nth_u64(n).map(u32::from_be_bytes)
175    }
176}
177
178impl Iterator for Ipv4CidrIterator {
179    type Item = u32;
180
181    #[inline]
182    fn next(&mut self) -> Option<Self::Item> {
183        self.iter.next().map(u32::from_be_bytes)
184    }
185
186    #[inline]
187    fn last(self) -> Option<Self::Item> {
188        self.iter.last().map(u32::from_be_bytes)
189    }
190
191    #[inline]
192    fn nth(&mut self, n: usize) -> Option<Self::Item> {
193        self.iter.nth(n).map(u32::from_be_bytes)
194    }
195}
196
197impl DoubleEndedIterator for Ipv4CidrIterator {
198    #[inline]
199    fn next_back(&mut self) -> Option<Self::Item> {
200        self.iter.next_back().map(u32::from_be_bytes)
201    }
202
203    #[inline]
204    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
205        self.iter.nth_back(n).map(u32::from_be_bytes)
206    }
207}
208
209// TODO: Ipv4CidrIpv4AddrIterator
210
211/// To iterate IPv4 CIDRs.
212#[derive(Debug)]
213pub struct Ipv4CidrIpv4AddrIterator {
214    iter: Ipv4CidrU8ArrayIterator,
215}
216
217impl Ipv4CidrIpv4AddrIterator {
218    #[inline]
219    pub fn new(cidr: &Ipv4Cidr) -> Self {
220        Self {
221            iter: Ipv4CidrU8ArrayIterator::new(cidr)
222        }
223    }
224}
225
226impl Ipv4CidrIpv4AddrIterator {
227    #[inline]
228    pub fn nth_u64(&mut self, n: u64) -> Option<Ipv4Addr> {
229        self.iter.nth_u64(n).map(|a| a.into())
230    }
231}
232
233impl Iterator for Ipv4CidrIpv4AddrIterator {
234    type Item = Ipv4Addr;
235
236    #[inline]
237    fn next(&mut self) -> Option<Self::Item> {
238        self.iter.next().map(|a| a.into())
239    }
240
241    #[inline]
242    fn last(self) -> Option<Self::Item> {
243        self.iter.last().map(|a| a.into())
244    }
245
246    #[inline]
247    fn nth(&mut self, n: usize) -> Option<Self::Item> {
248        self.iter.nth(n).map(|a| a.into())
249    }
250}
251
252impl DoubleEndedIterator for Ipv4CidrIpv4AddrIterator {
253    #[inline]
254    fn next_back(&mut self) -> Option<Self::Item> {
255        self.iter.next_back().map(|a| a.into())
256    }
257
258    #[inline]
259    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
260        self.iter.nth_back(n).map(|a| a.into())
261    }
262}