args.rs (2807B)
1 use std::collections::HashSet; 2 use syn::{ 3 parse::{Parse, ParseStream}, 4 punctuated::{Pair, Punctuated}, 5 Expr, ExprArray, ExprLit, Ident, Lit, LitStr, Token, 6 }; 7 8 pub enum Arg { 9 Command(LitStr), 10 Commands(HashSet<LitStr>), 11 //DmOnly 12 } 13 14 impl Parse for Arg { 15 fn parse(input: ParseStream) -> syn::Result<Self> { 16 let ident = input.call(Ident::parse)?; 17 let arg_name = ident.to_string(); 18 match &arg_name[..] { 19 "command" => { 20 if input.peek(Token![=]) { 21 let _: Token![=] = input.parse()?; 22 Ok(Self::Command(input.parse()?)) 23 } else { 24 Err(input.error("expected `=`")) 25 } 26 } 27 "commands" => { 28 if input.peek(Token![=]) { 29 let _: Token![=] = input.parse()?; 30 let array: ExprArray = input.parse()?; 31 32 if !array.attrs.is_empty() { 33 return Err(syn::Error::new_spanned( 34 &array.attrs[0], 35 "attributes are not allowed here", 36 )); 37 } 38 39 let commands = array 40 .elems 41 .into_pairs() 42 .map(Pair::into_value) 43 .map(|expr| { 44 if let Expr::Lit(ExprLit { attrs, lit }) = expr { 45 if !attrs.is_empty() { 46 return Err(syn::Error::new_spanned( 47 &attrs[0], 48 "attributes are not allowed here", 49 )); 50 } 51 52 if let Lit::Str(s) = lit { 53 Ok(s) 54 } else { 55 Err(syn::Error::new_spanned(lit, "expected string literal")) 56 } 57 } else { 58 Err(syn::Error::new_spanned(expr, "expected string literal")) 59 } 60 }) 61 .collect::<Result<_, _>>()?; 62 63 Ok(Self::Commands(commands)) 64 } else { 65 Err(input.error("expected `=`")) 66 } 67 } 68 _ => Err(syn::Error::new_spanned(ident, "unknown ruma_bot option")), 69 } 70 } 71 } 72 73 pub struct Args(pub Vec<Arg>); 74 75 impl Parse for Args { 76 fn parse(input: ParseStream) -> syn::Result<Self> { 77 let args = Punctuated::<Arg, Token![,]>::parse_terminated(input)?; 78 Ok(Self(args.into_iter().collect())) 79 } 80 }