1 #![feature(proc_macro_diagnostic)]
2 
3 #[macro_use] extern crate quote;
4 extern crate devise;
5 extern crate proc_macro;
6 
7 use proc_macro::TokenStream;
8 use devise::*;
9 
10 #[proc_macro_derive(FromFormValue)]
derive_from_form_value(input: TokenStream) -> TokenStream11 pub fn derive_from_form_value(input: TokenStream) -> TokenStream {
12     DeriveGenerator::build_for(input, quote!(impl<'__v> ::rocket::request::FromFormValue<'__v>))
13         .data_support(DataSupport::Enum)
14         .validate_enum(|generator, data| {
15             // This derive only works for variants that are nullary.
16             for variant in data.variants() {
17                 if !variant.fields().count() == 0 {
18                     return Err(variant.span().error("variants cannot have fields"));
19                 }
20             }
21 
22             // Emit a warning if the enum is empty.
23             if data.variants.is_empty() {
24                 generator.input.span().warning("deriving for empty enum").emit();
25             }
26 
27             Ok(())
28         })
29         .function(|_, inner| quote! {
30             type Error = &'__v ::rocket::http::RawStr;
31 
32             fn from_form_value(
33                 value: &'__v ::rocket::http::RawStr
34             ) -> ::std::result::Result<Self, Self::Error> {
35                 let uncased = value.as_uncased_str();
36                 #inner
37                 ::std::result::Result::Err(value)
38             }
39         })
40         .try_map_enum(null_enum_mapper)
41         .map_variant(|_, variant| {
42             let variant_str = variant.ident.to_string();
43             let builder = variant.builder(|_| unreachable!());
44             quote! {
45                 if uncased == #variant_str {
46                     return ::std::result::Result::Ok(#builder);
47                 }
48             }
49         })
50         .to_tokens()
51 }
52