Remove use of the 'try_trait' feature.

Add the 'try_outcome' macro to replace uses of '?' on 'Outcome'.
This commit is contained in:
Jacob Pratt 2019-09-10 21:04:34 -04:00 committed by Sergio Benitez
parent b95b6765e1
commit e3c1a4ad3a
11 changed files with 89 additions and 45 deletions

View File

@ -145,7 +145,7 @@ pub fn database_attr(attr: TokenStream, input: TokenStream) -> Result<TokenStrea
fn from_request(request: &'a #request::Request<'r>) -> #request::Outcome<Self, ()> {
use ::rocket::{Outcome, http::Status};
let pool = request.guard::<::rocket::State<#pool_type>>()?;
let pool = ::rocket::try_outcome!(request.guard::<::rocket::State<#pool_type>>());
match pool.0.get() {
Ok(conn) => Outcome::Success(#guard_type(conn)),

View File

@ -143,7 +143,7 @@ impl<'a, T: Deserialize<'a>> FromData<'a> for Json<T> {
}
fn from_data(_: &Request<'_>, o: Transformed<'a, Self>) -> Outcome<Self, Self::Error> {
let string = o.borrowed()?;
let string = try_outcome!(o.borrowed());
match serde_json::from_str(&string) {
Ok(v) => Success(Json(v)),
Err(e) => {

View File

@ -131,7 +131,7 @@ impl<'a, T: Deserialize<'a>> FromData<'a> for MsgPack<T> {
fn from_data(_: &Request<'_>, o: Transformed<'a, Self>) -> Outcome<Self, Self::Error> {
use self::Error::*;
let buf = o.borrowed()?;
let buf = try_outcome!(o.borrowed());
match rmp_serde::from_slice(&buf) {
Ok(val) => Success(MsgPack(val)),
Err(e) => {

View File

@ -219,7 +219,7 @@ pub type Transformed<'a, T> =
/// // Retrieve a borrow to the now transformed `String` (an &str). This
/// // is only correct because we know we _always_ return a `Borrowed` from
/// // `transform` above.
/// let string = outcome.borrowed()?;
/// let string = try_outcome!(outcome.borrowed());
///
/// // Perform a crude, inefficient parse.
/// let splits: Vec<&str> = string.split(" ").collect();
@ -370,16 +370,17 @@ pub trait FromData<'a>: Sized {
/// following:
///
/// ```rust
/// # #[macro_use] extern crate rocket;
/// # use rocket::data::{Data, FromData, Transformed, Outcome};
/// # fn f<'a>(outcome: Transformed<'a, Data>) -> Outcome<Data, <Data as FromData<'a>>::Error> {
/// // If `Owned` was returned from `transform`:
/// let data = outcome.owned()?;
/// let data = try_outcome!(outcome.owned());
/// # unimplemented!()
/// # }
///
/// # fn g<'a>(outcome: Transformed<'a, Data>) -> Outcome<Data, <Data as FromData<'a>>::Error> {
/// // If `Borrowed` was returned from `transform`:
/// let data = outcome.borrowed()?;
/// let data = try_outcome!(outcome.borrowed());
/// # unimplemented!()
/// # }
/// ```
@ -399,7 +400,7 @@ impl<'f> FromData<'f> for Data {
#[inline(always)]
fn from_data(_: &Request<'_>, outcome: Transformed<'f, Self>) -> Outcome<Self, Self::Error> {
Success(outcome.owned()?)
outcome.owned()
}
}
@ -517,7 +518,7 @@ impl<'a, T: FromDataSimple> FromData<'a> for T {
#[inline(always)]
fn from_data(req: &Request<'_>, o: Transformed<'a, Self>) -> Outcome<Self, Self::Error> {
T::from_data(req, o.owned()?)
T::from_data(req, try_outcome!(o.owned()))
}
}

View File

@ -1,4 +1,3 @@
#![feature(try_trait)]
#![feature(proc_macro_hygiene)]
#![feature(crate_visibility_modifier)]
@ -95,16 +94,19 @@
//! [testing chapter of the guide]: https://rocket.rs/v0.5/guide/testing/#testing
#[allow(unused_imports)] #[macro_use] extern crate rocket_codegen;
// FIXME(rustdoc): We should be able to doc(inline) and not doc the
// rocket_codegen crate at all. Alas, doc-inlining will currently 1) show hidden
// proc-macros, and 2) result in proc-macros pointing to the wrong docs.
#[doc(hidden)] pub use rocket_codegen::*;
#[macro_use] extern crate log;
#[macro_use] extern crate pear;
#[doc(hidden)] #[macro_use] pub mod logger;
#[macro_use] pub mod outcome;
pub mod local;
pub mod request;
pub mod response;
pub mod outcome;
pub mod config;
pub mod data;
pub mod handler;

View File

@ -79,7 +79,6 @@
//! `None`.
use std::fmt;
use std::ops::Try;
use yansi::{Paint, Color};
@ -601,28 +600,68 @@ impl<S, E, F> Outcome<S, E, F> {
}
}
impl<S, E, F> Try for Outcome<S, E, F> {
type Ok = S;
type Error = Result<F, E>;
fn into_result(self) -> Result<Self::Ok, Self::Error> {
match self {
Success(val) => Ok(val),
Forward(val) => Err(Ok(val)),
Failure(val) => Err(Err(val)),
}
}
fn from_error(val: Self::Error) -> Self {
match val {
Ok(val) => Forward(val),
Err(val) => Failure(val),
}
}
fn from_ok(val: Self::Ok) -> Self {
Success(val)
}
/// Unwraps an [`Outcome`] to its success value, otherwise propagating the
/// forward or failure.
///
/// In the case of a `Forward` or `Failure` variant, the inner type is passed to
/// [`From`](std::convert::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
///
/// ```rust,no_run
/// # #![feature(proc_macro_hygiene)]
/// # #[macro_use] extern crate rocket;
/// # use std::sync::atomic::{AtomicUsize, Ordering};
/// use rocket::request::{self, Request, FromRequest, State};
/// use rocket::outcome::Outcome::*;
///
/// #[derive(Default)]
/// struct Atomics {
/// uncached: AtomicUsize,
/// cached: AtomicUsize,
/// }
///
/// struct Guard1;
/// struct Guard2;
///
/// impl<'a, 'r> FromRequest<'a, 'r> for Guard1 {
/// type Error = ();
///
/// fn from_request(req: &'a Request<'r>) -> request::Outcome<Self, ()> {
/// // Attempt to fetch the guard, passing through any error or forward.
/// let atomics = try_outcome!(req.guard::<State<'_, Atomics>>());
/// atomics.uncached.fetch_add(1, Ordering::Relaxed);
/// req.local_cache(|| atomics.cached.fetch_add(1, Ordering::Relaxed));
///
/// Success(Guard1)
/// }
/// }
///
/// impl<'a, 'r> FromRequest<'a, 'r> for Guard2 {
/// type Error = ();
///
/// fn from_request(req: &'a Request<'r>) -> request::Outcome<Self, ()> {
/// // Attempt to fetch the guard, passing through any error or forward.
/// let guard1: Guard1 = try_outcome!(req.guard::<Guard1>());
/// Success(Guard2)
/// }
/// }
/// ```
#[macro_export]
macro_rules! try_outcome {
($expr:expr $(,)?) => (match $expr {
$crate::outcome::Outcome::Success(val) => val,
$crate::outcome::Outcome::Failure(e) => {
return $crate::outcome::Outcome::Failure(::std::convert::From::from(e))
},
$crate::outcome::Outcome::Forward(f) => {
return $crate::outcome::Outcome::Forward(::std::convert::From::from(f))
},
});
}
impl<S, E, F> fmt::Debug for Outcome<S, E, F> {

View File

@ -211,7 +211,7 @@ impl<'f, T: FromForm<'f>> FromData<'f> for Form<T> {
}
fn from_data(_: &Request<'_>, o: Transformed<'f, Self>) -> Outcome<Self, Self::Error> {
<Form<T>>::from_data(o.borrowed()?, true).map(Form)
<Form<T>>::from_data(try_outcome!(o.borrowed()), true).map(Form)
}
}

View File

@ -105,7 +105,7 @@ impl<'f, T: FromForm<'f>> FromData<'f> for LenientForm<T> {
}
fn from_data(_: &Request<'_>, o: Transformed<'f, Self>) -> Outcome<Self, Self::Error> {
<Form<T>>::from_data(o.borrowed()?, false).map(LenientForm)
<Form<T>>::from_data(try_outcome!(o.borrowed()), false).map(LenientForm)
}
}

View File

@ -245,7 +245,7 @@ impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
/// type Error = ();
///
/// fn from_request(request: &Request<'_>) -> request::Outcome<User, ()> {
/// let db = request.guard::<Database>()?;
/// let db = try_outcome!(request.guard::<Database>());
/// request.cookies()
/// .get_private("user_id")
/// .and_then(|cookie| cookie.value().parse().ok())
@ -259,7 +259,7 @@ impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
///
/// fn from_request(request: &Request<'_>) -> request::Outcome<Admin, ()> {
/// // This will unconditionally query the database!
/// let user = request.guard::<User>()?;
/// let user = try_outcome!(request.guard::<User>());
///
/// if user.is_admin {
/// Outcome::Success(Admin { user })
@ -326,7 +326,7 @@ impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
/// type Error = std::convert::Infallible;
///
/// fn from_request(request: &'a Request<'_>) -> request::Outcome<Self, Self::Error> {
/// let user = request.guard::<&User>()?;
/// let user = try_outcome!(request.guard::<&User>());
///
/// if user.is_admin {
/// Outcome::Success(Admin { user })

View File

@ -6,7 +6,7 @@ mod tests;
use std::{io, env};
use std::fs::File;
use rocket::{Request, Handler, Route, Data, Catcher};
use rocket::{Request, Handler, Route, Data, Catcher, try_outcome};
use rocket::http::{Status, RawStr};
use rocket::response::{self, Responder, status::Custom};
use rocket::handler::Outcome;
@ -30,10 +30,11 @@ fn name<'a>(req: &'a Request, _: Data) -> Outcome<'a> {
}
fn echo_url<'r>(req: &'r Request, _: Data) -> Outcome<'r> {
let param = req.get_param::<&RawStr>(1)
let param_outcome = req.get_param::<&RawStr>(1)
.and_then(|res| res.ok())
.into_outcome(Status::BadRequest)?;
.into_outcome(Status::BadRequest);
let param = try_outcome!(param_outcome);
Outcome::try_from(req, RawStr::from_str(param).url_decode())
}
@ -79,10 +80,11 @@ impl CustomHandler {
impl Handler for CustomHandler {
fn handle<'r>(&self, req: &'r Request, data: Data) -> Outcome<'r> {
let id = req.get_param::<&RawStr>(0)
let id_outcome = req.get_param::<&RawStr>(0)
.and_then(|res| res.ok())
.or_forward(data)?;
.or_forward(data);
let id = try_outcome!(id_outcome);
Outcome::from(req, format!("{} - {}", self.data, id))
}
}

View File

@ -22,7 +22,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for Guard1 {
type Error = ();
fn from_request(req: &'a Request<'r>) -> request::Outcome<Self, ()> {
let atomics = req.guard::<State<'_, Atomics>>()?;
let atomics = try_outcome!(req.guard::<State<'_, Atomics>>());
atomics.uncached.fetch_add(1, Ordering::Relaxed);
req.local_cache(|| atomics.cached.fetch_add(1, Ordering::Relaxed));
@ -34,7 +34,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for Guard2 {
type Error = ();
fn from_request(req: &'a Request<'r>) -> request::Outcome<Self, ()> {
req.guard::<Guard1>()?;
try_outcome!(req.guard::<Guard1>());
Success(Guard2)
}
}