error_rail/traits/
with_error.rs

1use crate::ErrorVec;
2
3/// Abstraction over types that carry an error variant which can be remapped.
4///
5/// This trait provides a generic interface for types that contain both success and error cases,
6/// allowing transformation of the error type while preserving the success value.
7///
8/// # Type Parameters
9///
10/// * `E` - The current error type contained in the implementor
11///
12/// # Associated Types
13///
14/// * `Success` - The success value type when no error is present
15/// * `ErrorOutput<G>` - The output type after mapping the error to type `G`
16///
17/// # Examples
18///
19/// ```
20/// use error_rail::traits::WithError;
21///
22/// let result: Result<i32, &str> = Err("original error");
23/// let mapped = result.fmap_error(|e| format!("Error: {}", e));
24/// assert_eq!(mapped, Err("Error: original error".to_string()));
25/// ```
26pub trait WithError<E> {
27    type Success;
28
29    type ErrorOutput<G>;
30
31    /// Maps the error value using `f`, producing a new container with error type `G`.
32    ///
33    /// This operation leaves the success case untouched and only transforms the error.
34    ///
35    /// # Arguments
36    ///
37    /// * `f` - A function that transforms the error from type `E` to type `G`
38    ///
39    /// # Examples
40    ///
41    /// ```
42    /// use error_rail::traits::WithError;
43    ///
44    /// let result: Result<i32, u32> = Err(404);
45    /// let mapped = result.fmap_error(|code| format!("HTTP {}", code));
46    /// assert_eq!(mapped, Err("HTTP 404".to_string()));
47    /// ```
48    fn fmap_error<F, G>(self, f: F) -> Self::ErrorOutput<G>
49    where
50        F: Fn(E) -> G;
51
52    /// Converts the container into a `Result`, taking only the first error if invalid.
53    ///
54    /// **⚠️ DEPRECATED**: Use [`to_result_first()`](Self::to_result_first) or
55    /// [`to_result_all()`](Self::to_result_all) for explicit error handling.
56    ///
57    /// For types that are already `Result`, this is a no-op.
58    /// For other types, this extracts the success/error into standard Result form.
59    ///
60    /// # Examples
61    ///
62    /// ```
63    /// use error_rail::traits::WithError;
64    ///
65    /// let result: Result<i32, &str> = Ok(42);
66    /// assert_eq!(result.to_result(), Ok(42));
67    /// ```
68    #[deprecated(
69        since = "0.6.0",
70        note = "Use to_result_first() or to_result_all() for explicit error handling"
71    )]
72    fn to_result(self) -> Result<Self::Success, E>;
73
74    /// Converts the container into a `Result`, taking only the first error if invalid.
75    ///
76    /// This method explicitly indicates that only the first error will be returned,
77    /// potentially losing additional errors in multi-error scenarios.
78    ///
79    /// # Examples
80    ///
81    /// ```
82    /// use error_rail::traits::WithError;
83    ///
84    /// let result: Result<i32, &str> = Ok(42);
85    /// assert_eq!(result.to_result_first(), Ok(42));
86    /// ```
87    fn to_result_first(self) -> Result<Self::Success, E>;
88
89    /// Converts the container into a `Result`, preserving all errors if invalid.
90    ///
91    /// This method returns all accumulated errors in a `Vec<E>`, ensuring no error
92    /// information is lost during the conversion.
93    ///
94    /// # Examples
95    ///
96    /// ```
97    /// use error_rail::traits::WithError;
98    ///
99    /// let result: Result<i32, &str> = Ok(42);
100    /// assert_eq!(result.to_result_all(), Ok(42));
101    /// ```
102    fn to_result_all(self) -> Result<Self::Success, ErrorVec<E>>;
103}
104
105impl<T, E> WithError<E> for Result<T, E> {
106    type Success = T;
107    type ErrorOutput<G> = Result<T, G>;
108
109    fn fmap_error<F, G>(self, f: F) -> Self::ErrorOutput<G>
110    where
111        F: FnOnce(E) -> G,
112    {
113        match self {
114            Ok(t) => Ok(t),
115            Err(e) => Err(f(e)),
116        }
117    }
118
119    fn to_result(self) -> Result<Self::Success, E> {
120        self.to_result_first()
121    }
122
123    fn to_result_first(self) -> Result<Self::Success, E> {
124        self
125    }
126
127    fn to_result_all(self) -> Result<Self::Success, ErrorVec<E>> {
128        match self {
129            Ok(t) => Ok(t),
130            Err(e) => {
131                let mut error_vec = ErrorVec::new();
132                error_vec.push(e);
133                Err(error_vec)
134            }
135        }
136    }
137}