rocket::outcome

Macro try_outcome

Source
pub macro try_outcome($expr:expr $(,)?) {
    ...
}
Expand description

Unwraps a Success or propagates a Forward or Error by returning early.

§Syntax

The macro has the following “signature”:

use rocket::outcome::Outcome;

// Returns the inner `S` if `outcome` is `Outcome::Success`. Otherwise
// returns from the caller with `Outcome<impl From<E>, impl From<F>>`.
fn try_outcome<S, E, F>(outcome: Outcome<S, E, F>) -> S

This is just like ? (or previously, try!), but for Outcome. In the case of a Forward or Error variant, the inner type is passed to From, allowing for the conversion between specific and more general types. The resulting forward/error is immediately returned. Because of the early return, try_outcome! can only be used in methods that return Outcome.

§Example

use std::sync::atomic::{AtomicUsize, Ordering};

use rocket::State;
use rocket::request::{self, Request, FromRequest};
use rocket::outcome::{try_outcome, Outcome::*};

#[derive(Default)]
struct Atomics {
    uncached: AtomicUsize,
    cached: AtomicUsize,
}

struct Guard1;
struct Guard2;

#[rocket::async_trait]
impl<'r> FromRequest<'r> for Guard1 {
    type Error = ();

    async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, ()> {
        // Attempt to fetch the guard, passing through any error or forward.
        let atomics = try_outcome!(req.guard::<&State<Atomics>>().await);
        atomics.uncached.fetch_add(1, Ordering::Relaxed);
        req.local_cache(|| atomics.cached.fetch_add(1, Ordering::Relaxed));

        Success(Guard1)
    }
}

#[rocket::async_trait]
impl<'r> FromRequest<'r> for Guard2 {
    type Error = ();

    async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, ()> {
        // Attempt to fetch the guard, passing through any error or forward.
        let guard1: Guard1 = try_outcome!(req.guard::<Guard1>().await);
        Success(Guard2)
    }
}