1use ipnet::{IpNet, Ipv4Net};
2use std::net::Ipv4Addr;
3
4pub trait ILog2Sub1 {
6 fn ilog2_sub1(&self) -> u32;
7}
8
9impl ILog2Sub1 for u32 {
10 fn ilog2_sub1(&self) -> u32 {
11 if *self == 0 {
12 0
13 } else {
14 31 - self.leading_zeros()
15 }
16 }
17}
18
19pub fn largest_ipv4_block(current: u32, end: u32) -> u8 {
22 let tz = current.trailing_zeros();
23 let span = (end - current + 1).ilog2_sub1();
24 let max_block = tz.min(span);
25 (32 - max_block) as u8
26}
27
28pub fn ipv4_summarize_range(start: u32, end: u32) -> Vec<IpNet> {
30 let mut cidrs = Vec::new();
31 let mut current = start;
32
33 while current <= end {
34 let max_size = largest_ipv4_block(current, end);
35 if let Ok(net) = Ipv4Net::new(Ipv4Addr::from(current), max_size) {
36 cidrs.push(IpNet::V4(net));
37 let block_size = 1u32 << (32 - max_size);
38 current = current.saturating_add(block_size);
39 } else {
40 break;
41 }
42 }
43
44 cidrs
45}