Propogate error types in FromParam and FromSegment parses.

This commit is contained in:
Sergio Benitez 2016-10-31 18:51:19 +01:00
parent 639cd425ee
commit 4326c9103e
2 changed files with 30 additions and 10 deletions

View File

@ -144,18 +144,26 @@ impl RouteGenerateExt for RouteParams {
}
};
// Note: the `None` case shouldn't happen if a route is matched.
let ident = param.ident().prepend(PARAM_PREFIX);
let expr = match param {
Param::Single(_) => quote_expr!(ecx, _req.get_param($i)),
Param::Many(_) => quote_expr!(ecx, _req.get_segments($i)),
Param::Single(_) => quote_expr!(ecx, match _req.get_param_str($i) {
Some(s) => <$ty as ::rocket::request::FromParam>::from_param(s),
None => return ::rocket::Response::forward(_data)
}),
Param::Many(_) => quote_expr!(ecx, match _req.get_raw_segments($i) {
Some(s) => <$ty as ::rocket::request::FromSegments>::from_segments(s),
None => return ::rocket::Response::forward(_data)
}),
};
let original_ident = param.ident();
fn_param_statements.push(quote_stmt!(ecx,
let $ident: $ty = match $expr {
Ok(v) => v,
Err(e) => {
println!(" => Failed to parse '{}': {:?}",
stringify!($ident), e);
stringify!($original_ident), e);
return ::rocket::Response::forward(_data)
}
};

View File

@ -8,7 +8,7 @@ use error::Error;
use super::{FromParam, FromSegments};
use router::Route;
use http::uri::{URI, URIBuf};
use http::uri::{URI, URIBuf, Segments};
use http::hyper::{header, HyperCookie, HyperHeaders, HyperMethod, HyperRequestUri};
use http::{Method, ContentType, Cookies};
@ -45,14 +45,20 @@ impl Request {
/// let my_param: T = request.get_param(n);
/// }
/// ```
#[inline(always)]
pub fn get_param<'r, T: FromParam<'r>>(&'r self, n: usize) -> Result<T, Error> {
let param = self.get_param_str(n).ok_or(Error::NoKey)?;
T::from_param(param).map_err(|_| Error::BadParse)
}
/// Get the `n`th path parameter, if it exists.
#[doc(hidden)]
pub fn get_param_str(&self, n: usize) -> Option<&str> {
let params = self.params.borrow();
if n >= params.len() {
debug!("{} is >= param count {}", n, params.len());
Err(Error::NoKey)
None
} else {
T::from_param(params[n]).map_err(|_| Error::BadParse)
Some(&params[n])
}
}
@ -73,16 +79,22 @@ impl Request {
/// `request.get_segments::<T>(1)` will attempt to parse the segments
/// `"there/i/am/here"` as type `T`.
pub fn get_segments<'r, T: FromSegments<'r>>(&'r self, i: usize) -> Result<T, Error> {
let segments = self.get_raw_segments(i).ok_or(Error::NoKey)?;
T::from_segments(segments).map_err(|_| Error::BadParse)
}
/// Get the segments beginning at the `i`th, if they exists.
#[doc(hidden)]
pub fn get_raw_segments(&self, i: usize) -> Option<Segments> {
if i >= self.uri().segment_count() {
debug!("{} is >= segment count {}", i, self.uri().segment_count());
Err(Error::NoKey)
None
} else {
// TODO: Really want to do self.uri.segments().skip(i).into_inner(),
// but the std lib doesn't implement it for Skip.
let mut segments = self.uri.as_uri().segments();
for _ in segments.by_ref().take(i) { /* do nothing */ }
T::from_segments(segments).map_err(|_| Error::BadParse)
Some(segments)
}
}