mux/driver: map a mid-read halt to completed=false (Stop is not a failure)
The finish stage and the highway path already treat Error::Halted as a clean operator stop (completed=false), but the header pump (`stream.read()?`) and the frame pump (`Err(e) => return Err(e)`) propagated it as a hard error. Since slow recovery reads dominate wall-clock, a Stop almost always lands mid-read, so it surfaced as a mux failure instead of a resumable incomplete outcome — breaking the driver's own "a clean operator stop is not an error" contract and diverging from the ISO/Url highway (which returns Ok(None) on halt). Both read arms now route Error::Halted to the completed=false path. Adds error::is_halt(&io::Error) (typed, mirrors is_skippable_title_stub) as the check. Two regression tests cover a halt landing mid-header-read and mid-frame-read.
This commit is contained in:
@@ -912,6 +912,15 @@ pub fn is_skippable_title_stub(e: &std::io::Error) -> bool {
|
||||
matches!(io_error_code(e), Some(E_MKV_INVALID | E_CSS_KEY_MISSING))
|
||||
}
|
||||
|
||||
/// Whether an [`io::Error`](std::io::Error) is a cooperative user stop
|
||||
/// ([`Error::Halted`], code [`E_HALTED`]) — vs a structural failure. A stop is
|
||||
/// resumable, not a rip failure: `mux_stream` maps a mid-run halt to
|
||||
/// `completed = false`, and consumers preserve staging rather than quarantining.
|
||||
/// Typed replacement for the consumers' `E<code>`-leading-token string match.
|
||||
pub fn is_halt(e: &std::io::Error) -> bool {
|
||||
io_error_code(e) == Some(E_HALTED)
|
||||
}
|
||||
|
||||
impl Error {
|
||||
/// Borrow the drive-returned SPC-4 sense triple if this error is a
|
||||
/// [`Error::ScsiError`] carrying sense data. `None` for any other
|
||||
|
||||
Reference in New Issue
Block a user