windows_bindgen/types/
mod.rs

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        // This sorts types as follows:
106        // 1. functions are placed first
107        // 2. type name
108        // 3. type namespace
109        // 4. architecture
110        // 5. overloaded types
111
112        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        // Used by WinRT to indicate that a struct input parameter is passed by reference rather than by value on the ABI.
256        let is_const = blob.read_modifiers().iter().any(|def| {
257            let type_name = def.type_name();
258            type_name == TypeName::IsConst
259        });
260
261        // Used by WinRT to indicate an output parameter, but there are other ways to determine this direction so here
262        // it is only used to distinguish between slices and heap-allocated arrays.
263        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); // Used by WinRT to indicate an array
270
271        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}