Rename 'Outcome::Failure' to 'Outcome::Error'.

The primary motivation is to deconflate the leading `F`s in `Failure` and
`Forward`. In particular, when using a generics, we used `F` for forward, which
could easily be confused for `F` for `Failure`. This resolves the conflation.
This commit is contained in:
Sergio Benitez 2023-10-31 12:11:03 -05:00
parent 55b7d4574a
commit b6430e9970
35 changed files with 231 additions and 226 deletions

View File

@ -67,7 +67,7 @@ pub fn derive_database(input: TokenStream) -> TokenStream {
) -> rocket::request::Outcome<Self, Self::Error> { ) -> rocket::request::Outcome<Self, Self::Error> {
match #db_ty::fetch(req.rocket()) { match #db_ty::fetch(req.rocket()) {
Some(db) => rocket::outcome::Outcome::Success(db), Some(db) => rocket::outcome::Outcome::Success(db),
None => rocket::outcome::Outcome::Failure(( None => rocket::outcome::Outcome::Error((
rocket::http::Status::InternalServerError, ())) rocket::http::Status::InternalServerError, ()))
} }
} }

View File

@ -164,7 +164,7 @@ pub struct Initializer<D: Database>(Option<&'static str>, PhantomData<fn() -> D>
/// [`connect_timeout`](crate::Config::connect_timeout) seconds. /// [`connect_timeout`](crate::Config::connect_timeout) seconds.
/// * If the `Initializer` fairing was _not_ attached, the guard _fails_ with /// * If the `Initializer` fairing was _not_ attached, the guard _fails_ with
/// status `InternalServerError`. A [`Sentinel`] guards this condition, and so /// status `InternalServerError`. A [`Sentinel`] guards this condition, and so
/// this type of failure is unlikely to occur. A `None` error is returned. /// this type of error is unlikely to occur. A `None` error is returned.
/// * If a connection is not available within `connect_timeout` seconds or /// * If a connection is not available within `connect_timeout` seconds or
/// another error occurs, the guard _fails_ with status `ServiceUnavailable` /// another error occurs, the guard _fails_ with status `ServiceUnavailable`
/// and the error is returned in `Some`. /// and the error is returned in `Some`.
@ -288,9 +288,9 @@ impl<'r, D: Database> FromRequest<'r> for Connection<D> {
match D::fetch(req.rocket()) { match D::fetch(req.rocket()) {
Some(db) => match db.get().await { Some(db) => match db.get().await {
Ok(conn) => Outcome::Success(Connection(conn)), Ok(conn) => Outcome::Success(Connection(conn)),
Err(e) => Outcome::Failure((Status::ServiceUnavailable, Some(e))), Err(e) => Outcome::Error((Status::ServiceUnavailable, Some(e))),
}, },
None => Outcome::Failure((Status::InternalServerError, None)), None => Outcome::Error((Status::InternalServerError, None)),
} }
} }
} }

View File

@ -153,7 +153,7 @@ impl<'r> FromRequest<'r> for Metadata<'r> {
error_!("Uninitialized template context: missing fairing."); error_!("Uninitialized template context: missing fairing.");
info_!("To use templates, you must attach `Template::fairing()`."); info_!("To use templates, you must attach `Template::fairing()`.");
info_!("See the `Template` documentation for more information."); info_!("See the `Template` documentation for more information.");
request::Outcome::Failure((Status::InternalServerError, ())) request::Outcome::Error((Status::InternalServerError, ()))
}) })
} }
} }

View File

@ -213,7 +213,7 @@ impl<'r, K: 'static, C: Poolable> FromRequest<'r> for Connection<K, C> {
Some(c) => c.get().await.into_outcome((Status::ServiceUnavailable, ())), Some(c) => c.get().await.into_outcome((Status::ServiceUnavailable, ())),
None => { None => {
error_!("Missing database fairing for `{}`", std::any::type_name::<K>()); error_!("Missing database fairing for `{}`", std::any::type_name::<K>());
Outcome::Failure((Status::InternalServerError, ())) Outcome::Error((Status::InternalServerError, ()))
} }
} }
} }

View File

@ -126,9 +126,9 @@ fn request_guard_decl(guard: &Guard) -> TokenStream {
#_log::warn_!("Request guard `{}` is forwarding.", stringify!(#ty)); #_log::warn_!("Request guard `{}` is forwarding.", stringify!(#ty));
return #Outcome::Forward((#__data, __e)); return #Outcome::Forward((#__data, __e));
}, },
#Outcome::Failure((__c, __e)) => { #Outcome::Error((__c, __e)) => {
#_log::warn_!("Request guard `{}` failed: {:?}.", stringify!(#ty), __e); #_log::warn_!("Request guard `{}` failed: {:?}.", stringify!(#ty), __e);
return #Outcome::Failure(__c); return #Outcome::Error(__c);
} }
}; };
} }
@ -189,9 +189,9 @@ fn data_guard_decl(guard: &Guard) -> TokenStream {
#_log::warn_!("Data guard `{}` is forwarding.", stringify!(#ty)); #_log::warn_!("Data guard `{}` is forwarding.", stringify!(#ty));
return #Outcome::Forward((__d, __e)); return #Outcome::Forward((__d, __e));
} }
#Outcome::Failure((__c, __e)) => { #Outcome::Error((__c, __e)) => {
#_log::warn_!("Data guard `{}` failed: {:?}.", stringify!(#ty), __e); #_log::warn_!("Data guard `{}` failed: {:?}.", stringify!(#ty), __e);
return #Outcome::Failure(__c); return #Outcome::Error(__c);
} }
}; };
} }

View File

