alt_failure/
result_ext.rs

1use core::fmt::Display;
2
3use {Compat, Context, Fail};
4
5/// Extension methods for `Result`.
6pub trait ResultExt<T, E> {
7    /// Wraps the error in `Compat` to make it compatible with older error
8    /// handling APIs that expect `std::error::Error`.
9    ///
10    /// # Examples
11    ///
12    /// ```
13    /// # fn main() {
14    /// #    tests::run_test();
15    /// # }
16    /// #
17    /// # #[cfg(not(all(feature = "std", feature = "derive")))] mod tests { pub fn run_test() { } }
18    /// #  
19    /// # #[cfg(all(feature = "std", feature = "derive"))] mod tests {
20    /// use std::error::Error;
21    /// # use std::fmt;
22    /// #
23    /// # extern crate failure;
24    /// #
25    /// # use tests::failure::ResultExt;
26    /// #
27    /// # #[derive(Debug)]
28    /// struct CustomError;
29    ///
30    /// impl Error for CustomError {
31    ///     fn description(&self) -> &str {
32    ///         "My custom error message"
33    ///     }
34    ///
35    ///     fn cause(&self) -> Option<&Error> {
36    ///         None
37    ///     }
38    /// }
39    /// #
40    /// # impl fmt::Display for CustomError {
41    /// #     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
42    /// #         write!(f, "{}", self.description())
43    /// #     }
44    /// # }
45    /// #
46    /// # pub fn run_test() {
47    ///
48    /// let x = (|| -> Result<(), failure::Error> {
49    ///     Err(CustomError).compat()?
50    /// })().with_context(|e| {
51    ///     format!("An error occured: {}", e)
52    /// }).unwrap_err();
53    ///
54    /// let x = format!("{}", x);
55    ///
56    /// assert_eq!(x, "An error occured: My custom error message");
57    /// # }
58    ///
59    /// # }
60    /// ```
61    fn compat(self) -> Result<T, Compat<E>>;
62
63    /// Wraps the error type in a context type.
64    ///
65    /// # Examples
66    ///
67    /// ```
68    /// # #[cfg(all(feature = "std", feature = "derive"))]
69    /// # #[macro_use] extern crate failure;
70    /// #
71    /// # #[cfg(all(feature = "std", feature = "derive"))]
72    /// # #[macro_use] extern crate failure_derive;
73    /// #
74    /// # fn main() {
75    /// #    tests::run_test();
76    /// # }
77    /// #
78    /// # #[cfg(not(all(feature = "std", feature = "derive")))] mod tests { pub fn run_test() { } }
79    /// #
80    /// # #[cfg(all(feature = "std", feature = "derive"))] mod tests {
81    /// #
82    /// # use failure::{self, ResultExt};
83    /// #
84    /// #[derive(Fail, Debug)]
85    /// #[fail(display = "")]
86    /// struct CustomError;
87    /// #
88    /// # pub fn run_test() {
89    ///  
90    /// let x = (|| -> Result<(), failure::Error> {
91    ///     Err(CustomError)?
92    /// })().context(format!("An error occured")).unwrap_err();
93    ///
94    /// let x = format!("{}", x);
95    ///
96    /// assert_eq!(x, "An error occured");
97    /// # }
98    ///
99    /// # }
100    /// ```
101    fn context<D>(self, context: D) -> Result<T, Context<D>>
102    where
103        D: Display + Send + Sync + 'static;
104
105    /// Wraps the error type in a context type generated by looking at the
106    /// error value.
107    ///
108    /// # Examples
109    ///
110    /// ```
111    /// # #[cfg(all(feature = "std", feature = "derive"))]
112    /// # #[macro_use] extern crate failure;
113    /// #
114    /// # #[cfg(all(feature = "std", feature = "derive"))]
115    /// # #[macro_use] extern crate failure_derive;
116    /// #
117    /// # fn main() {
118    /// #    tests::run_test();
119    /// # }
120    /// #
121    /// # #[cfg(not(all(feature = "std", feature = "derive")))] mod tests { pub fn run_test() { } }
122    /// #
123    /// # #[cfg(all(feature = "std", feature = "derive"))] mod tests {
124    /// #
125    /// # use failure::{self, ResultExt};
126    /// #
127    /// #[derive(Fail, Debug)]
128    /// #[fail(display = "My custom error message")]
129    /// struct CustomError;
130    /// #
131    /// # pub fn run_test() {
132    ///
133    /// let x = (|| -> Result<(), failure::Error> {
134    ///     Err(CustomError)?
135    /// })().with_context(|e| {
136    ///     format!("An error occured: {}", e)
137    /// }).unwrap_err();
138    ///
139    /// let x = format!("{}", x);
140    ///
141    /// assert_eq!(x, "An error occured: My custom error message");
142    /// # }
143    ///
144    /// # }
145    /// ```
146    fn with_context<F, D>(self, f: F) -> Result<T, Context<D>>
147    where
148        F: FnOnce(&E) -> D,
149        D: Display + Send + Sync + 'static;
150}
151
152impl<T, E> ResultExt<T, E> for Result<T, E>
153where
154    E: Fail,
155{
156    fn compat(self) -> Result<T, Compat<E>> {
157        self.map_err(|err| err.compat())
158    }
159
160    fn context<D>(self, context: D) -> Result<T, Context<D>>
161    where
162        D: Display + Send + Sync + 'static,
163    {
164        self.map_err(|failure| failure.context(context))
165    }
166
167    fn with_context<F, D>(self, f: F) -> Result<T, Context<D>>
168    where
169        F: FnOnce(&E) -> D,
170        D: Display + Send + Sync + 'static,
171    {
172        self.map_err(|failure| {
173            let context = f(&failure);
174            failure.context(context)
175        })
176    }
177}
178
179with_std! {
180    use Error;
181
182    impl<T> ResultExt<T, Error> for Result<T, Error> {
183        fn compat(self) -> Result<T, Compat<Error>> {
184            self.map_err(|err| err.compat())
185        }
186
187        fn context<D>(self, context: D) -> Result<T, Context<D>> where
188            D: Display + Send + Sync + 'static
189        {
190            self.map_err(|failure| failure.context(context))
191        }
192
193        fn with_context<F, D>(self, f: F) -> Result<T, Context<D>> where
194            F: FnOnce(&Error) -> D,
195            D: Display + Send + Sync + 'static
196        {
197            self.map_err(|failure| {
198                let context = f(&failure);
199                failure.context(context)
200            })
201        }
202    }
203}