]> git.proxmox.com Git - rustc.git/blob - vendor/windows-bindgen/src/gen.rs
New upstream version 1.73.0+dfsg1
[rustc.git] / vendor / windows-bindgen / src / gen.rs
1 use super::*;
2
3 pub struct Gen<'a> {
4 pub reader: &'a Reader<'a>,
5 pub namespace: &'a str,
6 pub sys: bool,
7 pub cfg: bool,
8 pub doc: bool,
9 pub component: bool,
10 pub standalone: bool,
11 pub std: bool,
12 }
13
14 impl<'a> Gen<'a> {
15 pub fn new(reader: &'a Reader) -> Self {
16 Self {
17 reader,
18 namespace: "",
19 sys: false,
20 cfg: false,
21 doc: false,
22 component: false,
23 standalone: false,
24 std: false,
25 }
26 }
27
28 //
29 // TypeDef
30 //
31
32 pub fn type_def_name(&self, def: TypeDef, generics: &[Type]) -> TokenStream {
33 self.type_def_name_imp(def, generics, "")
34 }
35 pub fn type_def_vtbl_name(&self, def: TypeDef, generics: &[Type]) -> TokenStream {
36 self.type_def_name_imp(def, generics, "_Vtbl")
37 }
38 pub fn type_def_name_imp(&self, def: TypeDef, generics: &[Type], suffix: &str) -> TokenStream {
39 let type_name = self.reader.type_def_type_name(def);
40
41 if type_name.namespace.is_empty() {
42 to_ident(&self.scoped_name(def))
43 } else {
44 let mut namespace = self.namespace(type_name.namespace);
45 let mut name = to_ident(type_name.name);
46 name.push_str(suffix);
47
48 if generics.is_empty() || self.sys {
49 namespace.combine(&name);
50 namespace
51 } else {
52 let colon_separated = if !namespace.as_str().is_empty() {
53 quote! { :: }
54 } else {
55 quote! {}
56 };
57
58 let generics = generics.iter().map(|ty| self.type_name(ty));
59 quote! { #namespace #name #colon_separated<#(#generics),*> }
60 }
61 }
62 }
63
64 //
65 // Type
66 //
67
68 pub fn type_default_name(&self, ty: &Type) -> TokenStream {
69 if let Type::WinrtArray(ty) = ty {
70 self.type_default_name(ty)
71 } else {
72 let kind = self.type_name(ty);
73
74 if ty.is_generic() {
75 quote! { <#kind as ::windows::core::Type<#kind>>::Default }
76 } else if self.reader.type_is_nullable(ty) && !self.sys {
77 quote! { ::core::option::Option<#kind> }
78 } else {
79 kind
80 }
81 }
82 }
83
84 pub(crate) fn type_name(&self, ty: &Type) -> TokenStream {
85 match ty {
86 Type::Void => quote! { ::core::ffi::c_void },
87 Type::Bool => quote! { bool },
88 Type::Char => quote! { u16 },
89 Type::I8 => quote! { i8 },
90 Type::U8 => quote! { u8 },
91 Type::I16 => quote! { i16 },
92 Type::U16 => quote! { u16 },
93 Type::I32 => quote! { i32 },
94 Type::U32 => quote! { u32 },
95 Type::I64 => quote! { i64 },
96 Type::U64 => quote! { u64 },
97 Type::F32 => quote! { f32 },
98 Type::F64 => quote! { f64 },
99 Type::ISize => quote! { isize },
100 Type::USize => quote! { usize },
101 Type::String => {
102 let crate_name = self.crate_name();
103 quote! { #crate_name HSTRING }
104 }
105 Type::BSTR => {
106 let crate_name = self.crate_name();
107 quote! { #crate_name BSTR }
108 }
109 Type::IInspectable => {
110 let crate_name = self.crate_name();
111 quote! { #crate_name IInspectable }
112 }
113 Type::GUID => {
114 let crate_name = self.crate_name();
115 quote! { #crate_name GUID }
116 }
117 Type::IUnknown => {
118 let crate_name = self.crate_name();
119 quote! { #crate_name IUnknown }
120 }
121 Type::HRESULT => {
122 let crate_name = self.crate_name();
123 quote! { #crate_name HRESULT }
124 }
125 Type::PSTR => {
126 let crate_name = self.crate_name();
127 quote! { #crate_name PSTR }
128 }
129 Type::PWSTR => {
130 let crate_name = self.crate_name();
131 quote! { #crate_name PWSTR }
132 }
133 Type::PCSTR => {
134 let crate_name = self.crate_name();
135 quote! { #crate_name PCSTR }
136 }
137 Type::PCWSTR => {
138 let crate_name = self.crate_name();
139 quote! { #crate_name PCWSTR }
140 }
141 Type::Win32Array((ty, len)) => {
142 let name = self.type_default_name(ty);
143 let len = Literal::usize_unsuffixed(*len);
144 quote! { [#name; #len] }
145 }
146 Type::GenericParam(generic) => self.reader.generic_param_name(*generic).into(),
147 Type::TypeDef((def, generics)) => self.type_def_name(*def, generics),
148 Type::MutPtr((ty, pointers)) => {
149 let pointers = mut_ptrs(*pointers);
150 let ty = self.type_default_name(ty);
151 quote! { #pointers #ty }
152 }
153 Type::ConstPtr((ty, pointers)) => {
154 let pointers = const_ptrs(*pointers);
155 let ty = self.type_default_name(ty);
156 quote! { #pointers #ty }
157 }
158 Type::WinrtArray(ty) => self.type_name(ty),
159 Type::WinrtArrayRef(ty) => self.type_name(ty),
160 Type::WinrtConstRef(ty) => self.type_name(ty),
161 _ => unimplemented!(),
162 }
163 }
164 pub fn type_vtbl_name(&self, ty: &Type) -> TokenStream {
165 match ty {
166 Type::TypeDef((def, generics)) => self.type_def_vtbl_name(*def, generics),
167 _ => unimplemented!(),
168 }
169 }
170 pub fn type_abi_name(&self, ty: &Type) -> TokenStream {
171 if self.sys {
172 return self.type_default_name(ty);
173 }
174
175 match ty {
176 Type::IUnknown | Type::IInspectable => {
177 quote! { *mut ::core::ffi::c_void }
178 }
179 Type::String => {
180 quote! { ::std::mem::MaybeUninit<::windows::core::HSTRING> }
181 }
182 Type::BSTR => {
183 quote! { ::std::mem::MaybeUninit<::windows::core::BSTR> }
184 }
185 Type::Win32Array((kind, len)) => {
186 let name = self.type_abi_name(kind);
187 let len = Literal::usize_unsuffixed(*len);
188 quote! { [#name; #len] }
189 }
190 Type::GenericParam(generic) => {
191 let name = to_ident(self.reader.generic_param_name(*generic));
192 quote! { ::windows::core::AbiType<#name> }
193 }
194 Type::TypeDef((def, _)) => match self.reader.type_def_kind(*def) {
195 TypeKind::Enum => self.type_def_name(*def, &[]),
196 TypeKind::Struct => {
197 let tokens = self.type_def_name(*def, &[]);
198 if self.reader.type_def_is_blittable(*def) {
199 tokens
200 } else {
201 quote! { ::std::mem::MaybeUninit<#tokens> }
202 }
203 }
204 TypeKind::Delegate => {
205 if self
206 .reader
207 .type_def_flags(*def)
208 .contains(TypeAttributes::WINRT)
209 {
210 quote! { *mut ::core::ffi::c_void }
211 } else {
212 self.type_def_name(*def, &[])
213 }
214 }
215 _ => quote! { *mut ::core::ffi::c_void },
216 },
217 Type::MutPtr((kind, pointers)) => {
218 let pointers_tokens = gen_mut_ptrs(*pointers);
219 let kind = if *pointers > 1 {
220 self.type_name(kind)
221 } else {
222 self.type_abi_name(kind)
223 };
224 quote! { #pointers_tokens #kind }
225 }
226 Type::ConstPtr((kind, pointers)) => {
227 let pointers_tokens = gen_const_ptrs(*pointers);
228 let kind = if *pointers > 1 {
229 self.type_name(kind)
230 } else {
231 self.type_abi_name(kind)
232 };
233 quote! { #pointers_tokens #kind }
234 }
235 Type::WinrtArray(kind) => self.type_abi_name(kind),
236 Type::WinrtArrayRef(kind) => self.type_abi_name(kind),
237 _ => self.type_name(ty),
238 }
239 }
240
241 //
242 // Constraints
243 //
244
245 pub fn generic_phantoms(&self, generics: &[Type]) -> TokenStream {
246 let mut tokens = TokenStream::new();
247 for generic in generics {
248 let generic = self.type_name(generic);
249 tokens.combine(&quote! { ::core::marker::PhantomData::<#generic>, });
250 }
251 tokens
252 }
253 pub fn generic_named_phantoms(&self, generics: &[Type]) -> Vec<TokenStream> {
254 generics
255 .iter()
256 .map(|generic| {
257 let generic = self.type_name(generic);
258 quote! { #generic: ::core::marker::PhantomData::<#generic>, }
259 })
260 .collect()
261 }
262 pub fn generic_constraints(&self, generics: &[Type]) -> TokenStream {
263 let mut tokens = TokenStream::new();
264 for generic in generics {
265 let generic = self.type_name(generic);
266 tokens.combine(&quote! { #generic: ::windows::core::RuntimeType + 'static, });
267 }
268 tokens
269 }
270 pub fn generic_names(&self, generics: &[Type]) -> TokenStream {
271 let mut tokens = TokenStream::new();
272 for generic in generics {
273 let generic = self.type_name(generic);
274 tokens.combine(&quote! { #generic, });
275 }
276 tokens
277 }
278 /// The signature params which are generic (along with their relative index)
279 pub fn generic_params<'b>(
280 &'b self,
281 params: &'b [SignatureParam],
282 ) -> impl Iterator<Item = (usize, &SignatureParam)> + 'b {
283 params
284 .iter()
285 .filter(move |param| self.reader.signature_param_is_convertible(param))
286 .enumerate()
287 }
288 /// The generic param names (i.e., `T` in `fn foo<T>()`)
289 pub fn constraint_generics(&self, params: &[SignatureParam]) -> TokenStream {
290 let mut generics = self
291 .generic_params(params)
292 .map(|(position, _)| -> TokenStream { format!("P{position}").into() })
293 .peekable();
294
295 if generics.peek().is_some() {
296 quote!(#(#generics),*)
297 } else {
298 TokenStream::new()
299 }
300 }
301 /// A `where` clause for some constrained generic params
302 pub fn where_clause(&self, params: &[SignatureParam]) -> TokenStream {
303 let constraints = self.param_constraints(params);
304
305 if !constraints.is_empty() {
306 quote!(where #constraints)
307 } else {
308 quote!()
309 }
310 }
311 fn param_constraints(&self, params: &[SignatureParam]) -> TokenStream {
312 let mut tokens = TokenStream::new();
313 let gen_name = |position| {
314 let name: TokenStream = format!("P{position}").into();
315 name
316 };
317 for (position, param) in self.generic_params(params) {
318 match param.kind {
319 SignatureParamKind::TryInto => {
320 let name: TokenStream = gen_name(position);
321 let into = self.type_name(&param.ty);
322 tokens.combine(&quote! { #name: ::windows::core::TryIntoParam<#into>, });
323 }
324 SignatureParamKind::IntoParam => {
325 let name: TokenStream = gen_name(position);
326 let into = self.type_name(&param.ty);
327 tokens.combine(&quote! { #name: ::windows::core::IntoParam<#into>, });
328 }
329 _ => {}
330 }
331 }
332 tokens
333 }
334
335 //
336 // Cfg
337 //
338
339 /// Generates doc comments for types, free functions, and constants.
340 pub(crate) fn cfg_doc(&self, cfg: &Cfg) -> TokenStream {
341 if !self.doc {
342 quote! {}
343 } else {
344 let mut tokens = format!(r#"`\"{}\"`"#, to_feature(self.namespace));
345 let features = self.cfg_features_imp(cfg, self.namespace);
346
347 for features in features {
348 write!(tokens, r#", `\"{}\"`"#, to_feature(features)).unwrap();
349 }
350
351 if cfg.implement {
352 tokens.push_str(r#", `\"implement\"`"#)
353 }
354
355 format!(r#" #[doc = "*Required features: {tokens}*"]"#).into()
356 }
357 }
358
359 /// Generates doc comments for member functions (methods) and avoids redundantly declaring the
360 /// enclosing module feature required by the method's type.
361 pub(crate) fn cfg_method_doc(&self, cfg: &Cfg) -> TokenStream {
362 if !self.doc {
363 quote! {}
364 } else {
365 let features = self.cfg_features_imp(cfg, self.namespace);
366 if features.is_empty() {
367 quote! {}
368 } else {
369 let mut tokens = String::new();
370 for features in features {
371 write!(tokens, r#"`\"{}\"`, "#, to_feature(features)).unwrap();
372 }
373 tokens.truncate(tokens.len() - 2);
374 format!(r#"#[doc = "*Required features: {tokens}*"]"#).into()
375 }
376 }
377 }
378
379 pub(crate) fn cfg_features(&self, cfg: &Cfg) -> TokenStream {
380 let arches = &cfg.arches;
381 let arch = match arches.len() {
382 0 => quote! {},
383 1 => {
384 quote! { #[cfg(#(target_arch = #arches),*)] }
385 }
386 _ => {
387 quote! { #[cfg(any(#(target_arch = #arches),*))] }
388 }
389 };
390
391 let features = self.cfg_features_imp(cfg, self.namespace);
392
393 let features = match features.len() {
394 0 => quote! {},
395 1 => {
396 let features = features.iter().cloned().map(to_feature);
397 quote! { #[cfg(#(feature = #features)*)] }
398 }
399 _ => {
400 let features = features.iter().cloned().map(to_feature);
401 quote! { #[cfg(all( #(feature = #features),* ))] }
402 }
403 };
404
405 quote! { #arch #features }
406 }
407
408 fn cfg_features_imp(&self, cfg: &'a Cfg, namespace: &'a str) -> Vec<&'a str> {
409 let mut compact = Vec::<&'static str>::new();
410 if !self.standalone && !self.component {
411 for feature in cfg.types.keys() {
412 if !feature.is_empty() && !starts_with(namespace, feature) {
413 for pos in 0..compact.len() {
414 if starts_with(feature, unsafe { compact.get_unchecked(pos) }) {
415 compact.remove(pos);
416 break;
417 }
418 }
419 compact.push(feature);
420 }
421 }
422 }
423 compact
424 }
425
426 fn cfg_not_features(&self, cfg: &Cfg) -> TokenStream {
427 let features = self.cfg_features_imp(cfg, self.namespace);
428 if features.is_empty() {
429 quote! {}
430 } else {
431 match features.len() {
432 0 => quote! {},
433 1 => {
434 let features = features.iter().cloned().map(to_feature);
435 quote! { #[cfg(not(#(feature = #features)*))] }
436 }
437 _ => {
438 let features = features.iter().cloned().map(to_feature);
439 quote! { #[cfg(not(all( #(feature = #features),* )))] }
440 }
441 }
442 }
443 }
444
445 //
446 // Other helpers
447 //
448
449 pub(crate) fn namespace(&self, namespace: &str) -> TokenStream {
450 if self.standalone || namespace == self.namespace {
451 quote! {}
452 } else {
453 let is_external =
454 namespace.starts_with("Windows.") && !self.namespace.starts_with("Windows");
455 let mut relative = self.namespace.split('.').peekable();
456 let mut namespace = namespace.split('.').peekable();
457
458 while relative.peek() == namespace.peek() {
459 if relative.next().is_none() {
460 break;
461 }
462
463 namespace.next();
464 }
465
466 let mut tokens = TokenStream::new();
467
468 if is_external {
469 tokens.push_str("::windows::");
470 namespace.next();
471 } else {
472 for _ in 0..relative.count() {
473 tokens.push_str("super::");
474 }
475 }
476
477 for namespace in namespace {
478 tokens.push_str(namespace);
479 tokens.push_str("::");
480 }
481
482 tokens
483 }
484 }
485 pub fn crate_name(&self) -> TokenStream {
486 if self.standalone {
487 TokenStream::new()
488 } else if self.sys {
489 "::windows_sys::core::".into()
490 } else {
491 "::windows::core::".into()
492 }
493 }
494 fn scoped_name(&self, def: TypeDef) -> String {
495 if let Some(enclosing_type) = self.reader.type_def_enclosing_type(def) {
496 for (index, nested_type) in self.reader.nested_types(enclosing_type).enumerate() {
497 if self.reader.type_def_name(nested_type) == self.reader.type_def_name(def) {
498 return format!("{}_{index}", &self.scoped_name(enclosing_type));
499 }
500 }
501 }
502 self.reader.type_def_name(def).to_string()
503 }
504 pub fn value(&self, value: &Value) -> TokenStream {
505 match value {
506 Value::Bool(value) => quote! { #value },
507 Value::U8(value) => quote! { #value },
508 Value::I8(value) => quote! { #value },
509 Value::U16(value) => quote! { #value },
510 Value::I16(value) => quote! { #value },
511 Value::U32(value) => quote! { #value },
512 Value::I32(value) => quote! { #value },
513 Value::U64(value) => quote! { #value },
514 Value::I64(value) => quote! { #value },
515 Value::F32(value) => quote! { #value },
516 Value::F64(value) => quote! { #value },
517 Value::String(value) => {
518 let mut tokens = "\"".to_string();
519
520 for u in value.chars() {
521 write!(tokens, "{}", u.escape_default()).unwrap();
522 }
523
524 tokens.push('\"');
525 tokens.into()
526 }
527 _ => unimplemented!(),
528 }
529 }
530 pub fn typed_value(&self, value: &Value) -> TokenStream {
531 let literal = self.value(value);
532 match value {
533 Value::Bool(_) => quote! { bool = #literal },
534 Value::U8(_) => quote! { u8 = #literal },
535 Value::I8(_) => quote! { i8 = #literal },
536 Value::U16(_) => quote! { u16 = #literal },
537 Value::I16(_) => quote! { i16 = #literal },
538 Value::U32(_) => quote! { u32 = #literal },
539 Value::I32(_) => quote! { i32 = #literal },
540 Value::U64(_) => quote! { u64 = #literal },
541 Value::I64(_) => quote! { i64 = #literal },
542 Value::F32(_) => quote! { f32 = #literal },
543 Value::F64(_) => quote! { f64 = #literal },
544 Value::String(_) => {
545 quote! { &str = #literal }
546 }
547 _ => unimplemented!(),
548 }
549 }
550
551 pub fn guid(&self, value: &GUID) -> TokenStream {
552 let guid = self.type_name(&Type::GUID);
553 format!("{}::from_u128(0x{:08x?}_{:04x?}_{:04x?}_{:02x?}{:02x?}_{:02x?}{:02x?}{:02x?}{:02x?}{:02x?}{:02x?})", guid.into_string(), value.0, value.1, value.2, value.3, value.4, value.5, value.6, value.7, value.8, value.9, value.10).into()
554 }
555 pub fn interface_core_traits(
556 &self,
557 def: TypeDef,
558 _generics: &[Type],
559 ident: &TokenStream,
560 constraints: &TokenStream,
561 _phantoms: &TokenStream,
562 features: &TokenStream,
563 ) -> TokenStream {
564 let name = trim_tick(self.reader.type_def_name(def));
565 quote! {
566 #features
567 impl<#constraints> ::core::cmp::PartialEq for #ident {
568 fn eq(&self, other: &Self) -> bool {
569 self.0 == other.0
570 }
571 }
572 #features
573 impl<#constraints> ::core::cmp::Eq for #ident {}
574 #features
575 impl<#constraints> ::core::fmt::Debug for #ident {
576 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
577 f.debug_tuple(#name).field(&self.0).finish()
578 }
579 }
580 }
581 }
582 pub fn agile(
583 &self,
584 def: TypeDef,
585 ident: &TokenStream,
586 constraints: &TokenStream,
587 features: &TokenStream,
588 ) -> TokenStream {
589 if self.reader.type_def_is_agile(def) {
590 quote! {
591 #features
592 unsafe impl<#constraints> ::core::marker::Send for #ident {}
593 #features
594 unsafe impl<#constraints> ::core::marker::Sync for #ident {}
595 }
596 } else {
597 quote! {}
598 }
599 }
600 pub fn async_get(
601 &self,
602 def: TypeDef,
603 generics: &[Type],
604 ident: &TokenStream,
605 constraints: &TokenStream,
606 _phantoms: &TokenStream,
607 features: &TokenStream,
608 ) -> TokenStream {
609 let mut kind = self.reader.type_def_async_kind(def);
610 let mut async_generics = generics.to_vec();
611
612 if kind == AsyncKind::None {
613 for interface in self.reader.type_def_interfaces(def, generics) {
614 if let Type::TypeDef((interface_def, interface_generics)) = &interface.ty {
615 kind = self.reader.type_def_async_kind(*interface_def);
616 if kind != AsyncKind::None {
617 async_generics = interface_generics.to_vec();
618 break;
619 }
620 }
621 }
622 }
623
624 if kind == AsyncKind::None {
625 quote! {}
626 } else {
627 let return_type = match kind {
628 AsyncKind::Operation | AsyncKind::OperationWithProgress => {
629 self.type_name(&async_generics[0])
630 }
631 _ => quote! { () },
632 };
633
634 let handler = match kind {
635 AsyncKind::Action => quote! { AsyncActionCompletedHandler },
636 AsyncKind::ActionWithProgress => quote! { AsyncActionWithProgressCompletedHandler },
637 AsyncKind::Operation => quote! { AsyncOperationCompletedHandler },
638 AsyncKind::OperationWithProgress => {
639 quote! { AsyncOperationWithProgressCompletedHandler }
640 }
641 _ => unimplemented!(),
642 };
643
644 let namespace = self.namespace("Windows.Foundation");
645
646 quote! {
647 #features
648 impl<#constraints> #ident {
649 pub fn get(&self) -> ::windows::core::Result<#return_type> {
650 if self.Status()? == #namespace AsyncStatus::Started {
651 let (_waiter, signaler) = ::windows::imp::Waiter::new()?;
652 self.SetCompleted(&#namespace #handler::new(move |_sender, _args| {
653 // Safe because the waiter will only be dropped after being signaled.
654 unsafe { signaler.signal(); }
655 Ok(())
656 }))?;
657 }
658 self.GetResults()
659 }
660 }
661 #features
662 impl<#constraints> ::std::future::Future for #ident {
663 type Output = ::windows::core::Result<#return_type>;
664
665 fn poll(self: ::std::pin::Pin<&mut Self>, context: &mut ::std::task::Context) -> ::std::task::Poll<Self::Output> {
666 if self.Status()? == #namespace AsyncStatus::Started {
667 let waker = context.waker().clone();
668
669 let _ = self.SetCompleted(&#namespace #handler::new(move |_sender, _args| {
670 waker.wake_by_ref();
671 Ok(())
672 }));
673
674 ::std::task::Poll::Pending
675 } else {
676 ::std::task::Poll::Ready(self.GetResults())
677 }
678 }
679 }
680 }
681 }
682 }
683 pub fn interface_winrt_trait(
684 &self,
685 def: TypeDef,
686 generics: &[Type],
687 ident: &TokenStream,
688 constraints: &TokenStream,
689 _phantoms: &TokenStream,
690 features: &TokenStream,
691 ) -> TokenStream {
692 if self
693 .reader
694 .type_def_flags(def)
695 .contains(TypeAttributes::WINRT)
696 {
697 let type_signature = if self.reader.type_def_kind(def) == TypeKind::Class {
698 let type_signature =
699 Literal::byte_string(self.reader.type_def_signature(def, generics).as_bytes());
700 quote! { ::windows::imp::ConstBuffer::from_slice(#type_signature) }
701 } else {
702 let signature = Literal::byte_string(
703 format!("{{{:#?}}}", self.reader.type_def_guid(def).unwrap()).as_bytes(),
704 );
705
706 if generics.is_empty() {
707 quote! { ::windows::imp::ConstBuffer::from_slice(#signature) }
708 } else {
709 let generics = generics.iter().enumerate().map(|(index, g)| {
710 let g = self.type_name(g);
711 let semi = if index != generics.len() - 1 {
712 Some(quote! {
713 .push_slice(b";")
714 })
715 } else {
716 None
717 };
718
719 quote! {
720 .push_other(<#g as ::windows::core::RuntimeType>::SIGNATURE)
721 #semi
722 }
723 });
724
725 quote! {
726 {
727 ::windows::imp::ConstBuffer::new()
728 .push_slice(b"pinterface(")
729 .push_slice(#signature)
730 .push_slice(b";")
731 #(#generics)*
732 .push_slice(b")")
733 }
734 }
735 }
736 };
737
738 quote! {
739 #features
740 impl<#constraints> ::windows::core::RuntimeType for #ident {
741 const SIGNATURE: ::windows::imp::ConstBuffer = #type_signature;
742 }
743 }
744 } else {
745 quote! {}
746 }
747 }
748 pub fn runtime_name_trait(
749 &self,
750 def: TypeDef,
751 _generics: &[Type],
752 name: &TokenStream,
753 constraints: &TokenStream,
754 features: &TokenStream,
755 ) -> TokenStream {
756 if self
757 .reader
758 .type_def_flags(def)
759 .contains(TypeAttributes::WINRT)
760 {
761 // TODO: this needs to use a ConstBuffer-like facility to accomodate generics
762 let runtime_name = format!("{}", self.reader.type_def_type_name(def));
763
764 quote! {
765 #features
766 impl<#constraints> ::windows::core::RuntimeName for #name {
767 const NAME: &'static str = #runtime_name;
768 }
769 }
770 } else {
771 quote! {
772 #features
773 impl ::windows::core::RuntimeName for #name {}
774 }
775 }
776 }
777
778 pub fn interface_trait(
779 &self,
780 def: TypeDef,
781 generics: &[Type],
782 ident: &TokenStream,
783 constraints: &TokenStream,
784 features: &TokenStream,
785 has_unknown_base: bool,
786 ) -> TokenStream {
787 if let Some(default) = self.reader.type_def_default_interface(def) {
788 let default_name = self.type_name(&default);
789 let vtbl = self.type_vtbl_name(&default);
790 quote! {
791 #features
792 impl<#constraints> ::core::clone::Clone for #ident {
793 fn clone(&self) -> Self {
794 Self(self.0.clone())
795 }
796 }
797 #features
798 unsafe impl ::windows::core::Interface for #ident {
799 type Vtable = #vtbl;
800 }
801 #features
802 unsafe impl ::windows::core::ComInterface for #ident {
803 const IID: ::windows::core::GUID = <#default_name as ::windows::core::ComInterface>::IID;
804 }
805 }
806 } else {
807 let vtbl = self.type_def_vtbl_name(def, generics);
808 let guid = if generics.is_empty() {
809 match self.reader.type_def_guid(def) {
810 Some(guid) => self.guid(&guid),
811 None => {
812 quote! {
813 ::windows::core::GUID::zeroed()
814 }
815 }
816 }
817 } else {
818 quote! {
819 ::windows::core::GUID::from_signature(<Self as ::windows::core::RuntimeType>::SIGNATURE)
820 }
821 };
822
823 let phantoms = self.generic_phantoms(generics);
824
825 let mut tokens = quote! {
826 #features
827 unsafe impl<#constraints> ::windows::core::Interface for #ident {
828 type Vtable = #vtbl;
829 }
830 #features
831 impl<#constraints> ::core::clone::Clone for #ident {
832 fn clone(&self) -> Self {
833 Self(self.0.clone(), #phantoms)
834 }
835 }
836 };
837
838 if has_unknown_base {
839 tokens.combine(&quote! {
840 #features
841 unsafe impl<#constraints> ::windows::core::ComInterface for #ident {
842 const IID: ::windows::core::GUID = #guid;
843 }
844 });
845 }
846
847 tokens
848 }
849 }
850 pub fn interface_vtbl(
851 &self,
852 def: TypeDef,
853 generics: &[Type],
854 _ident: &TokenStream,
855 constraints: &TokenStream,
856 features: &TokenStream,
857 ) -> TokenStream {
858 let vtbl = self.type_def_vtbl_name(def, generics);
859 let mut methods = quote! {};
860 let mut method_names = MethodNames::new();
861 method_names.add_vtable_types(self, def);
862 let phantoms = self.generic_named_phantoms(generics);
863
864 match self.reader.type_def_vtables(def).last() {
865 Some(Type::IUnknown) => {
866 methods.combine(&quote! { pub base__: ::windows::core::IUnknown_Vtbl, })
867 }
868 Some(Type::IInspectable) => {
869 methods.combine(&quote! { pub base__: ::windows::core::IInspectable_Vtbl, })
870 }
871 Some(Type::TypeDef((def, _))) => {
872 let vtbl = self.type_def_vtbl_name(*def, &[]);
873 methods.combine(&quote! { pub base__: #vtbl, });
874 }
875 _ => {}
876 }
877
878 for method in self.reader.type_def_methods(def) {
879 if self.reader.method_def_name(method) == ".ctor" {
880 continue;
881 }
882 let name = method_names.add(self, method);
883 let signature = self.reader.method_def_signature(method, generics);
884 let mut cfg = self.reader.signature_cfg(&signature);
885 let signature = self.vtbl_signature(def, generics, &signature);
886 cfg.add_feature(self.reader.type_def_namespace(def));
887 let cfg_all = self.cfg_features(&cfg);
888 let cfg_not = self.cfg_not_features(&cfg);
889
890 let signature = quote! { pub #name: unsafe extern "system" fn #signature, };
891
892 if cfg_all.is_empty() {
893 methods.combine(&signature);
894 } else {
895 methods.combine(&quote! {
896 #cfg_all
897 #signature
898 #cfg_not
899 #name: usize,
900 });
901 }
902 }
903
904 quote! {
905 #features
906 #[repr(C)] #[doc(hidden)] pub struct #vtbl where #constraints {
907 #methods
908 #(pub #phantoms)*
909 }
910 }
911 }
912 pub fn vtbl_signature(
913 &self,
914 def: TypeDef,
915 _generics: &[Type],
916 signature: &Signature,
917 ) -> TokenStream {
918 let is_winrt = self
919 .reader
920 .type_def_flags(def)
921 .contains(TypeAttributes::WINRT);
922 let hresult = self.type_name(&Type::HRESULT);
923
924 let (trailing_return_type, return_type, udt_return_type) = if is_winrt {
925 if let Some(return_type) = &signature.return_type {
926 if let Type::WinrtArray(kind) = return_type {
927 let tokens = self.type_abi_name(kind);
928 (
929 quote! { result_size__: *mut u32, result__: *mut *mut #tokens },
930 quote! { -> #hresult },
931 quote! {},
932 )
933 } else {
934 let tokens = self.type_abi_name(return_type);
935 (
936 quote! { result__: *mut #tokens },
937 quote! { -> #hresult },
938 quote! {},
939 )
940 }
941 } else {
942 (quote! {}, quote! { -> #hresult }, quote! {})
943 }
944 } else if let Some(return_type) = &signature.return_type {
945 if self.reader.type_is_struct(return_type) {
946 let tokens = self.type_abi_name(return_type);
947 (quote! {}, quote! {}, quote! { result__: *mut #tokens, })
948 } else {
949 let tokens = self.type_default_name(return_type);
950 (quote! {}, quote! { -> #tokens }, quote! {})
951 }
952 } else {
953 (quote! {}, quote! {}, quote! {})
954 };
955
956 let params = signature.params.iter().map(|p| {
957 let name = self.param_name(p.def);
958 if is_winrt {
959 let abi = self.type_abi_name(&p.ty);
960 let abi_size_name: TokenStream =
961 format!("{}_array_size", self.reader.param_name(p.def)).into();
962
963 if self
964 .reader
965 .param_flags(p.def)
966 .contains(ParamAttributes::INPUT)
967 {
968 if p.ty.is_winrt_array() {
969 quote! { #abi_size_name: u32, #name: *const #abi, }
970 } else if p.ty.is_winrt_const_ref() {
971 quote! { #name: &#abi, }
972 } else {
973 quote! { #name: #abi, }
974 }
975 } else if p.ty.is_winrt_array() {
976 quote! { #abi_size_name: u32, #name: *mut #abi, }
977 } else if p.ty.is_winrt_array_ref() {
978 quote! { #abi_size_name: *mut u32, #name: *mut *mut #abi, }
979 } else {
980 quote! { #name: *mut #abi, }
981 }
982 } else {
983 match p.kind {
984 SignatureParamKind::ValueType => {
985 let abi = self.type_default_name(&p.ty);
986 quote! { #name: #abi, }
987 }
988 _ => {
989 let abi = self.type_abi_name(&p.ty);
990 quote! { #name: #abi, }
991 }
992 }
993 }
994 });
995
996 quote! { (this: *mut ::core::ffi::c_void, #udt_return_type #(#params)* #trailing_return_type) #return_type }
997 }
998 pub fn param_name(&self, param: Param) -> TokenStream {
999 // In Rust, function parameters cannot be named the same as structs. This avoids some collisions that occur in the win32 metadata.
1000 // See Icmp6SendEcho2 for an example.
1001 to_ident(&self.reader.param_name(param).to_lowercase())
1002 }
1003 pub fn return_sig(&self, signature: &Signature) -> TokenStream {
1004 if let Some(return_type) = &signature.return_type {
1005 let tokens = self.type_default_name(return_type);
1006 format!(" -> {}", tokens.as_str()).into()
1007 } else if self.reader.method_def_does_not_return(signature.def) {
1008 " -> !".into()
1009 } else {
1010 " -> ()".into()
1011 }
1012 }
1013 pub fn win32_args(&self, params: &[SignatureParam], kind: SignatureKind) -> TokenStream {
1014 let mut tokens = quote! {};
1015
1016 for (position, param) in params.iter().enumerate() {
1017 let new = match kind {
1018 SignatureKind::Query(query) if query.object == position => {
1019 quote! { &mut result__, }
1020 }
1021 SignatureKind::ReturnValue | SignatureKind::ResultValue
1022 if params.len() - 1 == position =>
1023 {
1024 quote! { &mut result__, }
1025 }
1026 SignatureKind::QueryOptional(query) if query.object == position => {
1027 quote! { result__ as *mut _ as *mut _, }
1028 }
1029 SignatureKind::Query(query) | SignatureKind::QueryOptional(query)
1030 if query.guid == position =>
1031 {
1032 quote! { &<T as ::windows::core::ComInterface>::IID, }
1033 }
1034 _ => {
1035 let name = self.param_name(param.def);
1036 let flags = self.reader.param_flags(param.def);
1037 match param.kind {
1038 SignatureParamKind::ArrayFixed(_)
1039 | SignatureParamKind::ArrayRelativeLen(_)
1040 | SignatureParamKind::ArrayRelativeByteLen(_) => {
1041 let map = if flags.contains(ParamAttributes::OPTIONAL) {
1042 quote! { #name.as_deref().map_or(::core::ptr::null(), |slice|slice.as_ptr()) }
1043 } else {
1044 quote! { #name.as_ptr() }
1045 };
1046 quote! { ::core::mem::transmute(#map), }
1047 }
1048 SignatureParamKind::ArrayRelativePtr(relative) => {
1049 let name = self.param_name(params[relative].def);
1050 let flags = self.reader.param_flags(params[relative].def);
1051 if flags.contains(ParamAttributes::OPTIONAL) {
1052 quote! { #name.as_deref().map_or(0, |slice|slice.len() as _), }
1053 } else {
1054 quote! { #name.len() as _, }
1055 }
1056 }
1057 SignatureParamKind::TryInto => {
1058 quote! { #name.try_into_param()?.abi(), }
1059 }
1060 SignatureParamKind::IntoParam => {
1061 quote! { #name.into_param().abi(), }
1062 }
1063 SignatureParamKind::OptionalPointer => {
1064 if flags.contains(ParamAttributes::OUTPUT) {
1065 quote! { ::core::mem::transmute(#name.unwrap_or(::std::ptr::null_mut())), }
1066 } else {
1067 quote! { ::core::mem::transmute(#name.unwrap_or(::std::ptr::null())), }
1068 }
1069 }
1070 SignatureParamKind::ValueType => {
1071 quote! { #name, }
1072 }
1073 SignatureParamKind::Blittable => {
1074 quote! { ::core::mem::transmute(#name), }
1075 }
1076 SignatureParamKind::Other => {
1077 quote! { ::core::mem::transmute_copy(#name), }
1078 }
1079 }
1080 }
1081 };
1082 tokens.combine(&new)
1083 }
1084
1085 tokens
1086 }
1087 pub fn win32_params(&self, params: &[SignatureParam], kind: SignatureKind) -> TokenStream {
1088 let mut tokens = quote! {};
1089
1090 let mut generic_params = self.generic_params(params);
1091 for (position, param) in params.iter().enumerate() {
1092 match kind {
1093 SignatureKind::Query(query) | SignatureKind::QueryOptional(query) => {
1094 if query.object == position || query.guid == position {
1095 continue;
1096 }
1097 }
1098 SignatureKind::ReturnValue | SignatureKind::ResultValue
1099 if params.len() - 1 == position =>
1100 {
1101 continue;
1102 }
1103 _ => {}
1104 }
1105
1106 let name = self.param_name(param.def);
1107
1108 match param.kind {
1109 SignatureParamKind::ArrayFixed(fixed) => {
1110 let ty = param.ty.deref();
1111 let ty = self.type_default_name(&ty);
1112 let len = Literal::u32_unsuffixed(fixed as _);
1113 let ty = if self
1114 .reader
1115 .param_flags(param.def)
1116 .contains(ParamAttributes::OUTPUT)
1117 {
1118 quote! { &mut [#ty; #len] }
1119 } else {
1120 quote! { &[#ty; #len] }
1121 };
1122 if self
1123 .reader
1124 .param_flags(param.def)
1125 .contains(ParamAttributes::OPTIONAL)
1126 {
1127 tokens.combine(&quote! { #name: ::core::option::Option<#ty>, });
1128 } else {
1129 tokens.combine(&quote! { #name: #ty, });
1130 }
1131 }
1132 SignatureParamKind::ArrayRelativeLen(_) => {
1133 let ty = param.ty.deref();
1134 let ty = self.type_default_name(&ty);
1135 let ty = if self
1136 .reader
1137 .param_flags(param.def)
1138 .contains(ParamAttributes::OUTPUT)
1139 {
1140 quote! { &mut [#ty] }
1141 } else {
1142 quote! { &[#ty] }
1143 };
1144 if self
1145 .reader
1146 .param_flags(param.def)
1147 .contains(ParamAttributes::OPTIONAL)
1148 {
1149 tokens.combine(&quote! { #name: ::core::option::Option<#ty>, });
1150 } else {
1151 tokens.combine(&quote! { #name: #ty, });
1152 }
1153 }
1154 SignatureParamKind::ArrayRelativeByteLen(_) => {
1155 let ty = if self
1156 .reader
1157 .param_flags(param.def)
1158 .contains(ParamAttributes::OUTPUT)
1159 {
1160 quote! { &mut [u8] }
1161 } else {
1162 quote! { &[u8] }
1163 };
1164 if self
1165 .reader
1166 .param_flags(param.def)
1167 .contains(ParamAttributes::OPTIONAL)
1168 {
1169 tokens.combine(&quote! { #name: ::core::option::Option<#ty>, });
1170 } else {
1171 tokens.combine(&quote! { #name: #ty, });
1172 }
1173 }
1174 SignatureParamKind::ArrayRelativePtr(_) => {}
1175 SignatureParamKind::TryInto | SignatureParamKind::IntoParam => {
1176 let (position, _) = generic_params.next().unwrap();
1177 let kind: TokenStream = format!("P{position}").into();
1178 tokens.combine(&quote! { #name: #kind, });
1179 }
1180 SignatureParamKind::OptionalPointer => {
1181 let kind = self.type_default_name(&param.ty);
1182 tokens.combine(&quote! { #name: ::core::option::Option<#kind>, });
1183 }
1184 SignatureParamKind::ValueType | SignatureParamKind::Blittable => {
1185 let kind = self.type_default_name(&param.ty);
1186 tokens.combine(&quote! { #name: #kind, });
1187 }
1188 SignatureParamKind::Other => {
1189 let kind = self.type_default_name(&param.ty);
1190 tokens.combine(&quote! { #name: &#kind, });
1191 }
1192 }
1193 }
1194
1195 tokens
1196 }
1197
1198 pub fn impl_signature(&self, def: TypeDef, signature: &Signature) -> TokenStream {
1199 if self
1200 .reader
1201 .type_def_flags(def)
1202 .contains(TypeAttributes::WINRT)
1203 {
1204 let is_delegate = self.reader.type_def_kind(def) == TypeKind::Delegate;
1205 let params = signature
1206 .params
1207 .iter()
1208 .map(|p| self.winrt_produce_type(p, !is_delegate));
1209
1210 let return_type = if let Some(return_type) = &signature.return_type {
1211 let tokens = self.type_name(return_type);
1212
1213 if return_type.is_winrt_array() {
1214 quote! { ::windows::core::Array<#tokens> }
1215 } else {
1216 tokens
1217 }
1218 } else {
1219 quote! { () }
1220 };
1221
1222 let this = if is_delegate {
1223 quote! {}
1224 } else {
1225 quote! { &self, }
1226 };
1227
1228 quote! { (#this #(#params),*) -> ::windows::core::Result<#return_type> }
1229 } else {
1230 let signature_kind = self.reader.signature_kind(signature);
1231 let mut params = quote! {};
1232
1233 if signature_kind == SignatureKind::ResultValue {
1234 for param in &signature.params[..signature.params.len() - 1] {
1235 params.combine(&self.win32_produce_type(param));
1236 }
1237 } else {
1238 for param in &signature.params {
1239 params.combine(&self.win32_produce_type(param));
1240 }
1241 }
1242
1243 let return_type = match signature_kind {
1244 SignatureKind::ReturnVoid => quote! {},
1245 SignatureKind::Query(_)
1246 | SignatureKind::QueryOptional(_)
1247 | SignatureKind::ResultVoid => quote! { -> ::windows::core::Result<()> },
1248 SignatureKind::ResultValue => {
1249 let return_type = signature.params[signature.params.len() - 1].ty.deref();
1250 let return_type = self.type_name(&return_type);
1251
1252 quote! { -> ::windows::core::Result<#return_type> }
1253 }
1254 _ => self.return_sig(signature),
1255 };
1256
1257 quote! { (&self, #params) #return_type }
1258 }
1259 }
1260 fn winrt_produce_type(&self, param: &SignatureParam, include_param_names: bool) -> TokenStream {
1261 let default_type = self.type_default_name(&param.ty);
1262
1263 let sig = if self
1264 .reader
1265 .param_flags(param.def)
1266 .contains(ParamAttributes::INPUT)
1267 {
1268 if param.ty.is_winrt_array() {
1269 quote! { &[#default_type] }
1270 } else if self.reader.type_is_primitive(&param.ty) {
1271 quote! { #default_type }
1272 } else if self.reader.type_is_nullable(&param.ty) {
1273 let type_name = self.type_name(&param.ty);
1274 quote! { ::core::option::Option<&#type_name> }
1275 } else {
1276 quote! { &#default_type }
1277 }
1278 } else if param.ty.is_winrt_array() {
1279 quote! { &mut [#default_type] }
1280 } else if param.ty.is_winrt_array_ref() {
1281 let kind = self.type_name(&param.ty);
1282 quote! { &mut ::windows::core::Array<#kind> }
1283 } else {
1284 quote! { &mut #default_type }
1285 };
1286
1287 if include_param_names {
1288 let name = self.param_name(param.def);
1289 quote! { #name: #sig }
1290 } else {
1291 sig
1292 }
1293 }
1294 fn win32_produce_type(&self, param: &SignatureParam) -> TokenStream {
1295 let name = self.param_name(param.def);
1296 let kind = self.type_default_name(&param.ty);
1297
1298 if self
1299 .reader
1300 .param_flags(param.def)
1301 .contains(ParamAttributes::INPUT)
1302 {
1303 if self.reader.type_is_primitive(&param.ty) {
1304 quote! { #name: #kind, }
1305 } else if self.reader.type_is_nullable(&param.ty) {
1306 let kind = self.type_name(&param.ty);
1307 quote! { #name: ::core::option::Option<&#kind>, }
1308 } else {
1309 quote! { #name: &#kind, }
1310 }
1311 } else {
1312 quote! { #name: #kind, }
1313 }
1314 }
1315 }
1316
1317 pub fn to_ident(name: &str) -> TokenStream {
1318 // keywords list based on https://doc.rust-lang.org/reference/keywords.html
1319 match name {
1320 "abstract" | "as" | "become" | "box" | "break" | "const" | "continue" | "crate" | "do"
1321 | "else" | "enum" | "extern" | "false" | "final" | "fn" | "for" | "if" | "impl" | "in"
1322 | "let" | "loop" | "macro" | "match" | "mod" | "move" | "mut" | "override" | "priv"
1323 | "pub" | "ref" | "return" | "static" | "struct" | "super" | "trait" | "true" | "type"
1324 | "typeof" | "unsafe" | "unsized" | "use" | "virtual" | "where" | "while" | "yield"
1325 | "try" | "async" | "await" | "dyn" => format!("r#{name}").into(),
1326 "Self" | "self" => format!("{name}_").into(),
1327 "_" => "unused".into(),
1328 _ => trim_tick(name).into(),
1329 }
1330 }
1331
1332 fn mut_ptrs(pointers: usize) -> TokenStream {
1333 "*mut ".repeat(pointers).into()
1334 }
1335
1336 fn const_ptrs(pointers: usize) -> TokenStream {
1337 "*const ".repeat(pointers).into()
1338 }
1339
1340 fn to_feature(name: &str) -> String {
1341 let mut feature = String::new();
1342
1343 for name in name.split('.').skip(1) {
1344 feature.push_str(name);
1345 feature.push('_');
1346 }
1347
1348 if feature.is_empty() {
1349 feature = name.to_string();
1350 } else {
1351 feature.truncate(feature.len() - 1);
1352 }
1353
1354 feature
1355 }
1356
1357 fn starts_with(namespace: &str, feature: &str) -> bool {
1358 if namespace == feature {
1359 return true;
1360 }
1361
1362 if namespace.len() > feature.len() && namespace.as_bytes().get(feature.len()) == Some(&b'.') {
1363 return namespace.starts_with(feature);
1364 }
1365
1366 false
1367 }
1368
1369 fn gen_mut_ptrs(pointers: usize) -> TokenStream {
1370 "*mut ".repeat(pointers).into()
1371 }
1372
1373 fn gen_const_ptrs(pointers: usize) -> TokenStream {
1374 "*const ".repeat(pointers).into()
1375 }
1376
1377 #[cfg(test)]
1378 mod tests {
1379 use super::*;
1380
1381 #[test]
1382 fn test_starts_with() {
1383 assert!(starts_with(
1384 "Windows.Win32.Graphics.Direct3D11on12",
1385 "Windows.Win32.Graphics.Direct3D11on12"
1386 ));
1387 assert!(starts_with(
1388 "Windows.Win32.Graphics.Direct3D11on12",
1389 "Windows.Win32.Graphics"
1390 ));
1391 assert!(!starts_with(
1392 "Windows.Win32.Graphics.Direct3D11on12",
1393 "Windows.Win32.Graphics.Direct3D11"
1394 ));
1395 assert!(!starts_with(
1396 "Windows.Win32.Graphics.Direct3D",
1397 "Windows.Win32.Graphics.Direct3D11"
1398 ));
1399 }
1400 }