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}