`cargo fmt --all -- --check` has failed on every run in this repository's history, identically on `main` and on every branch. This is #12. Mechanical: `cargo fmt --all`, nothing else. 154 files, all `.rs`, no other extension touched. `cargo check --workspace` exits 0 afterwards, so nothing changed semantically. ON THE ORDERING, WHICH WAS THE REAL QUESTION. HANDOFF-2026-09-06 section 7 warns this is the expensive fix: a whole-tree reformat before #7 and #8 return "would put a conflict in every file of 861 commits and make the reviews those items exist to enable unreadable". That is measurably too pessimistic, and it had been reasoned rather than tested. Measured here by three-way merging a rustfmt'd `main` against both unmerged branches, file by file: file/branch pairs tested 32 merges CLEAN 28 merges CONFLICTING 4 (8 conflict hunks total) sylpheed-cli/src/main.rs 1 hunk sylpheed-export/src/check.rs 1 sylpheed-export/src/screen.rs 4 sylpheed-export/src/video.rs 2 All four are against `auto/frame-blend-draw-path` only; `auto/port-p6-audio` does not conflict anywhere. The earlier framing -- 154 dirty files, 133 that cannot collide, 21 that can, the collision set carrying 147 of 774 hunks (19%) -- reproduces exactly. What it did not say is that most of the 21 still merge cleanly, because rustfmt's edits and the branches' edits rarely land on the same lines. So the cost of sweeping now is 4 files and 8 hunks for one branch, against a check that is otherwise red forever. Deliberately NOT folded into the WASM PR: 154 reformatted files would make that one unreviewable. Closes #12
85 lines
3.5 KiB
Rust
85 lines
3.5 KiB
Rust
//! Is a RATC child's name the printable run before its magic, or the `opt ` block?
|
|
//!
|
|
//! `ratc::parse` names each child by scanning backwards for the ASCII run that
|
|
//! precedes its magic. That is usually right, but it is a HEURISTIC, and the
|
|
//! real format states the name explicitly: immediately before each child sits
|
|
//!
|
|
//! "opt " | BE32 length | name | NUL | 3 bytes | <child magic>
|
|
//!
|
|
//! -- the same `opt ` block `ui_layout::opt_link` already decodes for a button's
|
|
//! focus link. When those 3 trailing bytes happen to be printable the heuristic
|
|
//! reads THEM as the name: the title screens' full-resolution background comes
|
|
//! out as `8AX` (bytes 38 41 58) instead of `pteff05.t32`, its element then
|
|
//! resolves to no sprite, and `compose` drops the screen's background.
|
|
//!
|
|
//! This compares the two readings for every RATC child in the paks given.
|
|
//!
|
|
//! cargo run -p sylpheed-formats --example ratc_child_names -- <pak>...
|
|
use sylpheed_formats::{pak, ratc};
|
|
|
|
/// The name stated by the `opt ` block that ends just before `at`.
|
|
fn opt_name(buf: &[u8], at: usize) -> Option<String> {
|
|
// The block is short; search back a bounded window for the tag.
|
|
let lo = at.saturating_sub(128);
|
|
let win = &buf[lo..at];
|
|
let pos = lo + win.windows(4).rposition(|w| w == b"opt ")?;
|
|
let len = u32::from_be_bytes(buf[pos + 4..pos + 8].try_into().ok()?) as usize;
|
|
if len == 0 || len > 64 || pos + 8 + len > at {
|
|
return None;
|
|
}
|
|
let s = String::from_utf8_lossy(&buf[pos + 8..pos + 8 + len]).to_string();
|
|
// It must be THIS child's block: name, NUL, then a short run to the magic.
|
|
if at - (pos + 8 + len) > 8 {
|
|
return None;
|
|
}
|
|
(!s.is_empty() && s.chars().all(|c| c.is_ascii_graphic())).then_some(s)
|
|
}
|
|
|
|
fn main() {
|
|
let mut children = 0usize;
|
|
let mut with_opt = 0usize;
|
|
let mut agree = 0usize;
|
|
let mut disagree: Vec<(String, usize, String, String)> = Vec::new();
|
|
for path in std::env::args().skip(1) {
|
|
let Ok(ar) = pak::PakArchive::open(&path) else {
|
|
continue;
|
|
};
|
|
let short = path.rsplit('/').next().unwrap_or(&path).to_string();
|
|
let entries: Vec<_> = ar.entries().to_vec();
|
|
for (i, e) in entries.iter().enumerate() {
|
|
let Ok(bytes) = ar.read(e) else { continue };
|
|
let Some(kids) = ratc::parse(&bytes) else {
|
|
continue;
|
|
};
|
|
for c in &kids {
|
|
children += 1;
|
|
let Some(o) = opt_name(&bytes, c.offset) else {
|
|
continue;
|
|
};
|
|
with_opt += 1;
|
|
if o == c.name {
|
|
agree += 1;
|
|
} else {
|
|
disagree.push((short.clone(), i, c.name.clone(), o));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
println!("RATC children scanned : {children}");
|
|
println!(" with an `opt ` block: {with_opt}");
|
|
println!(" scanned name AGREES : {agree}");
|
|
println!(" scanned name DIFFERS : {}", disagree.len());
|
|
let mut by_pair: std::collections::BTreeMap<(String, String), usize> = Default::default();
|
|
for (_, _, scanned, opt) in &disagree {
|
|
*by_pair.entry((scanned.clone(), opt.clone())).or_default() += 1;
|
|
}
|
|
println!("\ndistinct disagreements (scanned -> opt), with counts:");
|
|
for ((s, o), n) in &by_pair {
|
|
println!(" {s:24} -> {o:24} x{n}");
|
|
}
|
|
println!("\nfirst 20 occurrences:");
|
|
for (p, i, s, o) in disagree.iter().take(20) {
|
|
println!(" {p} entry {i:4} {s:20} -> {o}");
|
|
}
|
|
}
|