use std::fmt::Write as _;
use std::{env, fs, path::PathBuf};
use kryphocron_lexicons::{LexiconRegistryEntry, Tier, KRYPHOCRON_LEXICON_REGISTRY};
fn record_module_path(nsid: &str) -> String {
nsid.split('.')
.map(snake_case_segment)
.collect::<Vec<_>>()
.join("::")
}
fn snake_case_segment(segment: &str) -> String {
let mut out = String::with_capacity(segment.len() + 4);
for ch in segment.chars() {
if ch.is_ascii_uppercase() {
out.push('_');
out.push(ch.to_ascii_lowercase());
} else {
out.push(ch);
}
}
out
}
fn main() {
let mut entries: Vec<&LexiconRegistryEntry> = KRYPHOCRON_LEXICON_REGISTRY.iter().collect();
entries.sort_by_key(|e| e.nsid);
let mut src = String::new();
src.push_str("// @generated by kryphocron/build.rs (§5.4 post-processing). Do not edit.\n\n");
for e in &entries {
let ty = format!("::kryphocron_lexicons::{}::Main", record_module_path(e.nsid));
let witness = match e.tier {
Tier::Public => "PublicTier",
Tier::Private => "PrivateTier",
other => panic!(
"kryphocron build.rs: NSID `{}` has unhandled tier {other:?} — \
add a tier-witness mapping for the new tier",
e.nsid
),
};
writeln!(src, "impl crate::sealed::Sealed for {ty} {{}}").unwrap();
writeln!(
src,
"impl crate::tier::HasNsid for {ty} {{\n \
const NSID: &'static str = {:?};\n \
type Tier = crate::tier::{witness};\n}}\n",
e.nsid
)
.unwrap();
}
src.push_str(
"/// NSIDs for which the §5.4 build post-processing emitted a `HasNsid`\n\
/// impl — one per record type, sorted. Checked for set-equality against\n\
/// [`crate::KRYPHOCRON_LEXICON_REGISTRY`] (§5.3 bidirectional consistency).\n\
pub const KRYPHOCRON_IMPLEMENTED_NSIDS: &[&str] = &[\n",
);
for e in &entries {
writeln!(src, " {:?},", e.nsid).unwrap();
}
src.push_str("];\n\n");
src.push_str(
"const _: () = {\n \
assert!(\n \
KRYPHOCRON_IMPLEMENTED_NSIDS.len()\n \
== ::kryphocron_lexicons::KRYPHOCRON_LEXICON_REGISTRY.len(),\n \
\"HasNsid impl set / lexicon registry size mismatch — regenerate codegen\"\n \
);\n};\n",
);
let dest = PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR")).join("has_nsid_impls.rs");
fs::write(&dest, src).expect("write has_nsid_impls.rs");
println!("cargo:rerun-if-changed=build.rs");
}