macro_tools_attr_prop/
macro_tools_attr_prop.rs1#[ cfg( not( all( feature = "enabled", feature = "attr_prop", debug_assertions ) ) ) ]
30fn main(){}
31#[ cfg( all( feature = "enabled", feature = "attr_prop", debug_assertions ) ) ]
32fn main()
33{
34
35 use macro_tools::
36 {
37 ct,
38 syn_err,
39 return_syn_err,
40 qt,
41 Result,
42 AttributeComponent,
43 AttributePropertyComponent,
44 AttributePropertyBoolean,
45 AttributePropertySingletone,
46 Assign,
47 };
48
49 #[ derive( Debug, Default ) ]
51 pub struct ItemAttributes
52 {
53 pub mutator : AttributeMutator,
55 }
56
57 impl ItemAttributes
58 {
59 pub fn from_attrs< 'a >( attrs : impl Iterator< Item = & 'a syn::Attribute > ) -> Result< Self >
64 {
65 let mut result = Self::default();
66
67 let error = | attr : & syn::Attribute | -> syn::Error
69 {
70 let known_attributes = ct::str::format!
71 (
72 "Known attributes are: {}, {}.",
73 "debug",
74 AttributeMutator::KEYWORD,
75 );
76 syn_err!
77 (
78 attr,
79 "Expects an attribute of format '#[ attribute( key1 = val1, key2 = val2 ) ]'\n {known_attributes}\n But got: '{}'",
80 qt! { #attr }
81 )
82 };
83
84 for attr in attrs
85 {
86 let key_ident = attr.path().get_ident().ok_or_else( || error( attr ) )?;
87 let key_str = format!( "{}", key_ident );
88 match key_str.as_ref()
93 {
94 AttributeMutator::KEYWORD => result.assign( AttributeMutator::from_meta( attr )? ),
95 "debug" => {},
96 _ => {},
97 }
99 }
100
101 Ok( result )
102 }
103 }
104
105 #[ derive( Debug, Default ) ]
113 pub struct AttributeMutator
114 {
115 pub custom : AttributePropertyCustom,
118 pub debug : AttributePropertyDebug,
121 }
122
123 impl AttributeComponent for AttributeMutator
124 {
125 const KEYWORD : & 'static str = "mutator";
126
127 fn from_meta( attr : & syn::Attribute ) -> Result< Self >
129 {
130 match attr.meta
131 {
132 syn::Meta::List( ref meta_list ) =>
133 {
134 return syn::parse2::< AttributeMutator >( meta_list.tokens.clone() );
135 },
136 syn::Meta::Path( ref _path ) =>
137 {
138 return Ok( Default::default() )
139 },
140 _ => return_syn_err!
141 (
142 attr,
143 "Expects an attribute of format `#[ mutator( custom = true ) ]`. \nGot: {}",
144 qt! { #attr }
145 ),
146 }
147 }
148 }
149
150 impl< IntoT > Assign< AttributeMutator, IntoT > for ItemAttributes
152 where
153 IntoT : Into< AttributeMutator >,
154 {
155 #[ inline( always ) ]
156 fn assign( & mut self, component : IntoT )
157 {
158 self.mutator = component.into();
159 }
160 }
161
162 impl< IntoT > Assign< AttributePropertyDebug, IntoT > for AttributeMutator
164 where
165 IntoT : Into< AttributePropertyDebug >,
166 {
167 #[ inline( always ) ]
168 fn assign( & mut self, component : IntoT )
169 {
170 self.debug = component.into();
171 }
172 }
173
174 impl< IntoT > Assign< AttributePropertyCustom, IntoT > for AttributeMutator
176 where
177 IntoT : Into< AttributePropertyCustom >,
178 {
179 #[ inline( always ) ]
180 fn assign( & mut self, component : IntoT )
181 {
182 self.custom = component.into();
183 }
184 }
185
186 impl syn::parse::Parse for AttributeMutator
187 {
188 fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self >
189 {
190 let mut result = Self::default();
191
192 let error = | ident : & syn::Ident | -> syn::Error
193 {
194 let known = ct::str::format!
195 (
196 "Known entries of attribute {} are: {}, {}.",
197 AttributeMutator::KEYWORD,
198 AttributePropertyCustom::KEYWORD,
199 AttributePropertyDebug::KEYWORD,
200 );
201 syn_err!
202 (
203 ident,
204 r#"Expects an attribute of format '#[ mutator( custom = false ) ]'
205 {known}
206 But got: '{}'
207 "#,
208 qt! { #ident }
209 )
210 };
211
212 while !input.is_empty()
213 {
214 let lookahead = input.lookahead1();
215 if lookahead.peek( syn::Ident )
216 {
217 let ident : syn::Ident = input.parse()?;
218
219 match ident.to_string().as_str()
220 {
221 AttributePropertyCustom::KEYWORD => result.assign( AttributePropertyCustom::parse( input )? ),
222 AttributePropertyDebug::KEYWORD => result.assign( AttributePropertyDebug::from( true ) ),
223 _ => return Err( error( & ident ) ),
224 }
225 }
226 else
227 {
228 return Err( lookahead.error() );
229 }
230
231 if input.peek( syn::Token![,] )
233 {
234 input.parse::< syn::Token![,] >()?;
235 }
236 }
237
238 Ok( result )
239 }
240 }
241
242 #[ derive( Debug, Default, Clone, Copy ) ]
247 pub struct AttributePropertyDebugMarker;
248
249 impl AttributePropertyComponent for AttributePropertyDebugMarker
250 {
251 const KEYWORD : & 'static str = "debug";
252 }
253
254 pub type AttributePropertyDebug = AttributePropertySingletone< AttributePropertyDebugMarker >;
257
258 #[ derive( Debug, Default, Clone, Copy ) ]
263 pub struct AttributePropertyCustomMarker;
264
265 impl AttributePropertyComponent for AttributePropertyCustomMarker
266 {
267 const KEYWORD : & 'static str = "custom";
268 }
269
270 pub type AttributePropertyCustom = AttributePropertyBoolean< AttributePropertyCustomMarker >;
273
274 let input : syn::Attribute = syn::parse_quote!( #[ mutator( custom = true ) ] );
278 let attrs : ItemAttributes = ItemAttributes::from_attrs( std::iter::once( & input ) ).unwrap();
279 println!( "{:?}", attrs );
280
281 let attr : AttributePropertyBoolean< AttributePropertyDebugMarker > = AttributePropertyBoolean::default();
283 assert_eq!( attr.internal(), false );
284 let attr : AttributePropertyBoolean< AttributePropertyDebugMarker > = true.into();
285 assert_eq!( attr.internal(), true );
286 let attr : AttributePropertyBoolean< AttributePropertyDebugMarker > = false.into();
287 assert_eq!( attr.internal(), false );
288
289}