bothan_lib/worker/error.rs
1// ! Error types for asset workers.
2//!
3//! This module provides error handling functionality for asset workers. It defines
4//! a custom error type that can wrap other errors and provide additional context.
5//!
6//! The module provides:
7//!
8//! - The [`AssetWorkerError`] struct which serves as a universal error type for all worker implementations
9//! - Methods for creating errors with or without source errors
10//! - Implementations of standard error traits
11//!
12//! # Error Handling Strategy
13//!
14//! The error handling strategy in this module follows these principles:
15//!
16//! 1. **Context Preservation**: Errors include both a human-readable message and the original error
17//! 2. **Error Propagation**: The `From` trait implementation allows easy conversion from other error types
18//! 3. **Diagnostic Information**: Errors provide clear and helpful diagnostic information
19//!
20//! When implementing worker types, use this error type to provide consistent error
21//! handling throughout the asset worker system.
22
23use std::error::Error;
24use std::fmt;
25
26/// A custom error type for asset workers that wraps another error with an optional message.
27///
28/// `AssetWorkerError` provides a consistent error type for all asset worker implementations,
29/// allowing errors to be propagated with context. It can be used either as a standalone error
30/// with just a message, or it can wrap another error while adding additional context.
31///
32/// # Examples
33///
34/// Creating a standalone error:
35///
36/// ```
37/// use bothan_lib::worker::error::AssetWorkerError;
38///
39/// let error = AssetWorkerError::new("Failed to initialize worker");
40/// ```
41///
42/// Creating an error that wraps another error:
43///
44/// ```
45/// use bothan_lib::worker::error::AssetWorkerError;
46/// use std::io;
47///
48/// let io_error = io::Error::new(io::ErrorKind::NotFound, "Resource not found");
49/// let error = AssetWorkerError::with_source("Failed to fetch asset data", io_error);
50/// ```
51///
52/// Using the `From` trait for automatic conversion with the `?` operator for any error type that implements the `Error` trait:
53///
54/// ```
55/// use bothan_lib::worker::error::AssetWorkerError;
56/// use std::io;
57///
58/// fn process() -> Result<(), AssetWorkerError> {
59/// // The ? operator automatically converts io::Error to AssetWorkerError using From
60/// let result = std::fs::read_to_string("config.json")?;
61///
62/// // Process the result...
63/// Ok(())
64/// }
65/// ```
66///
67pub struct AssetWorkerError {
68 /// A human-readable error message.
69 pub msg: String,
70
71 /// The optional source error that caused this error.
72 pub source: Option<Box<dyn Error + Send + Sync>>,
73}
74
75impl AssetWorkerError {
76 /// Create a new `AssetWorkerError` with a message.
77 ///
78 /// This method creates a standalone error without a source error.
79 /// Use this when the error originates within the worker code.
80 ///
81 /// # Examples
82 ///
83 /// ```
84 /// use bothan_lib::worker::error::AssetWorkerError;
85 ///
86 /// let error = AssetWorkerError::new("Failed to initialize worker");
87 /// ```
88 pub fn new(msg: impl Into<String>) -> Self {
89 Self {
90 msg: msg.into(),
91 source: None,
92 }
93 }
94
95 /// Create a new `AssetWorkerError` with a message and a source error.
96 ///
97 /// This method creates an error that wraps another error, adding context
98 /// about the operation that was being performed when the error occurred.
99 ///
100 /// # Examples
101 ///
102 /// ```
103 /// use bothan_lib::worker::error::AssetWorkerError;
104 /// use std::io;
105 ///
106 /// let io_error = io::Error::new(io::ErrorKind::NotFound, "Resource not found");
107 /// let error = AssetWorkerError::with_source("Failed to fetch asset data", io_error);
108 /// ```
109 pub fn with_source<E>(msg: impl Into<String>, source: E) -> Self
110 where
111 E: Error + Send + Sync + 'static,
112 {
113 Self {
114 msg: msg.into(),
115 source: Some(Box::new(source)),
116 }
117 }
118}
119
120impl fmt::Display for AssetWorkerError {
121 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122 write!(f, "{}", self.msg)?;
123 if let Some(source) = &self.source {
124 write!(f, ": {}", source)?;
125 }
126 Ok(())
127 }
128}
129
130impl fmt::Debug for AssetWorkerError {
131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132 fmt::Display::fmt(self, f)
133 }
134}
135
136impl<E> From<E> for AssetWorkerError
137where
138 E: Error + Send + Sync + 'static,
139{
140 fn from(err: E) -> Self {
141 Self {
142 msg: format!("An error occurred: {}", err),
143 source: Some(Box::new(err)),
144 }
145 }
146}