plugins/native/znippy-plugin-elf/src/claim.rs
//! What the **path** claims about a binary's architecture — and nothing else.
//!
//! This is the one place in the crate that looks at a file name, and it exists
//! for exactly one query: **"which members lie about their architecture"**. A
//! path is a *claim*; the ELF header is the *fact* (law **E-0**,
//! `.nornir/elf-design.md` §2). Nothing here is ever written into a column that
//! states a fact — [`arch_claim`] fills the column literally called
//! `arch_claim`, and [`lies`] compares it against what the header actually said.
//!
//! Unconditional and dependency-free (pure `&str` -> `&str`), like the sibling
//! plugins' `member` module, so `--no-default-features` compiles for
//! `wasm32-unknown-unknown`.
/// Split a path into its tokens: `/`, `\`, `.` and `-` are separators.
///
/// `_` is **not** a separator, and that is load-bearing: splitting on it turns
/// `x86_64-unknown-linux-gnu` into `x86` + `64`, and `x86` is a *different*
/// architecture. A 64-bit triple read as a 32-bit claim would have made this
/// module manufacture the very lie it exists to detect.
fn tokens(path: &str) -> impl Iterator<Item = &str> {
path.split(['/', '\\', '.', '-'])
}
/// The architecture a *path* claims, canonicalised to the same vocabulary
/// [`crate::facts::machine_name`] writes into `elf_machine`.
///
/// `None` = the path claims nothing, which is not a lie.
///
/// Recognises the tokens that appear in a cargo target-triple directory
/// (`target/x86_64-unknown-linux-gnu/release/…`), in an artifact directory
/// (`…/aarch64/…`) and in a package file name (`gunnar-1.4.0.aarch64.rpm`).
pub fn arch_claim(path: &str) -> Option<&'static str> {
let mut found: Option<&'static str> = None;
for t in tokens(path) {
let canon = match t {
"x86" | "i386" | "i486" | "i586" | "i686" => "x86",
"x86_64" | "amd64" | "x64" => "x86-64",
"aarch64" | "arm64" => "aarch64",
"armv7" | "armv7l" | "armv6" | "arm" | "armhf" | "armel" => "arm",
"riscv64" | "riscv64gc" => "riscv64",
"ppc64le" | "powerpc64le" | "ppc64" | "powerpc64" => "powerpc64",
"s390x" => "s390x",
"loongarch64" => "loongarch64",
"mips64el" | "mips64" => "mips64",
_ => continue,
};
match found {
// Two DIFFERENT architectures in one path is not a claim we can act
// on — it is ambiguous, and an ambiguous claim is no claim. Saying
// "this path claims x86-64" about `.../x86_64/.../aarch64/...`
// would itself be the guess this module exists to prevent.
Some(prev) if prev != canon => return None,
_ => found = Some(canon),
}
}
found
}
/// Does the path's claim contradict the header's fact?
///
/// `false` when the path claimed nothing — that is silence, not a lie.
pub fn lies(claim: Option<&str>, machine: &str) -> bool {
match claim {
None => false,
Some(c) => c != machine,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_cargo_target_triple_directory_is_a_claim() {
assert_eq!(arch_claim("target/x86_64-unknown-linux-gnu/release/gunnar"), Some("x86-64"));
assert_eq!(arch_claim("target/aarch64-unknown-linux-musl/release/holger"), Some("aarch64"));
}
#[test]
fn a_bare_arch_directory_is_a_claim() {
assert_eq!(arch_claim("artifacts/aarch64/bin/korp"), Some("aarch64"));
assert_eq!(arch_claim("rpm/gunnar.riscv64gc.rpm"), Some("riscv64"));
}
#[test]
fn a_path_that_claims_nothing_is_not_a_lie() {
assert_eq!(arch_claim("bin/gunnar"), None);
assert!(!lies(None, "aarch64"));
}
#[test]
fn two_different_claims_in_one_path_are_no_claim() {
// An ambiguous path must not be resolved by picking one.
assert_eq!(arch_claim("build/x86_64-unknown-linux-gnu/aarch64/thing"), None);
}
#[test]
fn the_same_claim_twice_is_still_that_claim() {
assert_eq!(arch_claim("amd64/target/x86_64-unknown-linux-gnu/x"), Some("x86-64"));
}
#[test]
fn a_claim_that_disagrees_with_the_header_is_a_lie() {
assert!(lies(arch_claim("target/x86_64-unknown-linux-gnu/release/x"), "aarch64"));
assert!(!lies(arch_claim("target/x86_64-unknown-linux-gnu/release/x"), "x86-64"));
}
#[test]
fn aliases_fold_to_the_header_vocabulary() {
assert_eq!(arch_claim("pkg/amd64/x"), Some("x86-64"));
assert_eq!(arch_claim("pkg/arm64/x"), Some("aarch64"));
}
}