bigerror/
context.rs

1use derive_more as dm;
2
3#[cfg(not(feature = "std"))]
4use core::time::Duration;
5#[cfg(feature = "std")]
6use std::{path::Path, time::Duration};
7
8#[cfg(not(feature = "std"))]
9use alloc::{boxed::Box, format};
10
11use error_stack::Context;
12
13use crate::{
14    Index, Report, ThinContext,
15    attachment::{self, Display, FromTo, Unsupported, simple_type_name},
16    ty,
17};
18
19#[cfg(feature = "std")]
20use crate::AttachExt;
21
22use crate::{Field, attachment::DisplayDuration};
23
24/// Used to encapsulate opaque `dyn core::error::Error` types.
25///
26/// This wrapper allows you to work with arbitrary error types in a uniform way
27/// while preserving the original error information.
28#[derive(Debug, dm::Display)]
29#[display("{_0}")]
30pub struct BoxError(Box<dyn core::error::Error + 'static + Send + Sync>);
31impl ::core::error::Error for BoxError {}
32
33/// Represents errors emitted while processing bytes into an object.
34///
35/// This error type is commonly used by:
36/// * Codecs, serializers, and deserializers
37/// * Byte types such as `&[u8]`, `bytes::Bytes`, and `Vec<u8>`
38///
39/// Examples of types/traits that can emit decode errors:
40/// * [tonic::codec::Encoder](https://docs.rs/tonic/latest/tonic/codec/trait.Encoder.html)
41/// * [rkyv AllocSerializer](https://docs.rs/rkyv/latest/rkyv/ser/serializers/type.AllocSerializer.html)
42/// * [serde::Serializer](https://docs.rs/serde/latest/serde/trait.Serializer.html)
43#[derive(ThinContext)]
44#[bigerror(crate)]
45pub struct DecodeError;
46
47/// Represents errors emitted while turning an object into bytes.
48///
49/// This is the counterpart to [`DecodeError`] and is used in serialization,
50/// encoding, and similar byte-generation operations.
51#[derive(ThinContext)]
52#[bigerror(crate)]
53pub struct EncodeError;
54
55/// Represents errors emitted during authorization or verification checks.
56///
57/// This error type is used for authentication failures, permission denials,
58/// token validation errors, and similar security-related issues.
59#[derive(ThinContext)]
60#[bigerror(crate)]
61pub struct AuthError;
62
63/// Represents errors related to network operations.
64///
65/// This includes connection failures, timeouts, DNS resolution errors,
66/// and other network-related issues.
67#[derive(ThinContext)]
68#[bigerror(crate)]
69pub struct NetworkError;
70
71/// Represents errors emitted while processing strings (UTF-8 or otherwise).
72///
73/// This error type is commonly associated with:
74/// * The [`std::str::FromStr`] trait
75/// * The `.parse::<T>()` method
76/// * String validation and formatting operations
77#[derive(ThinContext)]
78#[bigerror(crate)]
79pub struct ParseError;
80
81/// Represents the conversion of an `Option<T>::None` into a [`Report`].
82///
83/// This error type is used when an expected value is missing, such as:
84/// * Missing keys in maps or dictionaries
85/// * Missing fields in data structures
86/// * Failed lookups or searches
87#[derive(ThinContext)]
88#[bigerror(crate)]
89pub struct NotFound;
90
91/// Represents errors related to database operations.
92///
93/// This includes connection errors, query failures, transaction issues,
94/// and other database-related problems.
95#[derive(ThinContext)]
96#[bigerror(crate)]
97pub struct DbError;
98
99/// Represents errors related to filesystem operations.
100///
101/// This includes file I/O errors, permission issues, path problems,
102/// and other filesystem-related operations such as those in [`std::fs`].
103#[derive(ThinContext)]
104#[bigerror(crate)]
105pub struct FsError;
106
107/// Represents errors emitted during the startup or provisioning phase of a program.
108///
109/// This includes configuration loading, resource initialization,
110/// dependency setup, and other bootstrap-related failures.
111#[derive(ThinContext)]
112#[bigerror(crate)]
113pub struct SetupError;
114
115/// Represents errors emitted during transformations between complex data types.
116///
117/// This error type is used for conversions between [non-scalar types](https://en.wikipedia.org/w/index.php?title=Scalar_processor&useskin=vector#Scalar_data_type)
118/// such as structs, enums, and unions. It's commonly used in type conversion,
119/// data mapping, and transformation operations.
120#[derive(ThinContext)]
121#[bigerror(crate)]
122pub struct ConversionError;
123
124/// Represents errors for invalid input data or parameters.
125///
126/// This error type is used when input validation fails, including:
127/// * Invalid parameter values
128/// * Malformed input data
129/// * Out-of-range values
130/// * Format violations
131#[derive(ThinContext)]
132#[bigerror(crate)]
133pub struct InvalidInput;
134
135/// Represents errors for invalid status conditions.
136///
137/// This error type is used when an operation encounters an unexpected
138/// or invalid status, such as state machine violations or status checks.
139#[derive(ThinContext)]
140#[bigerror(crate)]
141pub struct InvalidStatus;
142
143/// Represents errors for invalid state conditions.
144///
145/// This error type is used when an object or system is in an invalid state
146/// for the requested operation, including state machine violations and
147/// precondition failures.
148#[derive(ThinContext)]
149#[bigerror(crate)]
150pub struct InvalidState;
151
152/// Represents errors related to configuration issues.
153///
154/// This error type is emitted during runtime and indicates problems with:
155/// * Configuration file parsing
156/// * Invalid configuration values
157/// * Missing required settings
158/// * Default setting conflicts
159#[derive(ThinContext)]
160#[bigerror(crate)]
161pub struct ConfigError;
162
163/// Represents errors related to build processes.
164///
165/// This error type is typically emitted by:
166/// * `build.rs` script failures
167/// * Compilation errors
168/// * Build tool issues
169/// * Asset generation problems
170#[derive(ThinContext)]
171#[bigerror(crate)]
172pub struct BuildError;
173
174/// Represents a timeout error with duration information.
175///
176/// This error type wraps a [`Duration`] and provides formatted output
177/// showing the timeout value in a human-readable format.
178#[derive(Debug, dm::Display)]
179#[display("{}", Field::new("timeout", DisplayDuration(self.0)))]
180pub struct Timeout(pub Duration);
181impl ::core::error::Error for Timeout {}
182
183/// Represents errors from failed assertions or invariant violations.
184///
185/// This error type is used for assertion failures, contract violations,
186/// and other conditions that should never occur in correct program execution.
187#[derive(ThinContext)]
188#[bigerror(crate)]
189pub struct AssertionError;
190
191/// Trait for core error types that can be used in error reporting.
192///
193/// This trait combines the essential bounds needed for error types:
194/// `Debug`, `Display`, `Send`, `Sync`, and `'static`.
195pub trait CoreError: core::fmt::Debug + core::fmt::Display + Send + Sync + 'static {}
196
197impl<T> CoreError for T where T: core::fmt::Debug + core::fmt::Display + Send + Sync + 'static {}
198
199impl BoxError {
200    /// Create a new `BoxError` report from any error type.
201    ///
202    /// This method boxes the error and wraps it in a `Report`.
203    #[track_caller]
204    pub fn new<E>(err: E) -> Report<Self>
205    where
206        E: core::error::Error + 'static + Send + Sync,
207    {
208        Report::new(Self(Box::new(err)))
209    }
210
211    /// Create a `BoxError` report from an already-boxed error.
212    #[track_caller]
213    pub fn from(err: Box<dyn core::error::Error + 'static + Send + Sync>) -> Report<Self> {
214        Report::new(Self(err))
215    }
216}
217
218impl FsError {
219    /// Create a filesystem error with path information.
220    ///
221    /// This method creates an `FsError` report and attaches the path
222    /// that caused the error for better debugging.
223    #[cfg(feature = "std")]
224    #[track_caller]
225    pub fn with_path(path: impl AsRef<Path>) -> Report<Self> {
226        let path = path.as_ref().display().to_string();
227        Report::new(Self).attach_kv("path", path)
228    }
229}
230
231impl InvalidInput {
232    /// Create an invalid input error with path information.
233    ///
234    /// This method creates an `InvalidInput` report and attaches the path
235    /// that contained the invalid input.
236    #[cfg(feature = "std")]
237    #[track_caller]
238    pub fn with_path(path: impl AsRef<Path>) -> Report<Self> {
239        let path = path.as_ref().display().to_string();
240        Report::new(Self).attach_kv("path", path)
241    }
242
243    /// Create an invalid input error with type information.
244    ///
245    /// This method creates an `InvalidInput` report and attaches the type
246    /// name that was invalid.
247    #[track_caller]
248    pub fn type_name<T: ?Sized>() -> Report<Self> {
249        let type_name = simple_type_name::<T>();
250        Report::new(Self).attach(format!("type: {type_name}"))
251    }
252
253    /// Create an invalid input error for unsupported operations.
254    ///
255    /// This method creates an `InvalidInput` report indicating that
256    /// the requested operation is not supported.
257    #[track_caller]
258    pub fn unsupported() -> Report<Self> {
259        Report::new(Self).attach(Unsupported)
260    }
261}
262
263impl ConversionError {
264    /// Create a new conversion error with type information.
265    ///
266    /// This method creates a `ConversionError` report showing the source
267    /// and target types of the failed conversion.
268    #[track_caller]
269    pub fn new<F, T>() -> Report<Self> {
270        Report::new(Self).attach(FromTo(ty!(F), ty!(T)))
271    }
272
273    /// Create a conversion error from an existing context with type information.
274    ///
275    /// This method converts an existing error context into a `ConversionError`
276    /// and attaches the source and target type information.
277    #[track_caller]
278    pub fn from<F, T>(ctx: impl Context) -> Report<Self> {
279        Self::report(ctx).attach(FromTo(ty!(F), ty!(T)))
280    }
281}
282
283impl NotFound {
284    /// Create a not found error for a missing field.
285    ///
286    /// This method creates a `NotFound` report indicating that a specific
287    /// field is missing from a data structure.
288    #[track_caller]
289    pub fn with_field(field: &'static str) -> Report<Self> {
290        Report::new(Self).attach(Field::new(field, attachment::Missing))
291    }
292
293    /// Create a not found error for a missing indexed item.
294    ///
295    /// This method creates a `NotFound` report indicating that an item
296    /// at a specific index or key could not be found.
297    pub fn with_index<T, K: Display>(key: K) -> Report<Self> {
298        Self::attach_kv(Index(key), ty!(T))
299    }
300}
301
302impl ParseError {
303    /// Create a parse error for an invalid field.
304    ///
305    /// This method creates a `ParseError` report indicating that a specific
306    /// field could not be parsed correctly.
307    #[track_caller]
308    pub fn with_field(field: &'static str) -> Report<Self> {
309        Report::new(Self).attach(Field::new(field, attachment::Invalid))
310    }
311}