v0.13.0: zero English in library + API hygiene + dead-code sweep

Audit pass against the CLAUDE.md "no English text in library code" rule.
Found 9 call sites that violated the contract by stuffing English into
io::Error::new(kind, "…") or by abusing Error::DeviceNotFound { path }
as a free-form description field. Each is now a typed Error variant.

New variants and codes: ScsiInterfaceUnavailable (E1004), DeviceLocked
(E1005), IoKitPluginFailed (E1006), UnsupportedPlatform (E2003),
PlatformNotImplemented (E2004), MapfileInvalid (E6011), DiscUrlNotDirect
(E9009).

labels::apply() previously pushed Commentary/Descriptive/Score/IME and
" (Secondary)" English literals into AudioStream.label, leaking into
MKV titles + autorip UI. AudioStream now exposes structured `purpose:
LabelPurpose`, SubtitleStream `qualifier: LabelQualifier`. Callers
translate to localized text. label keeps codec-formatting only.

API hygiene: 11 mux/* modules dropped from `pub` to `pub(crate)` —
their *types* are still re-exported from lib.rs, but the modules were
leaking low-level EBML/TS/network primitives. Stream trait gets a real
rustdoc explaining read-vs-write split. lib.rs grouped re-exports into
documented sections. ScanOptions::with_keydb() removed (one-method-per-
action rule); use struct literal.

Dead-code sweep: removed lookahead.rs (orphan, never declared as mod),
tsreader.rs (TsDemuxReader unused), ebml::{write_int,read_vint,SEEK_*},
ts::{scan_first/last_pts,scan_duration,SCAN_HEAD/TAIL_SIZE,take/set_
remainder}, MkvMuxer codec_private_slots/filled fields and
fill_codec_private method (deferred-codecPrivate path never used since
the v0.10 PES rewrite). cargo clippy --all-targets -D warnings clean.

Tests: new error::tests for variant codes + Display "no English" guard +
io::ErrorKind mapping. 233 lib tests, all green (was 230).

Breaking: ScanOptions::with_keydb removed; mux/* modules pub(crate);
AudioStream and SubtitleStream gained required fields; UnsupportedDrive
{ product_revision: "Renesas not yet implemented" } no longer produced
(use PlatformNotImplemented).
This commit is contained in:
2026-04-24 16:41:02 -07:00
parent a0584aa9f1
commit 6fee7ae583
29 changed files with 651 additions and 544 deletions
+6 -1
View File
@@ -361,7 +361,9 @@ fn aacs_cross_validation_encrypt_then_decrypt() {
plaintext[off] = 0x47;
off += 192;
}
// Fill the rest with a recognisable pattern (prime modulus avoids artefacts)
// Fill the rest with a recognisable pattern (prime modulus avoids artefacts).
// Index-arithmetic — clearer with a counted loop than an enumerate chain.
#[allow(clippy::needless_range_loop)]
for i in 16..aacs::ALIGNED_UNIT_LEN {
if plaintext[i] == 0 {
plaintext[i] = (i % 251) as u8;
@@ -462,6 +464,7 @@ fn aacs_bus_decrypt_cross_validation() {
];
let mut plaintext = vec![0u8; aacs::ALIGNED_UNIT_LEN];
#[allow(clippy::needless_range_loop)]
for i in 0..aacs::ALIGNED_UNIT_LEN {
plaintext[i] = ((i * 3 + 17) & 0xFF) as u8;
}
@@ -494,6 +497,7 @@ fn css_roundtrip_with_snapshot() {
let mut sector = vec![0x00u8; 2048];
sector[0x14] = 0x30;
sector[0x54..0x59].copy_from_slice(&[0xDE, 0xAD, 0xBE, 0xEF, 0x42]);
#[allow(clippy::needless_range_loop)]
for i in 0x80..2048 {
sector[i] = ((i * 7 + 3) & 0xFF) as u8;
}
@@ -661,6 +665,7 @@ fn css_recover_title_key_with_exact_plaintext() {
sector[0x54..0x59].copy_from_slice(&seed);
let pes_header: [u8; 10] = [0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x80, 0x80, 0x05, 0x21];
sector[0x80..0x8A].copy_from_slice(&pes_header);
#[allow(clippy::needless_range_loop)]
for i in 0x8A..2048 {
sector[i] = ((i * 13 + 7) & 0xFF) as u8;
}