fire_scope/
ipv4_utils.rs

1use ipnet::{IpNet, Ipv4Net};
2use std::net::Ipv4Addr;
3
4/// u32用のヘルパートレイト。
5pub 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
19/// IPv4 の範囲 [current, end] の中で取れる最大のCIDRブロックサイズを求める。
20/// parse_ipv4.rs, overlap.rs で重複していたロジックを共通化。
21pub 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
28/// IPv4の開始~終了アドレスを最適なCIDRに分割して返す。
29pub 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}