1use quote::{ToTokens, quote};
6
7mod r#gen;
8use r#gen::gen_all;
9
10#[cfg(test)]
11mod tests;
12
13#[proc_macro_attribute]
36pub fn implement(
37 attributes: proc_macro::TokenStream,
38 type_tokens: proc_macro::TokenStream,
39) -> proc_macro::TokenStream {
40 implement_core(attributes.into(), type_tokens.into()).into()
41}
42
43fn implement_core(
44 attributes: proc_macro2::TokenStream,
45 item_tokens: proc_macro2::TokenStream,
46) -> proc_macro2::TokenStream {
47 let attributes = match syn::parse2::<ImplementAttributes>(attributes) {
48 Ok(a) => a,
49 Err(e) => return e.into_compile_error(),
50 };
51 let original_type = match syn::parse2::<syn::ItemStruct>(item_tokens) {
52 Ok(t) => t,
53 Err(e) => return e.into_compile_error(),
54 };
55
56 let inputs = ImplementInputs {
57 original_ident: original_type.ident.clone(),
58 interface_chains: convert_implements_to_interface_chains(attributes.implement),
59 trust_level: attributes.trust_level,
60 agile: attributes.agile,
61 impl_ident: quote::format_ident!("{}_Impl", &original_type.ident),
62 constraints: {
63 if let Some(where_clause) = &original_type.generics.where_clause {
64 where_clause.predicates.to_token_stream()
65 } else {
66 quote!()
67 }
68 },
69 generics: if !original_type.generics.params.is_empty() {
70 let mut params = quote! {};
71 original_type.generics.params.to_tokens(&mut params);
72 quote! { <#params> }
73 } else {
74 quote! { <> }
75 },
76 generics_idents: if !original_type.generics.params.is_empty() {
77 let idents: Vec<_> = original_type
78 .generics
79 .params
80 .iter()
81 .map(|param| {
82 let mut ident = quote! {};
83 match param {
84 syn::GenericParam::Type(ty) => ty.ident.to_tokens(&mut ident),
85 syn::GenericParam::Lifetime(lt) => lt.lifetime.to_tokens(&mut ident),
86 syn::GenericParam::Const(cnst) => cnst.ident.to_tokens(&mut ident),
87 };
88
89 ident
90 })
91 .collect();
92 quote! { <#(#idents),*> }
93 } else {
94 quote! { <> }
95 },
96 is_generic: !original_type.generics.params.is_empty(),
97 original_type,
98 };
99
100 let items = gen_all(&inputs);
101 let mut tokens = inputs.original_type.into_token_stream();
102 for item in items {
103 tokens.extend(item.into_token_stream());
104 }
105
106 tokens
107}
108
109struct ImplementInputs {
111 original_type: syn::ItemStruct,
113
114 original_ident: syn::Ident,
116
117 interface_chains: Vec<InterfaceChain>,
119
120 trust_level: usize,
122
123 agile: bool,
125
126 impl_ident: syn::Ident,
128
129 constraints: proc_macro2::TokenStream,
131
132 generics: proc_macro2::TokenStream,
135
136 generics_idents: proc_macro2::TokenStream,
139
140 is_generic: bool,
142}
143
144struct InterfaceChain {
146 field_ident: syn::Ident,
148
149 vtable_const_ident: syn::Ident,
152
153 implement: ImplementType,
154}
155
156struct ImplementType {
157 type_name: String,
158 generics: Vec<Self>,
159
160 span: proc_macro2::Span,
162}
163
164impl ImplementType {
165 fn to_ident(&self) -> proc_macro2::TokenStream {
166 let type_name = syn::parse_str::<proc_macro2::TokenStream>(&self.type_name)
167 .expect("Invalid token stream");
168 let generics = self.generics.iter().map(|g| g.to_ident());
169 quote! { #type_name<#(#generics,)*> }
170 }
171 fn to_vtbl_ident(&self) -> proc_macro2::TokenStream {
172 let ident = self.to_ident();
173 quote! {
174 <#ident as ::windows_core::Interface>::Vtable
175 }
176 }
177}
178
179#[derive(Default)]
180struct ImplementAttributes {
181 pub implement: Vec<ImplementType>,
182 pub trust_level: usize,
183 pub agile: bool,
184}
185
186impl syn::parse::Parse for ImplementAttributes {
187 fn parse(cursor: syn::parse::ParseStream) -> syn::parse::Result<Self> {
188 let mut input = Self {
189 agile: true,
190 ..Default::default()
191 };
192
193 while !cursor.is_empty() {
194 input.parse_implement(cursor)?;
195 }
196
197 Ok(input)
198 }
199}
200
201impl ImplementAttributes {
202 fn parse_implement(&mut self, cursor: syn::parse::ParseStream) -> syn::parse::Result<()> {
203 let tree = cursor.parse::<UseTree2>()?;
204 self.walk_implement(&tree, &mut String::new())?;
205
206 if !cursor.is_empty() {
207 cursor.parse::<syn::Token![,]>()?;
208 }
209
210 Ok(())
211 }
212
213 fn walk_implement(
214 &mut self,
215 tree: &UseTree2,
216 namespace: &mut String,
217 ) -> syn::parse::Result<()> {
218 match tree {
219 UseTree2::Path(input) => {
220 if !namespace.is_empty() {
221 namespace.push_str("::");
222 }
223
224 namespace.push_str(&input.ident.to_string());
225 self.walk_implement(&input.tree, namespace)?;
226 }
227 UseTree2::Name(_) => {
228 self.implement.push(tree.to_element_type(namespace)?);
229 }
230 UseTree2::Group(input) => {
231 for tree in &input.items {
232 self.walk_implement(tree, namespace)?;
233 }
234 }
235 UseTree2::TrustLevel(input) => self.trust_level = *input,
236 UseTree2::Agile(agile) => self.agile = *agile,
237 }
238
239 Ok(())
240 }
241}
242
243enum UseTree2 {
244 Path(UsePath2),
245 Name(UseName2),
246 Group(UseGroup2),
247 TrustLevel(usize),
248 Agile(bool),
249}
250
251impl UseTree2 {
252 fn to_element_type(&self, namespace: &mut String) -> syn::parse::Result<ImplementType> {
253 match self {
254 Self::Path(input) => {
255 if !namespace.is_empty() {
256 namespace.push_str("::");
257 }
258
259 namespace.push_str(&input.ident.to_string());
260 input.tree.to_element_type(namespace)
261 }
262 Self::Name(input) => {
263 let mut type_name = input.ident.to_string();
264 let span = input.ident.span();
265
266 if !namespace.is_empty() {
267 type_name = format!("{namespace}::{type_name}");
268 }
269
270 let mut generics = vec![];
271
272 for g in &input.generics {
273 generics.push(g.to_element_type(&mut String::new())?);
274 }
275
276 Ok(ImplementType {
277 type_name,
278 generics,
279 span,
280 })
281 }
282 Self::Group(input) => Err(syn::parse::Error::new(
283 input.brace_token.span.join(),
284 "Syntax not supported",
285 )),
286 _ => unimplemented!(),
287 }
288 }
289}
290
291struct UsePath2 {
292 pub ident: syn::Ident,
293 pub tree: Box<UseTree2>,
294}
295
296struct UseName2 {
297 pub ident: syn::Ident,
298 pub generics: Vec<UseTree2>,
299}
300
301struct UseGroup2 {
302 pub brace_token: syn::token::Brace,
303 pub items: syn::punctuated::Punctuated<UseTree2, syn::Token![,]>,
304}
305
306impl syn::parse::Parse for UseTree2 {
307 fn parse(input: syn::parse::ParseStream) -> syn::parse::Result<Self> {
308 let lookahead = input.lookahead1();
309 if lookahead.peek(syn::Ident) {
310 use syn::ext::IdentExt;
311 let ident = input.call(syn::Ident::parse_any)?;
312 if input.peek(syn::Token![::]) {
313 input.parse::<syn::Token![::]>()?;
314 Ok(Self::Path(UsePath2 {
315 ident,
316 tree: Box::new(input.parse()?),
317 }))
318 } else if input.peek(syn::Token![=]) {
319 if ident == "TrustLevel" {
320 input.parse::<syn::Token![=]>()?;
321 let span = input.span();
322 let value = input.call(syn::Ident::parse_any)?;
323 match value.to_string().as_str() {
324 "Partial" => Ok(Self::TrustLevel(1)),
325 "Full" => Ok(Self::TrustLevel(2)),
326 _ => Err(syn::parse::Error::new(
327 span,
328 "`TrustLevel` must be `Partial` or `Full`",
329 )),
330 }
331 } else if ident == "Agile" {
332 input.parse::<syn::Token![=]>()?;
333 let span = input.span();
334 let value = input.call(syn::Ident::parse_any)?;
335 match value.to_string().as_str() {
336 "true" => Ok(Self::Agile(true)),
337 "false" => Ok(Self::Agile(false)),
338 _ => Err(syn::parse::Error::new(
339 span,
340 "`Agile` must be `true` or `false`",
341 )),
342 }
343 } else {
344 Err(syn::parse::Error::new(
345 ident.span(),
346 "Unrecognized key-value pair",
347 ))
348 }
349 } else {
350 let generics = if input.peek(syn::Token![<]) {
351 input.parse::<syn::Token![<]>()?;
352 let mut generics = Vec::new();
353 loop {
354 generics.push(input.parse::<Self>()?);
355
356 if input.parse::<syn::Token![,]>().is_err() {
357 break;
358 }
359 }
360 input.parse::<syn::Token![>]>()?;
361 generics
362 } else {
363 Vec::new()
364 };
365
366 Ok(Self::Name(UseName2 { ident, generics }))
367 }
368 } else if lookahead.peek(syn::token::Brace) {
369 let content;
370 let brace_token = syn::braced!(content in input);
371 let items = content.parse_terminated(Self::parse, syn::Token![,])?;
372
373 Ok(Self::Group(UseGroup2 { brace_token, items }))
374 } else {
375 Err(lookahead.error())
376 }
377 }
378}
379
380fn convert_implements_to_interface_chains(implements: Vec<ImplementType>) -> Vec<InterfaceChain> {
381 let mut chains = Vec::with_capacity(implements.len());
382
383 for (i, implement) in implements.into_iter().enumerate() {
384 let mut ident_string = format!("interface{}", i + 1);
386
387 let suffix = get_interface_ident_suffix(&implement.type_name);
388 if !suffix.is_empty() {
389 ident_string.push('_');
390 ident_string.push_str(&suffix);
391 }
392 let field_ident = syn::Ident::new(&ident_string, implement.span);
393
394 let mut vtable_const_string = ident_string.clone();
395 vtable_const_string.make_ascii_uppercase();
396 vtable_const_string.insert_str(0, "VTABLE_");
397 let vtable_const_ident = syn::Ident::new(&vtable_const_string, implement.span);
398
399 chains.push(InterfaceChain {
400 implement,
401 field_ident,
402 vtable_const_ident,
403 });
404 }
405
406 chains
407}
408
409fn get_interface_ident_suffix(type_name: &str) -> String {
410 let mut suffix = String::new();
411 for c in type_name.chars() {
412 let c = c.to_ascii_lowercase();
413
414 if suffix.len() >= 20 {
415 break;
416 }
417
418 if c.is_ascii_alphanumeric() {
419 suffix.push(c);
420 }
421 }
422
423 suffix
424}