#[cfg(not(feature = "_dev_build_fresh"))]
fn main() {
println!("cargo:rerun-if-changed=build.rs");
}
#[cfg(feature = "_dev_build_fresh")]
fn main() {
use std::fs;
println!("cargo:rerun-if-changed=build.rs");
let iso3166_rs = generate_iso3166(RawCsvIso3166::from_csv_file());
let iata_rs = generate_iata_city(RawCsvIata::from_csv_file());
#[cfg(feature = "feat-build-fresh")]
{
use std::env;
let out_dir = env::var("OUT_DIR").expect("Failed to get OUT_DIR");
fs::write(format!("{out_dir}/iso3166.rs"), iso3166_rs)
.expect("Failed to write generated ISO 3166 file");
fs::write(format!("{out_dir}/iata.rs"), iata_rs)
.expect("Failed to write generated IATA file");
}
#[cfg(not(feature = "feat-build-fresh"))]
{
use std::process;
fs::write("./src/iso3166.rs", iso3166_rs).expect("Failed to write generated ISO 3166 file");
fs::write("./src/iata.rs", iata_rs).expect("Failed to write generated IATA file");
process::Command::new("rustfmt")
.arg("./src/iso3166.rs")
.arg("./src/iata.rs")
.status()
.expect("Failed to format the file");
}
}
#[cfg(feature = "_dev_build_fresh")]
fn generate_iso3166(iso3166s: Vec<RawCsvIso3166>) -> String {
use std::fmt::Write as _;
use std::fs;
println!("cargo:rerun-if-changed=template/iso3166.rs");
let mut generated =
fs::read_to_string("template/iso3166.rs").expect("Failed to read ISO 3166 template file");
generated.push_str("\nmapping! {\n");
for RawCsvIso3166 {
alpha_2_code,
alpha_3_code,
numeric_code,
independent: _,
short_name_en,
short_name_uppercase_en,
full_name_en,
short_name_zh,
} in iso3166s
{
generated
.write_fmt(format_args!(
" {alpha_2_code} {alpha_3_code} => {numeric_code}, {short_name_en:?}, \
{short_name_uppercase_en:?}, {full_name_en:?}, {short_name_zh:?};\n"
))
.expect("`write_fmt` failed");
}
generated.push_str("}\n");
generated
}
#[cfg(feature = "_dev_build_fresh")]
#[derive(serde_derive::Deserialize)]
struct RawCsvIso3166 {
alpha_2_code: String,
alpha_3_code: String,
numeric_code: u16,
#[allow(unused)]
independent: String,
short_name_en: Option<String>,
short_name_uppercase_en: Option<String>,
full_name_en: Option<String>,
short_name_zh: Option<String>,
}
#[cfg(feature = "_dev_build_fresh")]
impl RawCsvIso3166 {
fn from_csv_file() -> Vec<Self> {
let path = std::env::var("LOCODE_RAW_ISO3166_CSV").ok();
let mut rdr = csv::ReaderBuilder::new()
.has_headers(true)
.from_path(
path.as_deref()
.unwrap_or("data/locode-raw-iso3166/country-codes-with-cn.csv"),
)
.expect("Failed to read CSV file");
rdr.deserialize()
.map(|result| result.expect("Failed to deserialize CSV row"))
.collect()
}
}
#[cfg(feature = "_dev_build_fresh")]
fn generate_iata_city(mut items: Vec<RawCsvIata>) -> String {
use std::fmt::Write as _;
use std::fs;
println!("cargo:rerun-if-changed=template/iata.rs");
let mut generated =
fs::read_to_string("template/iata.rs").expect("Failed to read IATA template file");
items.sort_unstable_by(|l, r| l.city_code.cmp(&r.city_code));
items.dedup_by(|l, r| l.city_code.eq(&r.city_code));
generated.push_str("\nmapping! {\n");
for RawCsvIata {
time_zone,
city_code,
country,
city,
..
} in items
{
generated
.write_fmt(format_args!(
" {city_code} {country} => {city:?}, \"{time_zone}\";\n"
))
.expect("`write_fmt` failed");
}
generated.push_str("}\n");
generated
}
#[cfg(feature = "_dev_build_fresh")]
#[allow(unused)]
#[derive(serde_derive::Deserialize)]
struct RawCsvIata {
code: String,
icao: String,
name: String,
latitude: String,
longitude: String,
elevation: String,
url: Option<String>,
time_zone: String,
city_code: String,
country: String,
city: Option<String>,
state: Option<String>,
county: Option<String>,
r#type: String,
}
#[cfg(feature = "_dev_build_fresh")]
impl RawCsvIata {
fn from_csv_file() -> Vec<Self> {
let path = std::env::var("LOCODE_RAW_IATA_CSV").ok();
let mut rdr = csv::ReaderBuilder::new()
.has_headers(true)
.from_path(
path.as_deref()
.unwrap_or("data/locode-raw-airports/airports.csv"),
)
.expect("Failed to read CSV file");
rdr.deserialize()
.map(|result| result.expect("Failed to deserialize CSV row"))
.collect()
}
}