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