Skip to main content

orion_error/traits/
contextual.rs

1use crate::core::OperationContext;
2
3/// Extension methods for attaching operation context and position to an error.
4///
5/// [`doing("...")`](ErrorWith::doing) and [`at("...")`](ErrorWith::at) are the
6/// primary ways to annotate where and what was happening when the error occurred.
7///
8/// Implemented for [`StructError`](crate::StructError) and
9/// `Result<T, E>` where `E: ErrorWith`.
10///
11/// # Example
12///
13/// ```rust
14/// use orion_error::prelude::*;
15/// use orion_error::UnifiedReason;
16///
17/// let err = StructError::from(UnifiedReason::validation_error())
18///     .doing("parse config")      // what operation
19///     .at("config.toml");          // what resource
20///
21/// assert_eq!(err.action_main().as_deref(), Some("parse config"));
22/// assert_eq!(err.locator_main().as_deref(), Some("config.toml"));
23///
24/// // doing/at also works on Result chains:
25/// let result: Result<(), StructError<UnifiedReason>> =
26///     Err(StructError::from(UnifiedReason::validation_error()))
27///         .doing("validate")
28///         .at("input.json");
29/// assert!(result.is_err());
30/// ```
31pub trait ErrorWith {
32    fn position<S: Into<String>>(self, desc: S) -> Self;
33    fn with_context<C: Into<OperationContext>>(self, ctx: C) -> Self;
34    fn doing<S: Into<String>>(self, desc: S) -> Self
35    where
36        Self: Sized,
37    {
38        self.with_context(OperationContext::doing(desc))
39    }
40    fn at<C: Into<OperationContext>>(self, ctx: C) -> Self
41    where
42        Self: Sized,
43    {
44        self.with_context(ctx.into().into_at_context())
45    }
46}
47
48impl<T, E: ErrorWith> ErrorWith for Result<T, E> {
49    fn position<S: Into<String>>(self, desc: S) -> Self {
50        self.map_err(|e| e.position(desc))
51    }
52    fn with_context<C: Into<OperationContext>>(self, ctx: C) -> Self {
53        self.map_err(|e| e.with_context(ctx))
54    }
55}