intertrait_macros/
args.rs

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