80 findings, not the 14 the first run showed -- clippy stops at the first failing compilation unit, so `--keep-going` is what makes the list complete. 60 were machine-applicable (`cargo clippy --fix`). The rest by hand: * five descending `sort_by` -> `sort_by_key(Reverse(..))` * `chunks_exact(4)` on both sides of four zips, so the compared items stay `[u8; 4]` rather than one array against one slice * three `type` aliases for the census maps and the captured-quad tuple * `&PathBuf` -> `&Path` in two disc tests * two range loops; one of them keeps `#[allow(needless_range_loop)]` with the reason -- the index is into a map's value, which changes each iteration * the module doc list in `invert_capture` re-indented to markdown's rules * `blit`'s eight arguments get `#[allow(too_many_arguments)]`, not a struct One dead `let off = b.len();` in a `ratc` test is dropped rather than renamed. The sibling test at :162 is the one that asserts an offset; if this one was meant to as well, that is a test change and not a lint fix. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
108 lines
4.2 KiB
Rust
108 lines
4.2 KiB
Rust
//! Control for the new public accessor `ui_layout::sprite_blend_additive`.
|
|
//!
|
|
//! `blend_vs_t8ad_bit` established the field by reading the `T8aD` header inline.
|
|
//! The exporter cannot do that — `Element` exposed nothing at `+0x04`, which is
|
|
//! why a blend map keyed by SCREEN NAME had to be authored, and why the Japanese
|
|
//! menus were being asserted-by-omission to blend differently from the English
|
|
//! ones. This checks the accessor the exporter will actually call, against the
|
|
//! same 35 oracle rows, so a later refactor cannot silently change the field.
|
|
//!
|
|
//! cargo run -p sylpheed-formats --example blend_api_check
|
|
use std::path::PathBuf;
|
|
use sylpheed_formats::{pak::PakArchive, ui_layout};
|
|
|
|
/// (build entry, sprite, measured additive?) — from `data/blend-bit-vs-oracle.txt`,
|
|
/// every label an `RB_BLENDCONTROL0` value read out of the guest command stream.
|
|
const MEASURED: &[(usize, &str, bool)] = &[
|
|
(4, "ptbase2.t32", false),
|
|
(4, "ptlogo1.t32", false),
|
|
(4, "ptlogo2.t32", false),
|
|
(4, "ptlogo_tm.t32", false),
|
|
(4, "ptcopyright.t32", false),
|
|
(4, "ptlogo_back2.t32", false),
|
|
(4, "ptlogo_back2eff.t32", false),
|
|
(2, "ptbtn00.t32", false),
|
|
(2, "ptbtn00f.t32", true),
|
|
(5, "ptbase.t32", false),
|
|
(5, "ptmsg.t32", false),
|
|
(5, "ptbtn01f.t32", false),
|
|
(5, "ptbtneff01.t32", false),
|
|
(5, "pteff10.t32", true),
|
|
(5, "pteff12.t32", true),
|
|
(6, "pteff21.t32", true),
|
|
(6, "pteff22.t32", true),
|
|
(6, "pteff23.t32", true),
|
|
(6, "ptframe3.t32", true),
|
|
(6, "ptframe4.t32", true),
|
|
(6, "pteff03.t32", true),
|
|
(6, "pteff03a.t32", true),
|
|
];
|
|
|
|
fn main() {
|
|
let root = PathBuf::from(std::env::var("SYLPHEED_DISC").expect("SYLPHEED_DISC"));
|
|
let ar = PakArchive::open(root.join("dat/GP_TITLE.pak")).expect("GP_TITLE");
|
|
let (mut ok, mut bad, mut missing) = (0, 0, 0);
|
|
println!(
|
|
"{:<7} {:<22} {:<10} {:<10} ",
|
|
"entry", "sprite", "expected", "accessor"
|
|
);
|
|
for e in [2usize, 4, 5, 6] {
|
|
let by = ar.read(&ar.entries()[e]).expect("entry");
|
|
let b = ui_layout::parse_build(&by).expect("build");
|
|
for &(oe, name, additive) in MEASURED {
|
|
if oe != e {
|
|
continue;
|
|
}
|
|
// Prefer the Element accessor; fall back to the by-name one for
|
|
// focused variants, which are reached through `opt ` and carry no
|
|
// top-level element of their own.
|
|
let got = b
|
|
.elements
|
|
.iter()
|
|
.find(|x| x.sprite.as_deref() == Some(name))
|
|
.and_then(|el| ui_layout::sprite_blend_additive(&b, &by, el))
|
|
.or_else(|| ui_layout::blend_additive_by_name(&b, &by, name));
|
|
if got.is_none() {
|
|
println!("{e:<7} {name:<22} {additive:<10} {:<10} MISSING", "-");
|
|
missing += 1;
|
|
continue;
|
|
}
|
|
match got {
|
|
Some(g) if g == additive => {
|
|
ok += 1;
|
|
println!("{e:<7} {name:<22} {additive:<10} {g:<10} OK");
|
|
}
|
|
other => {
|
|
bad += 1;
|
|
println!("{e:<7} {name:<22} {additive:<10} {other:?} MISMATCH");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
println!(
|
|
"\n{ok} agree, {bad} mismatched, {missing} not found (of {})",
|
|
MEASURED.len()
|
|
);
|
|
// The control that removes the test's own subject: the accessor must also
|
|
// report a MIX. An accessor stuck at one value would pass every `false` row.
|
|
let by = ar.read(&ar.entries()[6]).expect("entry");
|
|
let b = ui_layout::parse_build(&by).expect("build");
|
|
let add = b
|
|
.elements
|
|
.iter()
|
|
.filter(|e| ui_layout::sprite_blend_additive(&b, &by, e) == Some(true))
|
|
.count();
|
|
let over = b
|
|
.elements
|
|
.iter()
|
|
.filter(|e| ui_layout::sprite_blend_additive(&b, &by, e) == Some(false))
|
|
.count();
|
|
println!("control -- entry 6 must report BOTH values: additive={add} alpha-over={over}");
|
|
assert!(add > 0 && over > 0, "accessor is not discriminating");
|
|
assert_eq!(
|
|
bad, 0,
|
|
"the public accessor disagrees with the committed oracle"
|
|
);
|
|
println!("PASS");
|
|
}
|