mirror of https://github.com/rwf2/Rocket.git
Allow ignoring unused items in query string with #[derive(FromFormIgnorable)].
This commit is contained in:
parent
f5ec470a7d
commit
0522ed0537
|
@ -49,9 +49,38 @@ fn get_struct_lifetime(ecx: &mut ExtCtxt, item: &Annotatable, span: Span)
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Use proper logging to emit the error messages.
|
||||
trait IgnoreExtraFieldStrategy {
|
||||
fn shall_ignore() -> bool;
|
||||
}
|
||||
|
||||
struct IgnoreExtraField;
|
||||
impl IgnoreExtraFieldStrategy for IgnoreExtraField {
|
||||
fn shall_ignore() -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
struct ProhibitExtraField;
|
||||
impl IgnoreExtraFieldStrategy for ProhibitExtraField {
|
||||
fn shall_ignore() -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_form_derive(ecx: &mut ExtCtxt, span: Span, meta_item: &MetaItem,
|
||||
annotated: &Annotatable, push: &mut FnMut(Annotatable)) {
|
||||
from_form_derive_imp::<ProhibitExtraField>(ecx, span, meta_item, annotated, push)
|
||||
}
|
||||
|
||||
pub fn from_form_ignorable_derive(ecx: &mut ExtCtxt, span: Span, meta_item: &MetaItem,
|
||||
annotated: &Annotatable, push: &mut FnMut(Annotatable)) {
|
||||
from_form_derive_imp::<IgnoreExtraField>(ecx, span, meta_item, annotated, push)
|
||||
}
|
||||
|
||||
// TODO: Use proper logging to emit the error messages.
|
||||
fn from_form_derive_imp<S: IgnoreExtraFieldStrategy>
|
||||
(ecx: &mut ExtCtxt, span: Span, meta_item: &MetaItem,
|
||||
annotated: &Annotatable, push: &mut FnMut(Annotatable)) {
|
||||
let struct_lifetime = get_struct_lifetime(ecx, annotated, span);
|
||||
let (lifetime_var, trait_generics) = match struct_lifetime {
|
||||
lifetime@Some(_) => (lifetime, ty::LifetimeBounds::empty()),
|
||||
|
@ -110,7 +139,7 @@ pub fn from_form_derive(ecx: &mut ExtCtxt, span: Span, meta_item: &MetaItem,
|
|||
),
|
||||
attributes: vec![],
|
||||
is_unsafe: false,
|
||||
combine_substructure: c_s(Box::new(from_form_substructure)),
|
||||
combine_substructure: c_s(Box::new(from_form_substructure::<S>)),
|
||||
unify_fieldless_variants: false,
|
||||
}
|
||||
],
|
||||
|
@ -122,7 +151,8 @@ pub fn from_form_derive(ecx: &mut ExtCtxt, span: Span, meta_item: &MetaItem,
|
|||
trait_def.expand(ecx, meta_item, annotated, push);
|
||||
}
|
||||
|
||||
fn from_form_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> P<Expr> {
|
||||
fn from_form_substructure<S: IgnoreExtraFieldStrategy>
|
||||
(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> P<Expr> {
|
||||
// Check that we specified the methods to the argument correctly.
|
||||
const EXPECTED_ARGS: usize = 1;
|
||||
let arg = if substr.nonself_args.len() == EXPECTED_ARGS {
|
||||
|
@ -197,6 +227,9 @@ fn from_form_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substruct
|
|||
|
||||
// The actual match statement. Iterate through all of the fields in the form
|
||||
// and use the $arms generated above.
|
||||
|
||||
let shall_ignore = S::shall_ignore();
|
||||
|
||||
stmts.push(quote_stmt!(cx,
|
||||
for (k, v) in $arg {
|
||||
match k.as_str() {
|
||||
|
@ -207,10 +240,12 @@ fn from_form_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substruct
|
|||
* in sync with Rocket::preprocess. */
|
||||
}
|
||||
_ => {
|
||||
if !$shall_ignore {
|
||||
println!(" => {}={} has no matching field in struct.",
|
||||
k, v);
|
||||
$return_err_stmt
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
).unwrap());
|
||||
|
|
|
@ -182,7 +182,8 @@ pub fn plugin_registrar(reg: &mut Registry) {
|
|||
reg.register_macro("errors", macros::errors);
|
||||
|
||||
register_derives!(reg,
|
||||
"derive_FromForm" => from_form_derive
|
||||
"derive_FromForm" => from_form_derive,
|
||||
"derive_FromFormIgnorable" => from_form_ignorable_derive
|
||||
);
|
||||
|
||||
register_decorators!(reg,
|
||||
|
|
|
@ -12,6 +12,12 @@ struct TodoTask {
|
|||
completed: bool
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, FromFormIgnorable)]
|
||||
struct TodoTaskIgnorable {
|
||||
description: String,
|
||||
completed: bool
|
||||
}
|
||||
|
||||
// TODO: Make deriving `FromForm` for this enum possible.
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum FormOption {
|
||||
|
@ -94,6 +100,27 @@ fn main() {
|
|||
completed: false
|
||||
}));
|
||||
|
||||
// Same number of arguments: simple case.
|
||||
let task: Option<TodoTaskIgnorable> = parse("description=Hello&completed=on");
|
||||
assert_eq!(task, Some(TodoTaskIgnorable {
|
||||
description: "Hello".to_string(),
|
||||
completed: true
|
||||
}));
|
||||
|
||||
// Argument in string but not in form.
|
||||
let task: Option<TodoTaskIgnorable> = parse("other=a&description=Hello&completed=on");
|
||||
assert_eq!(task, Some(TodoTaskIgnorable {
|
||||
description: "Hello".to_string(),
|
||||
completed: true
|
||||
}));
|
||||
|
||||
// Ensure _method isn't required.
|
||||
let task: Option<TodoTaskIgnorable> = parse("_method=patch&description=Hello&completed=off");
|
||||
assert_eq!(task, Some(TodoTaskIgnorable {
|
||||
description: "Hello".to_string(),
|
||||
completed: false
|
||||
}));
|
||||
|
||||
let form_string = &[
|
||||
"password=testing", "checkbox=off", "checkbox=on", "number=10",
|
||||
"checkbox=off", "textarea=", "select=a", "radio=c",
|
||||
|
|
Loading…
Reference in New Issue