@ -239,8 +239,7 @@ macro_rules! route_attribute {
/// ///
/// If a request guard fails, the request is forwarded if the /// If a request guard fails, the request is forwarded if the
/// [`Outcome`] is `Forward` or failed if the [`Outcome`] is /// [`Outcome`] is `Forward` or failed if the [`Outcome`] is
/// `Failure`. See [`FromRequest` Outcomes] for further /// `Error`. See [`FromRequest` Outcomes] for further detail.
/// detail.
/// ///
/// 2. Path and query guards in an unspecified order. If a path /// 2. Path and query guards in an unspecified order. If a path
/// or query guard fails, the request is forwarded. /// or query guard fails, the request is forwarded.
@ -249,7 +248,7 @@ macro_rules! route_attribute {
/// ///
/// If a data guard fails, the request is forwarded if the /// If a data guard fails, the request is forwarded if the
/// [`Outcome`] is `Forward` or failed if the [`Outcome`] is /// [`Outcome`] is `Forward` or failed if the [`Outcome`] is
/// `Failure`. See [`FromData`] for further detail. /// `Error`. See [`FromData`] for further detail.
/// ///
/// If all validation succeeds, the decorated function is called. /// If all validation succeeds, the decorated function is called.
/// The returned value is used to generate a [`Response`] via the /// The returned value is used to generate a [`Response`] via the
@ -448,7 +447,7 @@ pub fn main(args: TokenStream, input: TokenStream) -> TokenStream {
/// #[rocket::main] /// #[rocket::main]
/// async fn main() { /// async fn main() {
/// // Recall that an uninspected `Error` will cause a pretty-printed panic, /// // Recall that an uninspected `Error` will cause a pretty-printed panic,
/// // so rest assured failures do not go undetected when using `#[launch]`. /// // so rest assured errors do not go undetected when using `#[launch]`.
/// let _ = rocket().launch().await; /// let _ = rocket().launch().await;
/// } /// }
/// ``` /// ```

View File

@ -8,7 +8,7 @@ macro_rules! assert_parse_eq {
match from_str($from) { match from_str($from) {
Ok(output) => { Ok(output) => {
if output != expected { if output != expected {
println!("Failure on: {:?}", $from); println!("Error on: {:?}", $from);
assert_eq!(output, expected, "{} != {}", output, expected); assert_eq!(output, expected, "{} != {}", output, expected);
} }
} }
@ -53,7 +53,7 @@ macro_rules! assert_displays_eq {
Ok(output) => { Ok(output) => {
let output_string = output.to_string(); let output_string = output.to_string();
if output_string != string { if output_string != string {
println!("Failure on: {:?}", $string); println!("Error on: {:?}", $string);
println!("Got: {:?}", output_string); println!("Got: {:?}", output_string);
println!("Parsed as: {:?}", output); println!("Parsed as: {:?}", output);
panic!("failed"); panic!("failed");

View File

@ -533,7 +533,7 @@ impl fmt::Display for Name<'_> {
impl fmt::Display for Error { impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
Error::Parse(e) => write!(f, "parse failure: {}", e), Error::Parse(e) => write!(f, "parse error: {}", e),
Error::Incomplete(_) => write!(f, "incomplete certificate data"), Error::Incomplete(_) => write!(f, "incomplete certificate data"),
Error::Trailing(n) => write!(f, "found {} trailing bytes", n), Error::Trailing(n) => write!(f, "found {} trailing bytes", n),
Error::Empty => write!(f, "empty certificate chain"), Error::Empty => write!(f, "empty certificate chain"),

View File

@ -16,12 +16,14 @@ use yansi::Paint;
/// ///
/// * A failing guard. /// * A failing guard.
/// * A failing responder. /// * A failing responder.
/// * A forwarding guard.
/// * Routing failure. /// * Routing failure.
/// ///
/// Each failure is paired with a status code. Guards and responders indicate /// Each error or forward is paired with a status code. Guards and responders
/// the status code themselves via their `Err` return value while a routing /// indicate the status code themselves via their `Err` and `Outcome` return
/// failure is always a `404`. Rocket invokes the error handler for the catcher /// value. A complete routing failure is always a `404`. Rocket invokes the
/// with the error's status code. /// error handler for the catcher with an error's status code, or in the case of
/// every route resulting in a forward, the last forwarded status code.
/// ///
/// ### Error Handler Restrictions /// ### Error Handler Restrictions
/// ///
@ -31,14 +33,18 @@ use yansi::Paint;
/// ///
/// # Routing /// # Routing
/// ///
/// An error arising from a particular request _matches_ a catcher _iff_: /// If a route fails by returning an error [`Outcome`], Rocket routes the
/// erroring request to the highest precedence catcher among all the catchers
/// that match. Precedence is determined by the catcher's _base_, which is
/// provided as the first argument to [`Rocket::register()`]. Catchers with more
/// non-empty segments have a higher precedence.
/// ///
/// * It is a default catcher _or_ has a status code matching the error code. /// Rocket provides [built-in defaults](#built-in-default), but _default_
/// * Its base is a prefix of the normalized/decoded request URI path. /// catchers can also be registered. A _default_ catcher is a catcher with no
/// explicit status code: `None`.
/// ///
/// A _default_ catcher is a catcher with no explicit status code: `None`. The /// [`Outcome`]: crate::request::Outcome
/// catcher's _base_ is provided as the first argument to /// [`Rocket::register()`]: crate::Rocket::register()
/// [`Rocket::register()`](crate::Rocket::register()).
/// ///
/// # Collisions /// # Collisions
/// ///

View File

@ -288,7 +288,7 @@ impl Config {
/// ///
/// # Panics /// # Panics
/// ///
/// If extraction fails, prints an error message indicating the failure and /// If extraction fails, prints an error message indicating the error and
/// panics. For a version that doesn't panic, use [`Config::try_from()`]. /// panics. For a version that doesn't panic, use [`Config::try_from()`].
/// ///
/// # Example /// # Example

View File

@ -52,7 +52,7 @@ enum Kind {
/// ``` /// ```
/// ///
/// When running in any other profile with the `secrets` feature enabled, /// When running in any other profile with the `secrets` feature enabled,
/// providing a key of `0` or not provided a key at all results in a failure at /// providing a key of `0` or not provided a key at all results in an error at
/// launch-time: /// launch-time:
/// ///
/// ```rust /// ```rust
@ -67,7 +67,7 @@ enum Kind {
/// .select(profile.clone()); /// .select(profile.clone());
/// ///
/// let rocket = rocket::custom(figment); /// let rocket = rocket::custom(figment);
/// let error = Client::tracked(rocket).expect_err("failure in non-debug"); /// let error = Client::tracked(rocket).expect_err("error in non-debug");
/// assert!(matches!(error.kind(), ErrorKind::InsecureSecretKey(profile))); /// assert!(matches!(error.kind(), ErrorKind::InsecureSecretKey(profile)));
/// ``` /// ```
/// ///

View File

@ -260,10 +260,10 @@ macro_rules! impl_strict_from_data_from_capped {
Success(p) if p.is_complete() => Success(p.into_inner()), Success(p) if p.is_complete() => Success(p.into_inner()),
Success(_) => { Success(_) => {
let e = Error::new(UnexpectedEof, "data limit exceeded"); let e = Error::new(UnexpectedEof, "data limit exceeded");
Failure((Status::BadRequest, e.into())) Error((Status::BadRequest, e.into()))
}, },
Forward(d) => Forward(d), Forward(d) => Forward(d),
Failure((s, e)) => Failure((s, e)), Error((s, e)) => Error((s, e)),
} }
} }
} }

View File

@ -10,14 +10,14 @@ pub type Outcome<'r, T, E = <T as FromData<'r>>::Error>
= outcome::Outcome<T, (Status, E), (Data<'r>, Status)>; = outcome::Outcome<T, (Status, E), (Data<'r>, Status)>;
impl<'r, S, E> IntoOutcome<S, (Status, E), (Data<'r>, Status)> for Result<S, E> { impl<'r, S, E> IntoOutcome<S, (Status, E), (Data<'r>, Status)> for Result<S, E> {
type Failure = Status; type Error = Status;
type Forward = (Data<'r>, Status); type Forward = (Data<'r>, Status);
#[inline] #[inline]
fn into_outcome(self, status: Status) -> Outcome<'r, S, E> { fn into_outcome(self, status: Status) -> Outcome<'r, S, E> {
match self { match self {
Ok(val) => Success(val), Ok(val) => Success(val),
Err(err) => Failure((status, err)) Err(err) => Error((status, err))
} }
} }
@ -251,6 +251,7 @@ impl<'r, S, E> IntoOutcome<S, (Status, E), (Data<'r>, Status)> for Result<S, E>
/// use rocket::request::{self, Request}; /// use rocket::request::{self, Request};
/// use rocket::data::{self, Data, FromData, ToByteUnit}; /// use rocket::data::{self, Data, FromData, ToByteUnit};
/// use rocket::http::{Status, ContentType}; /// use rocket::http::{Status, ContentType};
/// use rocket::outcome::Outcome;
/// ///
/// #[derive(Debug)] /// #[derive(Debug)]
/// enum Error { /// enum Error {
@ -266,12 +267,11 @@ impl<'r, S, E> IntoOutcome<S, (Status, E), (Data<'r>, Status)> for Result<S, E>
/// ///
/// async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> data::Outcome<'r, Self> { /// async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> data::Outcome<'r, Self> {
/// use Error::*; /// use Error::*;
/// use rocket::outcome::Outcome::*;
/// ///
/// // Ensure the content type is correct before opening the data. /// // Ensure the content type is correct before opening the data.
/// let person_ct = ContentType::new("application", "x-person"); /// let person_ct = ContentType::new("application", "x-person");
/// if req.content_type() != Some(&person_ct) { /// if req.content_type() != Some(&person_ct) {
/// return Forward((data, Status::NotFound)); /// return Outcome::Forward((data, Status::NotFound));
/// } /// }
/// ///
/// // Use a configured limit with name 'person' or fallback to default. /// // Use a configured limit with name 'person' or fallback to default.
@ -280,8 +280,8 @@ impl<'r, S, E> IntoOutcome<S, (Status, E), (Data<'r>, Status)> for Result<S, E>
/// // Read the data into a string. /// // Read the data into a string.
/// let string = match data.open(limit).into_string().await { /// let string = match data.open(limit).into_string().await {
/// Ok(string) if string.is_complete() => string.into_inner(), /// Ok(string) if string.is_complete() => string.into_inner(),
/// Ok(_) => return Failure((Status::PayloadTooLarge, TooLarge)), /// Ok(_) => return Outcome::Error((Status::PayloadTooLarge, TooLarge)),
/// Err(e) => return Failure((Status::InternalServerError, Io(e))), /// Err(e) => return Outcome::Error((Status::InternalServerError, Io(e))),
/// }; /// };
/// ///
/// // We store `string` in request-local cache for long-lived borrows. /// // We store `string` in request-local cache for long-lived borrows.
@ -290,16 +290,16 @@ impl<'r, S, E> IntoOutcome<S, (Status, E), (Data<'r>, Status)> for Result<S, E>
/// // Split the string into two pieces at ':'. /// // Split the string into two pieces at ':'.
/// let (name, age) = match string.find(':') { /// let (name, age) = match string.find(':') {
/// Some(i) => (&string[..i], &string[(i + 1)..]), /// Some(i) => (&string[..i], &string[(i + 1)..]),
/// None => return Failure((Status::UnprocessableEntity, NoColon)), /// None => return Outcome::Error((Status::UnprocessableEntity, NoColon)),
/// }; /// };
/// ///
/// // Parse the age. /// // Parse the age.
/// let age: u16 = match age.parse() { /// let age: u16 = match age.parse() {
/// Ok(age) => age, /// Ok(age) => age,
/// Err(_) => return Failure((Status::UnprocessableEntity, InvalidAge)), /// Err(_) => return Outcome::Error((Status::UnprocessableEntity, InvalidAge)),
/// }; /// };
/// ///
/// Success(Person { name, age }) /// Outcome::Success(Person { name, age })
/// } /// }
/// } /// }
/// ///
@ -331,7 +331,7 @@ pub trait FromData<'r>: Sized {
/// ///
/// If validation and parsing succeeds, an outcome of `Success` is returned. /// If validation and parsing succeeds, an outcome of `Success` is returned.
/// If the data is not appropriate given the type of `Self`, `Forward` is /// If the data is not appropriate given the type of `Self`, `Forward` is
/// returned. If parsing fails, `Failure` is returned. /// returned. If parsing fails, `Error` is returned.
async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self>; async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self>;
} }
@ -428,7 +428,7 @@ impl<'r, T: FromData<'r> + 'r> FromData<'r> for Result<T, T::Error> {
async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> { async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> {
match T::from_data(req, data).await { match T::from_data(req, data).await {
Success(v) => Success(Ok(v)), Success(v) => Success(Ok(v)),
Failure((_, e)) => Success(Err(e)), Error((_, e)) => Success(Err(e)),
Forward(d) => Forward(d), Forward(d) => Forward(d),
} }
} }
@ -441,7 +441,7 @@ impl<'r, T: FromData<'r>> FromData<'r> for Option<T> {
async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> { async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> {
match T::from_data(req, data).await { match T::from_data(req, data).await {
Success(v) => Success(Some(v)), Success(v) => Success(Some(v)),
Failure(..) | Forward(..) => Success(None), Error(..) | Forward(..) => Success(None),
} }
} }
} }

View File

@ -212,9 +212,9 @@ impl Error {
crate::config::pretty_print_error(error.clone()); crate::config::pretty_print_error(error.clone());
"aborting due to invalid configuration" "aborting due to invalid configuration"
} }
ErrorKind::SentinelAborts(ref failures) => { ErrorKind::SentinelAborts(ref errors) => {
error!("Rocket failed to launch due to aborting sentinels:"); error!("Rocket failed to launch due to aborting sentinels:");
for sentry in failures { for sentry in errors {
let name = sentry.type_name.primary().bold(); let name = sentry.type_name.primary().bold();
let (file, line, col) = sentry.location; let (file, line, col) = sentry.location;
info_!("{} ({}:{}:{})", name, file, line, col); info_!("{} ({}:{}:{})", name, file, line, col);

View File

@ -66,7 +66,7 @@ pub type Result<T = Rocket<Build>, E = Rocket<Build>> = std::result::Result<T, E
// We might imagine that a request fairing returns an `Outcome`. If it returns // We might imagine that a request fairing returns an `Outcome`. If it returns
// `Success`, we don't do any routing and use that response directly. Same if it // `Success`, we don't do any routing and use that response directly. Same if it
// returns `Failure`. We only route if it returns `Forward`. I've chosen not to // returns `Error`. We only route if it returns `Forward`. I've chosen not to
// go this direction because I feel like request guards are the correct // go this direction because I feel like request guards are the correct
// mechanism to use here. In other words, enabling this at the fairing level // mechanism to use here. In other words, enabling this at the fairing level
// encourages implicit handling, a bad practice. Fairings can still, however, // encourages implicit handling, a bad practice. Fairings can still, however,
@ -125,7 +125,7 @@ pub type Result<T = Rocket<Build>, E = Rocket<Build>> = std::result::Result<T, E
/// recursively attaching ignite fairings. It returns `Ok` if it would like /// recursively attaching ignite fairings. It returns `Ok` if it would like
/// ignition and launch to proceed nominally and `Err` otherwise. If an /// ignition and launch to proceed nominally and `Err` otherwise. If an
/// ignite fairing returns `Err`, launch will be aborted. All ignite /// ignite fairing returns `Err`, launch will be aborted. All ignite
/// fairings are executed even if one or more signal a failure. /// fairings are executed even if one or more signal an error.
/// ///
/// * **<a name="liftoff">Liftoff</a> (`on_liftoff`)** /// * **<a name="liftoff">Liftoff</a> (`on_liftoff`)**
/// ///
@ -417,7 +417,7 @@ pub type Result<T = Rocket<Build>, E = Rocket<Build>> = std::result::Result<T, E
/// async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, ()> { /// async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, ()> {
/// match *request.local_cache(|| TimerStart(None)) { /// match *request.local_cache(|| TimerStart(None)) {
/// TimerStart(Some(time)) => request::Outcome::Success(StartTime(time)), /// TimerStart(Some(time)) => request::Outcome::Success(StartTime(time)),
/// TimerStart(None) => request::Outcome::Failure((Status::InternalServerError, ())), /// TimerStart(None) => request::Outcome::Error((Status::InternalServerError, ())),
/// } /// }
/// } /// }
/// } /// }

View File

@ -350,7 +350,7 @@ impl<'v> Errors<'v> {
/// Returns the highest [`Error::status()`] of all of the errors in `self` /// Returns the highest [`Error::status()`] of all of the errors in `self`
/// or [`Status::InternalServerError`] if `self` is empty. This is the /// or [`Status::InternalServerError`] if `self` is empty. This is the
/// status that is set by the [`Form`](crate::form::Form) data guard on /// status that is set by the [`Form`](crate::form::Form) data guard on
/// failure. /// error.
/// ///
/// See [`Error::status()`] for the corresponding status code of each /// See [`Error::status()`] for the corresponding status code of each
/// [`Error`] variant. /// [`Error`] variant.

View File

@ -65,8 +65,8 @@ use crate::form::prelude::*;
/// ///
/// If the request `ContentType` _does_ identify as a form but the form data /// If the request `ContentType` _does_ identify as a form but the form data
/// does not parse as `T`, according to `T`'s [`FromForm`] implementation, the /// does not parse as `T`, according to `T`'s [`FromForm`] implementation, the
/// guard **fails**. The `Failure` variant contains of the [`Errors`] emitted by /// guard **fails**. The `Error` variant contains a vector of the [`Errors`]
/// `T`'s `FromForm` parser. If the error is not caught by a /// emitted by `T`'s `FromForm` parser. If the error is not caught by a
/// [`form::Result<T>`](Result) or `Option<Form<T>>` data guard, the status code /// [`form::Result<T>`](Result) or `Option<Form<T>>` data guard, the status code
/// is set to [`Errors::status()`], and the corresponding error catcher is /// is set to [`Errors::status()`], and the corresponding error catcher is
/// called. /// called.
@ -334,7 +334,7 @@ impl<'r, T: FromForm<'r>> FromData<'r> for Form<T> {
match T::finalize(context) { match T::finalize(context) {
Ok(value) => Outcome::Success(Form(value)), Ok(value) => Outcome::Success(Form(value)),
Err(e) => Outcome::Failure((e.status(), e)), Err(e) => Outcome::Error((e.status(), e)),
} }
} }
} }

View File

@ -297,7 +297,7 @@ impl<'v> FromFormField<'v> for Capped<&'v str> {
match <Capped<&'v str> as FromData>::from_data(f.request, f.data).await { match <Capped<&'v str> as FromData>::from_data(f.request, f.data).await {
Outcome::Success(p) => Ok(p), Outcome::Success(p) => Ok(p),
Outcome::Failure((_, e)) => Err(e)?, Outcome::Error((_, e)) => Err(e)?,
Outcome::Forward(..) => { Outcome::Forward(..) => {
Err(Error::from(ErrorKind::Unexpected).with_entity(Entity::DataField))? Err(Error::from(ErrorKind::Unexpected).with_entity(Entity::DataField))?
} }
@ -318,7 +318,7 @@ impl<'v> FromFormField<'v> for Capped<String> {
match <Capped<String> as FromData>::from_data(f.request, f.data).await { match <Capped<String> as FromData>::from_data(f.request, f.data).await {
Outcome::Success(p) => Ok(p), Outcome::Success(p) => Ok(p),
Outcome::Failure((_, e)) => Err(e)?, Outcome::Error((_, e)) => Err(e)?,
Outcome::Forward(..) => { Outcome::Forward(..) => {
Err(Error::from(ErrorKind::Unexpected).with_entity(Entity::DataField))? Err(Error::from(ErrorKind::Unexpected).with_entity(Entity::DataField))?
} }
@ -354,7 +354,7 @@ impl<'v> FromFormField<'v> for Capped<&'v [u8]> {
match <Capped<&'v [u8]> as FromData>::from_data(f.request, f.data).await { match <Capped<&'v [u8]> as FromData>::from_data(f.request, f.data).await {
Outcome::Success(p) => Ok(p), Outcome::Success(p) => Ok(p),
Outcome::Failure((_, e)) => Err(e)?, Outcome::Error((_, e)) => Err(e)?,
Outcome::Forward(..) => { Outcome::Forward(..) => {
Err(Error::from(ErrorKind::Unexpected).with_entity(Entity::DataField))? Err(Error::from(ErrorKind::Unexpected).with_entity(Entity::DataField))?
} }

View File

@ -40,7 +40,7 @@ impl<'r, 'i> Parser<'r, 'i> {
match parser { match parser {
Ok(storage) => Outcome::Success(storage), Ok(storage) => Outcome::Success(storage),
Err(e) => Outcome::Failure((e.status(), e.into())) Err(e) => Outcome::Error((e.status(), e.into()))
} }
} }

View File

@ -159,7 +159,7 @@ crate::export! {
/// Equality validator: succeeds exactly when `a` == `b`, using [`PartialEq`]. /// Equality validator: succeeds exactly when `a` == `b`, using [`PartialEq`].
/// ///
/// On failure, returns a validation error with the following message: /// On error, returns a validation error with the following message:
/// ///
/// ```text /// ```text
/// value does not match expected value /// value does not match expected value
@ -236,7 +236,7 @@ pub fn dbg_eq<'v, A, B>(a: &A, b: B) -> Result<'v, ()>
/// Negative equality validator: succeeds exactly when `a` != `b`, using /// Negative equality validator: succeeds exactly when `a` != `b`, using
/// [`PartialEq`]. /// [`PartialEq`].
/// ///
/// On failure, returns a validation error with the following message: /// On error, returns a validation error with the following message:
/// ///
/// ```text /// ```text
/// value is equal to an invalid value /// value is equal to an invalid value
@ -361,7 +361,7 @@ impl<L, T: Len<L>> Len<L> for crate::serde::msgpack::MsgPack<T> {
/// Length validator: succeeds when the length of a value is within a `range`. /// Length validator: succeeds when the length of a value is within a `range`.
/// ///
/// The value must implement [`Len`]. On failure, returns an [`InvalidLength`] /// The value must implement [`Len`]. On error, returns an [`InvalidLength`]
/// error. See [`Len`] for supported types and how their length is computed. /// error. See [`Len`] for supported types and how their length is computed.
/// ///
/// [`InvalidLength`]: crate::form::error::ErrorKind::InvalidLength /// [`InvalidLength`]: crate::form::error::ErrorKind::InvalidLength
@ -504,7 +504,7 @@ impl<I, T: Contains<I> + ?Sized> Contains<I> for &T {
/// [`Contains<I>`](Contains) where `I` is the type of the `item`. See /// [`Contains<I>`](Contains) where `I` is the type of the `item`. See
/// [`Contains`] for supported types and items. /// [`Contains`] for supported types and items.
/// ///
/// On failure, returns a validation error with the following message: /// On error, returns a validation error with the following message:
/// ///
/// ```text /// ```text
/// value is equal to an invalid value /// value is equal to an invalid value
@ -590,7 +590,7 @@ pub fn dbg_contains<'v, V, I>(value: V, item: I) -> Result<'v, ()>
/// [`Contains<I>`](Contains) where `I` is the type of the `item`. See /// [`Contains<I>`](Contains) where `I` is the type of the `item`. See
/// [`Contains`] for supported types and items. /// [`Contains`] for supported types and items.
/// ///
/// On failure, returns a validation error with the following message: /// On error, returns a validation error with the following message:
/// ///
/// ```text /// ```text
/// value contains a disallowed item /// value contains a disallowed item
@ -670,7 +670,7 @@ pub fn dbg_omits<'v, V, I>(value: V, item: I) -> Result<'v, ()>
/// Integer range validator: succeeds when an integer value is within a range. /// Integer range validator: succeeds when an integer value is within a range.
/// ///
/// The value must be an integer type that implement `TryInto<isize> + Copy`. On /// The value must be an integer type that implement `TryInto<isize> + Copy`. On
/// failure, returns an [`OutOfRange`] error. /// error, returns an [`OutOfRange`] error.
/// ///
/// [`OutOfRange`]: crate::form::error::ErrorKind::OutOfRange /// [`OutOfRange`]: crate::form::error::ErrorKind::OutOfRange
/// ///
@ -719,7 +719,7 @@ pub fn range<'v, V, R>(value: &V, range: R) -> Result<'v, ()>
/// the `item`. The iterator must be [`Clone`]. See [`Contains`] for supported /// the `item`. The iterator must be [`Clone`]. See [`Contains`] for supported
/// types and items. The item must be [`Debug`]. /// types and items. The item must be [`Debug`].
/// ///
/// On failure, returns a [`InvalidChoice`] error with the debug representation /// On error, returns a [`InvalidChoice`] error with the debug representation
/// of each item in `items`. /// of each item in `items`.
/// ///
/// [`InvalidChoice`]: crate::form::error::ErrorKind::InvalidChoice /// [`InvalidChoice`]: crate::form::error::ErrorKind::InvalidChoice
@ -762,7 +762,7 @@ pub fn one_of<'v, V, I, R>(value: V, items: R) -> Result<'v, ()>
/// File type validator: succeeds when a [`TempFile`] has the Content-Type /// File type validator: succeeds when a [`TempFile`] has the Content-Type
/// `content_type`. /// `content_type`.
/// ///
/// On failure, returns a validation error with one of the following messages: /// On error, returns a validation error with one of the following messages:
/// ///
/// ```text /// ```text
/// // the file has an incorrect extension /// // the file has an incorrect extension
@ -810,7 +810,7 @@ pub fn ext<'v>(file: &TempFile<'_>, r#type: ContentType) -> Result<'v, ()> {
/// when a more case-specific option does not exist. It succeeds exactly when /// when a more case-specific option does not exist. It succeeds exactly when
/// `f` returns `true` and fails otherwise. /// `f` returns `true` and fails otherwise.
/// ///
/// On failure, returns a validation error with the message `msg`. /// On error, returns a validation error with the message `msg`.
/// ///
/// # Example /// # Example
/// ///
@ -860,7 +860,7 @@ pub fn with<'v, V, F, M>(value: V, f: F, msg: M) -> Result<'v, ()>
/// Along with [`with`], this is the most generic validator. It succeeds /// Along with [`with`], this is the most generic validator. It succeeds
/// exactly when `f` returns `Ok` and fails otherwise. /// exactly when `f` returns `Ok` and fails otherwise.
/// ///
/// On failure, returns a validation error with the message in the `Err` /// On error, returns a validation error with the message in the `Err`
/// variant converted into a string. /// variant converted into a string.
/// ///
/// # Example /// # Example

View File

@ -149,12 +149,12 @@ impl FileServer {
if !options.contains(Options::IndexFile) && !path.is_dir() { if !options.contains(Options::IndexFile) && !path.is_dir() {
let path = path.display(); let path = path.display();
error!("FileServer path '{}' is not a directory.", path.primary()); error!("FileServer path '{}' is not a directory.", path.primary());
warn_!("Aborting early to prevent inevitable handler failure."); warn_!("Aborting early to prevent inevitable handler error.");
panic!("invalid directory: refusing to continue"); panic!("invalid directory: refusing to continue");
} else if !path.exists() { } else if !path.exists() {
let path = path.display(); let path = path.display();
error!("FileServer path '{}' is not a file.", path.primary()); error!("FileServer path '{}' is not a file.", path.primary());
warn_!("Aborting early to prevent inevitable handler failure."); warn_!("Aborting early to prevent inevitable handler error.");
panic!("invalid file: refusing to continue"); panic!("invalid file: refusing to continue");
} }
} }

View File

@ -1,10 +1,10 @@
//! Success, failure, and forward handling. //! Success, error, and forward handling.
//! //!
//! The `Outcome<S, E, F>` type is similar to the standard library's `Result<S, //! The `Outcome<S, E, F>` type is similar to the standard library's `Result<S,
//! E>` type. It is an enum with three variants, each containing a value: //! E>` type. It is an enum with three variants, each containing a value:
//! `Success(S)`, which represents a successful outcome, `Failure(E)`, which //! `Success(S)`, which represents a successful outcome, `Error(E)`, which
//! represents a failing outcome, and `Forward(F)`, which represents neither a //! represents an erroring outcome, and `Forward(F)`, which represents neither a
//! success or failure, but instead, indicates that processing could not be //! success or error, but instead, indicates that processing could not be
//! handled and should instead be _forwarded_ to whatever can handle the //! handled and should instead be _forwarded_ to whatever can handle the
//! processing next. //! processing next.
//! //!
@ -35,15 +35,15 @@
//! `Success(S)`. If `from_data` returns a `Success`, the `Success` value will //! `Success(S)`. If `from_data` returns a `Success`, the `Success` value will
//! be unwrapped and the value will be used as the value of `my_val`. //! be unwrapped and the value will be used as the value of `my_val`.
//! //!
//! # Failure //! # Error
//! //!
//! A failure `Outcome<S, E, F>`, `Failure(E)`, is returned when a function //! An error `Outcome<S, E, F>`, `Error(E)`, is returned when a function
//! fails with some error and no processing can or should continue as a result. //! fails with some error and no processing can or should continue as a result.
//! The meaning of a failure depends on the context. //! The meaning of an error depends on the context.
//! //!
//! In Rocket, a `Failure` generally means that a request is taken out of normal //! In Rocket, an `Error` generally means that a request is taken out of normal
//! processing. The request is then given to the catcher corresponding to some //! processing. The request is then given to the catcher corresponding to some
//! status code. Users can catch failures by requesting a type of `Result<S, E>` //! status code. Users can catch errors by requesting a type of `Result<S, E>`
//! or `Option<S>` in request handlers. For example, if a user's handler looks //! or `Option<S>` in request handlers. For example, if a user's handler looks
//! like: //! like:
//! //!
@ -56,10 +56,9 @@
//! ``` //! ```
//! //!
//! The [`FromData`] implementation for the type `S` returns an `Outcome` with a //! The [`FromData`] implementation for the type `S` returns an `Outcome` with a
//! `Success(S)` and `Failure(E)`. If `from_data` returns a `Failure`, the //! `Success(S)` and `Error(E)`. If `from_data` returns an `Error`, the `Error`
//! `Failure` value will be unwrapped and the value will be used as the `Err` //! value will be unwrapped and the value will be used as the `Err` value of
//! value of `my_val` while a `Success` will be unwrapped and used the `Ok` //! `my_val` while a `Success` will be unwrapped and used the `Ok` value.
//! value.
//! //!
//! # Forward //! # Forward
//! //!
@ -79,11 +78,11 @@
//! ``` //! ```
//! //!
//! The [`FromData`] implementation for the type `S` returns an `Outcome` with a //! The [`FromData`] implementation for the type `S` returns an `Outcome` with a
//! `Success(S)`, `Failure(E)`, and `Forward(F)`. If the `Outcome` is a //! `Success(S)`, `Error(E)`, and `Forward(F)`. If the `Outcome` is a
//! `Forward`, the `hello` handler isn't called. Instead, the incoming request //! `Forward`, the `hello` handler isn't called. Instead, the incoming request
//! is forwarded, or passed on to, the next matching route, if any. Ultimately, //! is forwarded, or passed on to, the next matching route, if any. Ultimately,
//! if there are no non-forwarding routes, forwarded requests are handled by the //! if there are no non-forwarding routes, forwarded requests are handled by the
//! 404 catcher. Similar to `Failure`s, users can catch `Forward`s by requesting //! 404 catcher. Similar to `Error`s, users can catch `Forward`s by requesting
//! a type of `Option<S>`. If an `Outcome` is a `Forward`, the `Option` will be //! a type of `Option<S>`. If an `Outcome` is a `Forward`, the `Option` will be
//! `None`. //! `None`.
@ -93,8 +92,8 @@ use yansi::{Paint, Color};
use self::Outcome::*; use self::Outcome::*;
/// An enum representing success (`Success`), failure (`Failure`), or /// An enum representing success (`Success`), error (`Error`), or forwarding
/// forwarding (`Forward`). /// (`Forward`).
/// ///
/// See the [top level documentation](crate::outcome) for detailed information. /// See the [top level documentation](crate::outcome) for detailed information.
#[must_use] #[must_use]
@ -102,24 +101,24 @@ use self::Outcome::*;
pub enum Outcome<S, E, F> { pub enum Outcome<S, E, F> {
/// Contains the success value. /// Contains the success value.
Success(S), Success(S),
/// Contains the failure error value. /// Contains the error error value.
Failure(E), Error(E),
/// Contains the value to forward on. /// Contains the value to forward on.
Forward(F), Forward(F),
} }
/// Conversion trait from some type into an Outcome type. /// Conversion trait from some type into an Outcome type.
pub trait IntoOutcome<S, E, F> { pub trait IntoOutcome<S, E, F> {
/// The type to use when returning an `Outcome::Failure`. /// The type to use when returning an `Outcome::Error`.
type Failure: Sized; type Error: Sized;
/// The type to use when returning an `Outcome::Forward`. /// The type to use when returning an `Outcome::Forward`.
type Forward: Sized; type Forward: Sized;
/// Converts `self` into an `Outcome`. If `self` represents a success, an /// Converts `self` into an `Outcome`. If `self` represents a success, an
/// `Outcome::Success` is returned. Otherwise, an `Outcome::Failure` is /// `Outcome::Success` is returned. Otherwise, an `Outcome::Error` is
/// returned with `failure` as the inner value. /// returned with `error` as the inner value.
fn into_outcome(self, failure: Self::Failure) -> Outcome<S, E, F>; fn into_outcome(self, error: Self::Error) -> Outcome<S, E, F>;
/// Converts `self` into an `Outcome`. If `self` represents a success, an /// Converts `self` into an `Outcome`. If `self` represents a success, an
/// `Outcome::Success` is returned. Otherwise, an `Outcome::Forward` is /// `Outcome::Success` is returned. Otherwise, an `Outcome::Forward` is
@ -128,14 +127,14 @@ pub trait IntoOutcome<S, E, F> {
} }
impl<S, E, F> IntoOutcome<S, E, F> for Option<S> { impl<S, E, F> IntoOutcome<S, E, F> for Option<S> {
type Failure = E; type Error = E;
type Forward = F; type Forward = F;
#[inline] #[inline]
fn into_outcome(self, failure: E) -> Outcome<S, E, F> { fn into_outcome(self, error: E) -> Outcome<S, E, F> {
match self { match self {
Some(val) => Success(val), Some(val) => Success(val),
None => Failure(failure) None => Error(error)
} }
} }
@ -208,7 +207,7 @@ impl<S, E, F> Outcome<S, E, F> {
/// let x: Outcome<i32, &str, usize> = Success(10); /// let x: Outcome<i32, &str, usize> = Success(10);
/// assert_eq!(x.is_success(), true); /// assert_eq!(x.is_success(), true);
/// ///
/// let x: Outcome<i32, &str, usize> = Failure("Hi! I'm an error."); /// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
/// assert_eq!(x.is_success(), false); /// assert_eq!(x.is_success(), false);
/// ///
/// let x: Outcome<i32, &str, usize> = Forward(25); /// let x: Outcome<i32, &str, usize> = Forward(25);
@ -219,7 +218,7 @@ impl<S, E, F> Outcome<S, E, F> {
matches!(self, Success(_)) matches!(self, Success(_))
} }
/// Return true if this `Outcome` is a `Failure`. /// Return true if this `Outcome` is an `Error`.
/// ///
/// # Examples /// # Examples
/// ///
@ -228,17 +227,17 @@ impl<S, E, F> Outcome<S, E, F> {
/// # use rocket::outcome::Outcome::*; /// # use rocket::outcome::Outcome::*;
/// # /// #
/// let x: Outcome<i32, &str, usize> = Success(10); /// let x: Outcome<i32, &str, usize> = Success(10);
/// assert_eq!(x.is_failure(), false); /// assert_eq!(x.is_error(), false);
/// ///
/// let x: Outcome<i32, &str, usize> = Failure("Hi! I'm an error."); /// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
/// assert_eq!(x.is_failure(), true); /// assert_eq!(x.is_error(), true);
/// ///
/// let x: Outcome<i32, &str, usize> = Forward(25); /// let x: Outcome<i32, &str, usize> = Forward(25);
/// assert_eq!(x.is_failure(), false); /// assert_eq!(x.is_error(), false);
/// ``` /// ```
#[inline] #[inline]
pub fn is_failure(&self) -> bool { pub fn is_error(&self) -> bool {
matches!(self, Failure(_)) matches!(self, Error(_))
} }
/// Return true if this `Outcome` is a `Forward`. /// Return true if this `Outcome` is a `Forward`.
@ -252,7 +251,7 @@ impl<S, E, F> Outcome<S, E, F> {
/// let x: Outcome<i32, &str, usize> = Success(10); /// let x: Outcome<i32, &str, usize> = Success(10);
/// assert_eq!(x.is_forward(), false); /// assert_eq!(x.is_forward(), false);
/// ///
/// let x: Outcome<i32, &str, usize> = Failure("Hi! I'm an error."); /// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
/// assert_eq!(x.is_forward(), false); /// assert_eq!(x.is_forward(), false);
/// ///
/// let x: Outcome<i32, &str, usize> = Forward(25); /// let x: Outcome<i32, &str, usize> = Forward(25);
@ -275,7 +274,7 @@ impl<S, E, F> Outcome<S, E, F> {
/// let x: Outcome<i32, &str, usize> = Success(10); /// let x: Outcome<i32, &str, usize> = Success(10);
/// assert_eq!(x.succeeded(), Some(10)); /// assert_eq!(x.succeeded(), Some(10));
/// ///
/// let x: Outcome<i32, &str, usize> = Failure("Hi! I'm an error."); /// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
/// assert_eq!(x.succeeded(), None); /// assert_eq!(x.succeeded(), None);
/// ///
/// let x: Outcome<i32, &str, usize> = Forward(25); /// let x: Outcome<i32, &str, usize> = Forward(25);
@ -291,7 +290,7 @@ impl<S, E, F> Outcome<S, E, F> {
/// Converts from `Outcome<S, E, F>` to `Option<E>`. /// Converts from `Outcome<S, E, F>` to `Option<E>`.
/// ///
/// Returns the `Some` of the `Failure` if this is a `Failure`, otherwise /// Returns the `Some` of the `Error` if this is an `Error`, otherwise
/// returns `None`. `self` is consumed, and all other values are discarded. /// returns `None`. `self` is consumed, and all other values are discarded.
/// ///
/// ```rust /// ```rust
@ -301,7 +300,7 @@ impl<S, E, F> Outcome<S, E, F> {
/// let x: Outcome<i32, &str, usize> = Success(10); /// let x: Outcome<i32, &str, usize> = Success(10);
/// assert_eq!(x.failed(), None); /// assert_eq!(x.failed(), None);
/// ///
/// let x: Outcome<i32, &str, usize> = Failure("Hi! I'm an error."); /// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
/// assert_eq!(x.failed(), Some("Hi! I'm an error.")); /// assert_eq!(x.failed(), Some("Hi! I'm an error."));
/// ///
/// let x: Outcome<i32, &str, usize> = Forward(25); /// let x: Outcome<i32, &str, usize> = Forward(25);
@ -310,7 +309,7 @@ impl<S, E, F> Outcome<S, E, F> {
#[inline] #[inline]
pub fn failed(self) -> Option<E> { pub fn failed(self) -> Option<E> {
match self { match self {
Failure(val) => Some(val), Error(val) => Some(val),
_ => None _ => None
} }
} }
@ -327,7 +326,7 @@ impl<S, E, F> Outcome<S, E, F> {
/// let x: Outcome<i32, &str, usize> = Success(10); /// let x: Outcome<i32, &str, usize> = Success(10);
/// assert_eq!(x.forwarded(), None); /// assert_eq!(x.forwarded(), None);
/// ///
/// let x: Outcome<i32, &str, usize> = Failure("Hi! I'm an error."); /// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
/// assert_eq!(x.forwarded(), None); /// assert_eq!(x.forwarded(), None);
/// ///
/// let x: Outcome<i32, &str, usize> = Forward(25); /// let x: Outcome<i32, &str, usize> = Forward(25);
@ -355,7 +354,7 @@ impl<S, E, F> Outcome<S, E, F> {
/// let x: Outcome<i32, &str, usize> = Success(10); /// let x: Outcome<i32, &str, usize> = Success(10);
/// assert_eq!(x.success_or(false), Ok(10)); /// assert_eq!(x.success_or(false), Ok(10));
/// ///
/// let x: Outcome<i32, &str, usize> = Failure("Hi! I'm an error."); /// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
/// assert_eq!(x.success_or(false), Err(false)); /// assert_eq!(x.success_or(false), Err(false));
/// ///
/// let x: Outcome<i32, &str, usize> = Forward(25); /// let x: Outcome<i32, &str, usize> = Forward(25);
@ -384,7 +383,7 @@ impl<S, E, F> Outcome<S, E, F> {
/// let x: Outcome<i32, &str, usize> = Success(10); /// let x: Outcome<i32, &str, usize> = Success(10);
/// assert_eq!(x.success_or_else(|| false), Ok(10)); /// assert_eq!(x.success_or_else(|| false), Ok(10));
/// ///
/// let x: Outcome<i32, &str, usize> = Failure("Hi! I'm an error."); /// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
/// assert_eq!(x.success_or_else(|| false), Err(false)); /// assert_eq!(x.success_or_else(|| false), Err(false));
/// ///
/// let x: Outcome<i32, &str, usize> = Forward(25); /// let x: Outcome<i32, &str, usize> = Forward(25);
@ -407,14 +406,14 @@ impl<S, E, F> Outcome<S, E, F> {
/// let x: Outcome<i32, &str, usize> = Success(10); /// let x: Outcome<i32, &str, usize> = Success(10);
/// assert_eq!(x.as_ref(), Success(&10)); /// assert_eq!(x.as_ref(), Success(&10));
/// ///
/// let x: Outcome<i32, &str, usize> = Failure("Hi! I'm an error."); /// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
/// assert_eq!(x.as_ref(), Failure(&"Hi! I'm an error.")); /// assert_eq!(x.as_ref(), Error(&"Hi! I'm an error."));
/// ``` /// ```
#[inline] #[inline]
pub fn as_ref(&self) -> Outcome<&S, &E, &F> { pub fn as_ref(&self) -> Outcome<&S, &E, &F> {
match *self { match *self {
Success(ref val) => Success(val), Success(ref val) => Success(val),
Failure(ref val) => Failure(val), Error(ref val) => Error(val),
Forward(ref val) => Forward(val), Forward(ref val) => Forward(val),
} }
} }
@ -436,7 +435,7 @@ impl<S, E, F> Outcome<S, E, F> {
pub fn as_mut(&mut self) -> Outcome<&mut S, &mut E, &mut F> { pub fn as_mut(&mut self) -> Outcome<&mut S, &mut E, &mut F> {
match *self { match *self {
Success(ref mut val) => Success(val), Success(ref mut val) => Success(val),
Failure(ref mut val) => Failure(val), Error(ref mut val) => Error(val),
Forward(ref mut val) => Forward(val), Forward(ref mut val) => Forward(val),
} }
} }
@ -458,29 +457,29 @@ impl<S, E, F> Outcome<S, E, F> {
pub fn map<T, M: FnOnce(S) -> T>(self, f: M) -> Outcome<T, E, F> { pub fn map<T, M: FnOnce(S) -> T>(self, f: M) -> Outcome<T, E, F> {
match self { match self {
Success(val) => Success(f(val)), Success(val) => Success(f(val)),
Failure(val) => Failure(val), Error(val) => Error(val),
Forward(val) => Forward(val), Forward(val) => Forward(val),
} }
} }
/// Maps the `Failure` value using `f`. Maps an `Outcome<S, E, F>` to an /// Maps the `Error` value using `f`. Maps an `Outcome<S, E, F>` to an
/// `Outcome<S, T, F>` by applying the function `f` to the value of type `E` /// `Outcome<S, T, F>` by applying the function `f` to the value of type `E`
/// in `self` if `self` is an `Outcome::Failure`. /// in `self` if `self` is an `Outcome::Error`.
/// ///
/// ```rust /// ```rust
/// # use rocket::outcome::Outcome; /// # use rocket::outcome::Outcome;
/// # use rocket::outcome::Outcome::*; /// # use rocket::outcome::Outcome::*;
/// # /// #
/// let x: Outcome<i32, &str, usize> = Failure("hi"); /// let x: Outcome<i32, &str, usize> = Error("hi");
/// ///
/// let mapped = x.map_failure(|v| if v == "hi" { 10 } else { 0 }); /// let mapped = x.map_error(|v| if v == "hi" { 10 } else { 0 });
/// assert_eq!(mapped, Failure(10)); /// assert_eq!(mapped, Error(10));
/// ``` /// ```
#[inline] #[inline]
pub fn map_failure<T, M: FnOnce(E) -> T>(self, f: M) -> Outcome<S, T, F> { pub fn map_error<T, M: FnOnce(E) -> T>(self, f: M) -> Outcome<S, T, F> {
match self { match self {
Success(val) => Success(val), Success(val) => Success(val),
Failure(val) => Failure(f(val)), Error(val) => Error(f(val)),
Forward(val) => Forward(val), Forward(val) => Forward(val),
} }
} }
@ -502,7 +501,7 @@ impl<S, E, F> Outcome<S, E, F> {
pub fn map_forward<T, M: FnOnce(F) -> T>(self, f: M) -> Outcome<S, E, T> { pub fn map_forward<T, M: FnOnce(F) -> T>(self, f: M) -> Outcome<S, E, T> {
match self { match self {
Success(val) => Success(val), Success(val) => Success(val),
Failure(val) => Failure(val), Error(val) => Error(val),
Forward(val) => Forward(f(val)), Forward(val) => Forward(f(val)),
} }
} }
@ -523,7 +522,7 @@ impl<S, E, F> Outcome<S, E, F> {
/// let mapped = x.and_then(|v| match v { /// let mapped = x.and_then(|v| match v {
/// 10 => Success("10"), /// 10 => Success("10"),
/// 1 => Forward(false), /// 1 => Forward(false),
/// _ => Failure("30") /// _ => Error("30")
/// }); /// });
/// ///
/// assert_eq!(mapped, Success("10")); /// assert_eq!(mapped, Success("10"));
@ -532,15 +531,15 @@ impl<S, E, F> Outcome<S, E, F> {
pub fn and_then<T, M: FnOnce(S) -> Outcome<T, E, F>>(self, f: M) -> Outcome<T, E, F> { pub fn and_then<T, M: FnOnce(S) -> Outcome<T, E, F>>(self, f: M) -> Outcome<T, E, F> {
match self { match self {
Success(val) => f(val), Success(val) => f(val),
Failure(val) => Failure(val), Error(val) => Error(val),
Forward(val) => Forward(val), Forward(val) => Forward(val),
} }
} }
/// Converts from `Outcome<S, E, F>` to `Outcome<S, T, F>` using `f` to map /// Converts from `Outcome<S, E, F>` to `Outcome<S, T, F>` using `f` to map
/// `Failure(E)` to `Failure(T)`. /// `Error(E)` to `Error(T)`.
/// ///
/// If `self` is not `Failure`, `self` is returned. /// If `self` is not `Error`, `self` is returned.
/// ///
/// # Examples /// # Examples
/// ///
@ -548,21 +547,21 @@ impl<S, E, F> Outcome<S, E, F> {
/// # use rocket::outcome::Outcome; /// # use rocket::outcome::Outcome;
/// # use rocket::outcome::Outcome::*; /// # use rocket::outcome::Outcome::*;
/// # /// #
/// let x: Outcome<i32, &str, bool> = Failure("hi"); /// let x: Outcome<i32, &str, bool> = Error("hi");
/// ///
/// let mapped = x.failure_then(|v| match v { /// let mapped = x.error_then(|v| match v {
/// "hi" => Failure(10), /// "hi" => Error(10),
/// "test" => Forward(false), /// "test" => Forward(false),
/// _ => Success(10) /// _ => Success(10)
/// }); /// });
/// ///
/// assert_eq!(mapped, Failure(10)); /// assert_eq!(mapped, Error(10));
/// ``` /// ```
#[inline] #[inline]
pub fn failure_then<T, M: FnOnce(E) -> Outcome<S, T, F>>(self, f: M) -> Outcome<S, T, F> { pub fn error_then<T, M: FnOnce(E) -> Outcome<S, T, F>>(self, f: M) -> Outcome<S, T, F> {
match self { match self {
Success(val) => Success(val), Success(val) => Success(val),
Failure(val) => f(val), Error(val) => f(val),
Forward(val) => Forward(val), Forward(val) => Forward(val),
} }
} }
@ -583,7 +582,7 @@ impl<S, E, F> Outcome<S, E, F> {
/// let mapped = x.forward_then(|v| match v { /// let mapped = x.forward_then(|v| match v {
/// Some(true) => Success(10), /// Some(true) => Success(10),
/// Some(false) => Forward(20), /// Some(false) => Forward(20),
/// None => Failure("10") /// None => Error("10")
/// }); /// });
/// ///
/// assert_eq!(mapped, Forward(20)); /// assert_eq!(mapped, Forward(20));
@ -592,13 +591,13 @@ impl<S, E, F> Outcome<S, E, F> {
pub fn forward_then<T, M: FnOnce(F) -> Outcome<S, E, T>>(self, f: M) -> Outcome<S, E, T> { pub fn forward_then<T, M: FnOnce(F) -> Outcome<S, E, T>>(self, f: M) -> Outcome<S, E, T> {
match self { match self {
Success(val) => Success(val), Success(val) => Success(val),
Failure(val) => Failure(val), Error(val) => Error(val),
Forward(val) => f(val), Forward(val) => f(val),
} }
} }
/// Converts `Outcome<S, E, F>` to `Result<S, E>` by identity mapping /// Converts `Outcome<S, E, F>` to `Result<S, E>` by identity mapping
/// `Success(S)` and `Failure(E)` to `Result<T, E>` and mapping `Forward(F)` /// `Success(S)` and `Error(E)` to `Result<T, E>` and mapping `Forward(F)`
/// to `Result<T, E>` using `f`. /// to `Result<T, E>` using `f`.
/// ///
/// ```rust /// ```rust
@ -608,7 +607,7 @@ impl<S, E, F> Outcome<S, E, F> {
/// let x: Outcome<i32, &str, usize> = Success(10); /// let x: Outcome<i32, &str, usize> = Success(10);
/// assert_eq!(x.ok_map_forward(|x| Ok(x as i32 + 1)), Ok(10)); /// assert_eq!(x.ok_map_forward(|x| Ok(x as i32 + 1)), Ok(10));
/// ///
/// let x: Outcome<i32, &str, usize> = Failure("hello"); /// let x: Outcome<i32, &str, usize> = Error("hello");
/// assert_eq!(x.ok_map_forward(|x| Ok(x as i32 + 1)), Err("hello")); /// assert_eq!(x.ok_map_forward(|x| Ok(x as i32 + 1)), Err("hello"));
/// ///
/// let x: Outcome<i32, &str, usize> = Forward(0); /// let x: Outcome<i32, &str, usize> = Forward(0);
@ -620,13 +619,13 @@ impl<S, E, F> Outcome<S, E, F> {
{ {
match self { match self {
Outcome::Success(s) => Ok(s), Outcome::Success(s) => Ok(s),
Outcome::Failure(e) => Err(e), Outcome::Error(e) => Err(e),
Outcome::Forward(v) => f(v), Outcome::Forward(v) => f(v),
} }
} }
/// Converts `Outcome<S, E, F>` to `Result<S, E>` by identity mapping /// Converts `Outcome<S, E, F>` to `Result<S, E>` by identity mapping
/// `Success(S)` and `Forward(F)` to `Result<T, F>` and mapping `Failure(E)` /// `Success(S)` and `Forward(F)` to `Result<T, F>` and mapping `Error(E)`
/// to `Result<T, F>` using `f`. /// to `Result<T, F>` using `f`.
/// ///
/// ```rust /// ```rust
@ -634,21 +633,21 @@ impl<S, E, F> Outcome<S, E, F> {
/// # use rocket::outcome::Outcome::*; /// # use rocket::outcome::Outcome::*;
/// # /// #
/// let x: Outcome<i32, &str, usize> = Success(10); /// let x: Outcome<i32, &str, usize> = Success(10);
/// assert_eq!(x.ok_map_failure(|s| Ok(123)), Ok(10)); /// assert_eq!(x.ok_map_error(|s| Ok(123)), Ok(10));
/// ///
/// let x: Outcome<i32, &str, usize> = Failure("hello"); /// let x: Outcome<i32, &str, usize> = Error("hello");
/// assert_eq!(x.ok_map_failure(|s| Ok(123)), Ok(123)); /// assert_eq!(x.ok_map_error(|s| Ok(123)), Ok(123));
/// ///
/// let x: Outcome<i32, &str, usize> = Forward(0); /// let x: Outcome<i32, &str, usize> = Forward(0);
/// assert_eq!(x.ok_map_failure(|s| Ok(123)), Err(0)); /// assert_eq!(x.ok_map_error(|s| Ok(123)), Err(0));
/// ``` /// ```
#[inline] #[inline]
pub fn ok_map_failure<M>(self, f: M) -> Result<S, F> pub fn ok_map_error<M>(self, f: M) -> Result<S, F>
where M: FnOnce(E) -> Result<S, F> where M: FnOnce(E) -> Result<S, F>
{ {
match self { match self {
Outcome::Success(s) => Ok(s), Outcome::Success(s) => Ok(s),
Outcome::Failure(e) => f(e), Outcome::Error(e) => f(e),
Outcome::Forward(v) => Err(v), Outcome::Forward(v) => Err(v),
} }
} }
@ -657,7 +656,7 @@ impl<S, E, F> Outcome<S, E, F> {
fn formatting(&self) -> (Color, &'static str) { fn formatting(&self) -> (Color, &'static str) {
match *self { match *self {
Success(..) => (Color::Green, "Success"), Success(..) => (Color::Green, "Success"),
Failure(..) => (Color::Red, "Failure"), Error(..) => (Color::Red, "Error"),
Forward(..) => (Color::Yellow, "Forward"), Forward(..) => (Color::Yellow, "Forward"),
} }
} }
@ -675,7 +674,7 @@ impl<'a, S: Send + 'a, E: Send + 'a, F: Send + 'a> Outcome<S, E, F> {
crate::export! { crate::export! {
/// Unwraps a [`Success`](Outcome::Success) or propagates a `Forward` or /// Unwraps a [`Success`](Outcome::Success) or propagates a `Forward` or
/// `Failure`. /// `Error` by returning early.
/// ///
/// # Syntax /// # Syntax
/// ///
@ -691,7 +690,7 @@ crate::export! {
/// ``` /// ```
/// ///
/// This is just like `?` (or previously, `try!`), but for `Outcome`. In the /// This is just like `?` (or previously, `try!`), but for `Outcome`. In the
/// case of a `Forward` or `Failure` variant, the inner type is passed to /// case of a `Forward` or `Error` variant, the inner type is passed to
/// [`From`](std::convert::From), allowing for the conversion between /// [`From`](std::convert::From), allowing for the conversion between
/// specific and more general types. The resulting forward/error is /// specific and more general types. The resulting forward/error is
/// immediately returned. Because of the early return, `try_outcome!` can /// immediately returned. Because of the early return, `try_outcome!` can
@ -746,8 +745,8 @@ crate::export! {
macro_rules! try_outcome { macro_rules! try_outcome {
($expr:expr $(,)?) => (match $expr { ($expr:expr $(,)?) => (match $expr {
$crate::outcome::Outcome::Success(val) => val, $crate::outcome::Outcome::Success(val) => val,
$crate::outcome::Outcome::Failure(e) => { $crate::outcome::Outcome::Error(e) => {
return $crate::outcome::Outcome::Failure(::std::convert::From::from(e)) return $crate::outcome::Outcome::Error(::std::convert::From::from(e))
}, },
$crate::outcome::Outcome::Forward(f) => { $crate::outcome::Outcome::Forward(f) => {
return $crate::outcome::Outcome::Forward(::std::convert::From::from(f)) return $crate::outcome::Outcome::Forward(::std::convert::From::from(f))

View File

@ -1,3 +1,4 @@
use std::convert::Infallible;
use std::fmt::Debug; use std::fmt::Debug;
use std::net::{IpAddr, SocketAddr}; use std::net::{IpAddr, SocketAddr};
@ -12,14 +13,14 @@ use crate::http::uri::{Host, Origin};
pub type Outcome<S, E> = outcome::Outcome<S, (Status, E), Status>; pub type Outcome<S, E> = outcome::Outcome<S, (Status, E), Status>;
impl<S, E> IntoOutcome<S, (Status, E), Status> for Result<S, E> { impl<S, E> IntoOutcome<S, (Status, E), Status> for Result<S, E> {
type Failure = Status; type Error = Status;
type Forward = Status; type Forward = Status;
#[inline] #[inline]
fn into_outcome(self, status: Status) -> Outcome<S, E> { fn into_outcome(self, status: Status) -> Outcome<S, E> {
match self { match self {
Ok(val) => Success(val), Ok(val) => Success(val),
Err(err) => Failure((status, err)) Err(err) => Error((status, err))
} }
} }
@ -85,8 +86,8 @@ impl<S, E> IntoOutcome<S, (Status, E), Status> for Result<S, E> {
/// ``` /// ```
/// ///
/// Request guards always fire in left-to-right declaration order. In the /// Request guards always fire in left-to-right declaration order. In the
/// example above, the order is `a` followed by `b` followed by `c`. Failure is /// example above, the order is `a` followed by `b` followed by `c`. Errors are
/// short-circuiting; if one guard fails, the remaining are not attempted. /// short-circuiting; if one guard errors, the remaining are not attempted.
/// ///
/// # Outcomes /// # Outcomes
/// ///
@ -99,12 +100,12 @@ impl<S, E> IntoOutcome<S, (Status, E), Status> for Result<S, E> {
/// the value for the corresponding parameter. As long as all other guards /// the value for the corresponding parameter. As long as all other guards
/// succeed, the request will be handled. /// succeed, the request will be handled.
/// ///
/// * **Failure**(Status, E) /// * **Error**(Status, E)
/// ///
/// If the `Outcome` is [`Failure`], the request will fail with the given /// If the `Outcome` is [`Error`], the request will fail with the given
/// status code and error. The designated error [`Catcher`](crate::Catcher) /// status code and error. The designated error [`Catcher`](crate::Catcher)
/// will be used to respond to the request. Note that users can request types /// will be used to respond to the request. Note that users can request types
/// of `Result<S, E>` and `Option<S>` to catch `Failure`s and retrieve the /// of `Result<S, E>` and `Option<S>` to catch `Error`s and retrieve the
/// error value. /// error value.
/// ///
/// * **Forward**(Status) /// * **Forward**(Status)
@ -191,7 +192,7 @@ impl<S, E> IntoOutcome<S, (Status, E), Status> for Result<S, E> {
/// ///
/// The type `T` is derived from the incoming request using `T`'s /// The type `T` is derived from the incoming request using `T`'s
/// `FromRequest` implementation. If derivation is a `Success`, the value is /// `FromRequest` implementation. If derivation is a `Success`, the value is
/// returned in `Ok`. If the derivation is a `Failure`, the error value is /// returned in `Ok`. If the derivation is an `Error`, the error value is
/// returned in `Err`. If the derivation is a `Forward`, the request is /// returned in `Err`. If the derivation is a `Forward`, the request is
/// forwarded with the same status code as the original forward. /// forwarded with the same status code as the original forward.
/// ///
@ -232,9 +233,9 @@ impl<S, E> IntoOutcome<S, (Status, E), Status> for Result<S, E> {
/// } /// }
/// ///
/// match req.headers().get_one("x-api-key") { /// match req.headers().get_one("x-api-key") {
/// None => Outcome::Failure((Status::BadRequest, ApiKeyError::Missing)), /// None => Outcome::Error((Status::BadRequest, ApiKeyError::Missing)),
/// Some(key) if is_valid(key) => Outcome::Success(ApiKey(key)), /// Some(key) if is_valid(key) => Outcome::Success(ApiKey(key)),
/// Some(_) => Outcome::Failure((Status::BadRequest, ApiKeyError::Invalid)), /// Some(_) => Outcome::Error((Status::BadRequest, ApiKeyError::Invalid)),
/// } /// }
/// } /// }
/// } /// }
@ -390,7 +391,7 @@ pub trait FromRequest<'r>: Sized {
/// Derives an instance of `Self` from the incoming request metadata. /// Derives an instance of `Self` from the incoming request metadata.
/// ///
/// If the derivation is successful, an outcome of `Success` is returned. If /// If the derivation is successful, an outcome of `Success` is returned. If
/// the derivation fails in an unrecoverable fashion, `Failure` is returned. /// the derivation fails in an unrecoverable fashion, `Error` is returned.
/// `Forward` is returned to indicate that the request should be forwarded /// `Forward` is returned to indicate that the request should be forwarded
/// to other matching routes, if any. /// to other matching routes, if any.
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error>; async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error>;
@ -398,27 +399,27 @@ pub trait FromRequest<'r>: Sized {
#[crate::async_trait] #[crate::async_trait]
impl<'r> FromRequest<'r> for Method { impl<'r> FromRequest<'r> for Method {
type Error = std::convert::Infallible; type Error = Infallible;
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> { async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {
Success(request.method()) Success(request.method())
} }
} }
#[crate::async_trait] #[crate::async_trait]
impl<'r> FromRequest<'r> for &'r Origin<'r> { impl<'r> FromRequest<'r> for &'r Origin<'r> {
type Error = std::convert::Infallible; type Error = Infallible;
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> { async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {
Success(request.uri()) Success(request.uri())
} }
} }
#[crate::async_trait] #[crate::async_trait]
impl<'r> FromRequest<'r> for &'r Host<'r> { impl<'r> FromRequest<'r> for &'r Host<'r> {
type Error = std::convert::Infallible; type Error = Infallible;
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> { async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {
match request.host() { match request.host() {
Some(host) => Success(host), Some(host) => Success(host),
None => Forward(Status::NotFound) None => Forward(Status::NotFound)
@ -428,9 +429,9 @@ impl<'r> FromRequest<'r> for &'r Host<'r> {
#[crate::async_trait] #[crate::async_trait]
impl<'r> FromRequest<'r> for &'r Route { impl<'r> FromRequest<'r> for &'r Route {
type Error = std::convert::Infallible; type Error = Infallible;
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> { async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {
match request.route() { match request.route() {
Some(route) => Success(route), Some(route) => Success(route),
None => Forward(Status::InternalServerError) None => Forward(Status::InternalServerError)
@ -440,18 +441,18 @@ impl<'r> FromRequest<'r> for &'r Route {
#[crate::async_trait] #[crate::async_trait]
impl<'r> FromRequest<'r> for &'r CookieJar<'r> { impl<'r> FromRequest<'r> for &'r CookieJar<'r> {
type Error = std::convert::Infallible; type Error = Infallible;
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> { async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {
Success(request.cookies()) Success(request.cookies())
} }
} }
#[crate::async_trait] #[crate::async_trait]
impl<'r> FromRequest<'r> for &'r Accept { impl<'r> FromRequest<'r> for &'r Accept {
type Error = std::convert::Infallible; type Error = Infallible;
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> { async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {
match request.accept() { match request.accept() {
Some(accept) => Success(accept), Some(accept) => Success(accept),
None => Forward(Status::NotFound) None => Forward(Status::NotFound)
@ -461,9 +462,9 @@ impl<'r> FromRequest<'r> for &'r Accept {
#[crate::async_trait] #[crate::async_trait]
impl<'r> FromRequest<'r> for &'r ContentType { impl<'r> FromRequest<'r> for &'r ContentType {
type Error = std::convert::Infallible; type Error = Infallible;
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> { async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {
match request.content_type() { match request.content_type() {
Some(content_type) => Success(content_type), Some(content_type) => Success(content_type),
None => Forward(Status::NotFound) None => Forward(Status::NotFound)
@ -473,9 +474,9 @@ impl<'r> FromRequest<'r> for &'r ContentType {
#[crate::async_trait] #[crate::async_trait]
impl<'r> FromRequest<'r> for IpAddr { impl<'r> FromRequest<'r> for IpAddr {
type Error = std::convert::Infallible; type Error = Infallible;
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> { async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {
match request.client_ip() { match request.client_ip() {
Some(addr) => Success(addr), Some(addr) => Success(addr),
None => Forward(Status::NotFound) None => Forward(Status::NotFound)
@ -485,9 +486,9 @@ impl<'r> FromRequest<'r> for IpAddr {
#[crate::async_trait] #[crate::async_trait]
impl<'r> FromRequest<'r> for SocketAddr { impl<'r> FromRequest<'r> for SocketAddr {
type Error = std::convert::Infallible; type Error = Infallible;
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> { async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {
match request.remote() { match request.remote() {
Some(addr) => Success(addr), Some(addr) => Success(addr),
None => Forward(Status::NotFound) None => Forward(Status::NotFound)
@ -497,12 +498,12 @@ impl<'r> FromRequest<'r> for SocketAddr {
#[crate::async_trait] #[crate::async_trait]
impl<'r, T: FromRequest<'r>> FromRequest<'r> for Result<T, T::Error> { impl<'r, T: FromRequest<'r>> FromRequest<'r> for Result<T, T::Error> {
type Error = std::convert::Infallible; type Error = Infallible;
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> { async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {
match T::from_request(request).await { match T::from_request(request).await {
Success(val) => Success(Ok(val)), Success(val) => Success(Ok(val)),
Failure((_, e)) => Success(Err(e)), Error((_, e)) => Success(Err(e)),
Forward(status) => Forward(status), Forward(status) => Forward(status),
} }
} }
@ -510,21 +511,21 @@ impl<'r, T: FromRequest<'r>> FromRequest<'r> for Result<T, T::Error> {
#[crate::async_trait] #[crate::async_trait]
impl<'r, T: FromRequest<'r>> FromRequest<'r> for Option<T> { impl<'r, T: FromRequest<'r>> FromRequest<'r> for Option<T> {
type Error = std::convert::Infallible; type Error = Infallible;
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> { async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {
match T::from_request(request).await { match T::from_request(request).await {
Success(val) => Success(Some(val)), Success(val) => Success(Some(val)),
Failure(_) | Forward(_) => Success(None), Error(_) | Forward(_) => Success(None),
} }
} }
} }
#[crate::async_trait] #[crate::async_trait]
impl<'r, T: FromRequest<'r>> FromRequest<'r> for Outcome<T, T::Error> { impl<'r, T: FromRequest<'r>> FromRequest<'r> for Outcome<T, T::Error> {
type Error = std::convert::Infallible; type Error = Infallible;
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> { async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Infallible> {
Success(T::from_request(request).await) Success(T::from_request(request).await)
} }
} }

View File

@ -111,7 +111,7 @@ use crate::request::Request;
/// * An `Ok(Response)` indicates success. The `Response` will be written out /// * An `Ok(Response)` indicates success. The `Response` will be written out
/// to the client. /// to the client.
/// ///
/// * An `Err(Status)` indicates failure. The error catcher for `Status` will /// * An `Err(Status)` indicates an error. The error catcher for `Status` will
/// be invoked to generate a response. /// be invoked to generate a response.
/// ///
/// # Implementation Tips /// # Implementation Tips

View File

@ -141,7 +141,7 @@ pub trait Handler: Cloneable + Send + Sync + 'static {
/// The variant of `Outcome` returned by the returned `Future` determines /// The variant of `Outcome` returned by the returned `Future` determines
/// what Rocket does next. If the return value is a `Success(Response)`, the /// what Rocket does next. If the return value is a `Success(Response)`, the
/// wrapped `Response` is used to respond to the client. If the return value /// wrapped `Response` is used to respond to the client. If the return value
/// is a `Failure(Status)`, the error catcher for `Status` is invoked to /// is an `Error(Status)`, the error catcher for `Status` is invoked to
/// generate a response. Otherwise, if the return value is `Forward(Data)`, /// generate a response. Otherwise, if the return value is `Forward(Data)`,
/// the next matching route is attempted. If there are no other matching /// the next matching route is attempted. If there are no other matching
/// routes, the `404` error catcher is invoked. /// routes, the `404` error catcher is invoked.
@ -172,7 +172,7 @@ impl<'r, 'o: 'r> Outcome<'o> {
/// Return the `Outcome` of response to `req` from `responder`. /// Return the `Outcome` of response to `req` from `responder`.
/// ///
/// If the responder returns `Ok`, an outcome of `Success` is returned with /// If the responder returns `Ok`, an outcome of `Success` is returned with
/// the response. If the responder returns `Err`, an outcome of `Failure` is /// the response. If the responder returns `Err`, an outcome of `Error` is
/// returned with the status code. /// returned with the status code.
/// ///
/// # Example /// # Example
@ -188,14 +188,14 @@ impl<'r, 'o: 'r> Outcome<'o> {
pub fn from<R: Responder<'r, 'o>>(req: &'r Request<'_>, responder: R) -> Outcome<'r> { pub fn from<R: Responder<'r, 'o>>(req: &'r Request<'_>, responder: R) -> Outcome<'r> {
match responder.respond_to(req) { match responder.respond_to(req) {
Ok(response) => Outcome::Success(response), Ok(response) => Outcome::Success(response),
Err(status) => Outcome::Failure(status) Err(status) => Outcome::Error(status)
} }
} }
/// Return the `Outcome` of response to `req` from `responder`. /// Return the `Outcome` of response to `req` from `responder`.
/// ///
/// If the responder returns `Ok`, an outcome of `Success` is returned with /// If the responder returns `Ok`, an outcome of `Success` is returned with
/// the response. If the responder returns `Err`, an outcome of `Failure` is /// the response. If the responder returns `Err`, an outcome of `Error` is
/// returned with the status code. /// returned with the status code.
/// ///
/// # Example /// # Example
@ -214,7 +214,7 @@ impl<'r, 'o: 'r> Outcome<'o> {
let responder = result.map_err(crate::response::Debug); let responder = result.map_err(crate::response::Debug);
match responder.respond_to(req) { match responder.respond_to(req) {
Ok(response) => Outcome::Success(response), Ok(response) => Outcome::Success(response),
Err(status) => Outcome::Failure(status) Err(status) => Outcome::Error(status)
} }
} }
@ -243,8 +243,8 @@ impl<'r, 'o: 'r> Outcome<'o> {
} }
} }
/// Return an `Outcome` of `Failure` with the status code `code`. This is /// Return an `Outcome` of `Error` with the status code `code`. This is
/// equivalent to `Outcome::Failure(code)`. /// equivalent to `Outcome::Error(code)`.
/// ///
/// This method exists to be used during manual routing. /// This method exists to be used during manual routing.
/// ///
@ -255,12 +255,12 @@ impl<'r, 'o: 'r> Outcome<'o> {
/// use rocket::http::Status; /// use rocket::http::Status;
/// ///
/// fn bad_req_route<'r>(_: &'r Request, _: Data<'r>) -> route::Outcome<'r> { /// fn bad_req_route<'r>(_: &'r Request, _: Data<'r>) -> route::Outcome<'r> {
/// route::Outcome::failure(Status::BadRequest) /// route::Outcome::error(Status::BadRequest)
/// } /// }
/// ``` /// ```
#[inline(always)] #[inline(always)]
pub fn failure(code: Status) -> Outcome<'r> { pub fn error(code: Status) -> Outcome<'r> {
Outcome::Failure(code) Outcome::Error(code)
} }
/// Return an `Outcome` of `Forward` with the data `data`. This is /// Return an `Outcome` of `Forward` with the data `data`. This is

View File

@ -76,7 +76,7 @@ use crate::sentinel::Sentry;
/// higher precedence during routing than routes with higher ranks. Thus, routes /// higher precedence during routing than routes with higher ranks. Thus, routes
/// are attempted in ascending rank order. If a higher precedence route returns /// are attempted in ascending rank order. If a higher precedence route returns
/// an `Outcome` of `Forward`, the next highest precedence route is attempted, /// an `Outcome` of `Forward`, the next highest precedence route is attempted,
/// and so on, until a route returns `Success` or `Failure`, or there are no /// and so on, until a route returns `Success` or `Error`, or there are no
/// more routes to try. When all routes have been attempted, Rocket issues a /// more routes to try. When all routes have been attempted, Rocket issues a
/// `404` error, handled by the appropriate [`Catcher`](crate::Catcher). /// `404` error, handled by the appropriate [`Catcher`](crate::Catcher).
/// ///

View File

@ -201,12 +201,12 @@ impl<'r, T: Deserialize<'r>> FromData<'r> for Json<T> {
match Self::from_data(req, data).await { match Self::from_data(req, data).await {
Ok(value) => Outcome::Success(value), Ok(value) => Outcome::Success(value),
Err(Error::Io(e)) if e.kind() == io::ErrorKind::UnexpectedEof => { Err(Error::Io(e)) if e.kind() == io::ErrorKind::UnexpectedEof => {
Outcome::Failure((Status::PayloadTooLarge, Error::Io(e))) Outcome::Error((Status::PayloadTooLarge, Error::Io(e)))
}, },
Err(Error::Parse(s, e)) if e.classify() == serde_json::error::Category::Data => { Err(Error::Parse(s, e)) if e.classify() == serde_json::error::Category::Data => {
Outcome::Failure((Status::UnprocessableEntity, Error::Parse(s, e))) Outcome::Error((Status::UnprocessableEntity, Error::Parse(s, e)))
}, },
Err(e) => Outcome::Failure((Status::BadRequest, e)), Err(e) => Outcome::Error((Status::BadRequest, e)),
} }
} }

View File

@ -170,15 +170,15 @@ impl<'r, T: Deserialize<'r>> FromData<'r> for MsgPack<T> {
match Self::from_data(req, data).await { match Self::from_data(req, data).await {
Ok(value) => Outcome::Success(value), Ok(value) => Outcome::Success(value),
Err(Error::InvalidDataRead(e)) if e.kind() == io::ErrorKind::UnexpectedEof => { Err(Error::InvalidDataRead(e)) if e.kind() == io::ErrorKind::UnexpectedEof => {
Outcome::Failure((Status::PayloadTooLarge, Error::InvalidDataRead(e))) Outcome::Error((Status::PayloadTooLarge, Error::InvalidDataRead(e)))
}, },
| Err(e@Error::TypeMismatch(_)) | Err(e@Error::TypeMismatch(_))
| Err(e@Error::OutOfRange) | Err(e@Error::OutOfRange)
| Err(e@Error::LengthMismatch(_)) | Err(e@Error::LengthMismatch(_))
=> { => {
Outcome::Failure((Status::UnprocessableEntity, e)) Outcome::Error((Status::UnprocessableEntity, e))
}, },
Err(e) => Outcome::Failure((Status::BadRequest, e)), Err(e) => Outcome::Error((Status::BadRequest, e)),
} }
} }
} }

View File

@ -79,7 +79,7 @@
use crate::request::FromParam; use crate::request::FromParam;
use crate::form::{self, FromFormField, ValueField}; use crate::form::{self, FromFormField, ValueField};
/// Error returned on [`FromParam`] or [`FromFormField`] failure. /// Error returned on [`FromParam`] or [`FromFormField`] failures.
/// ///
pub use uuid_::Error; pub use uuid_::Error;

View File

@ -114,7 +114,7 @@ async fn hyper_service_fn(
} }
impl Rocket<Orbit> { impl Rocket<Orbit> {
/// Wrapper around `_send_response` to log a success or failure. /// Wrapper around `_send_response` to log a success or error.
#[inline] #[inline]
async fn send_response( async fn send_response(
&self, &self,
@ -290,12 +290,12 @@ impl Rocket<Orbit> {
request._set_method(Method::Get); request._set_method(Method::Get);
match self.route(request, data).await { match self.route(request, data).await {
Outcome::Success(response) => response, Outcome::Success(response) => response,
Outcome::Failure(status) => self.handle_error(status, request).await, Outcome::Error(status) => self.handle_error(status, request).await,
Outcome::Forward((_, status)) => self.handle_error(status, request).await, Outcome::Forward((_, status)) => self.handle_error(status, request).await,
} }
} }
Outcome::Forward((_, status)) => self.handle_error(status, request).await, Outcome::Forward((_, status)) => self.handle_error(status, request).await,
Outcome::Failure(status) => self.handle_error(status, request).await, Outcome::Error(status) => self.handle_error(status, request).await,
}; };
// Set the cookies. Note that error responses will only include cookies // Set the cookies. Note that error responses will only include cookies
@ -310,7 +310,7 @@ impl Rocket<Orbit> {
/// Tries to find a `Responder` for a given `request`. It does this by /// Tries to find a `Responder` for a given `request`. It does this by
/// routing the request and calling the handler for each matching route /// routing the request and calling the handler for each matching route
/// until one of the handlers returns success or failure, or there are no /// until one of the handlers returns success or error, or there are no
/// additional routes to try (forward). The corresponding outcome for each /// additional routes to try (forward). The corresponding outcome for each
/// condition is returned. /// condition is returned.
#[inline] #[inline]
@ -329,14 +329,14 @@ impl Rocket<Orbit> {
let name = route.name.as_deref(); let name = route.name.as_deref();
let outcome = handle(name, || route.handler.handle(request, data)).await let outcome = handle(name, || route.handler.handle(request, data)).await
.unwrap_or(Outcome::Failure(Status::InternalServerError)); .unwrap_or(Outcome::Error(Status::InternalServerError));
// Check if the request processing completed (Some) or if the // Check if the request processing completed (Some) or if the
// request needs to be forwarded. If it does, continue the loop // request needs to be forwarded. If it does, continue the loop
// (None) to try again. // (None) to try again.
info_!("{} {}", "Outcome:".primary().bold(), outcome); info_!("{} {}", "Outcome:".primary().bold(), outcome);
match outcome { match outcome {
o@Outcome::Success(_) | o@Outcome::Failure(_) => return o, o@Outcome::Success(_) | o@Outcome::Error(_) => return o,
Outcome::Forward(forwarded) => (data, status) = forwarded, Outcome::Forward(forwarded) => (data, status) = forwarded,
} }
} }
@ -380,7 +380,7 @@ impl Rocket<Orbit> {
// Invokes the catcher for `status`. Returns the response on success. // Invokes the catcher for `status`. Returns the response on success.
// //
// On catcher failure, the 500 error catcher is attempted. If _that_ fails, // On catcher error, the 500 error catcher is attempted. If _that_ errors,
// the (infallible) default 500 error cather is used. // the (infallible) default 500 error cather is used.
pub(crate) async fn handle_error<'s, 'r: 's>( pub(crate) async fn handle_error<'s, 'r: 's>(
&'s self, &'s self,

View File

@ -202,7 +202,7 @@ impl<'r, T: Send + Sync + 'static> FromRequest<'r> for &'r State<T> {
Some(state) => Outcome::Success(state), Some(state) => Outcome::Success(state),
None => { None => {
error_!("Attempted to retrieve unmanaged state `{}`!", type_name::<T>()); error_!("Attempted to retrieve unmanaged state `{}`!", type_name::<T>());
Outcome::Failure((Status::InternalServerError, ())) Outcome::Error((Status::InternalServerError, ()))
} }
} }
} }

View File

@ -38,7 +38,7 @@ fn upload<'r>(req: &'r Request, data: Data<'r>) -> route::BoxFuture<'r> {
Box::pin(async move { Box::pin(async move {
if !req.content_type().map_or(false, |ct| ct.is_plain()) { if !req.content_type().map_or(false, |ct| ct.is_plain()) {
println!(" => Content-Type of upload must be text/plain. Ignoring."); println!(" => Content-Type of upload must be text/plain. Ignoring.");
return route::Outcome::failure(Status::BadRequest); return route::Outcome::error(Status::BadRequest);
} }
let path = req.rocket().config().temp_dir.relative().join("upload.txt"); let path = req.rocket().config().temp_dir.relative().join("upload.txt");
@ -49,10 +49,10 @@ fn upload<'r>(req: &'r Request, data: Data<'r>) -> route::BoxFuture<'r> {
} }
println!(" => Failed copying."); println!(" => Failed copying.");
route::Outcome::failure(Status::InternalServerError) route::Outcome::error(Status::InternalServerError)
} else { } else {
println!(" => Couldn't open file: {:?}", file.unwrap_err()); println!(" => Couldn't open file: {:?}", file.unwrap_err());
route::Outcome::failure(Status::InternalServerError) route::Outcome::error(Status::InternalServerError)
} }
}) })
} }

View File

@ -263,7 +263,7 @@ would never forward. An `Ok` variant would indicate that `<id>` was a valid
! tip: It's not just forwards that can be caught! ! tip: It's not just forwards that can be caught!
In general, when any guard fails for any reason, including parameter guards, In general, when any guard fails for any reason, including parameter guards,
you can use an `Option` or `Result` type in its place to catch the failure. you can use an `Option` or `Result` type in its place to catch the error.
By the way, if you were to omit the `rank` parameter in the `user_str` or By the way, if you were to omit the `rank` parameter in the `user_str` or
`user_int` routes, Rocket would emit an error and abort launch, indicating that `user_int` routes, Rocket would emit an error and abort launch, indicating that
@ -353,7 +353,7 @@ fn index(param: isize, a: A, b: B, c: C) { /* ... */ }
``` ```
Request guards always fire in left-to-right declaration order. In the example Request guards always fire in left-to-right declaration order. In the example
above, the order will be `A` followed by `B` followed by `C`. Failure is above, the order will be `A` followed by `B` followed by `C`. Errors are
short-circuiting; if one guard fails, the remaining are not attempted. To learn short-circuiting; if one guard fails, the remaining are not attempted. To learn
more about request guards and implementing them, see the [`FromRequest`] more about request guards and implementing them, see the [`FromRequest`]
documentation. documentation.
@ -484,7 +484,7 @@ The three routes above encode authentication _and_ authorization. The
the admin panel displayed. If the user is not an admin, the `AdminUser` guard the admin panel displayed. If the user is not an admin, the `AdminUser` guard
will forward. Since the `admin_panel_user` route is ranked next highest, it is will forward. Since the `admin_panel_user` route is ranked next highest, it is
attempted next. This route succeeds if there is _any_ user signed in, and an attempted next. This route succeeds if there is _any_ user signed in, and an
authorization failure message is displayed. Finally, if a user isn't signed in, authorization error message is displayed. Finally, if a user isn't signed in,
the `admin_panel_redirect` route is attempted. Since this route has no guards, the `admin_panel_redirect` route is attempted. Since this route has no guards,
it always succeeds. The user is redirected to a log in page. it always succeeds. The user is redirected to a log in page.
@ -522,7 +522,7 @@ If the `User` guard forwards or fails, the `Option` will be `None`. If it
succeeds, it will be `Some(User)`. succeeds, it will be `Some(User)`.
For guards that may fail (and not just forward), the `Result<T, E>` guard allows For guards that may fail (and not just forward), the `Result<T, E>` guard allows
retrieving the error type `E` on failure. As an example, when the retrieving the error type `E` on error. As an example, when the
[`mtls::Certificate`] type fails, it reports the reason in an [`mtls::Error`] [`mtls::Certificate`] type fails, it reports the reason in an [`mtls::Error`]
type. The value can be retrieved in a handler by using a `Result<Certificate, type. The value can be retrieved in a handler by using a `Result<Certificate,
Error>` guard: Error>` guard:
@ -876,7 +876,7 @@ fields implement [`FromForm`], or equivalently, [`FromFormField`].
If a `POST /todo` request arrives, the form data will automatically be parsed If a `POST /todo` request arrives, the form data will automatically be parsed
into the `Task` structure. If the data that arrives isn't of the correct into the `Task` structure. If the data that arrives isn't of the correct
Content-Type, the request is forwarded. If the data doesn't parse or is simply Content-Type, the request is forwarded. If the data doesn't parse or is simply
invalid, a customizable error is returned. As before, a forward or failure can invalid, a customizable error is returned. As before, a forward or error can
be caught by using the `Option` and `Result` types: be caught by using the `Option` and `Result` types:
```rust ```rust

View File

@ -289,7 +289,7 @@ fn handler() -> &'static str {
`Option` is a _wrapping_ responder: an `Option<T>` can only be returned when `T` `Option` is a _wrapping_ responder: an `Option<T>` can only be returned when `T`
implements `Responder`. If the `Option` is `Some`, the wrapped responder is used implements `Responder`. If the `Option` is `Some`, the wrapped responder is used
to respond to the client. Otherwise, a error of **404 - Not Found** is returned to respond to the client. Otherwise, an error of **404 - Not Found** is returned
to the client. to the client.
This implementation makes `Option` a convenient type to return when it is not This implementation makes `Option` a convenient type to return when it is not

View File

@ -26,7 +26,7 @@ macro_rules! assert_form_parses {
Ok(v) => assert_eq!(v, $value, "{}", $form), Ok(v) => assert_eq!(v, $value, "{}", $form),
Err(e) => { Err(e) => {
eprintln!("form failed to parse\n> form: {:?}\n> error: {:?}", $form, e); eprintln!("form failed to parse\n> form: {:?}\n> error: {:?}", $form, e);
panic!("form parse failure"); panic!("form parse error");
} }
} }
); );