1use super::*;
2
3mod class;
4mod cpp_const;
5mod cpp_delegate;
6mod cpp_enum;
7mod cpp_fn;
8mod cpp_interface;
9mod cpp_method;
10mod cpp_struct;
11mod delegate;
12mod r#enum;
13mod interface;
14mod method;
15mod r#struct;
16
17pub use class::*;
18pub use cpp_const::*;
19pub use cpp_delegate::*;
20pub use cpp_enum::*;
21pub use cpp_fn::*;
22pub use cpp_interface::*;
23pub use cpp_method::*;
24pub use cpp_struct::*;
25pub use delegate::*;
26pub use interface::*;
27pub use method::*;
28pub use r#enum::*;
29pub use r#struct::*;
30
31#[derive(Clone, Debug, PartialEq, Eq, Hash)]
32pub enum Type {
33 CppFn(CppFn),
34 Class(Class),
35 Interface(Interface),
36 CppInterface(CppInterface),
37 Delegate(Delegate),
38 CppDelegate(CppDelegate),
39 Enum(Enum),
40 CppEnum(CppEnum),
41 Struct(Struct),
42 CppStruct(CppStruct),
43 CppConst(CppConst),
44
45 Generic(GenericParam),
46 PtrMut(Box<Self>, usize),
47 PtrConst(Box<Self>, usize),
48 ArrayFixed(Box<Self>, usize),
49 Array(Box<Self>),
50 ArrayRef(Box<Self>),
51 ConstRef(Box<Self>),
52 PrimitiveOrEnum(Box<Self>, Box<Self>),
53
54 Void,
55 Bool,
56 Char,
57 I8,
58 U8,
59 I16,
60 U16,
61 I32,
62 U32,
63 I64,
64 U64,
65 F32,
66 F64,
67 ISize,
68 USize,
69 String,
70 Object,
71 Type,
72
73 PSTR,
74 PCSTR,
75 PWSTR,
76 PCWSTR,
77 GUID,
78 HRESULT,
79 IUnknown,
80 BSTR,
81 BOOL,
82}
83
84impl Ord for Type {
85 fn cmp(&self, other: &Self) -> Ordering {
86 self.sort_key().cmp(&(other.sort_key()))
87 }
88}
89
90impl PartialOrd for Type {
91 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
92 Some(self.cmp(other))
93 }
94}
95
96#[derive(PartialEq)]
97pub enum Remap {
98 Type(Type),
99 Name(TypeName),
100 None,
101}
102
103impl Type {
104 fn sort_key(&self) -> (bool, TypeName, i32, i32) {
105 let kind = match self {
113 Self::CppFn(..) => 0,
114 Self::Class(..) => 1,
115 Self::Interface(..) => 2,
116 Self::CppInterface(..) => 3,
117 Self::Delegate(..) => 4,
118 Self::CppDelegate(..) => 5,
119 Self::Enum(..) => 6,
120 Self::CppEnum(..) => 7,
121 Self::Struct(..) => 8,
122 Self::CppStruct(..) => 9,
123 Self::CppConst(..) => 10,
124 _ => -1,
125 };
126
127 let arches = match self {
128 Self::CppFn(ty) => ty.method.arches(),
129 Self::CppStruct(ty) => ty.def.arches(),
130 Self::CppDelegate(ty) => ty.def.arches(),
131 _ => 0,
132 };
133
134 (kind != 0, self.type_name(), arches, kind)
135 }
136
137 fn is_intrinsic(&self) -> bool {
138 matches!(
139 self,
140 Self::Generic(..)
141 | Self::Void
142 | Self::Bool
143 | Self::Char
144 | Self::I8
145 | Self::U8
146 | Self::I16
147 | Self::U16
148 | Self::I32
149 | Self::U32
150 | Self::I64
151 | Self::U64
152 | Self::F32
153 | Self::F64
154 | Self::ISize
155 | Self::USize
156 )
157 }
158
159 pub fn remap(type_name: TypeName) -> Remap {
160 match type_name {
161 TypeName("System", "Guid") => Remap::Type(Self::GUID),
162 TypeName("Windows.Win32.Foundation", "PSTR") => Remap::Type(Self::PSTR),
163 TypeName("Windows.Win32.Foundation", "PWSTR") => Remap::Type(Self::PWSTR),
164 TypeName("Windows.Win32.System.WinRT", "HSTRING") => Remap::Type(Self::String),
165 TypeName("Windows.Win32.Foundation", "BSTR") => Remap::Type(Self::BSTR),
166 TypeName("Windows.Win32.System.WinRT", "IInspectable") => Remap::Type(Self::Object),
167 TypeName("Windows.Win32.Foundation", "CHAR") => Remap::Type(Self::I8),
168 TypeName("Windows.Win32.Foundation", "BOOLEAN") => Remap::Type(Self::Bool),
169 TypeName("Windows.Win32.Foundation", "BOOL") => Remap::Type(Self::BOOL),
170 TypeName("Windows.Win32.System.Com", "IUnknown") => Remap::Type(Self::IUnknown),
171 TypeName("System", "Type") => Remap::Type(Self::Type),
172
173 TypeName("Windows.Foundation", "HResult")
174 | TypeName("Windows.Win32.Foundation", "HRESULT") => Remap::Type(Self::HRESULT),
175
176 TypeName("Windows.Foundation", "EventRegistrationToken")
177 | TypeName("Windows.Win32.System.WinRT", "EventRegistrationToken") => {
178 Remap::Type(Self::I64)
179 }
180
181 TypeName("Windows.Win32.Graphics.Direct2D.Common", "D2D_MATRIX_3X2_F") => {
182 Remap::Name(TypeName("Windows.Foundation.Numerics", "Matrix3x2"))
183 }
184
185 TypeName("Windows.Win32.Graphics.Direct3D", "D3DMATRIX")
186 | TypeName("Windows.Win32.Graphics.Direct2D.Common", "D2D_MATRIX_4X4_F") => {
187 Remap::Name(TypeName("Windows.Foundation.Numerics", "Matrix4x4"))
188 }
189
190 TypeName("Windows.Win32.Graphics.Direct2D.Common", "D2D_POINT_2F")
191 | TypeName("Windows.Win32.Graphics.Direct2D.Common", "D2D_VECTOR_2F") => {
192 Remap::Name(TypeName("Windows.Foundation.Numerics", "Vector2"))
193 }
194
195 TypeName("Windows.Win32.Graphics.Direct2D.Common", "D2D_VECTOR_4F") => {
196 Remap::Name(TypeName("Windows.Foundation.Numerics", "Vector4"))
197 }
198
199 _ => Remap::None,
200 }
201 }
202
203 pub fn from_element_type(code: usize) -> Option<Self> {
204 match code as u8 {
205 ELEMENT_TYPE_VOID => Some(Self::Void),
206 ELEMENT_TYPE_BOOLEAN => Some(Self::Bool),
207 ELEMENT_TYPE_CHAR => Some(Self::Char),
208 ELEMENT_TYPE_I1 => Some(Self::I8),
209 ELEMENT_TYPE_U1 => Some(Self::U8),
210 ELEMENT_TYPE_I2 => Some(Self::I16),
211 ELEMENT_TYPE_U2 => Some(Self::U16),
212 ELEMENT_TYPE_I4 => Some(Self::I32),
213 ELEMENT_TYPE_U4 => Some(Self::U32),
214 ELEMENT_TYPE_I8 => Some(Self::I64),
215 ELEMENT_TYPE_U8 => Some(Self::U64),
216 ELEMENT_TYPE_R4 => Some(Self::F32),
217 ELEMENT_TYPE_R8 => Some(Self::F64),
218 ELEMENT_TYPE_I => Some(Self::ISize),
219 ELEMENT_TYPE_U => Some(Self::USize),
220 ELEMENT_TYPE_STRING => Some(Self::String),
221 ELEMENT_TYPE_OBJECT => Some(Self::Object),
222 _ => None,
223 }
224 }
225
226 #[track_caller]
227 pub fn from_ref(code: TypeDefOrRef, enclosing: Option<&CppStruct>, generics: &[Self]) -> Self {
228 if let TypeDefOrRef::TypeSpec(def) = code {
229 let mut blob = def.blob(0);
230 return Self::from_blob_impl(&mut blob, None, generics);
231 }
232
233 let mut code_name = code.type_name();
234
235 match Self::remap(code_name) {
236 Remap::Type(ty) => return ty,
237 Remap::Name(type_name) => {
238 code_name = type_name;
239 }
240 Remap::None => {}
241 }
242
243 if let Some(outer) = enclosing {
244 if code_name.namespace().is_empty() {
245 return Self::CppStruct(outer.nested[code_name.name()].clone());
246 }
247 }
248
249 code.reader()
250 .unwrap_full_name(code_name.namespace(), code_name.name())
251 }
252
253 #[track_caller]
254 pub fn from_blob(blob: &mut Blob, enclosing: Option<&CppStruct>, generics: &[Self]) -> Self {
255 let is_const = blob.read_modifiers().iter().any(|def| {
257 let type_name = def.type_name();
258 type_name == TypeName::IsConst
259 });
260
261 let is_ref = blob.try_read(ELEMENT_TYPE_BYREF as usize);
264
265 if blob.try_read(ELEMENT_TYPE_VOID as usize) {
266 return Self::Void;
267 }
268
269 let is_array = blob.try_read(ELEMENT_TYPE_SZARRAY as usize); let mut pointers = 0;
272
273 while blob.try_read(ELEMENT_TYPE_PTR as usize) {
274 pointers += 1;
275 }
276
277 let kind = Self::from_blob_impl(blob, enclosing, generics);
278
279 if pointers > 0 {
280 Self::PtrMut(Box::new(kind), pointers)
281 } else if is_const {
282 Self::ConstRef(Box::new(kind))
283 } else if is_array {
284 if is_ref {
285 Self::ArrayRef(Box::new(kind))
286 } else {
287 Self::Array(Box::new(kind))
288 }
289 } else {
290 kind
291 }
292 }
293
294 #[track_caller]
295 fn from_blob_impl(blob: &mut Blob, enclosing: Option<&CppStruct>, generics: &[Self]) -> Self {
296 let code = blob.read_u8();
297
298 if let Some(code) = Self::from_element_type(code as usize) {
299 return code;
300 }
301
302 match code {
303 ELEMENT_TYPE_VALUETYPE | ELEMENT_TYPE_CLASS => {
304 Self::from_ref(blob.decode(), enclosing, generics)
305 }
306 ELEMENT_TYPE_VAR => generics
307 .get(blob.read_usize())
308 .unwrap_or(&Self::Void)
309 .clone(),
310 ELEMENT_TYPE_ARRAY => {
311 let kind = Self::from_blob(blob, enclosing, generics);
312 let _rank = blob.read_usize();
313 let _count = blob.read_usize();
314 let bounds = blob.read_usize();
315 Self::ArrayFixed(Box::new(kind), bounds)
316 }
317 ELEMENT_TYPE_GENERICINST => {
318 let type_code = blob.read_u8();
319
320 debug_assert!(matches!(
321 type_code,
322 ELEMENT_TYPE_VALUETYPE | ELEMENT_TYPE_CLASS
323 ));
324
325 let code = blob.decode::<TypeDefOrRef>();
326 let code_name = code.type_name();
327
328 let mut ty = blob
329 .reader()
330 .unwrap_full_name(code_name.namespace(), code_name.name());
331
332 let mut item_generics = vec![];
333
334 for _ in 0..blob.read_usize() {
335 item_generics.push(Self::from_blob_impl(blob, enclosing, generics));
336 }
337
338 ty.set_generics(item_generics);
339 ty
340 }
341 rest => panic!("{rest:?}"),
342 }
343 }
344
345 pub fn to_const_type(&self) -> Self {
346 match self {
347 Self::PtrMut(ty, pointers) => Self::PtrMut(Box::new(ty.to_const_type()), *pointers),
348 Self::PtrConst(ty, pointers) => Self::PtrConst(Box::new(ty.to_const_type()), *pointers),
349 Self::PSTR => Self::PCSTR,
350 Self::PWSTR => Self::PCWSTR,
351 _ => self.clone(),
352 }
353 }
354
355 pub fn to_const_ptr(&self) -> Self {
356 match self {
357 Self::PtrMut(ty, pointers) => Self::PtrConst(ty.clone(), *pointers),
358 _ => self.clone(),
359 }
360 }
361
362 pub fn deref(&self) -> Self {
363 match self {
364 Self::PtrConst(ty, 1) | Self::PtrMut(ty, 1) => {
365 if **ty == Self::Void {
366 Self::U8
367 } else {
368 *ty.clone()
369 }
370 }
371 Self::PtrConst(ty, pointers) => Self::PtrConst(ty.clone(), pointers - 1),
372 Self::PtrMut(ty, pointers) => Self::PtrMut(ty.clone(), pointers - 1),
373 Self::PSTR | Self::PCSTR => Self::U8,
374 Self::PWSTR | Self::PCWSTR => Self::U16,
375 _ => self.clone(),
376 }
377 }
378
379 pub fn has_cpp_delegate(&self) -> bool {
380 match self {
381 Self::CppDelegate(..) => true,
382 Self::CppStruct(ty) => ty.has_cpp_delegate(),
383 _ => false,
384 }
385 }
386
387 pub fn is_interface(&self) -> bool {
388 matches!(
389 self,
390 Self::Class(_)
391 | Self::Interface(_)
392 | Self::Delegate(_)
393 | Self::CppInterface(_)
394 | Self::IUnknown
395 | Self::Object
396 )
397 }
398
399 pub fn write_name(&self, config: &Config) -> TokenStream {
400 if config.sys && self.is_interface() {
401 return quote! { *mut core::ffi::c_void };
402 }
403
404 match self {
405 Self::Void => quote! { core::ffi::c_void },
406 Self::Bool => quote! { bool },
407 Self::Char => quote! { u16 },
408 Self::I8 => quote! { i8 },
409 Self::U8 => quote! { u8 },
410 Self::I16 => quote! { i16 },
411 Self::U16 => quote! { u16 },
412 Self::I32 => quote! { i32 },
413 Self::U32 => quote! { u32 },
414 Self::I64 => quote! { i64 },
415 Self::U64 => quote! { u64 },
416 Self::F32 => quote! { f32 },
417 Self::F64 => quote! { f64 },
418 Self::ISize => quote! { isize },
419 Self::USize => quote! { usize },
420 Self::BSTR => {
421 let name = config.write_strings();
422 quote! { #name BSTR }
423 }
424 Self::IUnknown => {
425 let name = config.write_core();
426 quote! { #name IUnknown }
427 }
428 Self::GUID => {
429 let name = config.write_core();
430 quote! { #name GUID }
431 }
432 Self::HRESULT => {
433 let result = config.write_result();
434 quote! { #result HRESULT }
435 }
436 Self::BOOL => {
437 let result = config.write_result();
438 quote! { #result BOOL }
439 }
440 Self::String => {
441 let name = config.write_strings();
442 quote! { #name HSTRING }
443 }
444 Self::Object => {
445 let name = config.write_core();
446 quote! { #name IInspectable }
447 }
448 Self::PSTR => {
449 let name = config.write_strings();
450 quote! { #name PSTR }
451 }
452 Self::PCSTR => {
453 let name = config.write_strings();
454 quote! { #name PCSTR }
455 }
456 Self::PWSTR => {
457 let name = config.write_strings();
458 quote! { #name PWSTR }
459 }
460 Self::PCWSTR => {
461 let name = config.write_strings();
462 quote! { #name PCWSTR }
463 }
464 Self::CppInterface(ty) => ty.write_name(config),
465 Self::Struct(ty) => ty.write_name(config),
466 Self::Enum(ty) => ty.write_name(config),
467 Self::Interface(ty) => ty.write_name(config),
468 Self::CppStruct(ty) => ty.write_name(config),
469 Self::CppEnum(ty) => ty.write_name(config),
470 Self::CppFn(ty) => ty.write_name(config),
471 Self::CppConst(ty) => ty.write_name(config),
472 Self::CppDelegate(ty) => ty.write_name(config),
473 Self::Delegate(ty) => ty.write_name(config),
474 Self::Class(ty) => ty.write_name(config),
475 Self::Generic(param) => to_ident(param.name()),
476 Self::PtrMut(ty, pointers) => {
477 let pointers = write_ptr_mut(*pointers);
478 let ty = ty.write_default(config);
479 quote! { #pointers #ty }
480 }
481 Self::PtrConst(ty, pointers) => {
482 let pointers = write_ptr_const(*pointers);
483 let ty = ty.write_default(config);
484 quote! { #pointers #ty }
485 }
486 Self::ArrayFixed(ty, len) => {
487 let name = ty.write_default(config);
488 let len = Literal::usize_unsuffixed(*len);
489 quote! { [#name; #len] }
490 }
491 Self::Array(ty) => ty.write_name(config),
492 Self::ArrayRef(ty) => ty.write_name(config),
493 Self::ConstRef(ty) => ty.write_name(config),
494 Self::PrimitiveOrEnum(primitive, ty) => {
495 if config.sys {
496 primitive.write_name(config)
497 } else {
498 ty.write_name(config)
499 }
500 }
501 rest => panic!("{rest:?}"),
502 }
503 }
504
505 pub fn write_default(&self, config: &Config) -> TokenStream {
506 if config.sys {
507 return self.write_name(config);
508 }
509
510 if let Self::Array(ty) = self {
511 ty.write_default(config)
512 } else {
513 let tokens = self.write_name(config);
514
515 if matches!(self, Self::Generic(_)) {
516 quote! { <#tokens as windows_core::Type<#tokens>>::Default }
517 } else if self.is_interface() {
518 quote! { Option<#tokens> }
519 } else {
520 tokens
521 }
522 }
523 }
524
525 pub fn write_impl_name(&self, config: &Config) -> TokenStream {
526 match self {
527 Self::IUnknown | Self::Object => {
528 let name = config.write_core();
529 quote! { #name IUnknownImpl }
530 }
531 Self::CppInterface(ty) => ty.write_impl_name(config),
532 Self::Interface(ty) => ty.write_impl_name(config),
533 rest => panic!("{rest:?}"),
534 }
535 }
536
537 pub fn write_abi(&self, config: &Config) -> TokenStream {
538 if config.sys {
539 return self.write_name(config);
540 }
541
542 match self {
543 Self::IUnknown
544 | Self::Object
545 | Self::Delegate(_)
546 | Self::Class(_)
547 | Self::CppInterface(_)
548 | Self::Interface(_)
549 | Self::String
550 | Self::BSTR => quote! { *mut core::ffi::c_void },
551 Self::ArrayFixed(ty, len) => {
552 let name = ty.write_abi(config);
553 let len = Literal::usize_unsuffixed(*len);
554 quote! { [#name; #len] }
555 }
556 Self::Generic(name) => {
557 let name = to_ident(name.name());
558 quote! { windows_core::AbiType<#name> }
559 }
560 Self::Struct(ty) => {
561 let name = self.write_name(config);
562 if ty.is_copyable() {
563 name
564 } else {
565 quote! { core::mem::MaybeUninit<#name> }
566 }
567 }
568 Self::PtrMut(ty, pointers) => {
569 let ty = ty.write_abi(config);
570 let pointers = write_ptr_mut(*pointers);
571 quote! { #pointers #ty }
572 }
573 Self::PtrConst(ty, pointers) => {
574 let ty = ty.write_abi(config);
575 let pointers = write_ptr_const(*pointers);
576 quote! { #pointers #ty }
577 }
578 Self::PrimitiveOrEnum(ty, _) => ty.write_name(config),
579 ty => ty.write_name(config),
580 }
581 }
582
583 pub fn runtime_signature(&self) -> String {
584 match self {
585 Self::Bool => "b1".to_string(),
586 Self::Char => "c2".to_string(),
587 Self::I8 => "i1".to_string(),
588 Self::U8 => "u1".to_string(),
589 Self::I16 => "i2".to_string(),
590 Self::U16 => "u2".to_string(),
591 Self::I32 => "i4".to_string(),
592 Self::U32 => "u4".to_string(),
593 Self::I64 => "i8".to_string(),
594 Self::U64 => "u8".to_string(),
595 Self::F32 => "f4".to_string(),
596 Self::F64 => "f8".to_string(),
597 Self::ISize => "is".to_string(),
598 Self::USize => "us".to_string(),
599 Self::String => "string".to_string(),
600 Self::Object => "cinterface(IInspectable)".to_string(),
601 Self::GUID => "g16".to_string(),
602 Self::HRESULT => "struct(Windows.Foundation.HResult;i4)".to_string(),
603 Self::Class(ty) => ty.runtime_signature(),
604 Self::Delegate(ty) => ty.runtime_signature(),
605 Self::Enum(ty) => ty.runtime_signature(),
606 Self::Interface(ty) => ty.runtime_signature(),
607 Self::Struct(ty) => ty.runtime_signature(),
608 rest => panic!("{rest:?}"),
609 }
610 }
611
612 pub fn split_generic(&self) -> (Self, Vec<Self>) {
613 match self {
614 Self::Interface(ty) if !ty.generics.is_empty() => {
615 let base = ty
616 .def
617 .reader()
618 .unwrap_full_name(ty.def.namespace(), ty.def.name());
619 (base, ty.generics.clone())
620 }
621 Self::Delegate(ty) if !ty.generics.is_empty() => {
622 let base = ty
623 .def
624 .reader()
625 .unwrap_full_name(ty.def.namespace(), ty.def.name());
626 (base, ty.generics.clone())
627 }
628 _ => (self.clone(), vec![]),
629 }
630 }
631
632 pub fn decay(&self) -> &Self {
633 match self {
634 Self::PtrMut(ty, _) => ty,
635 Self::PtrConst(ty, _) => ty,
636 Self::ArrayFixed(ty, _) => ty.decay(),
637 Self::Array(ty) => ty,
638 Self::ArrayRef(ty) => ty,
639 Self::ConstRef(ty) => ty,
640 Self::PrimitiveOrEnum(_, ty) => ty,
641 _ => self,
642 }
643 }
644
645 pub fn is_exclusive(&self) -> bool {
646 match self {
647 Self::Interface(ty) => ty.def.has_attribute("ExclusiveToAttribute"),
648 _ => false,
649 }
650 }
651
652 pub fn is_winrt_array(&self) -> bool {
653 matches!(self, Self::Array(_))
654 }
655
656 pub fn is_winrt_array_ref(&self) -> bool {
657 matches!(self, Self::ArrayRef(_))
658 }
659
660 pub fn is_async(&self) -> bool {
661 match self {
662 Self::Interface(ty) => ty.def.is_async(),
663 _ => false,
664 }
665 }
666
667 pub fn is_copyable(&self) -> bool {
668 match self {
669 Self::Struct(ty) => ty.is_copyable(),
670 Self::CppStruct(ty) => ty.is_copyable(),
671 Self::Enum(_) => true,
672 Self::CppEnum(_) => true,
673 Self::CppDelegate(_) => true,
674
675 Self::Interface(..) | Self::CppInterface(..) | Self::Class(..) | Self::Delegate(..) => {
676 false
677 }
678
679 Self::String | Self::BSTR | Self::Object | Self::IUnknown | Self::Generic(_) => false,
680 Self::ArrayFixed(ty, _) => ty.is_copyable(),
681 Self::Array(ty) => ty.is_copyable(),
682 _ => true,
683 }
684 }
685
686 pub fn is_dropped(&self) -> bool {
687 match self {
688 Self::Struct(ty) => !ty.is_copyable(),
689 Self::CppInterface(..) => true,
690 Self::String | Self::BSTR | Self::Object | Self::IUnknown => true,
691 Self::ArrayFixed(ty, _) => ty.is_dropped(),
692 _ => false,
693 }
694 }
695
696 pub fn is_convertible(&self) -> bool {
697 matches!(
698 self,
699 Self::Delegate(..)
700 | Self::Interface(..)
701 | Self::Class(..)
702 | Self::CppInterface(..)
703 | Self::PCSTR
704 | Self::PCWSTR
705 | Self::Object
706 | Self::IUnknown
707 | Self::Generic(_)
708 )
709 }
710
711 pub fn is_const_ref(&self) -> bool {
712 matches!(self, Self::ConstRef(_))
713 }
714
715 pub fn is_primitive(&self) -> bool {
716 match self {
717 Self::Enum(_) | Self::CppEnum(_) | Self::CppDelegate(_) => true,
718 Self::CppStruct(ty) => ty.is_handle(),
719 Self::Bool
720 | Self::Char
721 | Self::I8
722 | Self::U8
723 | Self::I16
724 | Self::U16
725 | Self::I32
726 | Self::U32
727 | Self::I64
728 | Self::U64
729 | Self::F32
730 | Self::F64
731 | Self::ISize
732 | Self::USize
733 | Self::HRESULT
734 | Self::BOOL
735 | Self::PtrConst(_, _)
736 | Self::PtrMut(_, _) => true,
737 _ => false,
738 }
739 }
740
741 pub fn is_unsigned(&self) -> bool {
742 matches!(
743 self,
744 Self::U8 | Self::U16 | Self::U32 | Self::U64 | Self::USize
745 )
746 }
747
748 pub fn is_pointer(&self) -> bool {
749 matches!(self, Self::PtrConst(_, _) | Self::PtrMut(_, _))
750 }
751
752 pub fn is_byte_size(&self) -> bool {
753 match self {
754 Self::PtrConst(ty, _) | Self::PtrMut(ty, _) => ty.is_byte_size(),
755 Self::I8 | Self::U8 | Self::PSTR | Self::PCSTR => true,
756 _ => false,
757 }
758 }
759
760 pub fn is_void(&self) -> bool {
761 match self {
762 Self::PtrConst(ty, _) | Self::PtrMut(ty, _) => ty.is_void(),
763 Self::Void => true,
764 _ => false,
765 }
766 }
767
768 pub fn size(&self) -> usize {
769 match self {
770 Self::I8 | Self::U8 => 1,
771 Self::I16 | Self::U16 => 2,
772 Self::I64 | Self::U64 | Self::F64 => 8,
773 Self::GUID => 16,
774 Self::ArrayFixed(ty, len) => ty.size() * len,
775 Self::PrimitiveOrEnum(ty, _) => ty.size(),
776 Self::CppStruct(ty) => ty.size(),
777 Self::Struct(ty) => ty.size(),
778 Self::CppEnum(ty) => ty.size(),
779 _ => 4,
780 }
781 }
782
783 pub fn align(&self) -> usize {
784 match self {
785 Self::I8 | Self::U8 => 1,
786 Self::I16 | Self::U16 => 2,
787 Self::I64 | Self::U64 | Self::F64 => 8,
788 Self::ArrayFixed(ty, len) => ty.align() * len,
789 Self::CppStruct(ty) => ty.align(),
790 Self::Struct(ty) => ty.align(),
791 Self::CppEnum(ty) => ty.align(),
792 _ => 4,
793 }
794 }
795
796 pub fn underlying_type(&self) -> Self {
797 match self {
798 Self::Struct(ty) => ty.def.underlying_type(),
799 Self::CppEnum(ty) => ty.def.underlying_type(),
800 Self::Enum(ty) => ty.def.underlying_type(),
801 Self::CppStruct(ty) => ty.def.underlying_type(),
802 Self::HRESULT => Self::I32,
803 Self::BOOL => Self::I32,
804 _ => self.clone(),
805 }
806 }
807
808 fn write_no_deps(&self, config: &Config) -> TokenStream {
809 if !config.no_deps || !config.sys {
810 return quote! {};
811 }
812
813 match self {
814 Self::HRESULT => quote! { pub type HRESULT = i32; },
815 Self::BOOL => quote! { pub type BOOL = i32; },
816
817 Self::PWSTR => quote! { pub type PWSTR = *mut u16; },
818 Self::PCSTR => quote! { pub type PCSTR = *const u8; },
819 Self::PSTR => quote! { pub type PSTR = *mut u8; },
820 Self::PCWSTR => quote! { pub type PCWSTR = *const u16; },
821 Self::BSTR => quote! { pub type BSTR = *const u16; },
822 Self::String => {
823 quote! { pub type HSTRING = *mut core::ffi::c_void; }
824 }
825 Self::GUID => quote! {
826 #[repr(C)]
827 #[derive(Clone, Copy)]
828 pub struct GUID {
829 pub data1: u32,
830 pub data2: u16,
831 pub data3: u16,
832 pub data4: [u8; 8],
833 }
834 impl GUID {
835 pub const fn from_u128(uuid: u128) -> Self {
836 Self { data1: (uuid >> 96) as u32, data2: (uuid >> 80 & 0xffff) as u16, data3: (uuid >> 64 & 0xffff) as u16, data4: (uuid as u64).to_be_bytes() }
837 }
838 }
839 },
840 Self::IUnknown => quote! {
841 pub const IID_IUnknown: GUID = GUID::from_u128(0x00000000_0000_0000_c000_000000000046);
842 #[repr(C)]
843 pub struct IUnknown_Vtbl {
844 pub QueryInterface: unsafe extern "system" fn(this: *mut core::ffi::c_void, iid: *const GUID, interface: *mut *mut core::ffi::c_void) -> HRESULT,
845 pub AddRef: unsafe extern "system" fn(this: *mut core::ffi::c_void) -> u32,
846 pub Release: unsafe extern "system" fn(this: *mut core::ffi::c_void) -> u32,
847 }
848 },
849 Self::Object => quote! {
850 pub const IID_IInspectable: GUID = GUID::from_u128(0xaf86e2e0_b12d_4c6a_9c5a_d7aa65101e90);
851 #[repr(C)]
852 pub struct IInspectable_Vtbl {
853 pub base: IUnknown_Vtbl,
854 pub GetIids: unsafe extern "system" fn(this: *mut core::ffi::c_void, count: *mut u32, values: *mut *mut GUID) -> HRESULT,
855 pub GetRuntimeClassName: unsafe extern "system" fn(this: *mut core::ffi::c_void, value: *mut *mut core::ffi::c_void) -> HRESULT,
856 pub GetTrustLevel: unsafe extern "system" fn(this: *mut core::ffi::c_void, value: *mut i32) -> HRESULT,
857 }
858 },
859
860 _ => quote! {},
861 }
862 }
863
864 pub fn write(&self, config: &Config) -> TokenStream {
865 match self {
866 Self::Struct(ty) => ty.write(config),
867 Self::Enum(ty) => ty.write(config),
868 Self::Interface(ty) => ty.write(config),
869 Self::CppStruct(ty) => ty.write(config),
870 Self::CppEnum(ty) => ty.write(config),
871 Self::CppFn(ty) => ty.write(config),
872 Self::CppConst(ty) => ty.write(config),
873 Self::CppDelegate(ty) => ty.write(config),
874 Self::Delegate(ty) => ty.write(config),
875 Self::Class(ty) => ty.write(config),
876 Self::CppInterface(ty) => ty.write(config),
877
878 _ => self.write_no_deps(config),
879 }
880 }
881
882 pub fn set_generics(&mut self, generics: Vec<Self>) {
883 match self {
884 Self::Interface(ty) => ty.generics = generics,
885 Self::Delegate(ty) => ty.generics = generics,
886 rest => panic!("{rest:?}"),
887 }
888 }
889
890 pub fn type_name(&self) -> TypeName {
891 match self {
892 Self::Class(ty) => ty.type_name(),
893 Self::Delegate(ty) => ty.type_name(),
894 Self::Enum(ty) => ty.type_name(),
895 Self::Interface(ty) => ty.type_name(),
896 Self::Struct(ty) => ty.type_name(),
897 Self::CppDelegate(ty) => ty.type_name(),
898 Self::CppEnum(ty) => ty.type_name(),
899 Self::CppInterface(ty) => ty.type_name(),
900 Self::CppStruct(ty) => ty.type_name(),
901 Self::CppConst(ty) => ty.type_name(),
902 Self::CppFn(ty) => ty.type_name(),
903
904 Self::PSTR => TypeName("", "PSTR"),
905 Self::PCSTR => TypeName("", "PCSTR"),
906 Self::PWSTR => TypeName("", "PWSTR"),
907 Self::PCWSTR => TypeName("", "PCWSTR"),
908 Self::GUID => TypeName("", "GUID"),
909 Self::HRESULT => TypeName("", "HRESULT"),
910 Self::BOOL => TypeName("", "BOOL"),
911 Self::IUnknown => TypeName("", "IUnknown"),
912 Self::BSTR => TypeName("", "BSTR"),
913 Self::String => TypeName("", "String"),
914 Self::Object => TypeName("", "Object"),
915
916 _ => TypeName("", ""),
917 }
918 }
919
920 pub fn is_core(&self) -> bool {
921 matches!(
922 self,
923 Self::PSTR
924 | Self::PCSTR
925 | Self::PWSTR
926 | Self::PCWSTR
927 | Self::GUID
928 | Self::HRESULT
929 | Self::BOOL
930 | Self::IUnknown
931 | Self::Object
932 | Self::BSTR
933 | Self::String
934 )
935 }
936
937 pub fn write_result_map(&self) -> TokenStream {
938 if self.is_copyable() {
939 quote! { map(|| result__) }
940 } else if self.is_convertible() {
941 quote! { and_then(||windows_core::Type::from_abi(result__)) }
942 } else {
943 quote! { map(|| core::mem::transmute(result__)) }
944 }
945 }
946}
947
948impl Dependencies for Type {
949 fn combine(&self, dependencies: &mut TypeMap) {
950 let ty = self.decay();
951
952 if ty.is_intrinsic() {
953 return;
954 }
955
956 let mut nested = false;
957
958 if let Self::CppStruct(ty) = ty {
959 if ty.def.namespace().is_empty() {
960 nested = true;
961 }
962 }
963
964 let (ty, generics) = ty.split_generic();
965
966 for ty in generics {
967 ty.combine(dependencies);
968 }
969
970 if !nested && !dependencies.insert(ty.clone()) {
971 return;
972 }
973
974 if let Some(multi) = match &ty {
975 Self::CppStruct(ty) => Some(
976 ty.def
977 .reader()
978 .with_full_name(ty.def.namespace(), ty.def.name()),
979 ),
980 Self::CppFn(ty) => Some(
981 ty.method
982 .reader()
983 .with_full_name(ty.namespace, ty.method.name()),
984 ),
985 _ => None,
986 } {
987 multi.for_each(|multi| {
988 if ty != multi {
989 multi.combine(dependencies)
990 }
991 });
992 }
993
994 match &ty {
995 Self::Class(ty) => ty.combine(dependencies),
996 Self::Delegate(ty) => ty.combine(dependencies),
997 Self::Enum(..) => {}
998 Self::Interface(ty) => ty.combine(dependencies),
999 Self::Struct(ty) => ty.combine(dependencies),
1000 Self::CppConst(ty) => ty.combine(dependencies),
1001 Self::CppDelegate(ty) => ty.combine(dependencies),
1002 Self::CppFn(ty) => ty.combine(dependencies),
1003 Self::CppInterface(ty) => ty.combine(dependencies),
1004 Self::CppStruct(ty) => ty.combine(dependencies),
1005 Self::CppEnum(ty) => ty.combine(dependencies),
1006
1007 Self::IUnknown => {
1008 Self::GUID.combine(dependencies);
1009 Self::HRESULT.combine(dependencies);
1010 }
1011
1012 Self::Object => {
1013 Self::IUnknown.combine(dependencies);
1014 }
1015
1016 _ => {}
1017 }
1018 }
1019}
1020
1021pub fn interface_signature(def: TypeDef, generics: &[Type]) -> String {
1022 if generics.is_empty() {
1023 let guid = def.guid_attribute().unwrap();
1024 format!("{{{guid}}}")
1025 } else {
1026 let guid = def.guid_attribute().unwrap();
1027 let mut signature = format!("pinterface({{{guid}}}");
1028
1029 for generic in generics {
1030 signature.push(';');
1031 signature.push_str(&generic.runtime_signature())
1032 }
1033
1034 signature.push(')');
1035 signature
1036 }
1037}
1038
1039fn write_ptr_mut(pointers: usize) -> TokenStream {
1040 "*mut ".repeat(pointers).into()
1041}
1042
1043fn write_ptr_const(pointers: usize) -> TokenStream {
1044 "*const ".repeat(pointers).into()
1045}