1use crate::parse_ipv4::largest_ipv4_block;
2use ipnet::{IpNet, Ipv4Net, Ipv6Net};
3use std::net::Ipv4Addr;
4
5pub fn parse_ip_lines(
7 text: &str,
8 country_code: &str,
9) -> Result<(Vec<IpNet>, Vec<IpNet>), Box<dyn std::error::Error + Send + Sync>> {
10 let mut ipv4_list = Vec::new();
11 let mut ipv6_list = Vec::new();
12 for line in text.lines() {
13 if line.starts_with('#') || line.contains('*') || line.contains("reserved") {
15 continue;
16 }
17 let params: Vec<&str> = line.split('|').collect();
18 if params.len() < 5 {
19 continue;
20 }
21 if params[1] != country_code {
23 continue;
24 }
25 let ip_type = params[2];
26 if ip_type == "ipv4" || ip_type == "ipv6" {
27 match parse_ip_params(¶ms) {
28 Ok(nets) => {
29 if ip_type == "ipv4" {
30 ipv4_list.extend(nets);
31 } else {
32 ipv6_list.extend(nets);
33 }
34 }
35 Err(e) => {
36 eprintln!("parse_ip_paramsでエラー: {}", e);
37 }
38 }
39 }
40 }
41 Ok((ipv4_list, ipv6_list))
42}
43
44fn parse_ip_params(
46 params: &[&str],
47) -> Result<Vec<IpNet>, Box<dyn std::error::Error + Send + Sync>> {
48 let ip_type = params[2];
49 let start_str = params[3];
50 let value_str = params[4];
51 if ip_type == "ipv4" {
52 parse_ipv4(start_str, value_str)
53 } else if ip_type == "ipv6" {
54 parse_ipv6(start_str, value_str)
55 } else {
56 Ok(vec![])
57 }
58}
59
60fn parse_ipv4(
62 start_str: &str,
63 value_str: &str,
64) -> Result<Vec<IpNet>, Box<dyn std::error::Error + Send + Sync>> {
65 let start_v4 = start_str.parse::<Ipv4Addr>()?;
66 let width = value_str.parse::<u64>()?;
67 let start_num = u32::from(start_v4);
68
69 let end_num = start_num
70 .checked_add(width as u32)
71 .ok_or("範囲が大きすぎます")?
72 .checked_sub(1)
73 .ok_or("計算エラー")?;
74
75 let mut cidrs = Vec::new();
76 let mut current = start_num;
77 while current <= end_num {
78 let max_size = largest_ipv4_block(current, end_num);
79 let net = Ipv4Net::new(Ipv4Addr::from(current), max_size)?;
80 cidrs.push(IpNet::V4(net));
81
82 let block_size = 1u32 << (32 - max_size);
83 current = current.saturating_add(block_size);
84 }
85 Ok(cidrs)
86}
87
88fn parse_ipv6(
90 start_str: &str,
91 value_str: &str,
92) -> Result<Vec<IpNet>, Box<dyn std::error::Error + Send + Sync>> {
93 let cidr_str = format!("{}/{}", start_str, value_str);
95 let net = cidr_str.parse::<Ipv6Net>()?;
96 Ok(vec![IpNet::V6(net)])
97}