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