ctrlgen_impl/
parse_args.rs1use syn::bracketed;
2use syn::parse::Parse;
3use syn::punctuated::Punctuated;
4use syn::Attribute;
5use syn::Token;
6
7use crate::Params;
8use crate::Proxy;
9
10impl Parse for Proxy {
11 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
12 if input.peek(Token![trait]) {
17 let kwd: Token![trait] = input.parse()?;
18 Ok(Self::Trait(kwd, input.parse()?))
19 } else {
25 Err(syn::Error::new(
26 input.span(),
27 "Expected `struct`, `trait` or `impl`",
28 ))
29 }
30 }
31}
32
33impl Parse for Params {
34 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
35 let mut enum_attr = Attribute::parse_outer(input)?;
36
37 let visibility: syn::Visibility = input
38 .fork()
39 .parse::<syn::Visibility>()
40 .ok()
41 .and_then(|_| input.parse().ok())
42 .unwrap_or(syn::Visibility::Inherited);
43
44 let _: Token![enum] = input.parse()?;
45
46 let enum_name: syn::Ident = input.parse()?;
47 let mut returnval = None;
48 let mut proxies = Vec::new();
49 let mut context = None;
50
51 while input.peek(Token![,]) {
52 let _comma: Token![,] = input.parse()?;
53 if input.is_empty() {
54 break;
56 }
57 if input.peek(Token![trait]) {
58 proxies.extend(input.parse());
59 continue;
60 }
61
62 let arg: syn::Ident = input.parse()?;
63 match arg.to_string().as_str() {
64 "enum_attr" => {
65 let content;
66 enum_attr.push(Attribute {
67 pound_token: Token),
68 style: syn::AttrStyle::Outer,
69 bracket_token: bracketed!(content in input),
70 path: content.call(syn::Path::parse_mod_style)?,
71 tokens: content.parse()?,
72 })
73 }
74 "returnval" => {
75 if returnval.is_some() {
76 return Err(syn::Error::new_spanned(
77 arg,
78 "Argument `returnval` specified twice",
79 ));
80 }
81 let _eq: Token![=] = input.parse()?;
82 returnval = Some(input.parse()?)
83 }
84 "proxy" => {
85 let contents;
86 if input.peek(syn::token::Paren) {
87 let _paren = syn::parenthesized!(contents in input);
88 } else {
89 let _paren = syn::braced!(contents in input);
90 }
91 let punct: Punctuated<Proxy, Token![;]> =
92 Punctuated::parse_terminated(&contents)?;
93 proxies.extend(punct)
94 }
95 "context" => {
96 if context.is_some() {
97 return Err(syn::Error::new_spanned(
98 arg,
99 "Argument `context` specified twice",
100 ));
101 }
102 let contents;
103 let _paren = syn::parenthesized!(contents in input);
104
105 let ident = contents.parse()?;
106 let _colon: Token![:] = contents.parse()?;
107 let ty = contents.parse()?;
108
109 context = Some((ident, ty))
110 }
111 _ => {
112 return Err(syn::Error::new(
113 arg.span(),
114 format!("Unknown argument `{arg}` to ctrlgen"),
115 ))
116 }
117 };
118 }
119
120 Ok(Self {
121 visibility,
122 enum_name,
123 returnval,
124 proxies,
125 enum_attr,
126 context,
127 })
128 }
129}