Remove unneeded lifetime in Request.

Previously, a Request's only lifetime parameter referred to itself. This
causes many issues and is simply wrong. Instead, use `transmute` to make
the lifetime `static`. As long the contents inside Request don't move or
change, the references are valid. We keep the lifetime as a phantom in
`Request` for future use.
This commit is contained in:
Sergio Benitez 2016-10-06 20:57:17 -07:00
parent bcb9bd860b
commit 39f7f2d32b
1 changed files with 21 additions and 12 deletions

View File

@ -34,11 +34,10 @@ pub struct Request<'a> {
/// The data in the request.
pub data: Vec<u8>, // FIXME: Don't read this! (bad Hyper.)
uri: URIBuf, // FIXME: Should be URI (without Hyper).
params: RefCell<Vec<&'static str>>,
cookies: Cookies,
headers: HyperHeaders, // This sucks.
/// Indexes into the URI.
// params: RefCell<Vec<(usize, usize)>>,
params: RefCell<Option<Vec<&'a str>>>,
_phantom: Option<&'a str>,
}
impl<'a> Request<'a> {
@ -58,13 +57,13 @@ impl<'a> Request<'a> {
/// let my_param: T = request.get_param(n);
/// }
/// ```
pub fn get_param<T: FromParam<'a>>(&self, n: usize) -> Result<T, Error> {
pub fn get_param<'r, T: FromParam<'r>>(&'r self, n: usize) -> Result<T, Error> {
let params = self.params.borrow();
if params.is_none() || n >= params.as_ref().unwrap().len() {
debug!("{} is >= param count {}", n, params.as_ref().unwrap().len());
if n >= params.len() {
debug!("{} is >= param count {}", n, params.len());
Err(Error::NoKey)
} else {
T::from_param(params.as_ref().unwrap()[n]).map_err(|_| Error::BadParse)
T::from_param(params[n]).map_err(|_| Error::BadParse)
}
}
@ -101,12 +100,13 @@ impl<'a> Request<'a> {
#[doc(hidden)]
pub fn mock(method: Method, uri: &str) -> Request {
Request {
params: RefCell::new(None),
params: RefCell::new(vec![]),
method: method,
cookies: Cookies::new(&[]),
uri: URIBuf::from(uri),
data: vec![],
headers: HyperHeaders::new(),
_phantom: None,
}
}
@ -160,10 +160,18 @@ impl<'a> Request<'a> {
self.uri.as_uri()
}
// FIXME: Don't need a refcell for this.
#[doc(hidden)]
pub fn set_params(&'a self, route: &Route) {
*self.params.borrow_mut() = Some(route.get_params(self.uri.as_uri()))
pub fn set_params(&self, route: &Route) {
// We use transmute to cast the lifetime of self.uri.as_uri() to
// 'static. This is because that lifetime refers to the String in URIBuf
// in this structure, which is (obviously) guaranteed to live as long as
// the structure AS LONG AS it is not moved out or changed. AS A RESULT,
// the `uri` fields MUST NEVER be changed once it is set.
// TODO: Find a way to enforce these. Look at OwningRef for inspiration.
use ::std::mem::transmute;
*self.params.borrow_mut() = unsafe {
transmute(route.get_params(self.uri.as_uri()))
};
}
#[doc(hidden)]
@ -200,12 +208,13 @@ impl<'a> Request<'a> {
h_body.read_to_end(&mut data).unwrap();
let request = Request {
params: RefCell::new(None),
params: RefCell::new(vec![]),
method: method,
cookies: cookies,
uri: uri,
data: data,
headers: h_headers,
_phantom: None,
};
Ok(request)