use std::env;
use std::fs;
use std::path::{Path, PathBuf};
fn main() {
let out_dir = env::var("OUT_DIR").unwrap();
let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
let local_rules = PathBuf::from(&manifest_dir).join("rules");
let workspace_rules = PathBuf::from(&manifest_dir).join("../../rules");
let rules_dir = if local_rules.is_dir() {
local_rules
} else {
workspace_rules
.canonicalize()
.unwrap_or(workspace_rules)
};
println!("cargo:rerun-if-changed={}", rules_dir.display());
let mut base_entries = Vec::new();
let mut shopify_entries = Vec::new();
let mut woocommerce_entries = Vec::new();
if let Ok(entries) = fs::read_dir(&rules_dir) {
for entry in entries.flatten() {
let path = entry.path();
if path.is_file() && path.extension().map(|e| e == "toml").unwrap_or(false) {
println!("cargo:rerun-if-changed={}", path.display());
if let Some(name) = path.file_name().and_then(|n| n.to_str()) {
base_entries.push((name.to_string(), path.clone()));
}
}
}
}
collect_platform_rules(&rules_dir.join("shopify"), &mut shopify_entries);
collect_platform_rules(&rules_dir.join("woocommerce"), &mut woocommerce_entries);
base_entries.sort_by(|a, b| a.0.cmp(&b.0));
shopify_entries.sort_by(|a, b| a.0.cmp(&b.0));
woocommerce_entries.sort_by(|a, b| a.0.cmp(&b.0));
let mut code = String::new();
code.push_str("// Auto-generated by build.rs — do not edit\n\n");
code.push_str("/// Base validation rules embedded at compile time.\n");
code.push_str("/// These are loaded for all platforms as a fallback.\n");
code.push_str("pub const BASE_RULES: &[(&str, &str)] = &[\n");
for (name, path) in &base_entries {
code.push_str(&format!(
" (\"{}\", include_str!(\"{}\")),\n",
name,
path.display().to_string().replace('\\', "/")
));
}
code.push_str("];\n\n");
code.push_str("/// Shopify-specific validation rules embedded at compile time.\n");
code.push_str("pub const SHOPIFY_RULES: &[(&str, &str)] = &[\n");
for (name, path) in &shopify_entries {
code.push_str(&format!(
" (\"{}\", include_str!(\"{}\")),\n",
name,
path.display().to_string().replace('\\', "/")
));
}
code.push_str("];\n\n");
code.push_str("/// WooCommerce-specific validation rules embedded at compile time.\n");
code.push_str("pub const WOOCOMMERCE_RULES: &[(&str, &str)] = &[\n");
for (name, path) in &woocommerce_entries {
code.push_str(&format!(
" (\"{}\", include_str!(\"{}\")),\n",
name,
path.display().to_string().replace('\\', "/")
));
}
code.push_str("];\n");
let dest = Path::new(&out_dir).join("embedded_rules_gen.rs");
fs::write(&dest, code).expect("Failed to write generated embedded rules");
}
fn collect_platform_rules(dir: &Path, entries: &mut Vec<(String, PathBuf)>) {
if let Ok(dir_entries) = fs::read_dir(dir) {
println!("cargo:rerun-if-changed={}", dir.display());
for entry in dir_entries.flatten() {
let path = entry.path();
if path.is_file() && path.extension().map(|e| e == "toml").unwrap_or(false) {
println!("cargo:rerun-if-changed={}", path.display());
if let Some(name) = path.file_name().and_then(|n| n.to_str()) {
entries.push((name.to_string(), path.clone()));
}
}
}
}
}