use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::env;
use std::ffi::OsStr;
use std::fs;
use std::path::{Path, PathBuf};
use sha2::{Digest, Sha256};
use walkdir::WalkDir;
const INPUT_HASH_VERSION: &str = "vyre-conform.codegen-inputs.v1";
const REGEN_COMMAND: &str = "cargo build -p vyre-conform";
const GENERATED_COMMENT: &str =
"Source inputs: workspace Rust/TOML op specs, conform/defenders Rust/TOML manifests, and conform/build.rs sources.";
fn main() {
vyre_build_scan::scan_all(&[
vyre_build_scan::Registry {
scan_dir: "src/enforce/gates",
const_name: "ALL_GATES",
element_type: "&'static dyn crate::enforce::EnforceGate",
item_const_name: "REGISTERED",
output_file: "gates_registry.rs",
module_prefix: "crate::enforce::gates",
},
vyre_build_scan::Registry {
scan_dir: "src/enforce/enforcers",
const_name: "ALL_ENFORCERS",
element_type: "&'static dyn crate::enforce::RegisteredEnforcer",
item_const_name: "REGISTERED",
output_file: "enforcers_registry.rs",
module_prefix: "crate::enforce::enforcers",
},
vyre_build_scan::Registry {
scan_dir: "src/proof/oracles",
const_name: "ALL_ORACLES",
element_type: "&'static dyn crate::proof::oracles::Oracle",
item_const_name: "REGISTERED",
output_file: "oracles_registry.rs",
module_prefix: "crate::proof::oracles",
},
vyre_build_scan::Registry {
scan_dir: "src/generate/archetypes",
const_name: "ALL_ARCHETYPES",
element_type: "&'static dyn crate::generate::archetypes::Archetype",
item_const_name: "REGISTERED",
output_file: "archetypes_registry.rs",
module_prefix: "crate::generate::archetypes",
},
vyre_build_scan::Registry {
scan_dir: "src/adversarial/mutations",
const_name: "ALL_MUTATION_CLASSES",
element_type: "&'static dyn crate::adversarial::mutations::Mutator",
item_const_name: "REGISTERED",
output_file: "mutation_classes_registry.rs",
module_prefix: "crate::adversarial::mutations",
},
vyre_build_scan::Registry {
scan_dir: "src/spec/findings",
const_name: "ALL_FINDINGS",
element_type: "&'static dyn crate::spec::Finding",
item_const_name: "REGISTERED",
output_file: "findings_registry.rs",
module_prefix: "crate::spec::findings",
},
]);
println!("cargo:rerun-if-env-changed=VYRE_CONFORM_EXTRA_OP_DIR");
println!("cargo:rerun-if-env-changed=VYRE_CONFORM_ONLY_OP_DIRS");
let conform_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("manifest dir"));
let workspace_root = conform_dir.parent().expect("workspace root").to_path_buf();
let roots = discovery_roots(&workspace_root);
for root in &roots {
println!("cargo:rerun-if-changed={}", root.display());
}
let out_dir = PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR"));
if let Err(error) = write_build_outputs(&out_dir) {
panic!("{error}");
}
}
fn write_build_outputs(out_dir: &Path) -> Result<(), String> {
let conform_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
let workspace_root = workspace_root(&conform_dir)?;
let roots = discovery_roots(&workspace_root);
let ops = discover_ops(&workspace_root, &conform_dir, &roots)?;
fs::create_dir_all(out_dir)
.map_err(|error| format!("failed to create {}: {error}", out_dir.display()))?;
let registry = write_registry(out_dir, &ops)?;
let generated_ops = out_dir.join("generated_ops.rs");
fs::rename(out_dir.join("ops.rs"), &generated_ops).map_err(|error| {
format!(
"failed to rename generated ops {} to {}: {error}",
registry.path.display(),
generated_ops.display()
)
})?;
write_primitive_modules(out_dir, &ops)?;
write_defender_corpus(&conform_dir, out_dir)?;
write_output(
out_dir.join("coverage_report.md"),
coverage_report(&workspace_root, &ops),
)?;
Ok(())
}
fn discovery_roots(workspace_root: &Path) -> Vec<PathBuf> {
if let Some(only) = env::var_os("VYRE_CONFORM_ONLY_OP_DIRS") {
return env::split_paths(&only).collect();
}
let mut roots = vec![workspace_root.to_path_buf()];
if let Some(extra) = env::var_os("VYRE_CONFORM_EXTRA_OP_DIR") {
roots.extend(env::split_paths(&extra));
}
roots
}
#[derive(Clone, Debug)]
struct OpFile {
path: PathBuf,
rel_path: String,
module_name: String,
spec_accessor: String,
id: String,
layer: String,
category: String,
signature: String,
has_golden: bool,
has_kat: bool,
has_adversarial: bool,
has_proptest: bool,
source_sha256: String,
}
fn discover_ops(
workspace_root: &Path,
conform_dir: &Path,
roots: &[PathBuf],
) -> Result<Vec<OpFile>, String> {
let _ = conform_dir;
let mut ops = Vec::new();
let mut seen_paths = BTreeSet::new();
let mut seen_ids = BTreeMap::<String, PathBuf>::new();
let mut walk_errors = Vec::new();
for root in roots {
for entry in WalkDir::new(root).follow_links(false) {
let entry = match entry {
Ok(entry) => entry,
Err(error) => {
walk_errors.push(format!("{}: {error}", root.display()));
continue;
}
};
let path = entry.path();
if should_skip(path)
|| !entry.file_type().is_file()
|| path.extension() != Some(OsStr::new("rs"))
{
continue;
}
let canonical = path.canonicalize().unwrap_or_else(|_| path.to_path_buf());
if !seen_paths.insert(canonical) {
continue;
}
let source = match fs::read_to_string(path) {
Ok(source) => source,
Err(error) => {
return Err(format!(
"failed to read candidate op file {}: {error}. Fix: restore read permissions or remove this file from op discovery roots.",
path.display()
));
}
};
if !source.contains("pub const SPEC") {
continue;
}
let parsed = match syn::parse_file(&source) {
Ok(file) => file,
Err(error) => {
eprintln!(
"Warning: {} contains `pub const SPEC` but failed to parse as Rust: {error}. Skipping from generated registry.",
path.display()
);
continue;
}
};
let Some(spec_info) = discover_spec_info(&parsed, path) else {
continue;
};
let context = SpecContext::from_path(path);
let id = extract_op_id(&spec_info.spec_expr, &context, spec_info.spec_impl.as_deref(), 0)
.ok_or_else(|| {
format!(
"failed to infer op id in {}. Fix: provide a string literal as the first OpSpec argument, or define `pub const OP_ID`.",
path.display()
)
})?;
if let Some(previous) = seen_ids.insert(id.clone(), path.to_path_buf()) {
return Err(format!(
"duplicate op id '{id}' in {} and {}. Fix: give every op a unique id.",
previous.display(),
path.display()
));
}
let rel_path = relative_path(workspace_root, path);
let module_name = op_module_name(&id);
let layer =
extract_metadata_field(&parsed, "layer").unwrap_or_else(|| "L0".to_string());
let category = extract_metadata_field(&parsed, "category")
.unwrap_or_else(|| "unclassified".to_string());
let signature = extract_metadata_field(&parsed, "signature").unwrap_or_default();
ops.push(OpFile {
path: path.to_path_buf(),
rel_path,
module_name,
spec_accessor: spec_info.spec_accessor,
id,
layer,
category,
signature,
has_golden: has_non_empty_slice(&source, "GOLDEN"),
has_kat: has_non_empty_slice(&source, "KAT"),
has_adversarial: has_non_empty_slice(&source, "ADVERSARIAL"),
has_proptest: source.contains("proptest!") || source.contains("mod proptests"),
source_sha256: sha256_hex(source.as_bytes()),
});
}
}
if !walk_errors.is_empty() {
return Err(format!(
"op discovery encountered filesystem errors:\n- {}\nFix: restore access to these paths or remove them from VYRE_CONFORM_EXTRA_OP_DIR / VYRE_CONFORM_ONLY_OP_DIRS.",
walk_errors.join("\n- ")
));
}
ops.sort_by(|left, right| left.id.cmp(&right.id));
disambiguate_module_names(&mut ops);
Ok(ops)
}
fn disambiguate_module_names(ops: &mut [OpFile]) {
let mut counts = BTreeMap::<String, usize>::new();
for op in ops.iter() {
*counts.entry(op.module_name.clone()).or_default() += 1;
}
for op in ops {
if counts.get(&op.module_name).copied().unwrap_or_default() > 1 {
op.module_name = format!("{}_{}", op.module_name, collision_suffix(&op.path));
}
}
}
struct SpecInfo {
spec_expr: syn::Expr,
spec_impl: Option<String>,
spec_accessor: String,
}
trait ExprLike {
fn as_expr(&self) -> &syn::Expr;
}
impl ExprLike for syn::Expr {
fn as_expr(&self) -> &syn::Expr {
self
}
}
impl ExprLike for Box<syn::Expr> {
fn as_expr(&self) -> &syn::Expr {
self.as_ref()
}
}
fn clone_expr<E: ExprLike>(expr: &E) -> syn::Expr {
expr.as_expr().clone()
}
fn discover_spec_info(file: &syn::File, spec_path: &Path) -> Option<SpecInfo> {
for item in &file.items {
if let syn::Item::Const(item_const) = item {
if item_const.ident == "SPEC" {
let is_public = matches!(item_const.vis, syn::Visibility::Public(_));
if !is_public {
continue;
}
return Some(SpecInfo {
spec_expr: clone_expr(&item_const.expr),
spec_impl: None,
spec_accessor: "SPEC".to_string(),
});
}
}
if let syn::Item::Impl(item_impl) = item {
let impl_type = impl_type_ident(&item_impl.self_ty)?;
for impl_item in &item_impl.items {
let syn::ImplItem::Const(item_const) = impl_item else {
continue;
};
if item_const.ident == "SPEC"
&& matches!(item_const.vis, syn::Visibility::Public(_))
{
return Some(SpecInfo {
spec_expr: clone_expr(&item_const.expr),
spec_impl: Some(impl_type.clone()),
spec_accessor: format!("{impl_type}::SPEC"),
});
}
}
}
}
eprintln!(
"Warning: {} declares `pub const SPEC` but no discoverable exported constant was found. This file will be skipped.",
spec_path.display()
);
None
}
fn impl_type_ident(self_type: &syn::Type) -> Option<String> {
match self_type {
syn::Type::Path(ty) => ty
.path
.segments
.last()
.map(|segment| segment.ident.to_string()),
_ => None,
}
}
fn extract_metadata_field(file: &syn::File, field_name: &str) -> Option<String> {
for item in &file.items {
let syn::Item::Const(item_const) = item else {
continue;
};
if item_const.ident != "VYRE_OP_METADATA" {
continue;
}
let syn::Expr::Struct(expr_struct) = &*item_const.expr else {
continue;
};
for field in &expr_struct.fields {
let syn::Member::Named(ident) = &field.member else {
continue;
};
if ident == field_name {
return expr_to_string(&field.expr);
}
}
}
None
}
fn resolve_const_expr(
expr: &syn::Expr,
context: &SpecContext,
impl_name: Option<&str>,
depth: u8,
) -> Option<String> {
if depth > 8 {
return None;
}
match expr {
syn::Expr::Lit(expr_lit) => {
if let syn::Lit::Str(string) = &expr_lit.lit {
Some(string.value())
} else {
None
}
}
syn::Expr::Path(expr_path) => {
let path = &expr_path.path;
let last = path.segments.last()?;
let ident = last.ident.to_string();
if ident == "OP_ID" {
return context
.top_const_exprs
.get("OP_ID")
.and_then(|value| resolve_const_expr(value, context, impl_name, depth + 1));
}
if path.segments.len() == 2 {
if let Some(first) = path.segments.first() {
if first.ident == "Self" {
if let Some(impl_name) = impl_name {
if let Some(value) = context
.impl_const_exprs
.get(impl_name)
.and_then(|map| map.get(&ident))
{
return resolve_const_expr(
value,
context,
Some(impl_name),
depth + 1,
);
}
}
}
}
}
if let Some(impl_name) = impl_name {
if let Some(value) = context
.impl_const_exprs
.get(impl_name)
.and_then(|map| map.get(&ident))
{
return resolve_const_expr(value, context, Some(impl_name), depth + 1);
}
}
if let Some(value) = context.top_const_exprs.get(&ident) {
return resolve_const_expr(value, context, impl_name, depth + 1);
}
None
}
syn::Expr::Call(expr_call) => expr_call
.args
.first()
.and_then(|arg| resolve_const_expr(arg, context, impl_name, depth + 1)),
syn::Expr::Binary(expr_binary) => {
resolve_const_expr(&expr_binary.left, context, impl_name, depth + 1)
.or_else(|| resolve_const_expr(&expr_binary.right, context, impl_name, depth + 1))
}
syn::Expr::Paren(expr_paren) => {
resolve_const_expr(&expr_paren.expr, context, impl_name, depth + 1)
}
syn::Expr::Reference(reference) => {
resolve_const_expr(&reference.expr, context, impl_name, depth + 1)
}
syn::Expr::MethodCall(method_call) => {
resolve_const_expr(&method_call.receiver, context, impl_name, depth + 1)
}
syn::Expr::Assign(assign) => {
resolve_const_expr(&assign.left, context, impl_name, depth + 1)
.or_else(|| resolve_const_expr(&assign.right, context, impl_name, depth + 1))
}
syn::Expr::Block(block) => block
.block
.stmts
.iter()
.find_map(|stmt| expr_in_stmt(stmt, context, impl_name, depth + 1)),
syn::Expr::Struct(expr_struct) => expr_struct
.fields
.iter()
.find_map(|field| resolve_const_expr(&field.expr, context, impl_name, depth + 1)),
syn::Expr::Cast(expr_cast) => {
resolve_const_expr(&expr_cast.expr, context, impl_name, depth + 1)
}
syn::Expr::Index(expr_index) => {
resolve_const_expr(&expr_index.expr, context, impl_name, depth + 1)
}
syn::Expr::Field(field) => resolve_const_expr(&field.base, context, impl_name, depth + 1),
syn::Expr::Tuple(expr_tuple) => expr_tuple
.elems
.iter()
.find_map(|elem| resolve_const_expr(elem, context, impl_name, depth + 1)),
syn::Expr::Array(expr_array) => expr_array
.elems
.iter()
.find_map(|elem| resolve_const_expr(elem, context, impl_name, depth + 1)),
_ => None,
}
}
fn extract_op_id(
expr: &syn::Expr,
context: &SpecContext,
impl_name: Option<&str>,
depth: u8,
) -> Option<String> {
resolve_const_expr(expr, context, impl_name, depth)
}
fn expr_in_stmt(
stmt: &syn::Stmt,
context: &SpecContext,
impl_name: Option<&str>,
depth: u8,
) -> Option<String> {
match stmt {
syn::Stmt::Local(local) => local
.init
.as_ref()
.and_then(|init| extract_op_id(&init.expr, context, impl_name, depth + 1)),
syn::Stmt::Expr(expr, _) => extract_op_id(expr, context, impl_name, depth + 1),
_ => None,
}
}
#[derive(Default)]
struct SpecContext {
top_const_exprs: HashMap<String, syn::Expr>,
impl_const_exprs: HashMap<String, HashMap<String, syn::Expr>>,
}
impl SpecContext {
fn from_path(path: &Path) -> Self {
let mut context = Self::default();
let contents = fs::read_to_string(path).unwrap_or_default();
if let Ok(file) = syn::parse_file(&contents) {
context.index_file(&file);
}
if let Some(parent) = path.parent() {
for dir in std::iter::once(parent).chain(parent.parent()) {
let op_id_path = dir.join("op_id.rs");
if let Ok(op_id_source) = fs::read_to_string(&op_id_path) {
if let Ok(op_id_file) = syn::parse_file(&op_id_source) {
context.index_file(&op_id_file);
}
}
}
}
context
}
fn index_file(&mut self, file: &syn::File) {
for item in &file.items {
match item {
syn::Item::Const(const_item) => {
self.top_const_exprs
.insert(const_item.ident.to_string(), clone_expr(&const_item.expr));
}
syn::Item::Impl(item_impl) => {
let Some(impl_type) = impl_type_ident(&item_impl.self_ty) else {
continue;
};
for item in &item_impl.items {
if let syn::ImplItem::Const(const_item) = item {
self.impl_const_exprs
.entry(impl_type.clone())
.or_default()
.insert(const_item.ident.to_string(), clone_expr(&const_item.expr));
}
}
}
_ => {}
}
}
}
}
#[derive(Clone, Debug)]
struct GeneratedOutput {
path: PathBuf,
sha256: String,
}
fn write_output(path: PathBuf, content: String) -> Result<GeneratedOutput, String> {
if let Some(parent) = path.parent() {
fs::create_dir_all(parent)
.map_err(|error| format!("failed to create {}: {error}", parent.display()))?;
}
fs::write(&path, content.as_bytes())
.map_err(|error| format!("failed to write {}: {error}", path.display()))?;
Ok(GeneratedOutput {
path,
sha256: sha256_hex(content.as_bytes()),
})
}
fn write_registry(generated_dir: &Path, ops: &[OpFile]) -> Result<GeneratedOutput, String> {
let path = generated_dir.join("ops.rs");
let mut out = provenance("//");
for op in ops {
let path = escaped_module_path(generated_dir, &op.path);
out.push_str(&format!(
"#[path = {path}]\n#[allow(missing_docs, clippy::all)]\nmod {};\n",
op.module_name
));
}
out.push_str(&format!("pub const OP_COUNT: usize = {};\n", ops.len()));
out.push_str("pub const ALL_OPS: &[crate::OpSpec] = &[\n");
for op in ops {
out.push_str(&format!(" {}::{},\n", op.module_name, op.spec_accessor));
}
out.push_str("];\n");
out.push_str("pub fn all_generated_specs() -> Vec<crate::OpSpec> {\n ALL_OPS.to_vec()\n}\n");
out.push_str(
"pub fn all_generated_golden_samples() -> Vec<crate::verify::golden_samples::GoldenSample> {\n let mut out = Vec::new();\n",
);
for op in ops {
if op.has_golden {
out.push_str(&format!(
" out.extend_from_slice({}::GOLDEN);\n",
op.module_name
));
}
}
out.push_str(" out\n}\n");
out.push_str(
"pub fn all_generated_kat_vectors() -> Vec<vyre_spec::KatVector> {\n let mut out = Vec::new();\n",
);
for op in ops {
if op.has_kat {
out.push_str(&format!(
" out.extend_from_slice({}::KAT);\n",
op.module_name
));
}
}
out.push_str(" out\n}\n");
out.push_str(
"pub fn all_generated_adversarial_inputs() -> Vec<vyre_spec::AdversarialInput> {\n let mut out = Vec::new();\n",
);
for op in ops {
if op.has_adversarial {
out.push_str(&format!(
" out.extend_from_slice({}::ADVERSARIAL);\n",
op.module_name
));
}
}
out.push_str(" out\n}\n");
write_output(path, out)
}
fn write_primitive_modules(
generated_dir: &Path,
ops: &[OpFile],
) -> Result<GeneratedOutput, String> {
let path = generated_dir.join("primitive_ops.rs");
let mut out = provenance("//");
let primitive_ops = ops
.iter()
.filter(|op| is_primitive_spec_path(&op.rel_path))
.collect::<Vec<_>>();
for op in &primitive_ops {
let path = escaped_module_path(generated_dir, &op.path);
out.push_str(&format!(
"#[path = {path}]\n#[allow(missing_docs, clippy::all)]\npub mod {};\n",
op.module_name
));
}
out.push_str(&format!(
"pub const SPEC_COUNT: usize = {};\n",
primitive_ops.len()
));
out.push_str("pub fn specs() -> Vec<crate::OpSpec> {\n vec![\n");
for op in &primitive_ops {
out.push_str(&format!(
" {}::{},\n",
op.module_name, op.spec_accessor
));
}
out.push_str(" ]\n}\n");
write_output(path, out)
}
fn coverage_report(workspace_root: &Path, ops: &[OpFile]) -> String {
let mut out = markdown_provenance();
out.push_str("# Generated coverage report\n\nDo not edit by hand. Run `cargo build -p vyre-conform`.\n\n<!-- gate7-source-hashes:begin -->\n");
for op in ops {
let source_path = relative_path(workspace_root, &op.path);
out.push_str(&format!(
"<!-- gate7-source-sha256 {} {} -->\n",
source_path, op.source_sha256
));
}
out.push_str("<!-- gate7-source-hashes:end -->\n\n| id | layer | category | signature | status |\n|---|---|---|---|---|\n");
let mut needs_work = Vec::new();
for op in ops {
let status_column = format!(
"golden: {}; kat: {}; adversarial: {}; proptest: {}",
yes(op.has_golden),
yes(op.has_kat),
yes(op.has_adversarial),
yes(op.has_proptest),
);
out.push_str(&format!(
"| {} | {} | {} | {} | {} |\n",
op.id, op.layer, op.category, op.signature, status_column,
));
if !(op.has_golden && op.has_kat && op.has_adversarial && op.has_proptest) {
needs_work.push(op.id.as_str());
}
}
out.push_str("\n## NEEDS WORK\n\n");
for id in needs_work {
out.push_str(&format!("- `{id}`\n"));
}
out
}
#[derive(Debug)]
struct DefenderManifest {
id: String,
target_op_id: String,
description: String,
class: String,
expected_outcome: String,
fails_laws: Vec<String>,
witness_a: Option<u32>,
witness_b: Option<u32>,
}
#[derive(Debug)]
struct DefenderEntry {
module_name: String,
include_path: String,
manifest: DefenderManifest,
}
fn write_defender_corpus(
conform_dir: &Path,
generated_dir: &Path,
) -> Result<GeneratedOutput, String> {
let corpus_rs = generated_dir.join("defender_corpus.rs");
let defenders_dir = conform_dir.join("defenders");
if !defenders_dir.exists() {
return write_output(
corpus_rs,
format!(
"{}pub fn corpus_catalogs() -> Vec<crate::adversarial::defender::DefendantCatalog> {{ Vec::new() }}\npub fn corpus_metadata() -> Vec<DefenderMeta> {{ Vec::new() }}\n",
provenance("//")
),
);
}
let mut entries = Vec::new();
collect_defenders(&defenders_dir, &defenders_dir, &mut entries)?;
entries.sort_by(|left, right| left.module_name.cmp(&right.module_name));
write_output(corpus_rs, generate_corpus(&entries))
}
fn collect_defenders(
root: &Path,
dir: &Path,
out: &mut Vec<DefenderEntry>,
) -> Result<(), String> {
for entry in fs::read_dir(dir).map_err(|error| {
format!(
"failed to read defender directory {}: {error}. Fix: restore permissions.",
dir.display()
)
})? {
let path = entry
.map_err(|error| format!("failed to read defender entry: {error}"))?
.path();
if path.is_dir() {
collect_defenders(root, &path, out)?;
continue;
}
if path.extension().and_then(|s| s.to_str()) != Some("rs") {
continue;
}
let toml_path = path.with_extension("toml");
if !toml_path.exists() {
continue;
}
let manifest = parse_defender_manifest(
&fs::read_to_string(&toml_path)
.map_err(|error| format!("failed to read {}: {error}", toml_path.display()))?,
)?;
let rel = path.strip_prefix(root).unwrap_or(&path);
let module_name = rel
.parent()
.map(|parent| parent.join(path.file_stem().expect("defender stem")))
.unwrap_or_else(|| PathBuf::from(path.file_stem().expect("defender stem")))
.to_string_lossy()
.replace(['/', '\\'], "_")
.replace(['-', '.'], "_");
let include_path = path.to_string_lossy().replace('\\', "/");
out.push(DefenderEntry {
module_name,
include_path,
manifest,
});
}
Ok(())
}
fn parse_defender_manifest(content: &str) -> Result<DefenderManifest, String> {
let val: toml::Value = content
.parse()
.map_err(|error| format!("invalid defender TOML manifest: {error}"))?;
let get_str = |key: &str| -> Result<String, String> {
val.get(key)
.and_then(toml::Value::as_str)
.map(ToString::to_string)
.ok_or_else(|| format!("missing string field '{key}' in defender manifest"))
};
let get_u32 = |key: &str| -> Option<u32> {
val.get(key)
.and_then(toml::Value::as_integer)
.map(|i| i as u32)
};
let fails_laws = val
.get("fails_laws")
.and_then(toml::Value::as_array)
.map(|arr| {
arr.iter()
.map(|v| {
v.as_str()
.map(ToString::to_string)
.ok_or_else(|| "fails_laws must contain strings".to_string())
})
.collect::<Result<Vec<_>, _>>()
})
.transpose()?
.unwrap_or_default();
let (witness_a, witness_b) =
if let Some(arr) = val.get("expected_witness").and_then(toml::Value::as_array) {
let a = arr
.first()
.and_then(toml::Value::as_integer)
.map(|i| i as u32);
let b = arr
.get(1)
.and_then(toml::Value::as_integer)
.map(|i| i as u32);
(a, b)
} else {
(get_u32("witness_a"), get_u32("witness_b"))
};
Ok(DefenderManifest {
id: get_str("id")?,
target_op_id: get_str("target_op_id")?,
description: get_str("description")?,
class: get_str("class")?,
expected_outcome: get_str("expected_outcome")?,
fails_laws,
witness_a,
witness_b,
})
}
fn generate_corpus(entries: &[DefenderEntry]) -> String {
let mut out = provenance("//");
out.push_str(
"use crate::adversarial::defender::{Defendant, DefendantCatalog, MutationClass};\n\n",
);
for entry in entries {
out.push_str(&format!(
"mod {} {{\n include!(\"{}\");\n}}\n\n",
entry.module_name, entry.include_path
));
}
out.push_str("pub fn corpus_catalogs() -> Vec<DefendantCatalog> {\n");
out.push_str(" vec![\n");
let mut groups: BTreeMap<String, Vec<&DefenderEntry>> = BTreeMap::new();
for entry in entries {
groups
.entry(entry.manifest.target_op_id.clone())
.or_default()
.push(entry);
}
for (target_op_id, group) in groups {
out.push_str(&format!(
" DefendantCatalog {{\n target_op_id: {},\n defendants: vec![\n",
escape_str(&target_op_id)
));
for entry in group {
let manifest = &entry.manifest;
let witness = match (manifest.witness_a, manifest.witness_b) {
(Some(a), Some(b)) => format!("&[({}, {})]", a, b),
(Some(a), None) => format!("&[({}, 0)]", a),
_ => "&[]".to_string(),
};
let fails_laws = manifest
.fails_laws
.iter()
.map(|s| escape_str(s))
.collect::<Vec<_>>()
.join(", ");
out.push_str(&format!(
" Defendant {{\n id: {},\n target_op_id: {},\n description: {},\n class: {},\n broken_fn: {}::cpu_fn,\n fails_laws: &[{}],\n expected_witness: {},\n }},\n",
escape_str(&manifest.id),
escape_str(&manifest.target_op_id),
escape_str(&manifest.description),
mutation_variant(&manifest.class),
entry.module_name,
fails_laws,
witness,
));
}
out.push_str(" ],\n },\n");
}
out.push_str(" ]\n}\n\n");
out.push_str("#[derive(Debug, Clone)]\npub struct DefenderMeta {\n pub id: &'static str,\n pub class: &'static str,\n pub expected_outcome: &'static str,\n}\n\n");
out.push_str("pub fn corpus_metadata() -> Vec<DefenderMeta> {\n vec![\n");
for entry in entries {
let manifest = &entry.manifest;
out.push_str(&format!(
" DefenderMeta {{ id: {}, class: {}, expected_outcome: {} }},\n",
escape_str(&manifest.id),
escape_str(&manifest.class),
escape_str(&manifest.expected_outcome),
));
}
out.push_str(" ]\n}\n");
out
}
fn workspace_root(conform_dir: &Path) -> Result<PathBuf, String> {
conform_dir
.parent()
.map(Path::to_path_buf)
.ok_or_else(|| format!("{} has no workspace parent", conform_dir.display()))
}
fn should_skip(path: &Path) -> bool {
if path.ends_with("core/src/compiler/dominator_tree.rs") {
return true;
}
path.components().any(|component| {
let name = component.as_os_str();
name == ".git"
|| name == "target"
|| name == "docs"
|| name == "coordination"
|| name == "std"
})
}
fn op_module_name(op_id: &str) -> String {
let mut out = String::from("op_");
for ch in op_id.chars() {
if ch.is_ascii_alphanumeric() {
out.push(ch.to_ascii_lowercase());
} else {
out.push('_');
}
}
out
}
fn collision_suffix(path: &Path) -> String {
let hash = blake3::hash(path.to_string_lossy().as_bytes());
hash.to_hex()[..6].to_string()
}
fn expr_to_string(expr: &syn::Expr) -> Option<String> {
match expr {
syn::Expr::Lit(expr_lit) => match &expr_lit.lit {
syn::Lit::Str(lit_str) => Some(lit_str.value()),
_ => None,
},
syn::Expr::Path(expr_path) => expr_path
.path
.segments
.last()
.map(|seg| seg.ident.to_string()),
_ => None,
}
}
fn has_non_empty_slice(source: &str, name: &str) -> bool {
let Some(pos) = source.find(&format!("pub const {name}")) else {
return false;
};
let Some(eq) = source[pos..].find('=') else {
return false;
};
let tail = source[pos + eq + 1..].trim_start();
tail.starts_with("include!(")
|| tail.starts_with(&format!("{name}_GENERATED"))
|| (tail.starts_with("&[") && !tail.starts_with("&[]"))
}
fn provenance(prefix: &str) -> String {
format!(
"{prefix} @generated by conform/build.rs\n{prefix} {GENERATED_COMMENT}\n{prefix} Regenerate: {REGEN_COMMAND}\n\n"
)
}
fn markdown_provenance() -> String {
format!(
"<!-- @generated by conform/build.rs -->\n<!-- {GENERATED_COMMENT} -->\n<!-- Regenerate: {REGEN_COMMAND} -->\n\n",
)
}
fn relative_path(root: &Path, path: &Path) -> String {
path.strip_prefix(root)
.unwrap_or(path)
.to_string_lossy()
.replace('\\', "/")
}
fn escaped_module_path(_include_base: &Path, path: &Path) -> String {
format!("{:?}", path.to_string_lossy().replace('\\', "/"))
}
fn is_primitive_spec_path(rel_path: &str) -> bool {
rel_path.starts_with("src/specs/primitive/")
|| rel_path.ends_with("/src/specs/primitive")
|| rel_path.contains("/src/specs/primitive/")
|| rel_path.starts_with("core/src/ops/primitive/")
|| rel_path.ends_with("/core/src/ops/primitive")
|| rel_path.contains("/core/src/ops/primitive/")
}
fn yes(value: bool) -> &'static str {
if value {
"yes"
} else {
"no"
}
}
fn escape_str(s: &str) -> String {
format!("\"{}\"", s.replace('\\', "\\\\").replace('"', "\\\""))
}
fn mutation_variant(class: &str) -> &'static str {
match class {
"backdoor" => "MutationClass::Backdoor",
"drop-lsb" => "MutationClass::DropLsb",
"drop-msb" => "MutationClass::DropMsb",
"hardcoded-input" => "MutationClass::HardcodedInput",
"hardcoded-zero" => "MutationClass::HardcodedZero",
"mod-mask" => "MutationClass::ModMask",
"nondeterministic" => "MutationClass::Nondeterministic",
"off-by-one" => "MutationClass::OffByOne",
"pseudo-correct" => "MutationClass::PseudoCorrect",
"sign-flip" => "MutationClass::SignFlip",
"swapped-operand" => "MutationClass::SwappedOperand",
"unsupported" => "MutationClass::Unsupported",
_ => panic!("unknown defender mutation class `{class}`. Fix: add it to MutationClass and conform/build.rs."),
}
}
fn sha256_hex(bytes: &[u8]) -> String {
let digest = Sha256::digest(bytes);
hex_digest(digest.as_slice())
}
fn hex_digest(bytes: &[u8]) -> String {
const HEX: &[u8; 16] = b"0123456789abcdef";
let mut out = String::with_capacity(bytes.len() * 2);
for &byte in bytes {
out.push(HEX[(byte >> 4) as usize] as char);
out.push(HEX[(byte & 0xF) as usize] as char);
}
out
}