1use crate::{Error, Exn, ExnResult, Result};
16
17use super::impls::into_frame;
18
19pub trait ErrorExt: std::error::Error + Send + Sync + 'static {
21 #[track_caller]
24 fn raise(self) -> Error
25 where
26 Self: Sized,
27 {
28 let mut error = Some(self);
29 if let Some(error) = (&mut error as &mut dyn std::any::Any).downcast_mut::<Option<Error>>() {
30 return error.take().expect("the error has not been consumed");
31 }
32 Exn::new(error.expect("a different error type was not taken")).into_error()
33 }
34
35 #[track_caller]
37 fn raise_typed(self) -> Exn<Self>
38 where
39 Self: Sized,
40 {
41 Exn::new(self)
42 }
43
44 #[track_caller]
48 fn and_raise<T: std::error::Error + Send + Sync + 'static>(self, context: T) -> Error
49 where
50 Self: Sized,
51 {
52 self.and_raise_typed(context).into_error()
53 }
54
55 #[track_caller]
57 fn and_raise_typed<T: std::error::Error + Send + Sync + 'static>(self, context: T) -> Exn<T>
58 where
59 Self: Sized,
60 {
61 Exn::with_cause(self, context)
62 }
63
64 #[track_caller]
67 fn raise_erased(self) -> Exn
68 where
69 Self: Sized,
70 {
71 Exn::from_boxed_frame(into_frame(self))
72 }
73
74 #[track_caller]
76 fn raise_all<T, I>(self, sources: I) -> Exn<Self>
77 where
78 Self: Sized,
79 T: std::error::Error + Send + Sync + 'static,
80 I: IntoIterator,
81 I::Item: Into<Exn<T>>,
82 {
83 Exn::raise_all(sources, self)
84 }
85}
86
87impl<T> ErrorExt for T where T: std::error::Error + Send + Sync + 'static {}
88
89pub trait OptionExt {
91 type Some;
93
94 fn ok_or_raise<A, F>(self, err: F) -> Result<Self::Some>
96 where
97 A: std::error::Error + Send + Sync + 'static,
98 F: FnOnce() -> A;
99
100 fn ok_or_raise_typed<A, F>(self, err: F) -> ExnResult<Self::Some, A>
102 where
103 A: std::error::Error + Send + Sync + 'static,
104 F: FnOnce() -> A;
105
106 fn ok_or_raise_erased<A, F>(self, err: F) -> ExnResult<Self::Some>
109 where
110 A: std::error::Error + Send + Sync + 'static,
111 F: FnOnce() -> A;
112}
113
114impl<T> OptionExt for Option<T> {
115 type Some = T;
116
117 #[track_caller]
118 fn ok_or_raise<A, F>(self, err: F) -> Result<T>
119 where
120 A: std::error::Error + Send + Sync + 'static,
121 F: FnOnce() -> A,
122 {
123 match self {
124 Some(v) => Ok(v),
125 None => Err(err().raise()),
126 }
127 }
128
129 #[track_caller]
130 fn ok_or_raise_typed<A, F>(self, err: F) -> ExnResult<T, A>
131 where
132 A: std::error::Error + Send + Sync + 'static,
133 F: FnOnce() -> A,
134 {
135 match self {
136 Some(v) => Ok(v),
137 None => Err(Exn::new(err())),
138 }
139 }
140
141 #[track_caller]
142 fn ok_or_raise_erased<A, F>(self, err: F) -> ExnResult<T>
143 where
144 A: std::error::Error + Send + Sync + 'static,
145 F: FnOnce() -> A,
146 {
147 match self {
148 Some(v) => Ok(v),
149 None => Err(err().raise_erased()),
150 }
151 }
152}
153
154pub trait ResultExt {
156 type Success;
158
159 type Error: std::error::Error + Send + Sync + 'static;
161
162 #[track_caller]
166 fn or_raise<A, F>(self, err: F) -> Result<Self::Success>
167 where
168 Self: Sized,
169 A: std::error::Error + Send + Sync + 'static,
170 F: FnOnce() -> A,
171 {
172 self.or_raise_typed(err).map_err(Exn::into_error)
173 }
174
175 #[track_caller]
178 fn or_error(self) -> Result<Self::Success>;
179
180 fn or_raise_typed<A, F>(self, err: F) -> ExnResult<Self::Success, A>
182 where
183 A: std::error::Error + Send + Sync + 'static,
184 F: FnOnce() -> A;
185
186 fn or_erased(self) -> ExnResult<Self::Success>;
191
192 #[track_caller]
196 fn or_raise_erased<A, F>(self, err: F) -> ExnResult<Self::Success>
197 where
198 Self: Sized,
199 A: std::error::Error + Send + Sync + 'static,
200 F: FnOnce() -> A,
201 {
202 self.or_raise_typed(err).map_err(Exn::erased)
203 }
204}
205
206impl<T, E> ResultExt for std::result::Result<T, E>
207where
208 E: std::error::Error + Send + Sync + 'static,
209{
210 type Success = T;
211 type Error = E;
212
213 #[track_caller]
214 fn or_raise_typed<A, F>(self, err: F) -> ExnResult<Self::Success, A>
215 where
216 A: std::error::Error + Send + Sync + 'static,
217 F: FnOnce() -> A,
218 {
219 match self {
220 Ok(v) => Ok(v),
221 Err(e) => Err(e.and_raise_typed(err())),
222 }
223 }
224
225 #[track_caller]
226 fn or_error(self) -> Result<T> {
227 match self {
228 Ok(v) => Ok(v),
229 Err(e) => Err(e.raise()),
230 }
231 }
232
233 #[track_caller]
234 fn or_erased(self) -> ExnResult<Self::Success> {
235 match self {
236 Ok(v) => Ok(v),
237 Err(e) => Err(e.raise_erased()),
238 }
239 }
240}
241
242pub trait BoxedResultExt {
246 type Success;
248
249 fn or_erased(self) -> ExnResult<Self::Success>;
251}
252
253impl<T> BoxedResultExt for std::result::Result<T, Box<dyn std::error::Error + Send + Sync + 'static>> {
254 type Success = T;
255
256 #[track_caller]
257 fn or_erased(self) -> ExnResult<Self::Success> {
258 match self {
259 Ok(v) => Ok(v),
260 Err(e) => Err(Exn::new(crate::exn::Untyped::from_boxed(e))),
261 }
262 }
263}
264
265impl<T, E> ResultExt for ExnResult<T, E>
266where
267 E: std::error::Error + Send + Sync + 'static,
268{
269 type Success = T;
270 type Error = E;
271
272 #[track_caller]
273 fn or_raise_typed<A, F>(self, err: F) -> ExnResult<Self::Success, A>
274 where
275 A: std::error::Error + Send + Sync + 'static,
276 F: FnOnce() -> A,
277 {
278 match self {
279 Ok(v) => Ok(v),
280 Err(e) => Err(e.raise(err())),
281 }
282 }
283
284 fn or_error(self) -> Result<T> {
285 self.map_err(Exn::into_error)
286 }
287
288 #[track_caller]
289 fn or_erased(self) -> ExnResult<Self::Success> {
290 match self {
291 Ok(v) => Ok(v),
292 Err(e) => Err(e.erased()),
293 }
294 }
295}