1#![allow(missing_docs)]
9
10use crate::common::*;
11use crate::tpi::constants::*;
12use crate::tpi::primitive::*;
13
14#[non_exhaustive]
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub enum TypeData<'t> {
18 Primitive(PrimitiveType),
19 Class(ClassType<'t>),
20 Member(MemberType<'t>),
21 MemberFunction(MemberFunctionType),
22 OverloadedMethod(OverloadedMethodType<'t>),
23 Method(MethodType<'t>),
24 StaticMember(StaticMemberType<'t>),
25 Nested(NestedType<'t>),
26 BaseClass(BaseClassType),
27 VirtualBaseClass(VirtualBaseClassType),
28 VirtualFunctionTablePointer(VirtualFunctionTablePointerType),
29 Procedure(ProcedureType),
30 Pointer(PointerType),
31 Modifier(ModifierType),
32 Enumeration(EnumerationType<'t>),
33 Enumerate(EnumerateType<'t>),
34 Array(ArrayType),
35 Union(UnionType<'t>),
36 Bitfield(BitfieldType),
37 FieldList(FieldList<'t>),
38 ArgumentList(ArgumentList),
39 MethodList(MethodList),
40}
41
42impl<'t> TypeData<'t> {
43 pub fn name(&self) -> Option<RawString<'t>> {
45 let name = match self {
46 Self::Class(ClassType { ref name, .. })
47 | Self::Member(MemberType { ref name, .. })
48 | Self::OverloadedMethod(OverloadedMethodType { ref name, .. })
49 | Self::StaticMember(StaticMemberType { ref name, .. })
50 | Self::Nested(NestedType { ref name, .. })
51 | Self::Enumeration(EnumerationType { ref name, .. })
52 | Self::Enumerate(EnumerateType { ref name, .. })
53 | Self::Union(UnionType { ref name, .. }) => name,
54 _ => return None,
55 };
56
57 Some(*name)
58 }
59}
60
61pub(crate) fn parse_type_data<'t>(buf: &mut ParseBuffer<'t>) -> Result<TypeData<'t>> {
63 let leaf = buf.parse_u16()?;
64
65 match leaf {
66 LF_CLASS | LF_CLASS_ST | LF_STRUCTURE | LF_STRUCTURE_ST | LF_INTERFACE => {
71 let mut class = ClassType {
72 kind: match leaf {
73 LF_CLASS | LF_CLASS_ST => ClassKind::Class,
74 LF_STRUCTURE | LF_STRUCTURE_ST => ClassKind::Struct,
75 LF_INTERFACE => ClassKind::Interface,
76 _ => unreachable!(),
77 },
78 count: buf.parse_u16()?,
79 properties: TypeProperties(buf.parse_u16()?),
80 fields: parse_optional_type_index(buf)?,
81 derived_from: parse_optional_type_index(buf)?,
82 vtable_shape: parse_optional_type_index(buf)?,
83 size: parse_unsigned(buf)?,
84 name: parse_string(leaf, buf)?,
85 unique_name: None,
86 };
87
88 if class.properties.has_unique_name() {
89 class.unique_name = Some(parse_string(leaf, buf)?);
90 }
91
92 Ok(TypeData::Class(class))
93 }
94
95 LF_STRUCTURE19 => {
97 let mut class = ClassType {
98 kind: ClassKind::Struct,
99 properties: TypeProperties(buf.parse_u32()? as u16),
100 fields: parse_optional_type_index(buf)?,
101 derived_from: parse_optional_type_index(buf)?,
102 vtable_shape: parse_optional_type_index(buf)?,
103 count: buf.parse_u16()?,
104 size: parse_unsigned(buf)?,
105 name: parse_string(leaf, buf)?,
106 unique_name: None,
107 };
108
109 if class.properties.has_unique_name() {
110 class.unique_name = Some(parse_string(leaf, buf)?);
111 }
112
113 Ok(TypeData::Class(class))
114 }
115
116 LF_MEMBER | LF_MEMBER_ST => Ok(TypeData::Member(MemberType {
118 attributes: FieldAttributes(buf.parse_u16()?),
119 field_type: buf.parse()?,
120 offset: parse_unsigned(buf)?,
121 name: parse_string(leaf, buf)?,
122 })),
123
124 LF_NESTTYPE | LF_NESTTYPE_ST | LF_NESTTYPEEX | LF_NESTTYPEEX_ST => {
126 let raw_attr = match leaf {
128 LF_NESTTYPEEX | LF_NESTTYPEEX_ST => buf.parse_u16()?,
129 _ => {
130 buf.parse_u16()?;
132 0
134 }
135 };
136
137 Ok(TypeData::Nested(NestedType {
138 attributes: FieldAttributes(raw_attr),
139 nested_type: buf.parse()?,
140 name: parse_string(leaf, buf)?,
141 }))
142 }
143
144 LF_MFUNCTION => Ok(TypeData::MemberFunction(MemberFunctionType {
146 return_type: buf.parse()?,
147 class_type: buf.parse()?,
148 this_pointer_type: parse_optional_type_index(buf)?,
149 attributes: FunctionAttributes(buf.parse_u16()?),
150 parameter_count: buf.parse_u16()?,
151 argument_list: buf.parse()?,
152 this_adjustment: buf.parse_u32()?,
153 })),
154
155 LF_METHOD | LF_METHOD_ST => Ok(TypeData::OverloadedMethod(OverloadedMethodType {
157 count: buf.parse_u16()?,
158 method_list: buf.parse()?,
159 name: parse_string(leaf, buf)?,
160 })),
161
162 LF_ONEMETHOD | LF_ONEMETHOD_ST => {
164 let attr = FieldAttributes(buf.parse_u16()?);
165 Ok(TypeData::Method(MethodType {
166 attributes: attr,
167 method_type: buf.parse()?,
168 vtable_offset: if attr.is_intro_virtual() {
169 Some(buf.parse_u32()? as u32)
170 } else {
171 None
173 },
174 name: parse_string(leaf, buf)?,
175 }))
176 }
177
178 LF_BCLASS | LF_BINTERFACE => Ok(TypeData::BaseClass(BaseClassType {
180 kind: match leaf {
181 LF_BCLASS => ClassKind::Class,
182 LF_BINTERFACE => ClassKind::Interface,
183 _ => unreachable!(),
184 },
185 attributes: FieldAttributes(buf.parse_u16()?),
186 base_class: buf.parse()?,
187 offset: parse_unsigned(buf)? as u32,
188 })),
189
190 LF_VFUNCTAB => {
192 buf.parse_u16()?;
194 Ok(TypeData::VirtualFunctionTablePointer(
195 VirtualFunctionTablePointerType {
196 table: buf.parse()?,
197 },
198 ))
199 }
200
201 LF_STMEMBER | LF_STMEMBER_ST => Ok(TypeData::StaticMember(StaticMemberType {
203 attributes: FieldAttributes(buf.parse_u16()?),
204 field_type: buf.parse()?,
205 name: parse_string(leaf, buf)?,
206 })),
207
208 LF_POINTER => {
210 let underlying_type = buf.parse()?;
211 let attributes = PointerAttributes(buf.parse()?);
212
213 let containing_class = if attributes.pointer_to_member() {
214 Some(buf.parse()?)
215 } else {
216 None
217 };
218
219 Ok(TypeData::Pointer(PointerType {
220 underlying_type,
221 attributes,
222 containing_class,
223 }))
224 }
225
226 LF_PROCEDURE => Ok(TypeData::Procedure(ProcedureType {
228 return_type: parse_optional_type_index(buf)?,
229 attributes: FunctionAttributes(buf.parse_u16()?),
230 parameter_count: buf.parse_u16()?,
231 argument_list: buf.parse()?,
232 })),
233
234 LF_MODIFIER => {
236 let type_index = buf.parse()?;
237
238 let flags = buf.parse_u16()?;
240
241 Ok(TypeData::Modifier(ModifierType {
242 underlying_type: type_index,
243 constant: (flags & 0x01) != 0,
244 volatile: (flags & 0x02) != 0,
245 unaligned: (flags & 0x04) != 0,
246 }))
247 }
248
249 LF_ENUM | LF_ENUM_ST => {
251 let mut enumeration = EnumerationType {
252 count: buf.parse_u16()?,
253 properties: TypeProperties(buf.parse_u16()?),
254 underlying_type: buf.parse()?,
255 fields: buf.parse()?,
256 name: parse_string(leaf, buf)?,
257 unique_name: None,
258 };
259
260 if enumeration.properties.has_unique_name() {
261 enumeration.unique_name = Some(parse_string(leaf, buf)?);
262 }
263
264 Ok(TypeData::Enumeration(enumeration))
265 }
266
267 LF_ENUMERATE | LF_ENUMERATE_ST => Ok(TypeData::Enumerate(EnumerateType {
269 attributes: FieldAttributes(buf.parse_u16()?),
270 value: buf.parse()?,
271 name: parse_string(leaf, buf)?,
272 })),
273
274 LF_ARRAY | LF_ARRAY_ST | LF_STRIDED_ARRAY => {
276 let element_type = buf.parse()?;
277 let indexing_type = buf.parse()?;
278 let stride: Option<u32> = if leaf == LF_STRIDED_ARRAY {
279 Some(buf.parse_u32()?)
280 } else {
281 None
282 };
283
284 let mut dimensions: Vec<u32> = Vec::new();
285
286 loop {
287 let dim = parse_unsigned(buf)?;
288 if dim > u64::from(u32::max_value()) {
289 return Err(Error::UnimplementedFeature("u64 array sizes"));
290 }
291 dimensions.push(dim as u32);
292
293 if buf.is_empty() {
294 return Err(Error::UnexpectedEof);
296 }
297
298 if buf.peek_u8()? == 0x00 {
299 buf.parse_u8()?;
301 break;
302 }
303 }
304
305 parse_padding(buf)?;
307
308 assert!(buf.is_empty());
312
313 Ok(TypeData::Array(ArrayType {
314 element_type,
315 indexing_type,
316 stride,
317 dimensions,
318 }))
319 }
320
321 LF_UNION | LF_UNION_ST => {
323 let mut union = UnionType {
324 count: buf.parse_u16()?,
325 properties: TypeProperties(buf.parse_u16()?),
326 fields: buf.parse()?,
327 size: parse_unsigned(buf)?,
328 name: parse_string(leaf, buf)?,
329 unique_name: None,
330 };
331
332 if union.properties.has_unique_name() {
333 union.unique_name = Some(parse_string(leaf, buf)?);
334 }
335
336 Ok(TypeData::Union(union))
337 }
338
339 LF_BITFIELD => Ok(TypeData::Bitfield(BitfieldType {
341 underlying_type: buf.parse()?,
342 length: buf.parse_u8()?,
343 position: buf.parse_u8()?,
344 })),
345
346 LF_VTSHAPE => {
348 Err(Error::UnimplementedTypeKind(leaf))
350 }
351
352 LF_VFTABLE => {
354 Err(Error::UnimplementedTypeKind(leaf))
356 }
357
358 LF_VBCLASS | LF_IVBCLASS => Ok(TypeData::VirtualBaseClass(VirtualBaseClassType {
360 direct: leaf == LF_VBCLASS,
361 attributes: FieldAttributes(buf.parse_u16()?),
362 base_class: buf.parse()?,
363 base_pointer: buf.parse()?,
364 base_pointer_offset: parse_unsigned(buf)? as u32,
365 virtual_base_offset: parse_unsigned(buf)? as u32,
366 })),
367
368 LF_FIELDLIST => {
373 let mut fields: Vec<TypeData<'t>> = Vec::new();
374 let mut continuation: Option<TypeIndex> = None;
375
376 while !buf.is_empty() {
377 match buf.peek_u16()? {
378 LF_INDEX => {
379 buf.parse_u16()?;
382
383 continuation = Some(buf.parse()?);
385 }
386 _ => {
387 fields.push(parse_type_data(buf)?);
390 }
391 }
392
393 parse_padding(buf)?;
395 }
396
397 Ok(TypeData::FieldList(FieldList {
398 fields,
399 continuation,
400 }))
401 }
402
403 LF_ARGLIST => {
404 let count = buf.parse_u32()?;
405 let mut arglist: Vec<TypeIndex> = Vec::with_capacity(count as usize);
406 for _ in 0..count {
407 arglist.push(buf.parse()?);
408 }
409 Ok(TypeData::ArgumentList(ArgumentList { arguments: arglist }))
410 }
411
412 LF_METHODLIST => {
413 let mut methods: Vec<MethodListEntry> = Vec::new();
414
415 while !buf.is_empty() {
416 let attr = FieldAttributes(buf.parse_u16()?);
418 buf.parse_u16()?; methods.push(MethodListEntry {
421 attributes: attr,
422 method_type: buf.parse()?,
423 vtable_offset: if attr.is_intro_virtual() {
424 Some(buf.parse_u32()?)
425 } else {
426 None
427 },
428 });
429 }
430
431 Ok(TypeData::MethodList(MethodList { methods }))
432 }
433
434 _ => Err(Error::UnimplementedTypeKind(leaf)),
435 }
436}
437
438#[inline]
439fn parse_optional_type_index(buf: &mut ParseBuffer<'_>) -> Result<Option<TypeIndex>> {
440 let index = buf.parse()?;
441 if index == TypeIndex(0) || index == TypeIndex(0xffff) {
442 Ok(None)
443 } else {
444 Ok(Some(index))
445 }
446}
447
448#[inline]
449fn parse_string<'t>(leaf: u16, buf: &mut ParseBuffer<'t>) -> Result<RawString<'t>> {
450 if leaf > LF_ST_MAX {
451 buf.parse_cstring()
452 } else {
453 buf.parse_u8_pascal_string()
454 }
455}
456
457#[inline]
458fn parse_padding(buf: &mut ParseBuffer<'_>) -> Result<()> {
459 while !buf.is_empty() && buf.peek_u8()? >= 0xf0 {
460 let padding = buf.parse_u8()?;
461 if padding > 0xf0 {
462 buf.take((padding & 0x0f) as usize - 1)?;
465 }
466 }
467 Ok(())
468}
469
470fn parse_unsigned(buf: &mut ParseBuffer<'_>) -> Result<u64> {
472 let leaf = buf.parse_u16()?;
473 if leaf < LF_NUMERIC {
474 return Ok(u64::from(leaf));
476 }
477
478 match leaf {
479 LF_CHAR => Ok(u64::from(buf.parse_u8()?)),
480 LF_USHORT => Ok(u64::from(buf.parse_u16()?)),
481 LF_ULONG => Ok(u64::from(buf.parse_u32()?)),
482 LF_UQUADWORD => Ok(buf.parse_u64()?),
483 _ => {
484 if cfg!(debug_assertions) {
485 unreachable!();
486 } else {
487 Err(Error::UnexpectedNumericPrefix(leaf))
488 }
489 }
490 }
491}
492
493#[derive(Debug, Copy, Clone, PartialEq, Eq)]
512pub struct TypeProperties(u16);
513impl TypeProperties {
514 pub fn packed(self) -> bool {
516 self.0 & 0x0001 != 0
517 }
518
519 pub fn constructors(self) -> bool {
521 self.0 & 0x0002 != 0
522 }
523
524 pub fn overloaded_operators(self) -> bool {
526 self.0 & 0x0004 != 0
527 }
528
529 pub fn is_nested_type(self) -> bool {
531 self.0 & 0x0008 != 0
532 }
533
534 pub fn contains_nested_types(self) -> bool {
536 self.0 & 0x0010 != 0
537 }
538
539 pub fn overloaded_assignment(self) -> bool {
541 self.0 & 0x0020 != 0
542 }
543 pub fn overloaded_casting(self) -> bool {
544 self.0 & 0x0040 != 0
545 }
546
547 pub fn forward_reference(self) -> bool {
552 self.0 & 0x0080 != 0
553 }
554
555 pub fn scoped_definition(self) -> bool {
556 self.0 & 0x0100 != 0
557 }
558 pub fn has_unique_name(self) -> bool {
559 self.0 & 0x0200 != 0
560 }
561 pub fn sealed(self) -> bool {
562 self.0 & 0x0400 != 0
563 }
564 pub fn hfa(self) -> u8 {
565 ((self.0 & 0x1800) >> 11) as u8
566 }
567 pub fn intrinsic_type(self) -> bool {
568 self.0 & 0x1000 != 0
569 }
570 pub fn mocom(self) -> u8 {
571 ((self.0 & 0x6000) >> 14) as u8
572 }
573}
574
575#[derive(Debug, Copy, Clone, PartialEq, Eq)]
599pub struct FieldAttributes(u16);
600impl FieldAttributes {
601 #[inline]
602 pub fn access(self) -> u8 {
603 (self.0 & 0x0003) as u8
604 }
605 #[inline]
606 fn method_properties(self) -> u8 {
607 ((self.0 & 0x001c) >> 2) as u8
608 }
609
610 #[inline]
611 pub fn is_static(self) -> bool {
612 self.method_properties() == 0x02
613 }
614
615 #[inline]
616 pub fn is_virtual(self) -> bool {
617 self.method_properties() == 0x01
618 }
619
620 #[inline]
621 pub fn is_pure_virtual(self) -> bool {
622 self.method_properties() == 0x05
623 }
624
625 #[inline]
626 pub fn is_intro_virtual(self) -> bool {
627 matches!(self.method_properties(), 0x04 | 0x06)
628 }
629
630 }
632
633#[allow(unused)]
634#[repr(u8)]
635enum Access {
636 None = 0x00,
637 Private = 0x01,
638 Protected = 0x02,
639 Public = 0x03,
640}
641
642#[derive(Debug, Copy, Clone, PartialEq, Eq)]
653pub struct FunctionAttributes(u16);
654impl FunctionAttributes {
655 pub fn calling_convention(self) -> u8 {
656 (self.0 & 0xff) as u8
657 }
658 pub fn cxx_return_udt(self) -> bool {
659 (self.0 & 0x0100) > 0
660 }
661 pub fn is_constructor(self) -> bool {
662 (self.0 & 0x0200) > 0
663 }
664 pub fn is_constructor_with_virtual_bases(self) -> bool {
665 (self.0 & 0x0400) > 0
666 }
667}
668
669#[derive(Clone, Copy, Debug, PartialEq, Eq)]
671pub enum PointerKind {
672 Near16,
674 Far16,
676 Huge16,
678 BaseSeg,
680 BaseVal,
682 BaseSegVal,
684 BaseAddr,
686 BaseSegAddr,
688 BaseType,
690 BaseSelf,
692 Near32,
694 Far32,
696 Ptr64,
698}
699
700#[derive(Clone, Copy, Debug, PartialEq, Eq)]
702pub enum PointerMode {
703 Pointer,
705 LValueReference,
707 Member,
709 MemberFunction,
711 RValueReference,
713}
714
715#[derive(Clone, Copy, Debug, PartialEq, Eq)]
733pub struct PointerAttributes(u32);
734
735impl PointerAttributes {
736 pub fn pointer_kind(self) -> PointerKind {
738 match self.0 & 0x1f {
739 0x00 => PointerKind::Near16,
740 0x01 => PointerKind::Far16,
741 0x02 => PointerKind::Huge16,
742 0x03 => PointerKind::BaseSeg,
743 0x04 => PointerKind::BaseVal,
744 0x05 => PointerKind::BaseSegVal,
745 0x06 => PointerKind::BaseAddr,
746 0x07 => PointerKind::BaseSegAddr,
747 0x08 => PointerKind::BaseType,
748 0x09 => PointerKind::BaseSelf,
749 0x0a => PointerKind::Near32,
750 0x0b => PointerKind::Far32,
751 0x0c => PointerKind::Ptr64,
752 _ => unreachable!(),
753 }
754 }
755
756 pub fn pointer_mode(self) -> PointerMode {
758 match (self.0 >> 5) & 0x7 {
759 0x00 => PointerMode::Pointer,
760 0x01 => PointerMode::LValueReference,
761 0x02 => PointerMode::Member,
762 0x03 => PointerMode::MemberFunction,
763 0x04 => PointerMode::RValueReference,
764 _ => unreachable!(),
765 }
766 }
767
768 pub fn pointer_to_member(self) -> bool {
770 matches!(
771 self.pointer_mode(),
772 PointerMode::Member | PointerMode::MemberFunction
773 )
774 }
775
776 pub fn is_flat_32(self) -> bool {
778 (self.0 & 0x100) != 0
779 }
780
781 pub fn is_volatile(self) -> bool {
783 (self.0 & 0x200) != 0
784 }
785
786 pub fn is_const(self) -> bool {
788 (self.0 & 0x400) != 0
789 }
790
791 pub fn is_unaligned(self) -> bool {
793 (self.0 & 0x800) != 0
794 }
795
796 pub fn is_restrict(self) -> bool {
798 (self.0 & 0x1000) != 0
799 }
800
801 pub fn is_reference(self) -> bool {
803 matches!(
804 self.pointer_mode(),
805 PointerMode::LValueReference | PointerMode::RValueReference
806 )
807 }
808
809 pub fn size(self) -> u8 {
811 let size = ((self.0 >> 13) & 0x3f) as u8;
812 if size != 0 {
813 return size;
814 }
815
816 match self.pointer_kind() {
817 PointerKind::Near32 | PointerKind::Far32 => 4,
818 PointerKind::Ptr64 => 8,
819 _ => 0,
820 }
821 }
822
823 pub fn is_mocom(self) -> bool {
825 (self.0 & 0x40000) != 0
826 }
827}
828
829#[derive(Debug, Clone, PartialEq, Eq)]
833pub struct ClassType<'t> {
834 pub kind: ClassKind,
835
836 pub count: u16,
838 pub properties: TypeProperties,
839
840 pub fields: Option<TypeIndex>,
842
843 pub derived_from: Option<TypeIndex>,
845
846 pub vtable_shape: Option<TypeIndex>,
848
849 pub size: u64,
850
851 pub name: RawString<'t>,
853
854 pub unique_name: Option<RawString<'t>>,
856}
857
858#[derive(Debug, Copy, Clone, PartialEq, Eq)]
860pub enum ClassKind {
861 Class,
862 Struct,
863 Interface,
864}
865
866#[derive(Debug, Clone, PartialEq, Eq)]
868pub struct MemberType<'t> {
869 pub attributes: FieldAttributes,
870 pub field_type: TypeIndex,
871 pub offset: u64,
872 pub name: RawString<'t>,
873}
874
875#[derive(Debug, Copy, Clone, PartialEq, Eq)]
877pub struct MemberFunctionType {
878 pub return_type: TypeIndex,
879 pub class_type: TypeIndex,
880 pub this_pointer_type: Option<TypeIndex>,
881 pub attributes: FunctionAttributes,
882 pub parameter_count: u16,
883 pub argument_list: TypeIndex,
884 pub this_adjustment: u32,
885}
886
887#[derive(Debug, Clone, PartialEq, Eq)]
889pub struct OverloadedMethodType<'t> {
890 pub count: u16,
891 pub method_list: TypeIndex,
892 pub name: RawString<'t>,
893}
894
895#[derive(Debug, Clone, PartialEq, Eq)]
897pub struct MethodType<'t> {
898 pub attributes: FieldAttributes,
899 pub method_type: TypeIndex,
900 pub vtable_offset: Option<u32>,
901 pub name: RawString<'t>,
902}
903
904#[derive(Debug, Clone, PartialEq, Eq)]
906pub struct StaticMemberType<'t> {
907 pub attributes: FieldAttributes,
908 pub field_type: TypeIndex,
909 pub name: RawString<'t>,
910}
911
912#[derive(Debug, Clone, PartialEq, Eq)]
915pub struct NestedType<'t> {
916 pub attributes: FieldAttributes,
917 pub nested_type: TypeIndex,
918 pub name: RawString<'t>,
919}
920
921#[derive(Debug, Copy, Clone, PartialEq, Eq)]
923pub struct BaseClassType {
924 pub kind: ClassKind,
925 pub attributes: FieldAttributes,
926 pub base_class: TypeIndex,
927
928 pub offset: u32,
930}
931
932#[derive(Debug, Copy, Clone, PartialEq, Eq)]
934pub struct VirtualBaseClassType {
935 pub direct: bool,
936 pub attributes: FieldAttributes,
937 pub base_class: TypeIndex,
938 pub base_pointer: TypeIndex,
939
940 pub base_pointer_offset: u32,
941 pub virtual_base_offset: u32,
942}
943
944#[derive(Debug, Copy, Clone, PartialEq, Eq)]
946pub struct VirtualFunctionTablePointerType {
947 pub table: TypeIndex,
948}
949
950#[derive(Debug, Copy, Clone, PartialEq, Eq)]
952pub struct ProcedureType {
953 pub return_type: Option<TypeIndex>,
954 pub attributes: FunctionAttributes,
955 pub parameter_count: u16,
956 pub argument_list: TypeIndex,
957}
958
959#[derive(Debug, Copy, Clone, PartialEq, Eq)]
961pub struct PointerType {
962 pub underlying_type: TypeIndex,
963 pub attributes: PointerAttributes,
964 pub containing_class: Option<TypeIndex>,
965}
966
967#[derive(Debug, Copy, Clone, PartialEq, Eq)]
969pub struct ModifierType {
970 pub underlying_type: TypeIndex,
971 pub constant: bool,
972 pub volatile: bool,
973 pub unaligned: bool,
974}
975
976#[derive(Debug, Clone, PartialEq, Eq)]
978pub struct EnumerationType<'t> {
979 pub count: u16,
980 pub properties: TypeProperties,
981 pub underlying_type: TypeIndex,
982 pub fields: TypeIndex,
983 pub name: RawString<'t>,
984 pub unique_name: Option<RawString<'t>>,
985}
986
987#[derive(Debug, Clone, PartialEq, Eq)]
989pub struct EnumerateType<'t> {
990 pub attributes: FieldAttributes,
991 pub value: Variant,
992 pub name: RawString<'t>,
993}
994
995#[derive(Debug, Clone, PartialEq, Eq)]
998pub struct ArrayType {
999 pub element_type: TypeIndex,
1000 pub indexing_type: TypeIndex,
1001 pub stride: Option<u32>,
1002
1003 pub dimensions: Vec<u32>,
1013}
1014
1015#[derive(Debug, Clone, PartialEq, Eq)]
1017pub struct UnionType<'t> {
1018 pub count: u16,
1019 pub properties: TypeProperties,
1020 pub fields: TypeIndex,
1021 pub size: u64,
1022 pub name: RawString<'t>,
1023 pub unique_name: Option<RawString<'t>>,
1024}
1025
1026#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1028pub struct BitfieldType {
1029 pub underlying_type: TypeIndex,
1030 pub length: u8,
1031 pub position: u8,
1032}
1033
1034#[derive(Debug, Clone, PartialEq, Eq)]
1036pub struct FieldList<'t> {
1037 pub fields: Vec<TypeData<'t>>,
1038
1039 pub continuation: Option<TypeIndex>,
1042}
1043
1044#[derive(Debug, Clone, PartialEq, Eq)]
1046pub struct ArgumentList {
1047 pub arguments: Vec<TypeIndex>,
1048}
1049
1050#[derive(Debug, Clone, PartialEq, Eq)]
1052pub struct MethodList {
1053 pub methods: Vec<MethodListEntry>,
1054}
1055
1056#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1058pub struct MethodListEntry {
1059 pub attributes: FieldAttributes,
1060 pub method_type: TypeIndex,
1061 pub vtable_offset: Option<u32>,
1062}
1063
1064#[test]
1081fn kind_1609() {
1082 let data = &[
1083 9, 22, 0, 2, 0, 0, 22, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 6, 0, 72, 95, 115, 105, 122,
1084 101, 0, 46, 63, 65, 85, 72, 95, 115, 105, 122, 101, 64, 64, 0,
1085 ][..];
1086
1087 assert_eq!(
1088 parse_type_data(&mut ParseBuffer::from(data)).expect("parse"),
1089 TypeData::Class(ClassType {
1090 kind: ClassKind::Struct,
1091 count: 2,
1092 properties: TypeProperties(512),
1093 fields: Some(TypeIndex(0x1016)),
1094 derived_from: None,
1095 vtable_shape: None,
1096 size: 6,
1097 name: RawString::from("H_size"),
1098 unique_name: Some(RawString::from(".?AUH_size@@")),
1099 })
1100 );
1101}