mod form_items;
mod from_form;
mod from_form_value;
pub use self::form_items::FormItems;
pub use self::from_form::FromForm;
pub use self::from_form_value::FromFormValue;
use std::marker::PhantomData;
use std::fmt::{self, Debug};
use std::io::Read;
use http::Status;
use request::Request;
use data::{self, Data, FromData};
use outcome::Outcome::*;
pub struct Form<'f, T: FromForm<'f> + 'f> {
object: T,
form_string: String,
_phantom: PhantomData<&'f T>,
}
impl<'f, T: FromForm<'f> + 'f> Form<'f, T> {
pub fn get(&'f self) -> &'f T {
&self.object
}
pub fn get_mut(&'f mut self) -> &'f mut T {
&mut self.object
}
pub fn raw_form_string(&self) -> &str {
&self.form_string
}
fn new(form_string: String) -> Result<Self, (String, T::Error)> {
let long_lived_string: &'f str = unsafe {
::std::mem::transmute(form_string.as_str())
};
match T::from_form_string(long_lived_string) {
Ok(obj) => Ok(Form {
form_string: form_string,
object: obj,
_phantom: PhantomData
}),
Err(e) => Err((form_string, e))
}
}
}
impl<'f, T: FromForm<'f> + 'static> Form<'f, T> {
pub fn into_inner(self) -> T {
self.object
}
}
impl<'f, T: FromForm<'f> + Debug + 'f> Debug for Form<'f, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?} from form string: {:?}", self.object, self.form_string)
}
}
impl<'f, T: FromForm<'f>> FromData for Form<'f, T> where T::Error: Debug {
type Error = Option<String>;
fn from_data(request: &Request, data: Data) -> data::Outcome<Self, Self::Error> {
if !request.content_type().is_form() {
warn_!("Form data does not have form content type.");
return Forward(data);
}
let mut form_string = String::with_capacity(4096);
let mut stream = data.open().take(32768);
if let Err(e) = stream.read_to_string(&mut form_string) {
error_!("IO Error: {:?}", e);
Failure((Status::InternalServerError, None))
} else {
match Form::new(form_string) {
Ok(form) => Success(form),
Err((form_string, e)) => {
error_!("Failed to parse value from form: {:?}", e);
Failure((Status::BadRequest, Some(form_string)))
}
}
}
}
}
#[cfg(test)]
mod test {
use super::Form;
use ::request::FromForm;
struct Simple<'s> {
value: &'s str
}
struct Other {
value: String
}
impl<'s> FromForm<'s> for Simple<'s> {
type Error = &'s str;
fn from_form_string(fs: &'s str) -> Result<Simple<'s>, &'s str> {
Ok(Simple { value: fs })
}
}
impl<'s> FromForm<'s> for Other {
type Error = &'s str;
fn from_form_string(fs: &'s str) -> Result<Other, &'s str> {
Ok(Other { value: fs.to_string() })
}
}
#[test]
fn test_lifetime() {
let form_string = "hello=world".to_string();
let form: Form<Simple> = Form::new(form_string).unwrap();
let string: &str = form.get().value;
assert_eq!(string, "hello=world");
}
#[test]
fn test_lifetime_2() {
let form_string = "hello=world".to_string();
let mut _y = "hi";
let _form: Form<Simple> = Form::new(form_string).unwrap();
}
#[test]
fn test_lifetime_3() {
let form_string = "hello=world".to_string();
let form: Form<Other> = Form::new(form_string).unwrap();
fn should_compile(form: Form<Other>) -> String {
form.into_inner().value
}
assert_eq!(should_compile(form), "hello=world".to_string());
}
#[test]
fn test_lifetime_4() {
let form_string = "hello=world".to_string();
let form: Form<Simple> = Form::new(form_string).unwrap();
fn should_compile<'f>(_form: Form<'f, Simple<'f>>) { }
should_compile(form)
}
}