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) -> TokenStream11pub 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