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> {
match #db_ty::fetch(req.rocket()) {
Some(db) => rocket::outcome::Outcome::Success(db),
None => rocket::outcome::Outcome::Failure((
None => rocket::outcome::Outcome::Error((
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.
/// * If the `Initializer` fairing was _not_ attached, the guard _fails_ with
/// 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
/// another error occurs, the guard _fails_ with status `ServiceUnavailable`
/// 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()) {
Some(db) => match db.get().await {
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.");
info_!("To use templates, you must attach `Template::fairing()`.");
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, ())),
None => {
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));
return #Outcome::Forward((#__data, __e));
},
#Outcome::Failure((__c, __e)) => {
#Outcome::Error((__c, __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));
return #Outcome::Forward((__d, __e));
}
#Outcome::Failure((__c, __e)) => {
#Outcome::Error((__c, __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
/// [`Outcome`] is `Forward` or failed if the [`Outcome`] is
/// `Failure`. See [`FromRequest` Outcomes] for further
/// detail.
/// `Error`. See [`FromRequest` Outcomes] for further detail.
///
/// 2. Path and query guards in an unspecified order. If a path
/// 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
/// [`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.
/// 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]
/// async fn main() {
/// // 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;
/// }
/// ```

View File

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

View File

@ -533,7 +533,7 @@ impl fmt::Display for Name<'_> {
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
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::Trailing(n) => write!(f, "found {} trailing bytes", n),
Error::Empty => write!(f, "empty certificate chain"),

View File

@ -16,12 +16,14 @@ use yansi::Paint;
///
/// * A failing guard.
/// * A failing responder.
/// * A forwarding guard.
/// * Routing failure.
///
/// Each failure is paired with a status code. Guards and responders indicate
/// the status code themselves via their `Err` return value while a routing
/// failure is always a `404`. Rocket invokes the error handler for the catcher
/// with the error's status code.
/// Each error or forward is paired with a status code. Guards and responders
/// indicate the status code themselves via their `Err` and `Outcome` return
/// value. A complete routing failure is always a `404`. Rocket invokes the
/// 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
///
@ -31,14 +33,18 @@ use yansi::Paint;
///
/// # 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.
/// * Its base is a prefix of the normalized/decoded request URI path.
/// Rocket provides [built-in defaults](#built-in-default), but _default_
/// 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
/// catcher's _base_ is provided as the first argument to
/// [`Rocket::register()`](crate::Rocket::register()).
/// [`Outcome`]: crate::request::Outcome
/// [`Rocket::register()`]: crate::Rocket::register()
///
/// # Collisions
///

View File

@ -288,7 +288,7 @@ impl Config {
///
/// # 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()`].
///
/// # Example

View File

@ -52,7 +52,7 @@ enum Kind {
/// ```
///
/// 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:
///
/// ```rust
@ -67,7 +67,7 @@ enum Kind {
/// .select(profile.clone());
///
/// 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)));
/// ```
///

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(_) => {
let e = Error::new(UnexpectedEof, "data limit exceeded");
Failure((Status::BadRequest, e.into()))
Error((Status::BadRequest, e.into()))
},
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)>;
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);
#[inline]
fn into_outcome(self, status: Status) -> Outcome<'r, S, E> {
match self {
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::data::{self, Data, FromData, ToByteUnit};
/// use rocket::http::{Status, ContentType};
/// use rocket::outcome::Outcome;
///
/// #[derive(Debug)]
/// 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> {
/// use Error::*;
/// use rocket::outcome::Outcome::*;
///
/// // Ensure the content type is correct before opening the data.
/// let person_ct = ContentType::new("application", "x-person");
/// 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.
@ -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.
/// let string = match data.open(limit).into_string().await {
/// Ok(string) if string.is_complete() => string.into_inner(),
/// Ok(_) => return Failure((Status::PayloadTooLarge, TooLarge)),
/// Err(e) => return Failure((Status::InternalServerError, Io(e))),
/// Ok(_) => return Outcome::Error((Status::PayloadTooLarge, TooLarge)),
/// Err(e) => return Outcome::Error((Status::InternalServerError, Io(e))),
/// };
///
/// // 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 ':'.
/// let (name, age) = match string.find(':') {
/// Some(i) => (&string[..i], &string[(i + 1)..]),
/// None => return Failure((Status::UnprocessableEntity, NoColon)),
/// None => return Outcome::Error((Status::UnprocessableEntity, NoColon)),
/// };
///
/// // Parse the age.
/// let age: u16 = match age.parse() {
/// 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 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>;
}
@ -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> {
match T::from_data(req, data).await {
Success(v) => Success(Ok(v)),
Failure((_, e)) => Success(Err(e)),
Error((_, e)) => Success(Err(e)),
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> {
match T::from_data(req, data).await {
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());
"aborting due to invalid configuration"
}
ErrorKind::SentinelAborts(ref failures) => {
ErrorKind::SentinelAborts(ref errors) => {
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 (file, line, col) = sentry.location;
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
// `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
// mechanism to use here. In other words, enabling this at the fairing level
// 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
/// ignition and launch to proceed nominally and `Err` otherwise. If an
/// 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`)**
///
@ -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, ()> {
/// match *request.local_cache(|| TimerStart(None)) {
/// 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`
/// or [`Status::InternalServerError`] if `self` is empty. This is the
/// 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
/// [`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
/// does not parse as `T`, according to `T`'s [`FromForm`] implementation, the
/// guard **fails**. The `Failure` variant contains of the [`Errors`] emitted by
/// `T`'s `FromForm` parser. If the error is not caught by a
/// guard **fails**. The `Error` variant contains a vector of the [`Errors`]
/// 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
/// is set to [`Errors::status()`], and the corresponding error catcher is
/// called.
@ -334,7 +334,7 @@ impl<'r, T: FromForm<'r>> FromData<'r> for Form<T> {
match T::finalize(context) {
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 {
Outcome::Success(p) => Ok(p),
Outcome::Failure((_, e)) => Err(e)?,
Outcome::Error((_, e)) => Err(e)?,
Outcome::Forward(..) => {
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 {
Outcome::Success(p) => Ok(p),
Outcome::Failure((_, e)) => Err(e)?,
Outcome::Error((_, e)) => Err(e)?,
Outcome::Forward(..) => {
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 {
Outcome::Success(p) => Ok(p),
Outcome::Failure((_, e)) => Err(e)?,
Outcome::Error((_, e)) => Err(e)?,
Outcome::Forward(..) => {
Err(Error::from(ErrorKind::Unexpected).with_entity(Entity::DataField))?
}

View File

@ -40,7 +40,7 @@ impl<'r, 'i> Parser<'r, 'i> {
match parser {
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`].
///
/// On failure, returns a validation error with the following message:
/// On error, returns a validation error with the following message:
///
/// ```text
/// 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
/// [`PartialEq`].
///
/// On failure, returns a validation error with the following message:
/// On error, returns a validation error with the following message:
///
/// ```text
/// 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`.
///
/// 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.
///
/// [`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`] 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
/// 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`] 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
/// 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.
///
/// 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
///
@ -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
/// 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`.
///
/// [`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
/// `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
/// // 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
/// `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
///
@ -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
/// 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.
///
/// # Example

View File

@ -149,12 +149,12 @@ impl FileServer {
if !options.contains(Options::IndexFile) && !path.is_dir() {
let path = path.display();
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");
} else if !path.exists() {
let path = path.display();
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");
}
}

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,
//! E>` type. It is an enum with three variants, each containing a value:
//! `Success(S)`, which represents a successful outcome, `Failure(E)`, which
//! represents a failing outcome, and `Forward(F)`, which represents neither a
//! success or failure, but instead, indicates that processing could not be
//! `Success(S)`, which represents a successful outcome, `Error(E)`, which
//! represents an erroring outcome, and `Forward(F)`, which represents neither a
//! success or error, but instead, indicates that processing could not be
//! handled and should instead be _forwarded_ to whatever can handle the
//! processing next.
//!
@ -35,15 +35,15 @@
//! `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`.
//!
//! # 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.
//! 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
//! 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
//! like:
//!
@ -56,10 +56,9 @@
//! ```
//!
//! The [`FromData`] implementation for the type `S` returns an `Outcome` with a
//! `Success(S)` and `Failure(E)`. If `from_data` returns a `Failure`, the
//! `Failure` value will be unwrapped and the value will be used as the `Err`
//! value of `my_val` while a `Success` will be unwrapped and used the `Ok`
//! value.
//! `Success(S)` and `Error(E)`. If `from_data` returns an `Error`, the `Error`
//! value will be unwrapped and the value will be used as the `Err` value of
//! `my_val` while a `Success` will be unwrapped and used the `Ok` value.
//!
//! # Forward
//!
@ -79,11 +78,11 @@
//! ```
//!
//! 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
//! 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
//! 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
//! `None`.
@ -93,8 +92,8 @@ use yansi::{Paint, Color};
use self::Outcome::*;
/// An enum representing success (`Success`), failure (`Failure`), or
/// forwarding (`Forward`).
/// An enum representing success (`Success`), error (`Error`), or forwarding
/// (`Forward`).
///
/// See the [top level documentation](crate::outcome) for detailed information.
#[must_use]
@ -102,24 +101,24 @@ use self::Outcome::*;
pub enum Outcome<S, E, F> {
/// Contains the success value.
Success(S),
/// Contains the failure error value.
Failure(E),
/// Contains the error error value.
Error(E),
/// Contains the value to forward on.
Forward(F),
}
/// Conversion trait from some type into an Outcome type.
pub trait IntoOutcome<S, E, F> {
/// The type to use when returning an `Outcome::Failure`.
type Failure: Sized;
/// The type to use when returning an `Outcome::Error`.
type Error: Sized;
/// The type to use when returning an `Outcome::Forward`.
type Forward: Sized;
/// Converts `self` into an `Outcome`. If `self` represents a success, an
/// `Outcome::Success` is returned. Otherwise, an `Outcome::Failure` is
/// returned with `failure` as the inner value.
fn into_outcome(self, failure: Self::Failure) -> Outcome<S, E, F>;
/// `Outcome::Success` is returned. Otherwise, an `Outcome::Error` is
/// returned with `error` as the inner value.
fn into_outcome(self, error: Self::Error) -> Outcome<S, E, F>;
/// Converts `self` into an `Outcome`. If `self` represents a success, an
/// `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> {
type Failure = E;
type Error = E;
type Forward = F;
#[inline]
fn into_outcome(self, failure: E) -> Outcome<S, E, F> {
fn into_outcome(self, error: E) -> Outcome<S, E, F> {
match self {
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);
/// 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);
///
/// let x: Outcome<i32, &str, usize> = Forward(25);
@ -219,7 +218,7 @@ impl<S, E, F> Outcome<S, E, F> {
matches!(self, Success(_))
}
/// Return true if this `Outcome` is a `Failure`.
/// Return true if this `Outcome` is an `Error`.
///
/// # Examples
///
@ -228,17 +227,17 @@ impl<S, E, F> Outcome<S, E, F> {
/// # use rocket::outcome::Outcome::*;
/// #
/// 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.");
/// assert_eq!(x.is_failure(), true);
/// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
/// assert_eq!(x.is_error(), true);
///
/// let x: Outcome<i32, &str, usize> = Forward(25);
/// assert_eq!(x.is_failure(), false);
/// assert_eq!(x.is_error(), false);
/// ```
#[inline]
pub fn is_failure(&self) -> bool {
matches!(self, Failure(_))
pub fn is_error(&self) -> bool {
matches!(self, Error(_))
}
/// 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);
/// 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);
///
/// 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);
/// 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);
///
/// 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>`.
///
/// 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.
///
/// ```rust
@ -301,7 +300,7 @@ impl<S, E, F> Outcome<S, E, F> {
/// let x: Outcome<i32, &str, usize> = Success(10);
/// 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."));
///
/// let x: Outcome<i32, &str, usize> = Forward(25);
@ -310,7 +309,7 @@ impl<S, E, F> Outcome<S, E, F> {
#[inline]
pub fn failed(self) -> Option<E> {
match self {
Failure(val) => Some(val),
Error(val) => Some(val),
_ => None
}
}
@ -327,7 +326,7 @@ impl<S, E, F> Outcome<S, E, F> {
/// let x: Outcome<i32, &str, usize> = Success(10);
/// 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);
///
/// 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);
/// 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));
///
/// 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);
/// 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));
///
/// 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);
/// assert_eq!(x.as_ref(), Success(&10));
///
/// let x: Outcome<i32, &str, usize> = Failure("Hi! I'm an error.");
/// assert_eq!(x.as_ref(), Failure(&"Hi! I'm an error."));
/// let x: Outcome<i32, &str, usize> = Error("Hi! I'm an error.");
/// assert_eq!(x.as_ref(), Error(&"Hi! I'm an error."));
/// ```
#[inline]
pub fn as_ref(&self) -> Outcome<&S, &E, &F> {
match *self {
Success(ref val) => Success(val),
Failure(ref val) => Failure(val),
Error(ref val) => Error(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> {
match *self {
Success(ref mut val) => Success(val),
Failure(ref mut val) => Failure(val),
Error(ref mut val) => Error(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> {
match self {
Success(val) => Success(f(val)),
Failure(val) => Failure(val),
Error(val) => Error(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`
/// in `self` if `self` is an `Outcome::Failure`.
/// in `self` if `self` is an `Outcome::Error`.
///
/// ```rust
/// # 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 });
/// assert_eq!(mapped, Failure(10));
/// let mapped = x.map_error(|v| if v == "hi" { 10 } else { 0 });
/// assert_eq!(mapped, Error(10));
/// ```
#[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 {
Success(val) => Success(val),
Failure(val) => Failure(f(val)),
Error(val) => Error(f(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> {
match self {
Success(val) => Success(val),
Failure(val) => Failure(val),
Error(val) => Error(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 {
/// 10 => Success("10"),
/// 1 => Forward(false),
/// _ => Failure("30")
/// _ => Error("30")
/// });
///
/// 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> {
match self {
Success(val) => f(val),
Failure(val) => Failure(val),
Error(val) => Error(val),
Forward(val) => Forward(val),
}
}
/// 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
///
@ -548,21 +547,21 @@ impl<S, E, F> Outcome<S, E, F> {
/// # 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 {
/// "hi" => Failure(10),
/// let mapped = x.error_then(|v| match v {
/// "hi" => Error(10),
/// "test" => Forward(false),
/// _ => Success(10)
/// });
///
/// assert_eq!(mapped, Failure(10));
/// assert_eq!(mapped, Error(10));
/// ```
#[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 {
Success(val) => Success(val),
Failure(val) => f(val),
Error(val) => f(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 {
/// Some(true) => Success(10),
/// Some(false) => Forward(20),
/// None => Failure("10")
/// None => Error("10")
/// });
///
/// 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> {
match self {
Success(val) => Success(val),
Failure(val) => Failure(val),
Error(val) => Error(val),
Forward(val) => f(val),
}
}
/// 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`.
///
/// ```rust
@ -608,7 +607,7 @@ impl<S, E, F> Outcome<S, E, F> {
/// let x: Outcome<i32, &str, usize> = Success(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"));
///
/// let x: Outcome<i32, &str, usize> = Forward(0);
@ -620,13 +619,13 @@ impl<S, E, F> Outcome<S, E, F> {
{
match self {
Outcome::Success(s) => Ok(s),
Outcome::Failure(e) => Err(e),
Outcome::Error(e) => Err(e),
Outcome::Forward(v) => f(v),
}
}
/// 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`.
///
/// ```rust
@ -634,21 +633,21 @@ impl<S, E, F> Outcome<S, E, F> {
/// # use rocket::outcome::Outcome::*;
/// #
/// 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");
/// assert_eq!(x.ok_map_failure(|s| Ok(123)), Ok(123));
/// let x: Outcome<i32, &str, usize> = Error("hello");
/// assert_eq!(x.ok_map_error(|s| Ok(123)), Ok(123));
///
/// 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]
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>
{
match self {
Outcome::Success(s) => Ok(s),
Outcome::Failure(e) => f(e),
Outcome::Error(e) => f(e),
Outcome::Forward(v) => Err(v),
}
}
@ -657,7 +656,7 @@ impl<S, E, F> Outcome<S, E, F> {
fn formatting(&self) -> (Color, &'static str) {
match *self {
Success(..) => (Color::Green, "Success"),
Failure(..) => (Color::Red, "Failure"),
Error(..) => (Color::Red, "Error"),
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! {
/// Unwraps a [`Success`](Outcome::Success) or propagates a `Forward` or
/// `Failure`.
/// `Error` by returning early.
///
/// # Syntax
///
@ -691,7 +690,7 @@ crate::export! {
/// ```
///
/// 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
/// specific and more general types. The resulting forward/error is
/// immediately returned. Because of the early return, `try_outcome!` can
@ -746,8 +745,8 @@ crate::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::Error(e) => {
return $crate::outcome::Outcome::Error(::std::convert::From::from(e))
},
$crate::outcome::Outcome::Forward(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::net::{IpAddr, SocketAddr};
@ -12,14 +13,14 @@ use crate::http::uri::{Host, Origin};
pub type Outcome<S, E> = outcome::Outcome<S, (Status, E), Status>;
impl<S, E> IntoOutcome<S, (Status, E), Status> for Result<S, E> {
type Failure = Status;
type Error = Status;
type Forward = Status;
#[inline]
fn into_outcome(self, status: Status) -> Outcome<S, E> {
match self {
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
/// example above, the order is `a` followed by `b` followed by `c`. Failure is
/// short-circuiting; if one guard fails, the remaining are not attempted.
/// example above, the order is `a` followed by `b` followed by `c`. Errors are
/// short-circuiting; if one guard errors, the remaining are not attempted.
///
/// # 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
/// 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)
/// 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.
///
/// * **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
/// `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
/// 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") {
/// 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(_) => 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.
///
/// 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
/// to other matching routes, if any.
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error>;
@ -398,27 +399,27 @@ pub trait FromRequest<'r>: Sized {
#[crate::async_trait]
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())
}
}
#[crate::async_trait]
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())
}
}
#[crate::async_trait]
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() {
Some(host) => Success(host),
None => Forward(Status::NotFound)
@ -428,9 +429,9 @@ impl<'r> FromRequest<'r> for &'r Host<'r> {
#[crate::async_trait]
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() {
Some(route) => Success(route),
None => Forward(Status::InternalServerError)
@ -440,18 +441,18 @@ impl<'r> FromRequest<'r> for &'r Route {
#[crate::async_trait]
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())
}
}
#[crate::async_trait]
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() {
Some(accept) => Success(accept),
None => Forward(Status::NotFound)
@ -461,9 +462,9 @@ impl<'r> FromRequest<'r> for &'r Accept {
#[crate::async_trait]
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() {
Some(content_type) => Success(content_type),
None => Forward(Status::NotFound)
@ -473,9 +474,9 @@ impl<'r> FromRequest<'r> for &'r ContentType {
#[crate::async_trait]
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() {
Some(addr) => Success(addr),
None => Forward(Status::NotFound)
@ -485,9 +486,9 @@ impl<'r> FromRequest<'r> for IpAddr {
#[crate::async_trait]
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() {
Some(addr) => Success(addr),
None => Forward(Status::NotFound)
@ -497,12 +498,12 @@ impl<'r> FromRequest<'r> for SocketAddr {
#[crate::async_trait]
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 {
Success(val) => Success(Ok(val)),
Failure((_, e)) => Success(Err(e)),
Error((_, e)) => Success(Err(e)),
Forward(status) => Forward(status),
}
}
@ -510,21 +511,21 @@ impl<'r, T: FromRequest<'r>> FromRequest<'r> for Result<T, T::Error> {
#[crate::async_trait]
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 {
Success(val) => Success(Some(val)),
Failure(_) | Forward(_) => Success(None),
Error(_) | Forward(_) => Success(None),
}
}
}
#[crate::async_trait]
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)
}
}

View File

@ -111,7 +111,7 @@ use crate::request::Request;
/// * An `Ok(Response)` indicates success. The `Response` will be written out
/// 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.
///
/// # 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
/// 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
/// 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)`,
/// the next matching route is attempted. If there are no other matching
/// 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`.
///
/// 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.
///
/// # 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> {
match responder.respond_to(req) {
Ok(response) => Outcome::Success(response),
Err(status) => Outcome::Failure(status)
Err(status) => Outcome::Error(status)
}
}
/// Return the `Outcome` of response to `req` from `responder`.
///
/// 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.
///
/// # Example
@ -214,7 +214,7 @@ impl<'r, 'o: 'r> Outcome<'o> {
let responder = result.map_err(crate::response::Debug);
match responder.respond_to(req) {
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
/// equivalent to `Outcome::Failure(code)`.
/// Return an `Outcome` of `Error` with the status code `code`. This is
/// equivalent to `Outcome::Error(code)`.
///
/// This method exists to be used during manual routing.
///
@ -255,12 +255,12 @@ impl<'r, 'o: 'r> Outcome<'o> {
/// use rocket::http::Status;
///
/// fn bad_req_route<'r>(_: &'r Request, _: Data<'r>) -> route::Outcome<'r> {
/// route::Outcome::failure(Status::BadRequest)
/// route::Outcome::error(Status::BadRequest)
/// }
/// ```
#[inline(always)]
pub fn failure(code: Status) -> Outcome<'r> {
Outcome::Failure(code)
pub fn error(code: Status) -> Outcome<'r> {
Outcome::Error(code)
}
/// 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
/// are attempted in ascending rank order. If a higher precedence route returns
/// 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
/// `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 {
Ok(value) => Outcome::Success(value),
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 => {
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 {
Ok(value) => Outcome::Success(value),
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::OutOfRange)
| 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::form::{self, FromFormField, ValueField};
/// Error returned on [`FromParam`] or [`FromFormField`] failure.
/// Error returned on [`FromParam`] or [`FromFormField`] failures.
///
pub use uuid_::Error;

View File

@ -114,7 +114,7 @@ async fn hyper_service_fn(
}
impl Rocket<Orbit> {
/// Wrapper around `_send_response` to log a success or failure.
/// Wrapper around `_send_response` to log a success or error.
#[inline]
async fn send_response(
&self,
@ -290,12 +290,12 @@ impl Rocket<Orbit> {
request._set_method(Method::Get);
match self.route(request, data).await {
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::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
@ -310,7 +310,7 @@ impl Rocket<Orbit> {
/// Tries to find a `Responder` for a given `request`. It does this by
/// 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
/// condition is returned.
#[inline]
@ -329,14 +329,14 @@ impl Rocket<Orbit> {
let name = route.name.as_deref();
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
// request needs to be forwarded. If it does, continue the loop
// (None) to try again.
info_!("{} {}", "Outcome:".primary().bold(), 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,
}
}
@ -380,7 +380,7 @@ impl Rocket<Orbit> {
// 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.
pub(crate) async fn handle_error<'s, 'r: 's>(
&'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),
None => {
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 {
if !req.content_type().map_or(false, |ct| ct.is_plain()) {
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");
@ -49,10 +49,10 @@ fn upload<'r>(req: &'r Request, data: Data<'r>) -> route::BoxFuture<'r> {
}
println!(" => Failed copying.");
route::Outcome::failure(Status::InternalServerError)
route::Outcome::error(Status::InternalServerError)
} else {
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!
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
`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
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
more about request guards and implementing them, see the [`FromRequest`]
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
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
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,
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)`.
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`]
type. The value can be retrieved in a handler by using a `Result<Certificate,
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
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
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:
```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`
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.
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),
Err(e) => {
eprintln!("form failed to parse\n> form: {:?}\n> error: {:?}", $form, e);
panic!("form parse failure");
panic!("form parse error");
}
}
);