#[macro_use] extern crate rocket; use rocket::http::{Status, ContentType}; use rocket::form::{Form, Contextual, FromForm, FromFormField, Context}; use rocket::fs::TempFile; use rocket::fs::{FileServer, relative}; use rocket_contrib::templates::Template; #[derive(Debug, FromForm)] struct Password<'v> { #[field(validate = len(6..))] #[field(validate = eq(self.second))] first: &'v str, #[field(validate = eq(self.first))] second: &'v str, } #[derive(Debug, FromFormField)] enum Rights { Public, Reserved, Exclusive, } #[derive(Debug, FromFormField)] enum Category { Biology, Chemistry, Physics, #[field(value = "CS")] ComputerScience, } #[derive(Debug, FromForm)] struct Submission<'v> { #[field(validate = len(1..))] title: &'v str, date: time::Date, #[field(validate = len(1..=250))] r#abstract: &'v str, #[field(validate = ext(ContentType::PDF))] file: TempFile<'v>, #[field(validate = len(1..))] category: Vec, rights: Rights, ready: bool, } #[derive(Debug, FromForm)] struct Account<'v> { #[field(validate = len(1..))] name: &'v str, password: Password<'v>, #[field(validate = contains('@').or_else(msg!("invalid email address")))] email: &'v str, } #[derive(Debug, FromForm)] struct Submit<'v> { account: Account<'v>, submission: Submission<'v>, } #[get("/")] fn index<'r>() -> Template { Template::render("index", &Context::default()) } // NOTE: We use `Contextual` here because we want to collect all submitted form // fields to re-render forms with submitted values on error. If you have no such // need, do not use `Contextual`. Use the equivalent of `Form>`. #[post("/", data = "
")] fn submit<'r>(form: Form>>) -> (Status, Template) { let template = match form.value { Some(ref submission) => { println!("submission: {:#?}", submission); Template::render("success", &form.context) } None => Template::render("index", &form.context), }; (form.context.status(), template) } #[launch] fn rocket() -> _ { rocket::build() .mount("/", routes![index, submit]) .attach(Template::fairing()) .mount("/", FileServer::from(relative!("/static"))) }