This branch predates CI on `main`. `cargo fmt --all` only; no behaviour. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
112 lines
4.4 KiB
Rust
112 lines
4.4 KiB
Rust
//! Do `ui_layout`'s two IN-RANGE fallbacks ever fire? Counted, disc-wide.
|
|
//!
|
|
//! An in-range fallback supplies a value that is legitimate, so no output can
|
|
//! distinguish it from the real thing and inspection cannot settle it. The only
|
|
//! question that has an answer is *how often does it fire*.
|
|
//!
|
|
//! ui_layout.rs:1681 kf.time.unwrap_or(0) -- 0 is a real keyframe time
|
|
//! (pose 0's time IS 0), so a fabricated one is invisible.
|
|
//! ui_layout.rs:1010 pose_at(t).map(|k| k.fade >> 24).unwrap_or(0) > 0
|
|
//! -- alpha 0 is legitimate, and it makes "no pose here"
|
|
//! read as "fully transparent", biasing an occlusion test
|
|
//! toward NOT occluded.
|
|
//!
|
|
//! (ui_layout.rs:973's `unwrap_or(0)` is NOT counted: it is guarded two lines
|
|
//! later by `if tmax == 0 { return false; }`, so 0 is handled, not assumed.)
|
|
//!
|
|
//! cargo run -p sylpheed-formats --example inrange_fallback_count
|
|
use std::io::Write;
|
|
use std::path::PathBuf;
|
|
use sylpheed_formats::{pak::PakArchive, ui_layout};
|
|
|
|
fn main() {
|
|
let root = PathBuf::from(std::env::var("SYLPHEED_DISC").expect("SYLPHEED_DISC"));
|
|
let mut paks: Vec<PathBuf> = std::fs::read_dir(root.join("dat"))
|
|
.expect("dat/")
|
|
.filter_map(|e| e.ok().map(|e| e.path()))
|
|
.filter(|p| p.extension().is_some_and(|x| x == "pak"))
|
|
.collect();
|
|
paks.sort();
|
|
let (mut kf, mut untimed, mut builds) = (0u64, 0u64, 0u64);
|
|
let (mut queries, mut none_at) = (0u64, 0u64);
|
|
for pak in &paks {
|
|
let Ok(ar) = PakArchive::open(pak) else {
|
|
continue;
|
|
};
|
|
for e in ar.entries() {
|
|
let Ok(by) = ar.read(e) else { continue };
|
|
if !ui_layout::is_build(&by) {
|
|
continue;
|
|
}
|
|
let Some(b) = ui_layout::parse_build(&by) else {
|
|
continue;
|
|
};
|
|
builds += 1;
|
|
// (a) :1681 -- how many poses carry no time?
|
|
for el in &b.elements {
|
|
for k in &el.keyframes {
|
|
kf += 1;
|
|
if k.time.is_none() {
|
|
untimed += 1
|
|
}
|
|
}
|
|
}
|
|
// (b) :1010 -- ask every element for a pose at every time that any
|
|
// element declares, which is the set the occlusion test draws from.
|
|
let mut times: Vec<u32> = b
|
|
.elements
|
|
.iter()
|
|
.flat_map(|e| e.keyframes.iter().filter_map(|k| k.time))
|
|
.collect();
|
|
times.sort_unstable();
|
|
times.dedup();
|
|
for el in &b.elements {
|
|
for &t in × {
|
|
queries += 1;
|
|
if el.pose_at(t).is_none() {
|
|
none_at += 1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
print!(".");
|
|
std::io::stdout().flush().ok();
|
|
}
|
|
println!();
|
|
println!("{builds} builds, {kf} keyframes");
|
|
println!(":1681 untimed poses (the fallback would fabricate t=0): {untimed}");
|
|
println!(":1010 pose_at queries {queries}, of which None (fallback reads a=0): {none_at}");
|
|
// NEGATIVE CONTROL. Both counters above report 0, and a zero is the result
|
|
// this corpus has learned to distrust most -- it reads clean rather than
|
|
// suspicious. So prove the detector CAN see a hit: ask every element for a
|
|
// pose at a time no build declares. If pose_at is total, `none_out` is 0 too
|
|
// and the 0 above means nothing.
|
|
let mut out_queries = 0u64;
|
|
let mut none_out = 0u64;
|
|
for pak in &paks {
|
|
let Ok(ar) = PakArchive::open(pak) else {
|
|
continue;
|
|
};
|
|
for e in ar.entries() {
|
|
let Ok(by) = ar.read(e) else { continue };
|
|
if !ui_layout::is_build(&by) {
|
|
continue;
|
|
}
|
|
let Some(b) = ui_layout::parse_build(&by) else {
|
|
continue;
|
|
};
|
|
for el in &b.elements {
|
|
for &t in &[u32::MAX, 1_000_000u32] {
|
|
out_queries += 1;
|
|
if el.pose_at(t).is_none() {
|
|
none_out += 1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
println!("CONTROL pose_at at an undeclared time: {out_queries} queries, {none_out} None");
|
|
println!(" (if this is 0 the detector is blind and the 0 above is meaningless)");
|
|
println!("--- END ---");
|
|
}
|