error_rail/traits/with_error.rs
1/// Abstraction over types that carry an error variant which can be remapped.
2///
3/// This trait provides a generic interface for types that contain both success and error cases,
4/// allowing transformation of the error type while preserving the success value.
5///
6/// # Type Parameters
7///
8/// * `E` - The current error type contained in the implementor
9///
10/// # Associated Types
11///
12/// * `Success` - The success value type when no error is present
13/// * `ErrorOutput<G>` - The output type after mapping the error to type `G`
14///
15/// # Examples
16///
17/// ```
18/// use error_rail::traits::WithError;
19///
20/// let result: Result<i32, &str> = Err("original error");
21/// let mapped = result.fmap_error(|e| format!("Error: {}", e));
22/// assert_eq!(mapped, Err("Error: original error".to_string()));
23/// ```
24pub trait WithError<E> {
25 type Success;
26
27 type ErrorOutput<G>;
28
29 /// Maps the error value using `f`, producing a new container with error type `G`.
30 ///
31 /// This operation leaves the success case untouched and only transforms the error.
32 ///
33 /// # Arguments
34 ///
35 /// * `f` - A function that transforms the error from type `E` to type `G`
36 ///
37 /// # Examples
38 ///
39 /// ```
40 /// use error_rail::traits::WithError;
41 ///
42 /// let result: Result<i32, u32> = Err(404);
43 /// let mapped = result.fmap_error(|code| format!("HTTP {}", code));
44 /// assert_eq!(mapped, Err("HTTP 404".to_string()));
45 /// ```
46 fn fmap_error<F, G>(self, f: F) -> Self::ErrorOutput<G>
47 where
48 F: Fn(E) -> G;
49
50 /// Converts the container into a `Result`.
51 ///
52 /// For types that are already `Result`, this is a no-op.
53 /// For other types, this extracts the success/error into standard Result form.
54 ///
55 /// # Examples
56 ///
57 /// ```
58 /// use error_rail::traits::WithError;
59 ///
60 /// let result: Result<i32, &str> = Ok(42);
61 /// assert_eq!(result.to_result(), Ok(42));
62 /// ```
63 fn to_result(self) -> Result<Self::Success, E>;
64}
65
66impl<T, E: Clone> WithError<E> for Result<T, E> {
67 type Success = T;
68 type ErrorOutput<G> = Result<T, G>;
69
70 fn fmap_error<F, G>(self, f: F) -> Self::ErrorOutput<G>
71 where
72 F: FnOnce(E) -> G,
73 {
74 match self {
75 Ok(t) => Ok(t),
76 Err(e) => Err(f(e)),
77 }
78 }
79
80 fn to_result(self) -> Result<Self::Success, E> {
81 self
82 }
83}