use std::{env, path::PathBuf};
use quote::quote;
use regex::Regex;
#[derive(Debug, serde::Deserialize)]
struct Record {
country_code: String,
iban_format_swift: String,
iban_length: usize,
bban_bankid_start_offset: Option<usize>,
bban_bankid_stop_offset: Option<usize>,
bban_branchid_start_offset: Option<usize>,
bban_branchid_stop_offset: Option<usize>,
bban_checksum_start_offset: Option<usize>,
bban_checksum_stop_offset: Option<usize>,
}
fn main() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=registry.txt");
let mut reader = csv::ReaderBuilder::new()
.delimiter(b'|')
.has_headers(true)
.from_path("./registry.txt")
.expect("failed to create csv reader for registry.txt");
let pattern = Regex::new(r"(\d+)!(a|n|c|i)").expect("regex should be valid");
let countries = reader
.deserialize()
.map(|record| record.expect("valid record"))
.map(
|Record {
country_code,
iban_format_swift,
iban_length,
bban_bankid_start_offset,
bban_bankid_stop_offset,
bban_branchid_start_offset,
bban_branchid_stop_offset,
bban_checksum_start_offset,
bban_checksum_stop_offset,
}| {
let captures = pattern
.captures_iter(&iban_format_swift[2..])
.map(|captures| {
(
captures[1].parse::<usize>().unwrap(),
captures[2].parse::<char>().unwrap(),
)
})
.map(|(len, char)| quote! { (#len, #char) });
let captures = iban_format_swift[..2]
.as_bytes()
.iter()
.map(|byte| (1usize, char::from(*byte)))
.map(|(len, char)| quote! { (#len, #char) })
.chain(captures);
let bankid_offset = if let (Some(start), Some(end)) =
(bban_bankid_start_offset, bban_bankid_stop_offset)
{
quote! { Some((#start, #end + 1)) }
} else {
quote! { None }
};
let branch_offset = if let (Some(start), Some(end)) =
(bban_branchid_start_offset, bban_branchid_stop_offset)
{
quote! { Some((#start, #end + 1)) }
} else {
quote! { None }
};
let checksum_offset = if let (Some(start), Some(end)) =
(bban_checksum_start_offset, bban_checksum_stop_offset)
{
quote! { Some((#start, #end + 1)) }
} else {
quote! { None }
};
(
country_code,
quote! {
(
#iban_length,
&[#(#captures),*],
#bankid_offset,
#branch_offset,
#checksum_offset,
)
},
)
},
)
.collect::<Vec<_>>();
let mut map = phf_codegen::Map::new();
for (key, value) in &countries {
map.entry(key.as_str(), value.to_string().as_str());
}
let countries = map.build();
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
std::fs::write(
out_path.join("countries.rs"),
format!(
"#[allow(clippy::type_complexity, clippy::unreadable_literal, clippy::identity_op)]\nstatic COUNTRIES: ::phf::Map<&'static str, (usize, &'static [(usize, char)], Option<(usize, usize)>, Option<(usize, usize)>, Option<(usize, usize)>)> = {countries};\n",
),
)
.expect("failed to write countries file");
}