Use better types for 'Error' associated types.

This commit is contained in:
Sergio Benitez 2018-08-10 04:42:30 -07:00
parent d9bfc9b104
commit fe59a7fe38
7 changed files with 46 additions and 48 deletions

View File

@ -56,7 +56,7 @@ use Header;
/// [private cookie]: /rocket/http/enum.Cookies.html#private-cookies
///
/// ```rust
/// # #![feature(plugin, decl_macro)]
/// # #![feature(plugin, decl_macro, never_type)]
/// # #![plugin(rocket_codegen)]
/// # extern crate rocket;
/// #
@ -68,9 +68,9 @@ use Header;
/// struct User(usize);
///
/// impl<'a, 'r> FromRequest<'a, 'r> for User {
/// type Error = ();
/// type Error = !;
///
/// fn from_request(request: &'a Request<'r>) -> request::Outcome<User, ()> {
/// fn from_request(request: &'a Request<'r>) -> request::Outcome<User, !> {
/// request.cookies()
/// .get_private("user_id")
/// .and_then(|cookie| cookie.value().parse().ok())

View File

@ -226,14 +226,15 @@ pub trait FromData: Sized {
/// The identity implementation of `FromData`. Always returns `Success`.
impl FromData for Data {
type Error = ();
type Error = !;
fn from_data(_: &Request, data: Data) -> Outcome<Self, Self::Error> {
Success(data)
}
}
impl<T: FromData> FromData for Result<T, T::Error> {
type Error = ();
type Error = !;
fn from_data(request: &Request, data: Data) -> Outcome<Self, Self::Error> {
match T::from_data(request, data) {
@ -245,7 +246,7 @@ impl<T: FromData> FromData for Result<T, T::Error> {
}
impl<T: FromData> FromData for Option<T> {
type Error = ();
type Error = !;
fn from_data(request: &Request, data: Data) -> Outcome<Self, Self::Error> {
match T::from_data(request, data) {

View File

@ -181,21 +181,24 @@ impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
/// key == "valid_api_key"
/// }
///
/// #[derive(Debug)]
/// enum ApiKeyError {
/// BadCount,
/// Missing,
/// Invalid,
/// }
///
/// impl<'a, 'r> FromRequest<'a, 'r> for ApiKey {
/// type Error = ();
/// type Error = ApiKeyError;
///
/// fn from_request(request: &'a Request<'r>) -> request::Outcome<ApiKey, ()> {
/// fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
/// let keys: Vec<_> = request.headers().get("x-api-key").collect();
/// if keys.len() != 1 {
/// return Outcome::Failure((Status::BadRequest, ()));
/// match keys.len() {
/// 0 => Outcome::Failure((Status::BadRequest, ApiKeyError::Missing)),
/// 1 if is_valid(keys[0]) => Outcome::Success(ApiKey(keys[0].to_string())),
/// 1 => Outcome::Failure((Status::BadRequest, ApiKeyError::Invalid)),
/// _ => Outcome::Failure((Status::BadRequest, ApiKeyError::BadCount)),
/// }
///
/// let key = keys[0];
/// if !is_valid(keys[0]) {
/// return Outcome::Forward(());
/// }
///
/// return Outcome::Success(ApiKey(key.to_string()));
/// }
/// }
///
@ -219,7 +222,7 @@ impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
/// routes (`admin_dashboard` and `user_dashboard`):
///
/// ```rust
/// # #![feature(plugin, decl_macro)]
/// # #![feature(plugin, decl_macro, never_type)]
/// # #![plugin(rocket_codegen)]
/// # extern crate rocket;
/// #
@ -282,7 +285,7 @@ impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
/// used, as illustrated below:
///
/// ```rust
/// # #![feature(plugin, decl_macro)]
/// # #![feature(plugin, decl_macro, never_type)]
/// # #![plugin(rocket_codegen)]
/// # extern crate rocket;
/// #
@ -305,9 +308,9 @@ impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
/// # struct Admin<'a> { user: &'a User };
/// #
/// impl<'a, 'r> FromRequest<'a, 'r> for &'a User {
/// type Error = ();
/// type Error = !;
///
/// fn from_request(request: &'a Request<'r>) -> request::Outcome<&'a User, ()> {
/// fn from_request(request: &'a Request<'r>) -> request::Outcome<&'a User, !> {
/// // This closure will execute at most once per request, regardless of
/// // the number of times the `User` guard is executed.
/// let user_result = request.local_cache(|| {
@ -323,9 +326,9 @@ impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
/// }
///
/// impl<'a, 'r> FromRequest<'a, 'r> for Admin<'a> {
/// type Error = ();
/// type Error = !;
///
/// fn from_request(request: &'a Request<'r>) -> request::Outcome<Admin<'a>, ()> {
/// fn from_request(request: &'a Request<'r>) -> request::Outcome<Admin<'a>, !> {
/// let user = request.guard::<&User>()?;
///
/// if user.is_admin {
@ -356,7 +359,7 @@ pub trait FromRequest<'a, 'r>: Sized {
}
impl<'a, 'r> FromRequest<'a, 'r> for Method {
type Error = ();
type Error = !;
fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
Success(request.method())
@ -364,7 +367,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for Method {
}
impl<'a, 'r> FromRequest<'a, 'r> for &'a Origin<'a> {
type Error = ();
type Error = !;
fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
Success(request.uri())
@ -372,7 +375,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for &'a Origin<'a> {
}
impl<'a, 'r> FromRequest<'a, 'r> for &'r Route {
type Error = ();
type Error = !;
fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
match request.route() {
@ -383,7 +386,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for &'r Route {
}
impl<'a, 'r> FromRequest<'a, 'r> for Cookies<'a> {
type Error = ();
type Error = !;
fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
Success(request.cookies())
@ -391,7 +394,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for Cookies<'a> {
}
impl<'a, 'r> FromRequest<'a, 'r> for &'a Accept {
type Error = ();
type Error = !;
fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
match request.accept() {
@ -402,7 +405,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for &'a Accept {
}
impl<'a, 'r> FromRequest<'a, 'r> for &'a ContentType {
type Error = ();
type Error = !;
fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
match request.content_type() {
@ -413,7 +416,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for &'a ContentType {
}
impl<'a, 'r> FromRequest<'a, 'r> for SocketAddr {
type Error = ();
type Error = !;
fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
match request.remote() {
@ -424,7 +427,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for SocketAddr {
}
impl<'a, 'r, T: FromRequest<'a, 'r>> FromRequest<'a, 'r> for Result<T, T::Error> {
type Error = ();
type Error = T::Error;
fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
match T::from_request(request) {
@ -436,7 +439,7 @@ impl<'a, 'r, T: FromRequest<'a, 'r>> FromRequest<'a, 'r> for Result<T, T::Error>
}
impl<'a, 'r, T: FromRequest<'a, 'r>> FromRequest<'a, 'r> for Option<T> {
type Error = ();
type Error = !;
fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
match T::from_request(request) {

View File

@ -202,7 +202,7 @@ pub trait FromParam<'a>: Sized {
}
impl<'a> FromParam<'a> for &'a RawStr {
type Error = ();
type Error = !;
#[inline(always)]
fn from_param(param: &'a RawStr) -> Result<&'a RawStr, Self::Error> {

View File

@ -1,31 +1,25 @@
#![feature(plugin, decl_macro)]
#![feature(plugin, decl_macro, never_type)]
#![plugin(rocket_codegen)]
extern crate rocket;
use std::fmt;
use rocket::request::{self, Request, FromRequest};
use rocket::outcome::Outcome::*;
#[derive(Debug)]
struct HeaderCount(usize);
impl fmt::Display for HeaderCount {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl<'a, 'r> FromRequest<'a, 'r> for HeaderCount {
type Error = ();
fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, ()> {
type Error = !;
fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, !> {
Success(HeaderCount(request.headers().len()))
}
}
#[get("/")]
fn header_count(header_count: HeaderCount) -> String {
format!("Your request contained {} headers!", header_count)
format!("Your request contained {} headers!", header_count.0)
}
fn rocket() -> rocket::Rocket {

View File

@ -1,4 +1,4 @@
#![feature(plugin, decl_macro)]
#![feature(plugin, decl_macro, never_type)]
#![plugin(rocket_codegen)]
extern crate rocket;

View File

@ -1,4 +1,4 @@
#![feature(plugin, decl_macro)]
#![feature(plugin, decl_macro, never_type)]
#![plugin(rocket_codegen)]
extern crate rocket_contrib;
@ -24,9 +24,9 @@ struct Login {
struct User(usize);
impl<'a, 'r> FromRequest<'a, 'r> for User {
type Error = ();
type Error = !;
fn from_request(request: &'a Request<'r>) -> request::Outcome<User, ()> {
fn from_request(request: &'a Request<'r>) -> request::Outcome<User, !> {
request.cookies()
.get_private("user_id")
.and_then(|cookie| cookie.value().parse().ok())