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}