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