mirror of https://github.com/rwf2/Rocket.git
Add optional input for IntoOutcome. Add mapper methods to Outcome.
This is a breaking change to `IntoOutcome`. The MsgPack and JSON types now use `into_outcome` to generate the final `Outcome` from their `FromData` implementations. Resolves #98.
This commit is contained in:
parent
8555a0fad5
commit
7b48ca7103
|
@ -2,7 +2,7 @@ use std::ops::{Deref, DerefMut};
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
use rocket::config;
|
use rocket::config;
|
||||||
use rocket::outcome::Outcome;
|
use rocket::outcome::{Outcome, IntoOutcome};
|
||||||
use rocket::request::Request;
|
use rocket::request::Request;
|
||||||
use rocket::data::{self, Data, FromData};
|
use rocket::data::{self, Data, FromData};
|
||||||
use rocket::response::{self, Responder, content};
|
use rocket::response::{self, Responder, content};
|
||||||
|
@ -100,14 +100,10 @@ impl<T: Deserialize> FromData for JSON<T> {
|
||||||
.and_then(|c| c.limits.get("json"))
|
.and_then(|c| c.limits.get("json"))
|
||||||
.unwrap_or(LIMIT);
|
.unwrap_or(LIMIT);
|
||||||
|
|
||||||
let reader = data.open().take(size_limit);
|
serde_json::from_reader(data.open().take(size_limit))
|
||||||
match serde_json::from_reader(reader).map(|val| JSON(val)) {
|
.map(|val| JSON(val))
|
||||||
Ok(value) => Outcome::Success(value),
|
.map_err(|e| { error_!("Couldn't parse JSON body: {:?}", e); e })
|
||||||
Err(e) => {
|
.into_outcome(Status::BadRequest)
|
||||||
error_!("Couldn't parse JSON body: {:?}", e);
|
|
||||||
Outcome::Failure((Status::BadRequest, e))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::ops::{Deref, DerefMut};
|
||||||
use std::io::{Cursor, Read};
|
use std::io::{Cursor, Read};
|
||||||
|
|
||||||
use rocket::config;
|
use rocket::config;
|
||||||
use rocket::outcome::Outcome;
|
use rocket::outcome::{Outcome, IntoOutcome};
|
||||||
use rocket::request::Request;
|
use rocket::request::Request;
|
||||||
use rocket::data::{self, Data, FromData};
|
use rocket::data::{self, Data, FromData};
|
||||||
use rocket::response::{self, Responder, Response};
|
use rocket::response::{self, Responder, Response};
|
||||||
|
@ -120,13 +120,9 @@ impl<T: Deserialize> FromData for MsgPack<T> {
|
||||||
return Outcome::Failure((Status::BadRequest, e));
|
return Outcome::Failure((Status::BadRequest, e));
|
||||||
};
|
};
|
||||||
|
|
||||||
match rmp_serde::from_slice(&buf).map(|val| MsgPack(val)) {
|
rmp_serde::from_slice(&buf).map(|val| MsgPack(val))
|
||||||
Ok(value) => Outcome::Success(value),
|
.map_err(|e| { error_!("Couldn't parse MessagePack body: {:?}", e); e })
|
||||||
Err(e) => {
|
.into_outcome(Status::BadRequest)
|
||||||
error_!("Couldn't parse MessagePack body: {:?}", e);
|
|
||||||
Outcome::Failure((Status::BadRequest, e))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,13 @@ use data::Data;
|
||||||
pub type Outcome<S, E> = outcome::Outcome<S, (Status, E), Data>;
|
pub type Outcome<S, E> = outcome::Outcome<S, (Status, E), Data>;
|
||||||
|
|
||||||
impl<'a, S, E> IntoOutcome<S, (Status, E), Data> for Result<S, E> {
|
impl<'a, S, E> IntoOutcome<S, (Status, E), Data> for Result<S, E> {
|
||||||
|
type Input = Status;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_outcome(self) -> 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::InternalServerError, err))
|
Err(err) => Failure((status, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,7 +105,9 @@ pub enum Outcome<S, E, 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> {
|
||||||
fn into_outcome(self) -> Outcome<S, E, F>;
|
type Input: Sized;
|
||||||
|
|
||||||
|
fn into_outcome(self, input: Self::Input) -> Outcome<S, E, F>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S, E, F> Outcome<S, E, F> {
|
impl<S, E, F> Outcome<S, E, F> {
|
||||||
|
@ -329,6 +331,72 @@ impl<S, E, F> Outcome<S, E, F> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Maps an `Outcome<S, E, F>` to an `Outcome<T, E, F>` by applying the
|
||||||
|
/// function `f` to the value of type `S` in `self` if `self` is an
|
||||||
|
/// `Outcome::Success`.
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use rocket::outcome::Outcome;
|
||||||
|
/// # use rocket::outcome::Outcome::*;
|
||||||
|
/// #
|
||||||
|
/// let x: Outcome<i32, &str, usize> = Success(10);
|
||||||
|
///
|
||||||
|
/// let mapped = x.map(|v| if v == 10 { "10" } else { "not 10" });
|
||||||
|
/// assert_eq!(mapped, Success("10"));
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
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),
|
||||||
|
Forward(val) => Forward(val),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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`.
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use rocket::outcome::Outcome;
|
||||||
|
/// # use rocket::outcome::Outcome::*;
|
||||||
|
/// #
|
||||||
|
/// let x: Outcome<i32, &str, usize> = Failure("hi");
|
||||||
|
///
|
||||||
|
/// let mapped = x.map_failure(|v| if v == "hi" { 10 } else { 0 });
|
||||||
|
/// assert_eq!(mapped, Failure(10));
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn map_failure<T, M: FnOnce(E) -> T>(self, f: M) -> Outcome<S, T, F> {
|
||||||
|
match self {
|
||||||
|
Success(val) => Success(val),
|
||||||
|
Failure(val) => Failure(f(val)),
|
||||||
|
Forward(val) => Forward(val),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Maps an `Outcome<S, E, F>` to an `Outcome<S, E, T>` by applying the
|
||||||
|
/// function `f` to the value of type `F` in `self` if `self` is an
|
||||||
|
/// `Outcome::Forward`.
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use rocket::outcome::Outcome;
|
||||||
|
/// # use rocket::outcome::Outcome::*;
|
||||||
|
/// #
|
||||||
|
/// let x: Outcome<i32, &str, usize> = Forward(5);
|
||||||
|
///
|
||||||
|
/// let mapped = x.map_forward(|v| if v == 5 { "a" } else { "b" });
|
||||||
|
/// assert_eq!(mapped, Forward("a"));
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
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),
|
||||||
|
Forward(val) => Forward(f(val)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Converts from `Outcome<S, E, F>` to `Outcome<&mut S, &mut E, &mut F>`.
|
/// Converts from `Outcome<S, E, F>` to `Outcome<&mut S, &mut E, &mut F>`.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
|
|
@ -12,10 +12,13 @@ use http::uri::URI;
|
||||||
pub type Outcome<S, E> = outcome::Outcome<S, (Status, E), ()>;
|
pub type Outcome<S, E> = outcome::Outcome<S, (Status, E), ()>;
|
||||||
|
|
||||||
impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
|
impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
|
||||||
fn into_outcome(self) -> Outcome<S, E> {
|
type Input = Status;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn into_outcome(self, status: Status) -> Outcome<S, E> {
|
||||||
match self {
|
match self {
|
||||||
Ok(val) => Success(val),
|
Ok(val) => Success(val),
|
||||||
Err(val) => Failure((Status::BadRequest, val))
|
Err(err) => Failure((status, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -242,6 +242,6 @@ impl<'a, 'r> FromRequest<'a, 'r> for Flash<()> {
|
||||||
request.cookies().remove(cookie);
|
request.cookies().remove(cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
r.into_outcome()
|
r.into_outcome(Status::BadRequest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue