use anyhow::{Context, Result};
use bincode::{Decode, Encode, config};
use fst::MapBuilder;
use std::collections::BTreeMap;
use std::env;
use std::fs;
use std::fs::File;
use std::io::BufWriter;
use std::io::Write;
use std::io::{BufRead, BufReader};
use std::path::{Path, PathBuf};
use std::sync::Arc;
include!("compiler_logic.rs");
fn run() -> Result<()> {
let out_dir = env::var("OUT_DIR").context("Failed to get OUT_DIR environment variable")?;
let dest_path = Path::new(&out_dir);
let mut dict_map_builder = phf_codegen::Map::new();
let mut config_map_builder = phf_codegen::Map::new();
let dict_source_dir = PathBuf::from("assets/dictionaries");
if dict_source_dir.exists() {
let entries = fs::read_dir(&dict_source_dir)?;
for entry in entries {
let entry = entry?;
let path = entry.path();
if path.is_file() && path.extension().and_then(|s| s.to_str()) == Some("txt") {
let file_stem = path.file_stem().unwrap().to_str().unwrap();
let ocd2_key_name = format!("{file_stem}.ocd2");
let ocb_file_name = format!("{file_stem}.ocb");
let ocb_path = dest_path.join(&ocb_file_name);
let ocb_bytes = compile_dictionary(&path)?;
fs::write(&ocb_path, ocb_bytes)?;
let ocb_path_str = ocb_path.to_str().unwrap();
let value_code = format!("include_bytes!(r\"{ocb_path_str}\")");
dict_map_builder.entry(ocd2_key_name.clone(), &value_code);
}
}
}
let config_source_dir = PathBuf::from("assets/dictionaries");
let mut configs_to_add: Vec<(String, String)> = Vec::new();
if config_source_dir.exists() {
let entries = fs::read_dir(&config_source_dir)?;
for entry in entries {
let entry = entry?;
let path = entry.path();
if path.is_file() && path.extension().and_then(|s| s.to_str()) == Some("json") {
let file_name = path.file_name().unwrap().to_str().unwrap().to_string();
let content = fs::read_to_string(&path)?;
configs_to_add.push((file_name, content));
}
}
}
let formatted_config_values: Vec<String> = configs_to_add
.iter()
.map(|(_, content)| format!("r#\"{}\"#", content.trim()))
.collect();
for (i, (file_name, _)) in configs_to_add.iter().enumerate() {
config_map_builder.entry(file_name.clone(), &formatted_config_values[i]);
}
let generated_map_path = dest_path.join("embedded_map.rs");
let mut file = BufWriter::new(File::create(&generated_map_path)?);
writeln!(
&mut file,
"// @generated - This file is automatically generated by build.rs."
)?;
writeln!(
&mut file,
"pub static EMBEDDED_DICTS: phf::Map<&'static str, &'static [u8]> = {};",
dict_map_builder.build()
)?;
writeln!(
&mut file,
"pub static EMBEDDED_CONFIGS: phf::Map<&'static str, &'static str> = {};",
config_map_builder.build()
)?;
Ok(())
}
fn main() {
if let Err(e) = run() {
eprintln!("cargo:warning=Build script ferrous-opencc/build.rs failed: {e:?}");
std::process::exit(1);
}
}