1use proc_macro::TokenStream;
2use quote::quote;
3use syn;
4use syn::{LitStr, Meta};
5
6#[proc_macro_derive(Widget, attributes(widget))]
7pub fn widget_derive(input: TokenStream) -> TokenStream {
8 let input = syn::parse_macro_input!(input as syn::DeriveInput);
10 let name = &input.ident;
12
13 let mut style_value: Option<String> = None;
15 let mut script_value: Option<String> = None;
16
17 for option in input.attrs.into_iter() {
18 if let Meta::List(ref list) = option.meta {
19 if list.path.is_ident("widget") {
20 list.parse_nested_meta(|meta| {
21 if meta.path.is_ident("style") {
22 let value = meta.value()?;
23 let s: LitStr = value.parse()?;
24 style_value = Some(s.value());
25 }
26 if meta.path.is_ident("script") {
27 let value = meta.value()?;
28 let s: LitStr = value.parse()?;
29 script_value = Some(s.value());
30 }
31 Ok(())
32 })
33 .expect("Can't parse attribute widget, check syntax");
34 }
35 }
36 }
37
38 let style_str = style_value.expect("style is a mandatory attribute in widget macro");
39
40 let generated_code = quote! {
41 use std::ops::{Deref, DerefMut};
42
43
44 impl Into<Node> for #name {
45 fn into(self) -> Node {
46 let mut widget = self;
47 widget.render();
48 widget.node
49 }
50 }
51 impl Into<Node> for &mut #name {
52 fn into(self) -> Node {
53 let widget = self;
54 widget.render();
55 widget.node.clone()
56 }
57 }
58
59 impl Deref for #name {
60 type Target = Node;
61
62 fn deref(&self) -> &Self::Target {
63 &self.node
64 }
65 }
66 impl DerefMut for #name {
67 fn deref_mut(&mut self) -> &mut Self::Target {
68 &mut self.node
69 }
70 }
71
72 impl Widget for #name {
73 const STYLE: &'static str = include_str!(#style_str);
74 fn widget_name() -> &'static str {
75 "#name"
76 }
77
78 }
79 };
80 generated_code.into()
81}
82
83#[proc_macro_derive(Component)]
84pub fn component_derive(input: TokenStream) -> TokenStream {
85 let ast = syn::parse(input).unwrap();
88
89 impl_component_macro(&ast)
91}
92
93fn impl_component_macro(ast: &syn::DeriveInput) -> TokenStream {
94 let name = &ast.ident;
95 let generated_code = quote! {
96 impl Into<Node> for #name {
97 fn into(self) -> Node {
98 self.render()
99 }
100 }
101 };
102 generated_code.into()
103}
104
105#[proc_macro_derive(Appendable)]
106pub fn appendable_derive(input: TokenStream) -> TokenStream {
107 let ast = syn::parse(input).unwrap();
110
111 impl_appendable_macro(&ast)
113}
114
115fn impl_appendable_macro(ast: &syn::DeriveInput) -> TokenStream {
116 let name = &ast.ident;
117 let generated_code = quote! {
118 impl Appendable for #name {}
119 };
120 generated_code.into()
121}
122
123#[proc_macro_derive(Attributable)]
124pub fn attributable_derive(input: TokenStream) -> TokenStream {
125 let ast = syn::parse(input).unwrap();
128
129 impl_attributable_macro(&ast)
131}
132
133fn impl_attributable_macro(ast: &syn::DeriveInput) -> TokenStream {
134 let name = &ast.ident;
135 let generated_code = quote! {
136 impl Attributable for #name {}
137 };
138 generated_code.into()
139}
140
141#[proc_macro_derive(Classable)]
142pub fn classable_derive(input: TokenStream) -> TokenStream {
143 let ast = syn::parse(input).unwrap();
146
147 impl_classable_macro(&ast)
149}
150
151fn impl_classable_macro(ast: &syn::DeriveInput) -> TokenStream {
152 let name = &ast.ident;
153 let generated_code = quote! {
154 impl Classable for #name {}
155 };
156 generated_code.into()
157}
158#[proc_macro_derive(Colorable)]
159pub fn colorable_derive(input: TokenStream) -> TokenStream {
160 let ast = syn::parse(input).unwrap();
163
164 impl_colorable_macro(&ast)
166}
167
168fn impl_colorable_macro(ast: &syn::DeriveInput) -> TokenStream {
169 let name = &ast.ident;
170 let generated_code = quote! {
171 impl Colorable for #name {}
172 };
173 generated_code.into()
174}
175
176#[proc_macro_derive(Dimensionable)]
177pub fn dimensionable_derive(input: TokenStream) -> TokenStream {
178 let ast = syn::parse(input).unwrap();
181
182 impl_dimensionable_macro(&ast)
184}
185
186fn impl_dimensionable_macro(ast: &syn::DeriveInput) -> TokenStream {
187 let name = &ast.ident;
188 let generated_code = quote! {
189 impl Dimensionable for #name {}
190 };
191 generated_code.into()
192}
193
194#[proc_macro_derive(Cardifiable)]
195pub fn cardifiable_derive(input: TokenStream) -> TokenStream {
196 let ast = syn::parse(input).unwrap();
199
200 impl_cardifiable_macro(&ast)
202}
203
204fn impl_cardifiable_macro(ast: &syn::DeriveInput) -> TokenStream {
205 let name = &ast.ident;
206 let generated_code = quote! {
207 impl Cardifiable for #name {}
208 };
209 generated_code.into()
210}