1use super::*;
2
3#[derive(Clone, Debug, Hash, PartialEq, Eq, Ord, PartialOrd)]
4pub enum Type {
5 // Primitives in ECMA-335
6 Void,
7 Bool,
8 Char,
9 I8,
10 U8,
11 I16,
12 U16,
13 I32,
14 U32,
15 I64,
16 U64,
17 F32,
18 F64,
19 ISize,
20 USize,
21
22 // System types
23 GUID, // Both Win32 and WinRT agree that this is represented by System.Guid
24 String, // TODO: Win32 should use System.String when referring to an HSTRING
25 IInspectable, // TODO: Win32 should use System.Object when referring to an IInspectable
26 Type, // System.Type is needed since WinRT attribute use this as a parameter type.
27
28 // Regular ECMA-335 types that map to metadata
29 TypeRef(TypeName),
30 GenericParam(GenericParam),
31 TypeDef(TypeDef, Vec<Self>),
32
33 // Qualified types
34 MutPtr(Box<Self>, usize),
35 ConstPtr(Box<Self>, usize),
36 Win32Array(Box<Self>, usize),
37 WinrtArray(Box<Self>),
38 WinrtArrayRef(Box<Self>),
39 ConstRef(Box<Self>),
40
41 // TODO: temporary hack to accommodate Win32 metadata
42 PrimitiveOrEnum(Box<Self>, Box<Self>),
43
44 // TODO: these should not be "special" and just point to regular metadata types in Win32.Foundation
45 HRESULT, // TODO: Win32 should use Windows.Foundation.HResult when referring to HRESULT
46 IUnknown, // TODO: should be defined in Windows.Win32.Foundation.IUnknown
47 PSTR,
48 PWSTR,
49 PCSTR,
50 PCWSTR,
51 BSTR,
52}
53
54impl Type {
55 /// Creates a `Type` object from an `ELEMENT_TYPE` (see ECMA-335) type constant, typically
56 /// used to indicate the type of a constant or primitive type signature.
57 pub fn from_code(code: usize) -> Option<Self> {
58 match code as u8 {
59 ELEMENT_TYPE_VOID => Some(Self::Void),
60 ELEMENT_TYPE_BOOLEAN => Some(Self::Bool),
61 ELEMENT_TYPE_CHAR => Some(Self::Char),
62 ELEMENT_TYPE_I1 => Some(Self::I8),
63 ELEMENT_TYPE_U1 => Some(Self::U8),
64 ELEMENT_TYPE_I2 => Some(Self::I16),
65 ELEMENT_TYPE_U2 => Some(Self::U16),
66 ELEMENT_TYPE_I4 => Some(Self::I32),
67 ELEMENT_TYPE_U4 => Some(Self::U32),
68 ELEMENT_TYPE_I8 => Some(Self::I64),
69 ELEMENT_TYPE_U8 => Some(Self::U64),
70 ELEMENT_TYPE_R4 => Some(Self::F32),
71 ELEMENT_TYPE_R8 => Some(Self::F64),
72 ELEMENT_TYPE_I => Some(Self::ISize),
73 ELEMENT_TYPE_U => Some(Self::USize),
74 ELEMENT_TYPE_STRING => Some(Self::String),
75 ELEMENT_TYPE_OBJECT => Some(Self::IInspectable),
76 _ => None,
77 }
78 }
79
80 /// Converts the `Type` to an equivalent `const` variant if appropriate.
81 pub fn to_const_type(self) -> Self {
82 match self {
83 Self::MutPtr(kind, pointers) => Self::MutPtr(Box::new(kind.to_const_type()), pointers),
84 Self::ConstPtr(kind, pointers) => Self::ConstPtr(Box::new(kind.to_const_type()), pointers),
85 Self::PSTR => Self::PCSTR,
86 Self::PWSTR => Self::PCWSTR,
87 _ => self,
88 }
89 }
90
91 pub fn to_underlying_type(&self) -> Self {
92 match self {
93 Type::MutPtr(ty, _) => *ty.clone(),
94 Type::ConstPtr(ty, _) => *ty.clone(),
95 Type::Win32Array(ty, _) => *ty.clone(),
96 Type::WinrtArray(ty) => *ty.clone(),
97 Type::WinrtArrayRef(ty) => *ty.clone(),
98 Type::ConstRef(ty) => *ty.clone(),
99 _ => self.clone(),
100 }
101 }
102
103 /// Converts a mutable pointer type, if appropriate, to a const pointer type.
104 pub fn to_const_ptr(self) -> Self {
105 match self {
106 Self::MutPtr(kind, pointers) => Self::ConstPtr(kind, pointers),
107 _ => self,
108 }
109 }
110
111 /// Removes one level of indirection, typically used when transforming a logical return or array parameter
112 /// from its underlying type signature.
113 pub fn deref(&self) -> Self {
114 match self {
115 Self::ConstPtr(kind, 1) | Self::MutPtr(kind, 1) => {
116 if **kind == Self::Void {
117 Self::U8
118 } else {
119 *kind.clone()
120 }
121 }
122 Self::ConstPtr(kind, pointers) => Self::ConstPtr(kind.clone(), pointers - 1),
123 Self::MutPtr(kind, pointers) => Self::MutPtr(kind.clone(), pointers - 1),
124 Self::PSTR | Self::PCSTR => Self::U8,
125 Self::PWSTR | Self::PCWSTR => Self::U16,
126 _ => panic!("`deref` can only be called on pointer types"),
127 }
128 }
129
130 /// Returns `true` if the `Type` represents a WinRT array.
131 pub fn is_winrt_array(&self) -> bool {
132 matches!(self, Type::WinrtArray(_))
133 }
134
135 /// Returns `true` if the `Type` represents a mutable WinRT array reference.
136 pub fn is_winrt_array_ref(&self) -> bool {
137 matches!(self, Type::WinrtArrayRef(_))
138 }
139
140 /// Returns `true` if the `Type` represents an immutable WinRT array reference.
141 pub fn is_const_ref(&self) -> bool {
142 matches!(self, Type::ConstRef(_))
143 }
144
145 /// Returns `true` if the `Type` is a generic parameter.
146 pub fn is_generic(&self) -> bool {
147 matches!(self, Type::GenericParam(_))
148 }
149
150 /// Returns `true` if the `Type` is a pointer.
151 pub fn is_pointer(&self) -> bool {
152 matches!(self, Type::ConstPtr(_, _) | Type::MutPtr(_, _))
153 }
154
155 /// Returns `true` if the `Type` is unsigned.
156 pub fn is_unsigned(&self) -> bool {
157 matches!(self, Type::U8 | Type::U16 | Type::U32 | Type::U64 | Type::USize)
158 }
159
160 /// Returns `true` if the `Type` is incomplete.
161 pub fn is_void(&self) -> bool {
162 match self {
163 Type::ConstPtr(kind, _) | Type::MutPtr(kind, _) => kind.is_void(),
164 Type::Void => true,
165 _ => false,
166 }
167 }
168
169 /// Returns `true` if the `Type` has a byte-sized address.
170 pub fn is_byte_size(&self) -> bool {
171 match self {
172 Type::ConstPtr(kind, _) | Type::MutPtr(kind, _) => kind.is_byte_size(),
173 Type::I8 | Type::U8 | Type::PSTR | Type::PCSTR => true,
174 _ => false,
175 }
176 }
177
178 pub fn size(&self) -> usize {
179 match self {
180 Type::I8 | Type::U8 => 1,
181 Type::I16 | Type::U16 => 2,
182 Type::I64 | Type::U64 | Type::F64 => 8,
183 Type::GUID => 16,
184 Type::TypeDef(def, _) => def.size(),
185 Type::Win32Array(ty, len) => ty.size() * len,
186 Type::PrimitiveOrEnum(ty, _) => ty.size(),
187 _ => 4,
188 }
189 }
190
191 pub fn align(&self) -> usize {
192 match self {
193 Type::I8 | Type::U8 => 1,
194 Type::I16 | Type::U16 => 2,
195 Type::I64 | Type::U64 | Type::F64 => 8,
196 Type::GUID => 4,
197 Type::TypeDef(def, _) => def.align(),
198 Type::Win32Array(ty, len) => ty.align() * len,
199 _ => 4,
200 }
201 }
202}
203