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