1#![allow(clippy::bool_comparison)]
3
4use bitstring::BitString;
5
6#[derive(Clone, Debug)]
9pub struct IterInclusive<K> {
10 first: K, last: K, shared_len: usize, }
22
23impl<K> IterInclusive<K>
24where
25 K: BitString + Clone,
26{
27 fn empty() -> Self {
28 Self {
29 first: K::null(),
30 last: K::null(),
31 shared_len: 1,
32 }
33 }
34
35 fn all() -> Self {
36 Self {
37 first: K::null(),
38 last: K::null(),
39 shared_len: 0,
40 }
41 }
42}
43
44impl<K> Default for IterInclusive<K>
45where
46 K: BitString + Clone,
47{
48 fn default() -> Self {
49 Self::empty()
50 }
51}
52
53impl<K> Iterator for IterInclusive<K>
54where
55 K: BitString + Clone,
56{
57 type Item = K;
58
59 fn next(&mut self) -> Option<Self::Item> {
60 let first_len = self.first.len();
61 if self.shared_len > first_len {
62 return None;
63 }
64
65 if first_len == self.shared_len {
73 let last_len = self.last.len();
74 if last_len == self.shared_len {
75 self.shared_len = !0;
78 self.first.clip(0);
79 return Some(self.last.clone());
80 } else {
81 debug_assert!(
82 last_len == self.shared_len,
83 "first was shared prefix, but last was longer"
84 );
85 return None; }
87 }
88 let result = self.first.clone();
90 for pos in (self.shared_len + 1..first_len).rev() {
92 if false == self.first.get(pos) {
93 self.first.clip(pos + 1); self.first.flip(pos); return Some(result);
97 }
98 }
99
100 if true == self.first.get(self.shared_len) {
102 debug_assert!(
103 !self.first.get(self.shared_len),
104 "first should have a '0' after shared prefix"
105 );
106 return None; }
108 if false == self.last.get(self.shared_len) {
109 debug_assert!(
110 self.last.get(self.shared_len),
111 "last should have a '1' after shared prefix"
112 );
113 return None; }
115
116 self.first = self.last.clone();
118 let check_from = self.shared_len + 1; self.shared_len = self.last.len(); for pos in check_from..self.shared_len {
121 if self.first.get(pos) {
122 self.first.clip(pos + 1);
124 self.first.flip(pos);
125 self.shared_len = pos;
126 break;
127 }
128 }
129
130 Some(result)
131 }
132}
133
134pub fn iter_inclusive<K>(mut first: K, mut last: K) -> IterInclusive<K>
142where
143 K: BitString + Clone,
144{
145 let mut first_len = first.len();
151 while first_len > 0 && false == first.get(first_len - 1) {
152 first_len -= 1;
153 }
154 first.clip(first_len);
155
156 let mut last_len = last.len();
158 while last_len > 0 && true == last.get(last_len - 1) {
159 last_len -= 1;
160 }
161 last.clip(last_len);
162
163 let mut shared_len = first.shared_prefix_len(&last);
164
165 if shared_len == first_len {
166 while shared_len < last_len && false == last.get(shared_len) {
168 shared_len += 1;
169 }
170 first = last.clone();
172
173 if shared_len == last_len {
174 first.clip(shared_len);
176 } else {
177 first.clip(shared_len + 1);
179 first.flip(shared_len);
180 }
181 } else if shared_len == last_len {
182 while shared_len < first_len && true == first.get(shared_len) {
184 shared_len += 1;
185 }
186 last = first.clone();
188
189 if shared_len == first_len {
190 last.clip(shared_len);
192 } else {
193 last.clip(shared_len + 1);
195 last.flip(shared_len);
196 }
197 } else if first.get(shared_len) > last.get(shared_len) {
198 return IterInclusive::empty();
200 }
201 IterInclusive {
202 first,
203 last,
204 shared_len,
205 }
206}
207
208#[derive(Clone, Debug)]
212pub struct IterBetween<K> {
213 range: IterInclusive<K>,
214}
215
216impl<K> Default for IterBetween<K>
217where
218 K: BitString + Clone,
219{
220 fn default() -> Self {
221 Self {
222 range: IterInclusive::empty(),
223 }
224 }
225}
226
227impl<K> Iterator for IterBetween<K>
228where
229 K: BitString + Clone,
230{
231 type Item = K;
232
233 #[inline]
234 fn next(&mut self) -> Option<Self::Item> {
235 self.range.next()
236 }
237}
238
239fn increment<K>(key: &mut K) -> bool
240where
241 K: BitString + Clone,
242{
243 for pos in (0..key.len()).rev() {
245 if false == key.get(pos) {
246 key.clip(pos + 1);
247 key.flip(pos);
248 return true;
249 }
250 }
251 false
253}
254
255fn decrement<K>(key: &mut K) -> bool
256where
257 K: BitString + Clone,
258{
259 for pos in (0..key.len()).rev() {
261 if true == key.get(pos) {
262 key.clip(pos + 1);
263 key.flip(pos);
264 return true;
265 }
266 }
267 false
269}
270
271pub fn iter_between<K>(mut after: Option<K>, mut before: Option<K>) -> IterBetween<K>
275where
276 K: BitString + Clone,
277{
278 if let Some(start) = after.as_mut() {
279 if !increment(start) {
280 return IterBetween {
281 range: IterInclusive::empty(),
282 };
283 }
284 }
285 if let Some(end) = before.as_mut() {
286 if !decrement(end) {
287 return IterBetween {
288 range: IterInclusive::empty(),
289 };
290 }
291 }
292
293 let range = match (after, before) {
294 (Some(first), Some(last)) => iter_inclusive(first, last),
295 (Some(first), None) => {
296 let mut last = first.clone();
297 for pos in 0..last.len() {
299 if false == last.get(pos) {
300 last.clip(pos + 1);
301 last.flip(pos);
302 break;
303 }
304 }
305 iter_inclusive(first, last)
306 },
307 (None, Some(last)) => {
308 let mut first = last.clone();
309 for pos in 0..first.len() {
311 if true == first.get(pos) {
312 first.clip(pos + 1);
313 first.flip(pos);
314 break;
315 }
316 }
317 iter_inclusive(first, last)
318 },
319 (None, None) => IterInclusive::all(),
320 };
321 IterBetween { range }
322}
323
324#[cfg(test)]
325mod tests {
326 use super::iter_inclusive;
327 use alloc::vec::Vec;
328 use bitstring::BitLengthString;
329 use core::net::{
330 Ipv4Addr,
331 Ipv6Addr,
332 };
333
334 type Ipv4Cidr = BitLengthString<Ipv4Addr>;
335 type Ipv6Cidr = BitLengthString<Ipv6Addr>;
336
337 fn c4(a: &str, net: usize) -> Ipv4Cidr {
338 Ipv4Cidr::new(a.parse().unwrap(), net)
339 }
340
341 fn c6(a: &str, net: usize) -> Ipv6Cidr {
342 Ipv6Cidr::new(a.parse().unwrap(), net)
343 }
344
345 #[test]
346 fn testv4_1() {
347 assert_eq!(
348 iter_inclusive(c4("192.168.0.6", 32), c4("192.168.0.6", 32)).collect::<Vec<_>>(),
349 alloc::vec![c4("192.168.0.6", 32),]
350 );
351 }
352
353 #[test]
354 fn testv6_1() {
355 assert_eq!(
356 iter_inclusive(c6("::f0:4", 128), c6("::f0:10", 128)).collect::<Vec<_>>(),
357 alloc::vec![c6("::f0:4", 126), c6("::f0:8", 125), c6("::f0:10", 128),]
358 );
359 }
360}