1 use hashbrown::HashSet; 2 use syn::bracketed; 3 use syn::parse::{Parse, ParseStream, Result}; 4 use syn::punctuated::Punctuated; 5 use syn::{Error, Ident, Path, Token, Type}; 6 7 #[derive(Hash, PartialEq, Eq)] 8 pub enum Flag { 9 Sync, 10 } 11 12 impl Flag { from(ident: &Ident) -> Result<Self>13 fn from(ident: &Ident) -> Result<Self> { 14 match ident.to_string().as_str() { 15 "sync" => Ok(Flag::Sync), 16 unknown => { 17 let msg = format!("Unknown flag: {}", unknown); 18 Err(Error::new_spanned(ident, msg)) 19 } 20 } 21 } 22 } 23 24 pub struct Targets { 25 pub flags: HashSet<Flag>, 26 pub paths: Vec<Path>, 27 } 28 29 impl Parse for Targets { parse(input: ParseStream) -> Result<Self>30 fn parse(input: ParseStream) -> Result<Self> { 31 let mut flags = HashSet::new(); 32 let mut paths = Vec::new(); 33 34 if input.is_empty() { 35 return Ok(Targets { flags, paths }); 36 } 37 38 if input.peek(syn::token::Bracket) { 39 let content; 40 bracketed!(content in input); 41 for ident in Punctuated::<Ident, Token![,]>::parse_terminated(&content)? { 42 if !flags.insert(Flag::from(&ident)?) { 43 let msg = format!("Duplicated flag: {}", ident); 44 return Err(Error::new_spanned(ident, msg)); 45 } 46 } 47 } 48 49 if input.is_empty() { 50 return Ok(Targets { flags, paths }); 51 } 52 53 paths = Punctuated::<Path, Token![,]>::parse_terminated(input)? 54 .into_iter() 55 .collect(); 56 57 Ok(Targets { flags, paths }) 58 } 59 } 60 61 pub struct Casts { 62 pub ty: Type, 63 pub targets: Targets, 64 } 65 66 impl Parse for Casts { parse(input: ParseStream) -> Result<Self>67 fn parse(input: ParseStream) -> Result<Self> { 68 let ty: Type = input.parse()?; 69 input.parse::<Token![=>]>()?; 70 71 Ok(Casts { 72 ty, 73 targets: input.parse()?, 74 }) 75 } 76 } 77