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 /// [private cookie]: /rocket/http/enum.Cookies.html#private-cookies
/// ///
/// ```rust /// ```rust
/// # #![feature(plugin, decl_macro)] /// # #![feature(plugin, decl_macro, never_type)]
/// # #![plugin(rocket_codegen)] /// # #![plugin(rocket_codegen)]
/// # extern crate rocket; /// # extern crate rocket;
/// # /// #
@ -68,9 +68,9 @@ use Header;
/// struct User(usize); /// struct User(usize);
/// ///
/// impl<'a, 'r> FromRequest<'a, 'r> for User { /// 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() /// request.cookies()
/// .get_private("user_id") /// .get_private("user_id")
/// .and_then(|cookie| cookie.value().parse().ok()) /// .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`. /// The identity implementation of `FromData`. Always returns `Success`.
impl FromData for Data { impl FromData for Data {
type Error = (); type Error = !;
fn from_data(_: &Request, data: Data) -> Outcome<Self, Self::Error> { fn from_data(_: &Request, data: Data) -> Outcome<Self, Self::Error> {
Success(data) Success(data)
} }
} }
impl<T: FromData> FromData for Result<T, T::Error> { impl<T: FromData> FromData for Result<T, T::Error> {
type Error = (); type Error = !;
fn from_data(request: &Request, data: Data) -> Outcome<Self, Self::Error> { fn from_data(request: &Request, data: Data) -> Outcome<Self, Self::Error> {
match T::from_data(request, data) { 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> { impl<T: FromData> FromData for Option<T> {
type Error = (); type Error = !;
fn from_data(request: &Request, data: Data) -> Outcome<Self, Self::Error> { fn from_data(request: &Request, data: Data) -> Outcome<Self, Self::Error> {
match T::from_data(request, data) { 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" /// key == "valid_api_key"
/// } /// }
/// ///
/// #[derive(Debug)]
/// enum ApiKeyError {
/// BadCount,
/// Missing,
/// Invalid,
/// }
///
/// impl<'a, 'r> FromRequest<'a, 'r> for ApiKey { /// 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(); /// let keys: Vec<_> = request.headers().get("x-api-key").collect();
/// if keys.len() != 1 { /// match keys.len() {
/// return Outcome::Failure((Status::BadRequest, ())); /// 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`): /// routes (`admin_dashboard` and `user_dashboard`):
/// ///
/// ```rust /// ```rust
/// # #![feature(plugin, decl_macro)] /// # #![feature(plugin, decl_macro, never_type)]
/// # #![plugin(rocket_codegen)] /// # #![plugin(rocket_codegen)]
/// # extern crate rocket; /// # extern crate rocket;
/// # /// #
@ -282,7 +285,7 @@ impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
/// used, as illustrated below: /// used, as illustrated below:
/// ///
/// ```rust /// ```rust
/// # #![feature(plugin, decl_macro)] /// # #![feature(plugin, decl_macro, never_type)]
/// # #![plugin(rocket_codegen)] /// # #![plugin(rocket_codegen)]
/// # extern crate rocket; /// # extern crate rocket;
/// # /// #
@ -305,9 +308,9 @@ impl<S, E> IntoOutcome<S, (Status, E), ()> for Result<S, E> {
/// # struct Admin<'a> { user: &'a User }; /// # struct Admin<'a> { user: &'a User };
/// # /// #
/// impl<'a, 'r> FromRequest<'a, 'r> for &'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 /// // This closure will execute at most once per request, regardless of
/// // the number of times the `User` guard is executed. /// // the number of times the `User` guard is executed.
/// let user_result = request.local_cache(|| { /// 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> { /// 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>()?; /// let user = request.guard::<&User>()?;
/// ///
/// if user.is_admin { /// if user.is_admin {
@ -356,7 +359,7 @@ pub trait FromRequest<'a, 'r>: Sized {
} }
impl<'a, 'r> FromRequest<'a, 'r> for Method { impl<'a, 'r> FromRequest<'a, 'r> for Method {
type Error = (); type Error = !;
fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> { fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
Success(request.method()) 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> { 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> { fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
Success(request.uri()) 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 { impl<'a, 'r> FromRequest<'a, 'r> for &'r Route {
type Error = (); type Error = !;
fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> { fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
match request.route() { 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> { impl<'a, 'r> FromRequest<'a, 'r> for Cookies<'a> {
type Error = (); type Error = !;
fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> { fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
Success(request.cookies()) 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 { impl<'a, 'r> FromRequest<'a, 'r> for &'a Accept {
type Error = (); type Error = !;
fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> { fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
match request.accept() { 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 { impl<'a, 'r> FromRequest<'a, 'r> for &'a ContentType {
type Error = (); type Error = !;
fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> { fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
match request.content_type() { 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 { impl<'a, 'r> FromRequest<'a, 'r> for SocketAddr {
type Error = (); type Error = !;
fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> { fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
match request.remote() { 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> { 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> { fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
match T::from_request(request) { 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> { 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> { fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
match T::from_request(request) { match T::from_request(request) {

View File

@ -202,7 +202,7 @@ pub trait FromParam<'a>: Sized {
} }
impl<'a> FromParam<'a> for &'a RawStr { impl<'a> FromParam<'a> for &'a RawStr {
type Error = (); type Error = !;
#[inline(always)] #[inline(always)]
fn from_param(param: &'a RawStr) -> Result<&'a RawStr, Self::Error> { 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)] #![plugin(rocket_codegen)]
extern crate rocket; extern crate rocket;
use std::fmt;
use rocket::request::{self, Request, FromRequest}; use rocket::request::{self, Request, FromRequest};
use rocket::outcome::Outcome::*; use rocket::outcome::Outcome::*;
#[derive(Debug)] #[derive(Debug)]
struct HeaderCount(usize); 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 { impl<'a, 'r> FromRequest<'a, 'r> for HeaderCount {
type Error = (); type Error = !;
fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, ()> {
fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, !> {
Success(HeaderCount(request.headers().len())) Success(HeaderCount(request.headers().len()))
} }
} }
#[get("/")] #[get("/")]
fn header_count(header_count: HeaderCount) -> String { 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 { fn rocket() -> rocket::Rocket {

View File

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

View File

@ -1,4 +1,4 @@
#![feature(plugin, decl_macro)] #![feature(plugin, decl_macro, never_type)]
#![plugin(rocket_codegen)] #![plugin(rocket_codegen)]
extern crate rocket_contrib; extern crate rocket_contrib;
@ -24,9 +24,9 @@ struct Login {
struct User(usize); struct User(usize);
impl<'a, 'r> FromRequest<'a, 'r> for User { 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() request.cookies()
.get_private("user_id") .get_private("user_id")
.and_then(|cookie| cookie.value().parse().ok()) .and_then(|cookie| cookie.value().parse().ok())