From 4c295487364d9575f1689d56432794c55e245dda Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Wed, 4 Mar 2026 22:31:15 +0100 Subject: [PATCH] block: Add BlockError constructors and builder methods Add the construction and inspection API for BlockError, consisting on constructors that accept a kind and optional source, builder methods that attach context after the fact, and accessors for retrieving the kind, context, and typed source references. The builder pattern allows callers to enrich errors at each level of the call stack. Signed-off-by: Anatol Belski --- block/src/error.rs | 76 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/block/src/error.rs b/block/src/error.rs index 13d971685..9ea710c00 100644 --- a/block/src/error.rs +++ b/block/src/error.rs @@ -126,6 +126,82 @@ pub struct BlockError { ctx: Option, } +impl BlockError { + /// Create a new `BlockError` from a kind and a source error. + pub fn new(kind: BlockErrorKind, source: E) -> Self + where + E: StdError + Send + Sync + 'static, + { + Self { + kind, + source: Some(Box::new(source)), + ctx: None, + } + } + + /// Create a `BlockError` from just a kind, with no underlying cause. + pub fn from_kind(kind: BlockErrorKind) -> Self { + Self { + kind, + source: None, + ctx: None, + } + } + + /// Attach or replace the source error (builder-style). + pub fn with_source(mut self, source: E) -> Self + where + E: StdError + Send + Sync + 'static, + { + self.source = Some(Box::new(source)); + self + } + + /// Attach diagnostic context. + pub fn with_ctx(mut self, ctx: ErrorContext) -> Self { + self.ctx = Some(ctx); + self + } + + /// Shorthand: attach an operation name. + pub fn with_op(mut self, op: ErrorOp) -> Self { + self.ctx.get_or_insert_with(ErrorContext::default).op = Some(op); + self + } + + /// Shorthand: attach a file path. + pub fn with_path(mut self, path: impl Into) -> Self { + self.ctx.get_or_insert_with(ErrorContext::default).path = Some(path.into()); + self + } + + /// Shorthand: attach a byte offset. + pub fn with_offset(mut self, offset: u64) -> Self { + self.ctx.get_or_insert_with(ErrorContext::default).offset = Some(offset); + self + } + + /// The error classification. + pub fn kind(&self) -> BlockErrorKind { + self.kind + } + + /// The diagnostic context, if any. + pub fn context(&self) -> Option<&ErrorContext> { + self.ctx.as_ref() + } + + /// Access the underlying source error, if any. + pub fn source_ref(&self) -> Option<&(dyn StdError + Send + Sync + 'static)> { + self.source.as_deref() + } + + /// Try to downcast the source to a concrete type. + pub fn downcast_ref(&self) -> Option<&T> { + self.source.as_ref()?.downcast_ref::() + } +} + impl Display for BlockError { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "{}", self.kind)?;