#[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<Signature> = 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,
)?;
Ok(())
}
fn make_prex(sigs: Vec<Signature>) -> anyhow::Result<String> {
let mut prefixes: HashMap<u64, Vec<usize>> = 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<u64, Vec<usize>> = 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<Signature>) -> anyhow::Result<String> {
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<u64, usize> = 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<Signature>) -> anyhow::Result<String> {
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<Signature<'static>> = 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)
}