#[path = "src/sig.rs"] mod sigs; use std::{ collections::{hash_map::DefaultHasher, HashMap}, fs, hash::{Hash, Hasher}, }; use anyhow; use serde_json; use sigs::Signature; fn main() -> anyhow::Result<()> { let json = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/data/sigs.json")); let sigs: Vec = serde_json::from_str(json)?; let sigs_rs = make_sigs(sigs.clone())?; let head_rs = make_head(sigs.clone())?; let _prex_rs = make_prex(sigs)?; fs::write( concat!(env!("CARGO_MANIFEST_DIR"), "/src/data/sigs.rs"), sigs_rs, )?; fs::write( concat!(env!("CARGO_MANIFEST_DIR"), "/src/data/head.rs"), head_rs, )?; // fs::write( // concat!(env!("CARGO_MANIFEST_DIR"), "/src/data/prex.rs"), // prex_rs, // )?; Ok(()) } fn make_prex(sigs: Vec) -> anyhow::Result { let mut prefixes: HashMap> = HashMap::new(); for (i, sig) in sigs.iter().enumerate() { let mut s = DefaultHasher::new(); let mut header = vec![]; for byte in &sig.header { header.push(byte); header.hash(&mut s); let hash = s.finish(); if prefixes.contains_key(&hash) { prefixes.get_mut(&hash).unwrap().push(i); } else { prefixes.insert(hash, vec![i]); } } } let mut ret = String::from( "// Automatically generated with build.rs. Edit with care.\nuse std::collections::HashMap;\n", ); ret.push_str("thread_local!(pub static PREFIXES: HashMap> = HashMap::from([\n"); for (k, v) in prefixes { ret.push_str(format!("\t({}, vec![\n", k).as_str()); for i in v { ret.push_str(format!("\t\t{i},\n").as_str()); } ret.push_str("\t]),\n"); } ret.push_str("]));"); Ok(ret) } fn make_head(sigs: Vec) -> anyhow::Result { let mut ret = String::from( "// Automatically generated with build.rs. Edit with care.\nuse std::collections::HashMap;\n", ); ret.push_str("thread_local!(pub static HEADERS: HashMap = HashMap::from([\n"); let mut max_header_len_bytes = 0; for (i, sig) in sigs.iter().enumerate() { if sig.exts.len() > max_header_len_bytes { max_header_len_bytes = sig.exts.len(); } let mut s = DefaultHasher::new(); sig.header.hash(&mut s); let hash = s.finish(); ret.push_str( format!( "\t//d: {} -> hash({:?}) = {}\n", sig.description, sig.header, hash ) .as_str(), ); ret.push_str(format!("\t({}, {}),\n", hash, i).as_str()) } ret.push_str("]));\n"); ret.push_str( format!( "pub const MAX_HEADER_BYTES: usize = {};", max_header_len_bytes ) .as_str(), ); Ok(ret) } fn make_sigs(sigs: Vec) -> anyhow::Result { let mut ret = String::from( "// Automatically generated with build.rs. Edit with care.\nuse crate::sig::Signature;\n", ); ret.push_str("thread_local!(pub static SIGNATURES: Vec> = vec![\n"); for sig in sigs { ret.push_str("\tSignature {\n"); ret.push_str(format!("\t\tdescription: \"{}\",\n", sig.description).as_str()); ret.push_str(format!("\t\tclass: \"{}\",\n", sig.class).as_str()); ret.push_str("\t\texts: vec![\n"); for ext in &sig.exts { ret.push_str(format!("\t\t\t\"{}\",\n", ext).as_str()); } ret.push_str("\t\t],\n"); ret.push_str(format!("\t\toffset: {},\n", sig.offset).as_str()); ret.push_str("\t\theader: vec![\n"); for b in sig.header { ret.push_str(format!("\t\t\t{},\n", b).as_str()); } ret.push_str("\t\t],\n"); ret.push_str("\t\ttrailer: vec![\n"); for b in sig.trailer { ret.push_str(format!("\t\t\t{},\n", b).as_str()); } ret.push_str("\t\t],\n"); ret.push_str("\t},\n"); } ret.push_str("]);"); Ok(ret) }