Skip to main content

webdav_server/error/
internal.rs

1use std::{num::TryFromIntError, time::SystemTimeError};
2
3/// Low-level standard library errors wrapped into a common type for domain propagation.
4///
5/// This enum exists to bridge the gap between standard library error types (such as
6/// `TryFromIntError`) and the domain-specific error enums in `api`, `storage`, and
7/// `model`. Each domain error has an `Internal(#[from] internal::Error)` variant, and
8/// the [`crate::wrap_internal_err!`] macro generates the additional `From` implementations
9/// that allow the `?` operator to chain through two conversions automatically.
10///
11/// Consumers should never match on this type directly; it is an implementation detail
12/// of the error propagation chain.
13#[derive(thiserror::Error, Debug)]
14pub enum Error {
15    /// An integer type conversion overflowed or underflowed.
16    ///
17    /// Typically produced when converting between `usize`, `u64`, `i64`, and similar
18    /// primitive integer types using `TryFrom` or `TryInto`.
19    #[error("Integer conversion overflow : {}", .0)]
20    IntConversion(#[from] TryFromIntError),
21
22    /// A system time operation failed.
23    ///
24    /// Produced when a `SystemTime` value is before the Unix epoch, which can occur
25    /// when computing elapsed durations or converting to timestamp integers.
26    #[error("Time conversion failed : {}", .0)]
27    TimerError(#[from] SystemTimeError),
28
29    /// A freeform error message for cases not covered by the other variants.
30    ///
31    /// Used when a custom string description is the most practical way to surface
32    /// an internal condition without defining a new strongly-typed variant.
33    #[error("{}", .0)]
34    Message(String),
35}
36
37/// Wires up low-level standard library errors directly into your domain-specific error enums.
38///
39/// This macro generates the `From` implementations required to bypass the "double-from"
40/// limitation of the `?` operator. It automatically intercepts specific errors (like `TryFromIntError`)
41/// and wraps them in your target domain's `Internal` error variant.
42///
43/// # Example
44///
45/// ```rust
46/// use std::num::TryFromIntError;
47/// use std::time::SystemTimeError;
48/// // Assuming your crate is named `webdav_server`
49/// use webdav_server::error::internal::Error as InternalErr;
50/// use webdav_server::wrap_internal_err;
51///
52/// #[derive(thiserror::Error, Debug)]
53/// pub enum StorageError {
54///     // thiserror handles the immediate InternalErr -> StorageError conversion
55///     #[error(transparent)]
56///     Internal(#[from] InternalErr),
57/// }
58///
59/// // This macro generates the TryFromIntError -> InternalErr -> StorageError conversions!
60/// wrap_internal_err! {
61///     TryFromIntError,
62///     SystemTimeError
63///     => StorageError::Internal
64/// }
65///
66/// // Now you can use `?` on infallible casts in functions returning Result<T, StorageError>
67/// ```
68#[macro_export]
69macro_rules! wrap_internal_err {
70    ($($err:ty),+ $(,)? => $target:ident::$variant:ident) => {
71        $(
72            impl From<$err> for $target {
73                fn from(e: $err) -> Self {
74                    // Use $crate instead of crate so this resolves correctly anywhere it's called!
75                    $target::$variant($crate::error::internal::Error::from(e))
76                }
77            }
78        )+
79    };
80}