use std::fs;
use std::path::Path;
const FREQUENCIES_BLAKE3: &str = "0652a53f8ac8b1989a3c0a6f7290af1d41d4b58cd960b77f879b38223ccd7b0d";
const HUFFMAN_CODES_BLAKE3: &str =
"523769a934a407aa87d9ddef37ad186c546e205cb1280b0e9300d6e98c6dad0e";
fn verify_blake3(path: &str, expected_hex: &str) -> Result<(), String> {
let bytes = fs::read(path).map_err(|e| format!("cannot read {}: {}", path, e))?;
let actual = blake3::hash(&bytes).to_hex();
if actual.as_str() != expected_hex {
return Err(format!(
"BLAKE3 mismatch for {}\n expected: {}\n actual: {}\n\n\
The Huffman codebook has been tampered with or regenerated without updating \
the pinned hash. Any change here changes every VsfType::x byte and every \
downstream identity hash. If the change is intentional, update the constant \
in build.rs and bump vsf MAJOR version per the determinism contract.",
path, expected_hex, actual
));
}
Ok(())
}
fn main() {
println!("cargo::rustc-check-cfg=cfg(huffman_available)");
println!("cargo:rerun-if-changed=frequencies.bin");
println!("cargo:rerun-if-changed=huffman_codes.bin");
println!("cargo:rerun-if-changed=build.rs");
if !Path::new("huffman_codes.bin").exists() {
eprintln!(
"cargo:warning=huffman_codes.bin missing — text encoding will be unavailable in this build"
);
return;
}
if Path::new("frequencies.bin").exists() {
if let Err(msg) = verify_blake3("frequencies.bin", FREQUENCIES_BLAKE3) {
panic!("{}", msg);
}
}
if let Err(msg) = verify_blake3("huffman_codes.bin", HUFFMAN_CODES_BLAKE3) {
panic!("{}", msg);
}
println!("cargo:rustc-cfg=huffman_available");
}