v0.20.1: delete SectorReader, extract Disc::patch, doc/stub cleanup

WO-2 (delete SectorReader trait):
- The 0.18 trait split into SectorSource (read-only) and SectorSink
  (write-only) is final; the legacy SectorReader alias was a bridge.
- Renames every internal &mut dyn SectorReader (~25 sites) to
  &mut dyn SectorSource. The trait method capacity() becomes
  capacity_sectors() with a default of 0 (preserves SectorReader's
  default-0 behavior).
- Deletes the SectorReader trait, its blanket-to-Source bridge, and
  the FileSectorReader type alias. Adds explicit forwarding impls
  for Box<dyn SectorSource> and &mut dyn SectorSource so generic
  decorators like DecryptingSectorSource<S: SectorSource> compose.

WO-3a (extract Disc::patch):
- Moves Disc::patch (1230 lines) and bytes_bad_in_title from
  disc/mod.rs into disc/patch.rs as a split inherent impl. Zero
  behavior change — pure mechanical relocation. disc/mod.rs drops
  from 3,945 to 2,714 LOC.

WO-6 (partial):
- Deletes src/labels/png_filenames.rs — was a 72-LOC stub with
  detect() returning false, never wired into the PARSERS registry.

project docs doc drift fixes (audited 2026-05-13):
- JUMP_BASE_SECTORS: 256→1024 (64 MB base for UHD, not 8 MB)
- PASSN_DAMAGE_THRESHOLD_PCT: 12→6
- PASSN_SKIP_SECTORS_BASE: 64→32
- MAX_RANGE_SECS=180: replaced by proportional range_sectors × 25,
  capped at RANGE_BUDGET_CAP_SECS=1800.
This commit is contained in:
MattJackson
2026-05-13 11:36:55 -07:00
parent 4709a73c80
commit f1926c38dc
34 changed files with 1443 additions and 1597 deletions
+5 -5
View File
@@ -5,7 +5,7 @@
//! menu_base.prop provides stream number → button name mapping.
use super::{LabelPurpose, LabelQualifier, ParseResult, StreamLabel, StreamLabelType, vocab};
use crate::sector::SectorReader;
use crate::sector::SectorSource;
use crate::udf::UdfFs;
use std::collections::HashMap;
@@ -14,7 +14,7 @@ pub fn detect(udf: &UdfFs) -> bool {
|| super::jar_file_exists(udf, "language_streams.txt")
}
pub fn parse(reader: &mut dyn SectorReader, udf: &UdfFs) -> Option<ParseResult> {
pub fn parse(reader: &mut dyn SectorSource, udf: &UdfFs) -> Option<ParseResult> {
// Try language_streams.txt first (richer structured data)
let ls_labels = parse_language_streams(reader, udf);
@@ -55,7 +55,7 @@ fn merge(ls: Vec<StreamLabel>, mb: Vec<StreamLabel>) -> Vec<StreamLabel> {
// ── language_streams.txt parser ────────────────────────────────────────────
fn parse_language_streams(reader: &mut dyn SectorReader, udf: &UdfFs) -> Option<Vec<StreamLabel>> {
fn parse_language_streams(reader: &mut dyn SectorSource, udf: &UdfFs) -> Option<Vec<StreamLabel>> {
let data = super::read_jar_file(reader, udf, "language_streams.txt")?;
let text = std::str::from_utf8(&data).ok()?;
@@ -184,7 +184,7 @@ mod tests {
/// Build a minimal menu_base.prop text and run `parse_menu_base`'s
/// inner logic via a temporary closure. This isolates the prop
/// parsing without needing a SectorReader.
/// parsing without needing a SectorSource.
fn parse_props(text: &str) -> Vec<StreamLabel> {
// Mirror the inner loop of parse_menu_base exactly. Kept
// separate so the test doesn't need disc fixtures.
@@ -338,7 +338,7 @@ mod tests {
// ── menu_base.prop parser ──────────────────────────────────────────────────
fn parse_menu_base(reader: &mut dyn SectorReader, udf: &UdfFs) -> Option<Vec<StreamLabel>> {
fn parse_menu_base(reader: &mut dyn SectorSource, udf: &UdfFs) -> Option<Vec<StreamLabel>> {
let data = super::read_jar_file(reader, udf, "menu_base.prop")?;
let text = std::str::from_utf8(&data).ok()?;