fetch_ccip/
process.rs

1use crate::output::write_ip_lists_to_files;
2use crate::parse::parse_ip_lines;
3use ipnet::IpNet;
4use std::collections::BTreeSet;
5
6/// 指定された国コードと、ダウンロード済みのRIRファイル文字列から、
7/// IPアドレスをパースしてファイル書き込みまで実行する。
8pub async fn process_country_code(
9    country_code: &str,
10    rir_texts: &[String],
11    // 追記・上書きモードを受け取る引数を追加
12    mode: &str,
13) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
14    // パース結果をまとめる
15    // BTreeSetで重複排除+自動ソート
16    let (ipv4_set, ipv6_set) = parse_and_collect_ips(country_code, rir_texts)?;
17
18    // 結果をファイルに書き出す(mode引数を渡す)
19    write_ip_lists_to_files(country_code, &ipv4_set, &ipv6_set, mode)?;
20
21    Ok(())
22}
23
24/// 全RIRテキストから、指定国コードに合致するIPアドレスをすべて集約し、
25/// BTreeSetとして返す。
26fn parse_and_collect_ips(
27    country_code: &str,
28    rir_texts: &[String],
29) -> Result<(BTreeSet<IpNet>, BTreeSet<IpNet>), Box<dyn std::error::Error + Send + Sync>> {
30    let mut ipv4_vec = Vec::new();
31    let mut ipv6_vec = Vec::new();
32
33    for text in rir_texts {
34        match parse_ip_lines(text, country_code) {
35            Ok((v4, v6)) => {
36                ipv4_vec.extend(v4);
37                ipv6_vec.extend(v6);
38            }
39            Err(e) => {
40                eprintln!(
41                    "[parse_and_collect_ips] Error parsing for country code '{}': {}",
42                    country_code, e
43                );
44                // パース失敗時はスキップするが、必要に応じて Err で落としても良い。
45            }
46        }
47    }
48
49    // IpNetのOrd実装で昇順ソートされる
50    ipv4_vec.sort();
51    ipv6_vec.sort();
52
53    // BTreeSetに格納
54    // 重複排除 + 順序保持
55    let ipv4_set = ipv4_vec.into_iter().collect::<BTreeSet<IpNet>>();
56    let ipv6_set = ipv6_vec.into_iter().collect::<BTreeSet<IpNet>>();
57
58    Ok((ipv4_set, ipv6_set))
59}