use serde::Deserialize;
use std::{env, fs};
use std::path::Path;
#[derive(Deserialize)]
struct HashEntry {
r#type: String, hash: String,
}
fn main() {
let out_dir = std::env::var("OUT_DIR").unwrap();
let proto_dir = "motorcortex-msg";
let proto_file = "motorcortex-msg/motorcortex.proto";
let hash_file = "motorcortex-msg/motorcortex_hash.json";
let generated_file = Path::new(&out_dir).join("motorcortex.rs");
let destination = Path::new("src/msg/motorcortex_msg.rs");
println!("cargo:rerun-if-changed={}", proto_file);
println!("cargo:rerun-if-changed={}", hash_file);
if env::var("COPY_FILES").is_ok() {
prost_build::compile_protos(&[proto_file], &[proto_dir]).unwrap();
fs::copy(generated_file, destination).unwrap(); let hash_map = parse_hashes_from_json(hash_file).unwrap();
let modified_code = add_hashes_to_generated_code(&hash_map, &destination);
fs::write(destination, modified_code).unwrap(); }
}
fn parse_hashes_from_json(
json_path: &str,
) -> Result<std::collections::HashMap<String, u32>, Box<dyn std::error::Error>> {
let json_content = fs::read_to_string(json_path)?; let hash_entries: Vec<HashEntry> = serde_json::from_str(&json_content)?;
let mut hash_map = std::collections::HashMap::new();
for entry in hash_entries {
let hash_value = u32::from_str_radix(&entry.hash.trim_start_matches("0x"), 16)?; hash_map.insert(entry.r#type.clone(), hash_value); }
Ok(hash_map)
}
fn add_hashes_to_generated_code(
hash_map: &std::collections::HashMap<String, u32>,
rust_file_path: &Path,
) -> String {
let rust_code = fs::read_to_string(rust_file_path).unwrap(); let mut output_code = format!("use crate::Hash;\n{}", rust_code);
for (qualified_name, &hash_value) in hash_map {
let type_name = qualified_name.split('.').last().unwrap();
let hash_impl = format!(
r#"
impl Hash for {type_name} {{
const HASH: u32 = 0x{hash_value:08x};
}}
"#,
type_name = type_name,
hash_value = hash_value
);
output_code.push_str(&hash_impl);
}
output_code
}