Skip to content

Commit 1eb0e17

Browse files
authored
Merge pull request #221 from ryanoneill/feature/error-other-variant
Add Other(BoxedError) variant to EnvisionError
2 parents fa6edbb + 9fc128c commit 1eb0e17

File tree

1 file changed

+95
-0
lines changed

1 file changed

+95
-0
lines changed

src/error.rs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,22 @@ pub enum EnvisionError {
7070
/// Details about the subscription failure.
7171
detail: String,
7272
},
73+
74+
/// A catch-all variant for wrapping arbitrary errors.
75+
///
76+
/// Use this when an error does not fit into the other structured
77+
/// categories. It wraps any error that implements
78+
/// `std::error::Error + Send + Sync + 'static`.
79+
///
80+
/// # Example
81+
///
82+
/// ```rust
83+
/// use envision::error::EnvisionError;
84+
///
85+
/// let err = EnvisionError::other("something went wrong");
86+
/// assert_eq!(err.to_string(), "other error: something went wrong");
87+
/// ```
88+
Other(BoxedError),
7389
}
7490

7591
impl EnvisionError {
@@ -132,6 +148,29 @@ impl EnvisionError {
132148
detail: detail.into(),
133149
}
134150
}
151+
152+
/// Creates an `Other` error from any error type.
153+
///
154+
/// This is a convenience constructor that wraps an arbitrary error
155+
/// into the [`Other`](EnvisionError::Other) variant, avoiding the
156+
/// need for manual `.map_err()` calls.
157+
///
158+
/// # Example
159+
///
160+
/// ```rust
161+
/// use envision::error::EnvisionError;
162+
///
163+
/// let err = EnvisionError::other("something went wrong");
164+
/// assert_eq!(err.to_string(), "other error: something went wrong");
165+
///
166+
/// // Works with any error type
167+
/// let io_err = std::io::Error::other("disk full");
168+
/// let err = EnvisionError::other(io_err);
169+
/// assert!(err.to_string().contains("disk full"));
170+
/// ```
171+
pub fn other(err: impl Into<BoxedError>) -> Self {
172+
EnvisionError::Other(err.into())
173+
}
135174
}
136175

137176
impl fmt::Display for EnvisionError {
@@ -154,6 +193,7 @@ impl fmt::Display for EnvisionError {
154193
subscription_type, detail
155194
)
156195
}
196+
EnvisionError::Other(err) => write!(f, "other error: {}", err),
157197
}
158198
}
159199
}
@@ -162,6 +202,7 @@ impl std::error::Error for EnvisionError {
162202
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
163203
match self {
164204
EnvisionError::Io(err) => Some(err),
205+
EnvisionError::Other(err) => Some(err.as_ref()),
165206
EnvisionError::Render { .. }
166207
| EnvisionError::Config { .. }
167208
| EnvisionError::Subscription { .. } => None,
@@ -316,4 +357,58 @@ mod tests {
316357
_ => panic!("expected Subscription variant"),
317358
}
318359
}
360+
361+
#[test]
362+
fn other_from_string_error() {
363+
let err = EnvisionError::Other("something went wrong".into());
364+
assert!(matches!(err, EnvisionError::Other(_)));
365+
}
366+
367+
#[test]
368+
fn other_from_custom_error_type() {
369+
#[derive(Debug)]
370+
struct CustomError;
371+
372+
impl fmt::Display for CustomError {
373+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
374+
write!(f, "custom error occurred")
375+
}
376+
}
377+
378+
impl std::error::Error for CustomError {}
379+
380+
let err = EnvisionError::Other(Box::new(CustomError));
381+
assert!(matches!(err, EnvisionError::Other(_)));
382+
assert_eq!(err.to_string(), "other error: custom error occurred");
383+
}
384+
385+
#[test]
386+
fn other_error_display() {
387+
let err = EnvisionError::Other("unexpected failure".into());
388+
assert_eq!(err.to_string(), "other error: unexpected failure");
389+
}
390+
391+
#[test]
392+
fn other_error_source() {
393+
let io_err = std::io::Error::other("inner error");
394+
let err = EnvisionError::Other(Box::new(io_err));
395+
let source = std::error::Error::source(&err);
396+
assert!(source.is_some());
397+
assert_eq!(source.unwrap().to_string(), "inner error");
398+
}
399+
400+
#[test]
401+
fn other_convenience_constructor() {
402+
let err = EnvisionError::other("convenience test");
403+
assert!(matches!(err, EnvisionError::Other(_)));
404+
assert_eq!(err.to_string(), "other error: convenience test");
405+
}
406+
407+
#[test]
408+
fn other_convenience_constructor_with_io_error() {
409+
let io_err = std::io::Error::other("disk full");
410+
let err = EnvisionError::other(io_err);
411+
assert!(matches!(err, EnvisionError::Other(_)));
412+
assert!(err.to_string().contains("disk full"));
413+
}
319414
}

0 commit comments

Comments
 (0)