1 | use super::*; |
2 | |
3 | #[derive (Clone, Debug, Hash, PartialEq, Eq, Ord, PartialOrd)] |
4 | pub 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 | |
54 | impl 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 | |