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