rocket/outcome.rs
1//! Success, error, and forward handling.
2//!
3//! The `Outcome<S, E, F>` type is similar to the standard library's `Result<S,
4//! E>` type. It is an enum with three variants, each containing a value:
5//! `Success(S)`, which represents a successful outcome, `Error(E)`, which
6//! represents an erroring outcome, and `Forward(F)`, which represents neither a
7//! success or error, but instead, indicates that processing could not be
8//! handled and should instead be _forwarded_ to whatever can handle the
9//! processing next.
10//!
11//! The `Outcome` type is the return type of many of the core Rocket traits,
12//! including [`FromRequest`](crate::request::FromRequest), [`FromData`]
13//! [`Responder`]. It is also the return type of request handlers via the
14//! [`Response`](crate::response::Response) type.
15//!
16//! [`FromData`]: crate::data::FromData
17//! [`Responder`]: crate::response::Responder
18//!
19//! # Success
20//!
21//! A successful `Outcome<S, E, F>`, `Success(S)`, is returned from functions
22//! that complete successfully. The meaning of a `Success` outcome depends on
23//! the context. For instance, the `Outcome` of the `from_data` method of the
24//! [`FromData`] trait will be matched against the type expected by
25//! the user. For example, consider the following handler:
26//!
27//! ```rust
28//! # use rocket::post;
29//! # type S = String;
30//! #[post("/", data = "<my_val>")]
31//! fn hello(my_val: S) { /* ... */ }
32//! ```
33//!
34//! The [`FromData`] implementation for the type `S` returns an `Outcome` with a
35//! `Success(S)`. If `from_data` returns a `Success`, the `Success` value will
36//! be unwrapped and the value will be used as the value of `my_val`.
37//!
38//! # Error
39//!
40//! An error `Outcome<S, E, F>`, `Error(E)`, is returned when a function
41//! fails with some error and no processing can or should continue as a result.
42//! The meaning of an error depends on the context.
43//!
44//! In Rocket, an `Error` generally means that a request is taken out of normal
45//! processing. The request is then given to the catcher corresponding to some
46//! status code. Users can catch errors by requesting a type of `Result<S, E>`
47//! or `Option<S>` in request handlers. For example, if a user's handler looks
48//! like:
49//!
50//! ```rust
51//! # use rocket::post;
52//! # type S = Option<String>;
53//! # type E = std::convert::Infallible;
54//! #[post("/", data = "<my_val>")]
55//! fn hello(my_val: Result<S, E>) { /* ... */ }
56//! ```
57//!
58//! The [`FromData`] implementation for the type `S` returns an `Outcome` with a
59//! `Success(S)` and `Error(E)`. If `from_data` returns an `Error`, the `Error`
60//! value will be unwrapped and the value will be used as the `Err` value of
61//! `my_val` while a `Success` will be unwrapped and used the `Ok` value.
62//!
63//! # Forward
64//!
65//! A forward `Outcome<S, E, F>`, `Forward(F)`, is returned when a function
66//! wants to indicate that the requested processing should be _forwarded_ to the
67//! next available processor. Again, the exact meaning depends on the context.
68//!
69//! In Rocket, a `Forward` generally means that a request is forwarded to the
70//! next available request handler. For example, consider the following request
71//! handler:
72//!
73//! ```rust
74//! # use rocket::post;
75//! # type S = String;
76//! #[post("/", data = "<my_val>")]
77//! fn hello(my_val: S) { /* ... */ }
78//! ```
79//!
80//! The [`FromData`] implementation for the type `S` returns an `Outcome` with a
81//! `Success(S)`, `Error(E)`, and `Forward(F)`. If the `Outcome` is a
82//! `Forward`, the `hello` handler isn't called. Instead, the incoming request
83//! is forwarded, or passed on to, the next matching route, if any. Ultimately,
84//! if there are no non-forwarding routes, forwarded requests are handled by the
85//! 404 catcher. Similar to `Error`s, users can catch `Forward`s by requesting
86//! a type of `Option<S>`. If an `Outcome` is a `Forward`, the `Option` will be
87//! `None`.
88
89use crate::{route, request, response};
90use crate::data::{self, Data, FromData};
91use crate::http::Status;
92
93use self::Outcome::*;
94
95/// An enum representing success (`Success`), error (`Error`), or forwarding
96/// (`Forward`).
97///
98/// See the [top level documentation](crate::outcome) for detailed information.
99#[must_use]
100#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
101pub enum Outcome<S, E, F> {
102 /// Contains the success value.
103 Success(S),
104 /// Contains the error error value.
105 Error(E),
106 /// Contains the value to forward on.
107 Forward(F),
108}
109
110impl<S, E, F> Outcome<S, E, F> {
111 /// Unwraps the Outcome, yielding the contents of a Success.
112 ///
113 /// # Panics
114 ///
115 /// Panics if the value is not `Success`.
116 ///
117 /// # Examples
118 ///
119 /// ```rust
120 /// # use rocket::outcome::Outcome;
121 /// # use rocket::outcome::Outcome::*;
122 /// #
123 /// let x: Outcome<i32, &str, usize> = Success(10);
124 /// assert_eq!(x.unwrap(), 10);
125 /// ```
126 #[inline]
127 #[track_caller]
128 pub fn unwrap(self) -> S {
129 match self {
130 Success(val) => val,
131 _ => panic!("unwrapped a non-successful outcome")
132 }
133 }
134
135 /// Unwraps the Outcome, yielding the contents of a Success.
136 ///
137 /// # Panics
138 ///
139 /// If the value is not `Success`, panics with the given `message`.
140 ///
141 /// # Examples
142 ///
143 /// ```rust
144 /// # use rocket::outcome::Outcome;
145 /// # use rocket::outcome::Outcome::*;
146 /// #
147 /// let x: Outcome<i32, &str, usize> = Success(10);
148 /// assert_eq!(x.expect("success value"), 10);
149 /// ```
150 #[inline]
151 #[track_caller]
152 pub fn expect(self, message: &str) -> S {
153 match self {
154 Success(val) => val,
155 _ => panic!("unwrapped a non-successful outcome: {}", message)
156 }
157 }
158
159 /// Return true if this `Outcome` is a `Success`.
160 ///
161 /// # Examples
162 ///
163 /// ```rust
164 /// # use rocket::outcome::Outcome;
165 /// # use rocket::outcome::Outcome::*;
166 /// #
167 /// let x: Outcome<i32, &str, usize> = Success(10);
168 /// assert_eq!(x.is_success(), true);
169 ///
170 /// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
171 /// assert_eq!(x.is_success(), false);
172 ///
173 /// let x: Outcome<i32, &str, usize> = Forward(25);
174 /// assert_eq!(x.is_success(), false);
175 /// ```
176 #[inline]
177 pub fn is_success(&self) -> bool {
178 matches!(self, Success(_))
179 }
180
181 /// Return true if this `Outcome` is an `Error`.
182 ///
183 /// # Examples
184 ///
185 /// ```rust
186 /// # use rocket::outcome::Outcome;
187 /// # use rocket::outcome::Outcome::*;
188 /// #
189 /// let x: Outcome<i32, &str, usize> = Success(10);
190 /// assert_eq!(x.is_error(), false);
191 ///
192 /// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
193 /// assert_eq!(x.is_error(), true);
194 ///
195 /// let x: Outcome<i32, &str, usize> = Forward(25);
196 /// assert_eq!(x.is_error(), false);
197 /// ```
198 #[inline]
199 pub fn is_error(&self) -> bool {
200 matches!(self, Error(_))
201 }
202
203 /// Return true if this `Outcome` is a `Forward`.
204 ///
205 /// # Examples
206 ///
207 /// ```rust
208 /// # use rocket::outcome::Outcome;
209 /// # use rocket::outcome::Outcome::*;
210 /// #
211 /// let x: Outcome<i32, &str, usize> = Success(10);
212 /// assert_eq!(x.is_forward(), false);
213 ///
214 /// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
215 /// assert_eq!(x.is_forward(), false);
216 ///
217 /// let x: Outcome<i32, &str, usize> = Forward(25);
218 /// assert_eq!(x.is_forward(), true);
219 /// ```
220 #[inline]
221 pub fn is_forward(&self) -> bool {
222 matches!(self, Forward(_))
223 }
224
225 /// Converts from `Outcome<S, E, F>` to `Option<S>`.
226 ///
227 /// Returns the `Some` of the `Success` if this is a `Success`, otherwise
228 /// returns `None`. `self` is consumed, and all other values are discarded.
229 ///
230 /// ```rust
231 /// # use rocket::outcome::Outcome;
232 /// # use rocket::outcome::Outcome::*;
233 /// #
234 /// let x: Outcome<i32, &str, usize> = Success(10);
235 /// assert_eq!(x.succeeded(), Some(10));
236 ///
237 /// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
238 /// assert_eq!(x.succeeded(), None);
239 ///
240 /// let x: Outcome<i32, &str, usize> = Forward(25);
241 /// assert_eq!(x.succeeded(), None);
242 /// ```
243 #[inline]
244 pub fn succeeded(self) -> Option<S> {
245 match self {
246 Success(val) => Some(val),
247 _ => None
248 }
249 }
250
251 /// Converts from `Outcome<S, E, F>` to `Option<E>`.
252 ///
253 /// Returns the `Some` of the `Error` if this is an `Error`, otherwise
254 /// returns `None`. `self` is consumed, and all other values are discarded.
255 ///
256 /// ```rust
257 /// # use rocket::outcome::Outcome;
258 /// # use rocket::outcome::Outcome::*;
259 /// #
260 /// let x: Outcome<i32, &str, usize> = Success(10);
261 /// assert_eq!(x.failed(), None);
262 ///
263 /// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
264 /// assert_eq!(x.failed(), Some("Hi! I'm an error."));
265 ///
266 /// let x: Outcome<i32, &str, usize> = Forward(25);
267 /// assert_eq!(x.failed(), None);
268 /// ```
269 #[inline]
270 pub fn failed(self) -> Option<E> {
271 match self {
272 Error(val) => Some(val),
273 _ => None
274 }
275 }
276
277 /// Converts from `Outcome<S, E, F>` to `Option<F>`.
278 ///
279 /// Returns the `Some` of the `Forward` if this is a `Forward`, otherwise
280 /// returns `None`. `self` is consumed, and all other values are discarded.
281 ///
282 /// ```rust
283 /// # use rocket::outcome::Outcome;
284 /// # use rocket::outcome::Outcome::*;
285 /// #
286 /// let x: Outcome<i32, &str, usize> = Success(10);
287 /// assert_eq!(x.forwarded(), None);
288 ///
289 /// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
290 /// assert_eq!(x.forwarded(), None);
291 ///
292 /// let x: Outcome<i32, &str, usize> = Forward(25);
293 /// assert_eq!(x.forwarded(), Some(25));
294 /// ```
295 #[inline]
296 pub fn forwarded(self) -> Option<F> {
297 match self {
298 Forward(val) => Some(val),
299 _ => None
300 }
301 }
302
303 /// Returns a `Success` value as `Ok()` or `value` in `Err`. Converts from
304 /// `Outcome<S, E, F>` to `Result<S, T>` for a given `T`.
305 ///
306 /// Returns `Ok` with the `Success` value if this is a `Success`, otherwise
307 /// returns an `Err` with the provided value. `self` is consumed, and all
308 /// other values are discarded.
309 ///
310 /// ```rust
311 /// # use rocket::outcome::Outcome;
312 /// # use rocket::outcome::Outcome::*;
313 /// #
314 /// let x: Outcome<i32, &str, usize> = Success(10);
315 /// assert_eq!(x.success_or(false), Ok(10));
316 ///
317 /// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
318 /// assert_eq!(x.success_or(false), Err(false));
319 ///
320 /// let x: Outcome<i32, &str, usize> = Forward(25);
321 /// assert_eq!(x.success_or("whoops"), Err("whoops"));
322 /// ```
323 #[inline]
324 pub fn success_or<T>(self, value: T) -> Result<S, T> {
325 match self {
326 Success(val) => Ok(val),
327 _ => Err(value)
328 }
329 }
330
331 /// Returns a `Success` value as `Ok()` or `f()` in `Err`. Converts from
332 /// `Outcome<S, E, F>` to `Result<S, T>` for a given `T` produced from a
333 /// supplied function or closure.
334 ///
335 /// Returns `Ok` with the `Success` value if this is a `Success`, otherwise
336 /// returns an `Err` with the result of calling `f`. `self` is consumed, and
337 /// all other values are discarded.
338 ///
339 /// ```rust
340 /// # use rocket::outcome::Outcome;
341 /// # use rocket::outcome::Outcome::*;
342 /// #
343 /// let x: Outcome<i32, &str, usize> = Success(10);
344 /// assert_eq!(x.success_or_else(|| false), Ok(10));
345 ///
346 /// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
347 /// assert_eq!(x.success_or_else(|| false), Err(false));
348 ///
349 /// let x: Outcome<i32, &str, usize> = Forward(25);
350 /// assert_eq!(x.success_or_else(|| "whoops"), Err("whoops"));
351 /// ```
352 #[inline]
353 pub fn success_or_else<T, V: FnOnce() -> T>(self, f: V) -> Result<S, T> {
354 match self {
355 Success(val) => Ok(val),
356 _ => Err(f())
357 }
358 }
359
360 /// Converts from `Outcome<S, E, F>` to `Outcome<&S, &E, &F>`.
361 ///
362 /// ```rust
363 /// # use rocket::outcome::Outcome;
364 /// # use rocket::outcome::Outcome::*;
365 /// #
366 /// let x: Outcome<i32, &str, usize> = Success(10);
367 /// assert_eq!(x.as_ref(), Success(&10));
368 ///
369 /// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
370 /// assert_eq!(x.as_ref(), Error(&"Hi! I'm an error."));
371 /// ```
372 #[inline]
373 pub fn as_ref(&self) -> Outcome<&S, &E, &F> {
374 match *self {
375 Success(ref val) => Success(val),
376 Error(ref val) => Error(val),
377 Forward(ref val) => Forward(val),
378 }
379 }
380
381 /// Converts from `Outcome<S, E, F>` to `Outcome<&mut S, &mut E, &mut F>`.
382 ///
383 /// ```rust
384 /// # use rocket::outcome::Outcome;
385 /// # use rocket::outcome::Outcome::*;
386 /// #
387 /// let mut x: Outcome<i32, &str, usize> = Success(10);
388 /// if let Success(val) = x.as_mut() {
389 /// *val = 20;
390 /// }
391 ///
392 /// assert_eq!(x.unwrap(), 20);
393 /// ```
394 #[inline]
395 pub fn as_mut(&mut self) -> Outcome<&mut S, &mut E, &mut F> {
396 match *self {
397 Success(ref mut val) => Success(val),
398 Error(ref mut val) => Error(val),
399 Forward(ref mut val) => Forward(val),
400 }
401 }
402
403 /// Maps the `Success` value using `f`. Maps an `Outcome<S, E, F>` to an
404 /// `Outcome<T, E, F>` by applying the function `f` to the value of type `S`
405 /// in `self` if `self` is an `Outcome::Success`.
406 ///
407 /// ```rust
408 /// # use rocket::outcome::Outcome;
409 /// # use rocket::outcome::Outcome::*;
410 /// #
411 /// let x: Outcome<i32, &str, usize> = Success(10);
412 ///
413 /// let mapped = x.map(|v| if v == 10 { "10" } else { "not 10" });
414 /// assert_eq!(mapped, Success("10"));
415 /// ```
416 #[inline]
417 pub fn map<T, M: FnOnce(S) -> T>(self, f: M) -> Outcome<T, E, F> {
418 match self {
419 Success(val) => Success(f(val)),
420 Error(val) => Error(val),
421 Forward(val) => Forward(val),
422 }
423 }
424
425 /// Maps the `Error` value using `f`. Maps an `Outcome<S, E, F>` to an
426 /// `Outcome<S, T, F>` by applying the function `f` to the value of type `E`
427 /// in `self` if `self` is an `Outcome::Error`.
428 ///
429 /// ```rust
430 /// # use rocket::outcome::Outcome;
431 /// # use rocket::outcome::Outcome::*;
432 /// #
433 /// let x: Outcome<i32, &str, usize> = Error("hi");
434 ///
435 /// let mapped = x.map_error(|v| if v == "hi" { 10 } else { 0 });
436 /// assert_eq!(mapped, Error(10));
437 /// ```
438 #[inline]
439 pub fn map_error<T, M: FnOnce(E) -> T>(self, f: M) -> Outcome<S, T, F> {
440 match self {
441 Success(val) => Success(val),
442 Error(val) => Error(f(val)),
443 Forward(val) => Forward(val),
444 }
445 }
446
447 /// Maps the `Forward` value using `f`. Maps an `Outcome<S, E, F>` to an
448 /// `Outcome<S, E, T>` by applying the function `f` to the value of type `F`
449 /// in `self` if `self` is an `Outcome::Forward`.
450 ///
451 /// ```rust
452 /// # use rocket::outcome::Outcome;
453 /// # use rocket::outcome::Outcome::*;
454 /// #
455 /// let x: Outcome<i32, &str, usize> = Forward(5);
456 ///
457 /// let mapped = x.map_forward(|v| if v == 5 { "a" } else { "b" });
458 /// assert_eq!(mapped, Forward("a"));
459 /// ```
460 #[inline]
461 pub fn map_forward<T, M: FnOnce(F) -> T>(self, f: M) -> Outcome<S, E, T> {
462 match self {
463 Success(val) => Success(val),
464 Error(val) => Error(val),
465 Forward(val) => Forward(f(val)),
466 }
467 }
468
469 /// Converts from `Outcome<S, E, F>` to `Outcome<T, E, F>` using `f` to map
470 /// `Success(S)` to `Success(T)`.
471 ///
472 /// If `self` is not `Success`, `self` is returned.
473 ///
474 /// # Examples
475 ///
476 /// ```rust
477 /// # use rocket::outcome::Outcome;
478 /// # use rocket::outcome::Outcome::*;
479 /// #
480 /// let x: Outcome<i32, &str, bool> = Success(10);
481 ///
482 /// let mapped = x.and_then(|v| match v {
483 /// 10 => Success("10"),
484 /// 1 => Forward(false),
485 /// _ => Error("30")
486 /// });
487 ///
488 /// assert_eq!(mapped, Success("10"));
489 /// ```
490 #[inline]
491 pub fn and_then<T, M: FnOnce(S) -> Outcome<T, E, F>>(self, f: M) -> Outcome<T, E, F> {
492 match self {
493 Success(val) => f(val),
494 Error(val) => Error(val),
495 Forward(val) => Forward(val),
496 }
497 }
498
499 /// Converts from `Outcome<S, E, F>` to `Outcome<S, T, F>` using `f` to map
500 /// `Error(E)` to `Error(T)`.
501 ///
502 /// If `self` is not `Error`, `self` is returned.
503 ///
504 /// # Examples
505 ///
506 /// ```rust
507 /// # use rocket::outcome::Outcome;
508 /// # use rocket::outcome::Outcome::*;
509 /// #
510 /// let x: Outcome<i32, &str, bool> = Error("hi");
511 ///
512 /// let mapped = x.error_then(|v| match v {
513 /// "hi" => Error(10),
514 /// "test" => Forward(false),
515 /// _ => Success(10)
516 /// });
517 ///
518 /// assert_eq!(mapped, Error(10));
519 /// ```
520 #[inline]
521 pub fn error_then<T, M: FnOnce(E) -> Outcome<S, T, F>>(self, f: M) -> Outcome<S, T, F> {
522 match self {
523 Success(val) => Success(val),
524 Error(val) => f(val),
525 Forward(val) => Forward(val),
526 }
527 }
528
529 /// Converts from `Outcome<S, E, F>` to `Outcome<S, E, T>` using `f` to map
530 /// `Forward(F)` to `Forward(T)`.
531 ///
532 /// If `self` is not `Forward`, `self` is returned.
533 ///
534 /// # Examples
535 ///
536 /// ```rust
537 /// # use rocket::outcome::Outcome;
538 /// # use rocket::outcome::Outcome::*;
539 /// #
540 /// let x: Outcome<i32, &str, Option<bool>> = Forward(Some(false));
541 ///
542 /// let mapped = x.forward_then(|v| match v {
543 /// Some(true) => Success(10),
544 /// Some(false) => Forward(20),
545 /// None => Error("10")
546 /// });
547 ///
548 /// assert_eq!(mapped, Forward(20));
549 /// ```
550 #[inline]
551 pub fn forward_then<T, M: FnOnce(F) -> Outcome<S, E, T>>(self, f: M) -> Outcome<S, E, T> {
552 match self {
553 Success(val) => Success(val),
554 Error(val) => Error(val),
555 Forward(val) => f(val),
556 }
557 }
558
559 /// Converts `Outcome<S, E, F>` to `Result<S, E>` by identity mapping
560 /// `Success(S)` and `Error(E)` to `Result<T, E>` and mapping `Forward(F)`
561 /// to `Result<T, E>` using `f`.
562 ///
563 /// ```rust
564 /// # use rocket::outcome::Outcome;
565 /// # use rocket::outcome::Outcome::*;
566 /// #
567 /// let x: Outcome<i32, &str, usize> = Success(10);
568 /// assert_eq!(x.ok_map_forward(|x| Ok(x as i32 + 1)), Ok(10));
569 ///
570 /// let x: Outcome<i32, &str, usize> = Error("hello");
571 /// assert_eq!(x.ok_map_forward(|x| Ok(x as i32 + 1)), Err("hello"));
572 ///
573 /// let x: Outcome<i32, &str, usize> = Forward(0);
574 /// assert_eq!(x.ok_map_forward(|x| Ok(x as i32 + 1)), Ok(1));
575 /// ```
576 #[inline]
577 pub fn ok_map_forward<M>(self, f: M) -> Result<S, E>
578 where M: FnOnce(F) -> Result<S, E>
579 {
580 match self {
581 Outcome::Success(s) => Ok(s),
582 Outcome::Error(e) => Err(e),
583 Outcome::Forward(v) => f(v),
584 }
585 }
586
587 /// Converts `Outcome<S, E, F>` to `Result<S, E>` by identity mapping
588 /// `Success(S)` and `Forward(F)` to `Result<T, F>` and mapping `Error(E)`
589 /// to `Result<T, F>` using `f`.
590 ///
591 /// ```rust
592 /// # use rocket::outcome::Outcome;
593 /// # use rocket::outcome::Outcome::*;
594 /// #
595 /// let x: Outcome<i32, &str, usize> = Success(10);
596 /// assert_eq!(x.ok_map_error(|s| Ok(123)), Ok(10));
597 ///
598 /// let x: Outcome<i32, &str, usize> = Error("hello");
599 /// assert_eq!(x.ok_map_error(|s| Ok(123)), Ok(123));
600 ///
601 /// let x: Outcome<i32, &str, usize> = Forward(0);
602 /// assert_eq!(x.ok_map_error(|s| Ok(123)), Err(0));
603 /// ```
604 #[inline]
605 pub fn ok_map_error<M>(self, f: M) -> Result<S, F>
606 where M: FnOnce(E) -> Result<S, F>
607 {
608 match self {
609 Outcome::Success(s) => Ok(s),
610 Outcome::Error(e) => f(e),
611 Outcome::Forward(v) => Err(v),
612 }
613 }
614}
615
616impl<'a, S: Send + 'a, E: Send + 'a, F: Send + 'a> Outcome<S, E, F> {
617 /// Pins a future that resolves to `self`, returning a
618 /// [`BoxFuture`](crate::futures::future::BoxFuture) that resolves to
619 /// `self`.
620 #[inline]
621 pub fn pin(self) -> futures::future::BoxFuture<'a, Self> {
622 Box::pin(async move { self })
623 }
624}
625
626crate::export! {
627 /// Unwraps a [`Success`](Outcome::Success) or propagates a `Forward` or
628 /// `Error` by returning early.
629 ///
630 /// # Syntax
631 ///
632 /// The macro has the following "signature":
633 ///
634 /// ```rust
635 /// use rocket::outcome::Outcome;
636 ///
637 /// // Returns the inner `S` if `outcome` is `Outcome::Success`. Otherwise
638 /// // returns from the caller with `Outcome<impl From<E>, impl From<F>>`.
639 /// fn try_outcome<S, E, F>(outcome: Outcome<S, E, F>) -> S
640 /// # { unimplemented!() }
641 /// ```
642 ///
643 /// This is just like `?` (or previously, `try!`), but for `Outcome`. In the
644 /// case of a `Forward` or `Error` variant, the inner type is passed to
645 /// [`From`](std::convert::From), allowing for the conversion between
646 /// specific and more general types. The resulting forward/error is
647 /// immediately returned. Because of the early return, `try_outcome!` can
648 /// only be used in methods that return [`Outcome`].
649 ///
650 /// [`Outcome`]: crate::outcome::Outcome
651 ///
652 /// ## Example
653 ///
654 /// ```rust,no_run
655 /// # #[macro_use] extern crate rocket;
656 /// use std::sync::atomic::{AtomicUsize, Ordering};
657 ///
658 /// use rocket::State;
659 /// use rocket::request::{self, Request, FromRequest};
660 /// use rocket::outcome::{try_outcome, Outcome::*};
661 ///
662 /// #[derive(Default)]
663 /// struct Atomics {
664 /// uncached: AtomicUsize,
665 /// cached: AtomicUsize,
666 /// }
667 ///
668 /// struct Guard1;
669 /// struct Guard2;
670 ///
671 /// #[rocket::async_trait]
672 /// impl<'r> FromRequest<'r> for Guard1 {
673 /// type Error = ();
674 ///
675 /// async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, ()> {
676 /// // Attempt to fetch the guard, passing through any error or forward.
677 /// let atomics = try_outcome!(req.guard::<&State<Atomics>>().await);
678 /// atomics.uncached.fetch_add(1, Ordering::Relaxed);
679 /// req.local_cache(|| atomics.cached.fetch_add(1, Ordering::Relaxed));
680 ///
681 /// Success(Guard1)
682 /// }
683 /// }
684 ///
685 /// #[rocket::async_trait]
686 /// impl<'r> FromRequest<'r> for Guard2 {
687 /// type Error = ();
688 ///
689 /// async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, ()> {
690 /// // Attempt to fetch the guard, passing through any error or forward.
691 /// let guard1: Guard1 = try_outcome!(req.guard::<Guard1>().await);
692 /// Success(Guard2)
693 /// }
694 /// }
695 /// ```
696 macro_rules! try_outcome {
697 ($expr:expr $(,)?) => (match $expr {
698 $crate::outcome::Outcome::Success(val) => val,
699 $crate::outcome::Outcome::Error(e) => {
700 return $crate::outcome::Outcome::Error(::std::convert::From::from(e))
701 },
702 $crate::outcome::Outcome::Forward(f) => {
703 return $crate::outcome::Outcome::Forward(::std::convert::From::from(f))
704 },
705 });
706 }
707}
708
709/// Conversion trait from some type into an Outcome type.
710pub trait IntoOutcome<Outcome> {
711 /// The type to use when returning an `Outcome::Error`.
712 type Error: Sized;
713
714 /// The type to use when returning an `Outcome::Forward`.
715 type Forward: Sized;
716
717 /// Converts `self` into an `Outcome`. If `self` represents a success, an
718 /// `Outcome::Success` is returned. Otherwise, an `Outcome::Error` is
719 /// returned with `error` as the inner value.
720 fn or_error(self, error: Self::Error) -> Outcome;
721
722 /// Converts `self` into an `Outcome`. If `self` represents a success, an
723 /// `Outcome::Success` is returned. Otherwise, an `Outcome::Forward` is
724 /// returned with `forward` as the inner value.
725 fn or_forward(self, forward: Self::Forward) -> Outcome;
726}
727
728impl<S, E, F> IntoOutcome<Outcome<S, E, F>> for Option<S> {
729 type Error = E;
730 type Forward = F;
731
732 #[inline]
733 fn or_error(self, error: E) -> Outcome<S, E, F> {
734 match self {
735 Some(val) => Success(val),
736 None => Error(error)
737 }
738 }
739
740 #[inline]
741 fn or_forward(self, forward: F) -> Outcome<S, E, F> {
742 match self {
743 Some(val) => Success(val),
744 None => Forward(forward)
745 }
746 }
747}
748
749impl<'r, T: FromData<'r>> IntoOutcome<data::Outcome<'r, T>> for Result<T, T::Error> {
750 type Error = Status;
751 type Forward = (Data<'r>, Status);
752
753 #[inline]
754 fn or_error(self, error: Status) -> data::Outcome<'r, T> {
755 match self {
756 Ok(val) => Success(val),
757 Err(err) => Error((error, err))
758 }
759 }
760
761 #[inline]
762 fn or_forward(self, (data, forward): (Data<'r>, Status)) -> data::Outcome<'r, T> {
763 match self {
764 Ok(val) => Success(val),
765 Err(_) => Forward((data, forward))
766 }
767 }
768}
769
770impl<S, E> IntoOutcome<request::Outcome<S, E>> for Result<S, E> {
771 type Error = Status;
772 type Forward = Status;
773
774 #[inline]
775 fn or_error(self, error: Status) -> request::Outcome<S, E> {
776 match self {
777 Ok(val) => Success(val),
778 Err(err) => Error((error, err))
779 }
780 }
781
782 #[inline]
783 fn or_forward(self, status: Status) -> request::Outcome<S, E> {
784 match self {
785 Ok(val) => Success(val),
786 Err(_) => Forward(status)
787 }
788 }
789}
790
791impl<'r, 'o: 'r> IntoOutcome<route::Outcome<'r>> for response::Result<'o> {
792 type Error = ();
793 type Forward = (Data<'r>, Status);
794
795 #[inline]
796 fn or_error(self, _: ()) -> route::Outcome<'r> {
797 match self {
798 Ok(val) => Success(val),
799 Err(status) => Error(status),
800 }
801 }
802
803 #[inline]
804 fn or_forward(self, (data, forward): (Data<'r>, Status)) -> route::Outcome<'r> {
805 match self {
806 Ok(val) => Success(val),
807 Err(_) => Forward((data, forward))
808 }
809 }
810}