From 17694af625364dbf8552b285f379efcd90f68d06 Mon Sep 17 00:00:00 2001 From: MattJackson Date: Tue, 28 Jul 2026 12:45:58 -0700 Subject: [PATCH] error: add is_disc_level_no_key classifier (re-exported) Distinguishes a WHOLE-DISC key failure (E_NO_DISC_KEY / E_KEYDB_LOAD / E_AACS_NO_KEYS -- every title fails identically) from a per-title skippable stub. The engine's multi-title loop uses it to fail-fast on the first no-key title instead of iterating all N. Additive. --- src/error.rs | 15 +++++++++++++++ src/lib.rs | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/error.rs b/src/error.rs index 19254a8..4f06d44 100644 --- a/src/error.rs +++ b/src/error.rs @@ -929,6 +929,21 @@ pub fn is_halt(e: &std::io::Error) -> bool { io_error_code(e) == Some(E_HALTED) } +/// Whether an [`io::Error`](std::io::Error) is a **disc-level** key failure — +/// the disc as a whole cannot be decrypted, so EVERY title will fail the same +/// way. Distinct from a per-title skippable stub +/// ([`is_skippable_title_stub`]): `E_NO_DISC_KEY` (keydb present but no entry +/// for this disc), `E_KEYDB_LOAD` (no keydb at all), and `E_AACS_NO_KEYS` (no +/// usable AACS key material) are all whole-disc conditions. A multi-title rip +/// loop should stop immediately on this (fail-fast) rather than iterate every +/// title re-printing the same error. +pub fn is_disc_level_no_key(e: &std::io::Error) -> bool { + matches!( + io_error_code(e), + Some(E_NO_DISC_KEY | E_KEYDB_LOAD | E_AACS_NO_KEYS) + ) +} + impl Error { /// Borrow the drive-returned SPC-4 sense triple if this error is a /// [`Error::ScsiError`] carrying sense data. `None` for any other diff --git a/src/lib.rs b/src/lib.rs index e2e24c6..96bae02 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -155,7 +155,7 @@ pub use session::{ // All fallible APIs return `Result`. `Error` is a typed enum with a // numeric `code()`; **no English text in the library** — applications map // codes to localized messages. See `error.rs` for the full taxonomy. -pub use error::{Error, Result, is_halt, is_skippable_title_stub}; +pub use error::{Error, Result, is_disc_level_no_key, is_halt, is_skippable_title_stub}; // ─── Cooperative cancellation ─────────────────────────────────────────────── //