use std::env;
use std::error::Error;
use std::fs;
use std::path::{Path, PathBuf};
use serde_json::Value;
const RECORD: &str = "corpus/shapes.json";
fn main() -> Result<(), Box<dyn Error>> {
println!("cargo::rerun-if-changed=PROTOCOL");
println!("cargo::rerun-if-changed={RECORD}");
let root = PathBuf::from(env::var("CARGO_MANIFEST_DIR")?);
let stated = fs::read_to_string(root.join("PROTOCOL"))?;
let protocol: u32 = stated.trim().parse().map_err(|_| {
format!("the repo-root PROTOCOL file must state one integer; it states {stated:?}")
})?;
let record: Value = serde_json::from_str(&fs::read_to_string(root.join(RECORD))?)?;
let floor = stamp(record.get("floor"))
.ok_or_else(|| format!("{RECORD} states no `floor`; run `make corpus`"))?;
let edition = editions(&record)
.into_iter()
.max()
.ok_or_else(|| format!("{RECORD} stamps no field path; run `make corpus`"))?;
write(
&PathBuf::from(env::var("OUT_DIR")?).join("protocol.rs"),
protocol,
edition,
floor,
)?;
Ok(())
}
fn editions(record: &Value) -> Vec<u32> {
record
.get("shapes")
.and_then(Value::as_object)
.into_iter()
.flatten()
.filter_map(|(_, entry)| entry.get("signature")?.as_object())
.flatten()
.filter_map(|(_, at)| stamp(Some(at)))
.collect()
}
fn stamp(value: Option<&Value>) -> Option<u32> {
u32::try_from(value?.as_u64()?).ok()
}
fn write(out: &Path, protocol: u32, edition: u32, floor: u32) -> Result<(), Box<dyn Error>> {
fs::write(
out,
format!(
"/// The MAJOR this build speaks: the integer the repo-root\n\
/// `PROTOCOL` file states, compiled in by `build.rs`. The changelog\n\
/// of every bump is this module's own documentation.\n\
pub const PROTOCOL: u32 = {protocol};\n\
\n\
/// The edition of the corpus this build was generated from: the\n\
/// newest stamp in `corpus/shapes.json`, compiled in by `build.rs`\n\
/// (REMOTE §3.2, bl-1be7). The engine states it in its preface, so\n\
/// a seat that vendors the ledger can tell a field this engine\n\
/// cannot spell from a field it chose not to say.\n\
pub const EDITION: u32 = {edition};\n\
\n\
/// The edition at which the current major was cut: `floor` in\n\
/// `corpus/shapes.json`, compiled in by `build.rs`. Every path\n\
/// stamped at or below it is written by every engine of this\n\
/// major, so a peer that states no edition at all is read as\n\
/// speaking exactly this one.\n\
pub const FLOOR: u32 = {floor};\n"
),
)?;
Ok(())
}