block: Add BlockError struct with Display and Error impls

Add the single public crate error type. It combines a
BlockErrorKind for classification, an optional boxed source
for the underlying cause, and an optional ErrorContext for
diagnostics. Display renders the kind and context only,
leaving source traversal to error reporters so the cause
chain is not duplicated in human readable output.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This commit is contained in:
Anatol Belski
2026-03-04 22:29:54 +01:00
committed by Rob Bradford
parent 55504177cb
commit d5467dca8e
+40 -6
View File
@@ -16,6 +16,7 @@
//! +-- io::Error / etc. //! +-- io::Error / etc.
//! ``` //! ```
use std::error::Error as StdError;
use std::fmt::{self, Display, Formatter}; use std::fmt::{self, Display, Formatter};
use std::path::PathBuf; use std::path::PathBuf;
@@ -46,12 +47,12 @@ impl Display for BlockErrorKind {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self { match self {
Self::Io => write!(f, "I/O error"), Self::Io => write!(f, "I/O error"),
Self::InvalidFormat => write!(f, "invalid format"), Self::InvalidFormat => write!(f, "Invalid format"),
Self::UnsupportedFeature => write!(f, "unsupported feature"), Self::UnsupportedFeature => write!(f, "Unsupported feature"),
Self::CorruptImage => write!(f, "corrupt image"), Self::CorruptImage => write!(f, "Corrupt image"),
Self::OutOfBounds => write!(f, "out of bounds"), Self::OutOfBounds => write!(f, "Out of bounds"),
Self::NotFound => write!(f, "not found"), Self::NotFound => write!(f, "Not found"),
Self::Overflow => write!(f, "overflow"), Self::Overflow => write!(f, "Overflow"),
} }
} }
} }
@@ -109,3 +110,36 @@ impl Display for ErrorContext {
Ok(()) Ok(())
} }
} }
/// Unified error type for the block crate.
///
/// Pairs a stable [`BlockErrorKind`] classification with an optional
/// boxed source error (format-specific) and optional [`ErrorContext`].
///
/// Display renders kind + context only; the underlying cause is
/// exposed via [`std::error::Error::source()`] for reporters that
/// walk the chain.
#[derive(Debug)]
pub struct BlockError {
kind: BlockErrorKind,
source: Option<Box<dyn StdError + Send + Sync + 'static>>,
ctx: Option<ErrorContext>,
}
impl Display for BlockError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.kind)?;
if let Some(ctx) = &self.ctx {
write!(f, " ({ctx})")?;
}
Ok(())
}
}
impl StdError for BlockError {
fn source(&self) -> Option<&(dyn StdError + 'static)> {
self.source
.as_ref()
.map(|e| e.as_ref() as &(dyn StdError + 'static))
}
}