zng_var_proc_macros/
when_var.rs
1use syn::{
2 Attribute, Expr, Path, Token, parenthesized,
3 parse::{Parse, ParseStream},
4 parse_macro_input,
5 punctuated::Punctuated,
6};
7
8pub fn expand(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
9 let Input {
10 vars_mod,
11 conditions,
12 default:
13 DefaultArm {
14 attrs: default_attrs,
15 use_macro: default_use_macro,
16 value: default_value,
17 ..
18 },
19 ..
20 } = parse_macro_input!(input as Input);
21
22 let mut out = quote! {
24 #(#default_attrs)*
25 let mut __b = #vars_mod::types::WhenVarBuilder::new(#default_value);
26 };
27
28 if let Some(m) = default_use_macro {
29 let m = m.path;
30 out = quote! {
31 #m! {
32 #out
33 }
34 };
35 }
36
37 for ConditionArm {
39 attrs,
40 use_macro,
41 condition,
42 value,
43 ..
44 } in conditions
45 {
46 let mut arm = quote! {
47 #(#attrs)*
48 __b.push(#condition, #value);
49 };
50
51 if let Some(m) = use_macro {
52 let m = m.path;
53 arm = quote! {
54 #m! {
55 #arm
56 }
57 };
58 }
59
60 out.extend(arm);
61 }
62
63 out = quote! {
65 {
66 #out
67 __b.build()
68 }
69 };
70
71 out.into()
72}
73
74struct Input {
75 vars_mod: Path,
76 conditions: Punctuated<ConditionArm, Token![,]>,
77 default: DefaultArm,
78 _trailing_comma: Option<Token![,]>,
79}
80impl Parse for Input {
81 fn parse(input: ParseStream) -> syn::Result<Self> {
82 let vars_mod = input.parse()?;
83 let mut conditions = Punctuated::new();
84 while !input.peek(Token![_]) {
85 conditions.push(input.parse()?);
86 conditions.push_punct(input.parse()?);
87 }
88 Ok(Input {
89 vars_mod,
90 conditions,
91 default: input.parse()?,
92 _trailing_comma: input.parse()?,
93 })
94 }
95}
96
97struct ConditionArm {
98 attrs: Vec<Attribute>,
99 use_macro: Option<UseMacro>,
100 condition: Expr,
101 _fat_arrow_token: Token![=>],
102 value: Expr,
103}
104impl Parse for ConditionArm {
105 fn parse(input: ParseStream) -> syn::Result<Self> {
106 Ok(ConditionArm {
107 attrs: Attribute::parse_outer(input)?,
108 use_macro: if input.peek(Token![use]) { Some(input.parse()?) } else { None },
109 condition: input.parse()?,
110 _fat_arrow_token: input.parse()?,
111 value: input.parse()?,
112 })
113 }
114}
115
116struct DefaultArm {
117 attrs: Vec<Attribute>,
118 use_macro: Option<UseMacro>,
119 _wild_token: Token![_],
120 _fat_arrow_token: Token![=>],
121 value: Expr,
122}
123impl Parse for DefaultArm {
124 fn parse(input: ParseStream) -> syn::Result<Self> {
125 Ok(DefaultArm {
126 attrs: Attribute::parse_outer(input)?,
127 use_macro: if input.peek(Token![use]) { Some(input.parse()?) } else { None },
128 _wild_token: input.parse()?,
129 _fat_arrow_token: input.parse()?,
130 value: input.parse()?,
131 })
132 }
133}
134
135struct UseMacro {
136 path: Path,
137}
138impl Parse for UseMacro {
139 fn parse(input: ParseStream) -> syn::Result<Self> {
140 let _: Token![use] = input.parse()?;
141 let inner;
142 let _ = parenthesized!(inner in input);
143 Ok(UseMacro { path: inner.parse()? })
144 }
145}