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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
use syn::bracketed;
use syn::parse::Parse;
use syn::punctuated::Punctuated;
use syn::Attribute;
use syn::Token;
use crate::Params;
use crate::Proxy;
impl Parse for Proxy {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
if input.peek(Token![trait]) {
let kwd: Token![trait] = input.parse()?;
Ok(Self::Trait(kwd, input.parse()?))
} else {
Err(syn::Error::new(
input.span(),
"Expected `struct`, `trait` or `impl`",
))
}
}
}
impl Parse for Params {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let mut enum_attr = Attribute::parse_outer(input)?;
let visibility: syn::Visibility = input
.fork()
.parse::<syn::Visibility>()
.ok()
.and_then(|_| input.parse().ok())
.unwrap_or(syn::Visibility::Inherited);
let _: Token![enum] = input.parse()?;
let enum_name: syn::Ident = input.parse()?;
let mut returnval = None;
let mut proxies = Vec::new();
while input.peek(Token![,]) {
let _comma: Token![,] = input.parse()?;
if input.is_empty() {
break;
}
if input.peek(Token![trait]) {
proxies.extend(input.parse());
continue;
}
let arg: syn::Ident = input.parse()?;
match arg.to_string().as_str() {
"enum_attr" => {
let content;
enum_attr.push(Attribute {
pound_token: Token),
style: syn::AttrStyle::Outer,
bracket_token: bracketed!(content in input),
path: content.call(syn::Path::parse_mod_style)?,
tokens: content.parse()?,
})
}
"returnval" => {
if returnval.is_some() {
return Err(syn::Error::new_spanned(
arg,
"Argument `returnval` specified twice",
));
}
let _eq: Token![=] = input.parse()?;
returnval = Some(input.parse()?)
}
"proxy" => {
let contents;
if input.peek(syn::token::Paren) {
let _paren = syn::parenthesized!(contents in input);
} else {
let _paren = syn::braced!(contents in input);
}
let punct: Punctuated<Proxy, Token![;]> =
Punctuated::parse_terminated(&contents)?;
proxies.extend(punct)
}
_ => {
return Err(syn::Error::new(
arg.span(),
format!("Unknown argument `{arg}` to ctrlgen"),
))
}
};
}
Ok(Self {
visibility,
enum_name,
returnval,
proxies,
enum_attr,
})
}
}