ms_codeview/types/
kind.rs

1/// Identifies type records. Also called "leaf" records.
2#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
3pub struct Leaf(pub u16);
4
5macro_rules! cv_leaf {
6    (
7        $(
8            $code:expr, $name:ident ;
9        )*
10    ) => {
11        #[allow(non_upper_case_globals)]
12        #[allow(missing_docs)]
13        impl Leaf {
14            $(
15                pub const $name: Leaf = Leaf($code);
16            )*
17        }
18
19        static LEAF_NAMES: &[(Leaf, &str)] = &[
20            $(
21                (Leaf($code), stringify!($name)),
22            )*
23        ];
24    }
25}
26
27cv_leaf! {
28    0x0001, LF_MODIFIER_16t;
29    0x0002, LF_POINTER_16t;
30    0x0003, LF_ARRAY_16t;
31    0x0004, LF_CLASS_16t;
32    0x0005, LF_STRUCTURE_16t;
33    0x0006, LF_UNION_16t;
34    0x0007, LF_ENUM_16t;
35    0x0008, LF_PROCEDURE_16t;
36    0x0009, LF_MFUNCTION_16t;
37    0x000a, LF_VTSHAPE;
38    0x000c, LF_COBOL1;
39    0x000e, LF_LABEL;
40    0x000f, LF_NULL;
41    0x0014, LF_ENDPRECOMP;
42    0x020c, LF_REFSYM;
43    0x040b, LF_FRIENDCLS;   // (in field list) friend class
44    0x1001, LF_MODIFIER;
45    0x1002, LF_POINTER;
46    0x1008, LF_PROCEDURE;
47    0x1009, LF_MFUNCTION;
48    0x100a, LF_COBOL0;
49    0x100b, LF_BARRAY;
50    0x100d, LF_VFTPATH;
51    0x100f, LF_OEM;
52    0x1011, LF_OEM2;
53    0x1200, LF_SKIP;
54    0x1201, LF_ARGLIST;
55    0x1203, LF_FIELDLIST;
56    0x1204, LF_DERIVED;
57    0x1205, LF_BITFIELD;
58    0x1206, LF_METHODLIST;
59    0x1207, LF_DIMCONU;
60    0x1208, LF_DIMCONLU;
61    0x1209, LF_DIMVARU;
62    0x120a, LF_DIMVARLU;
63    0x1400, LF_BCLASS;      // (in field list) real (non-virtual) base class
64    0x1401, LF_VBCLASS;     // (in field list) direct virtual base class
65    0x1402, LF_IVBCLASS;    // (in field list) indirect virtual base class
66    0x1404, LF_INDEX;       // (in field list) index to another type record
67    0x1409, LF_VFUNCTAB;    // (in field list) virtual function table pointer
68    0x140c, LF_VFUNCOFF;    // (in field list) virtual function offset
69    0x1502, LF_ENUMERATE;   // (in field list) an enumerator value
70    0x1503, LF_ARRAY;
71    0x1504, LF_CLASS;
72    0x1505, LF_STRUCTURE;
73    0x1506, LF_UNION;
74    0x1507, LF_ENUM;
75    0x1508, LF_DIMARRAY;
76    0x1509, LF_PRECOMP;
77    0x150a, LF_ALIAS;
78    0x150b, LF_DEFARG;
79    0x150c, LF_FRIENDFCN;   // (in field list) friend function
80    0x150d, LF_MEMBER;      // (in field list) data member
81    0x150e, LF_STMEMBER;    // (in field list) static data member
82    0x150f, LF_METHOD;      // (in field list) method group (overloaded methods), not single method
83    0x1510, LF_NESTEDTYPE;  // (in field list) nested type definition
84    0x1511, LF_ONEMETHOD;   // (in field list) a single method
85    0x1512, LF_NESTEDTYPEEX;// (in field list) nested type extended definition
86    0x1514, LF_MANAGED;
87    0x1515, LF_TYPESERVER2;
88    0x1519, LF_INTERFACE;
89    0x151d, LF_VFTABLE;
90
91    // --- end of types ---
92
93    // 0x1601..=0x1607 are only present in IPI stream, not TPI stream.
94
95    0x1601, LF_FUNC_ID;         // global func ID
96    0x1602, LF_MFUNC_ID;        // member func ID
97    0x1603, LF_BUILDINFO;       // build info: tool, version, command line, src/pdb file
98    0x1604, LF_SUBSTR_LIST;     // similar to LF_ARGLIST, for list of sub strings
99    0x1605, LF_STRING_ID;       // string ID
100
101    // source and line on where an UDT is defined
102    // only generated by compiler
103    0x1606, LF_UDT_SRC_LINE;
104
105    // module, source and line on where an UDT is defined
106    // only generated by linker
107    0x1607, LF_UDT_MOD_SRC_LINE;
108
109    // The following four kinds were added to the wrong place in this enumeration.
110    // They should have been added befor LF_TYPE_LAST.
111    // But now it has been too late to change this :-(
112
113    0x1608, LF_CLASS2;       // LF_CLASS with 32bit property field
114    0x1609, LF_STRUCTURE2;   // LF_STRUCTURE with 32bit property field
115    0x160a, LF_UNION2;       // LF_UNION with 32bit property field
116    0x160b, LF_INTERFACE2;   // LF_INTERFACE with 32bit property field
117
118    // These values are used for encoding numeric constants.
119//    0x8000, LF_NUMERIC;
120    0x8000, LF_CHAR;            // i8
121    0x8001, LF_SHORT;           // i16
122    0x8002, LF_USHORT;          // u16
123    0x8003, LF_LONG;            // i32
124    0x8004, LF_ULONG;           // u32
125    0x8005, LF_REAL32;          // f32
126    0x8006, LF_REAL64;          // f64
127    0x8007, LF_REAL80;
128    0x8008, LF_REAL128;
129    0x8009, LF_QUADWORD;        // i64
130    0x800a, LF_UQUADWORD;       // u64
131    0x800b, LF_REAL48;
132    0x800c, LF_COMPLEX32;
133    0x800d, LF_COMPLEX64;
134    0x800e, LF_COMPLEX80;
135    0x800f, LF_COMPLEX128;
136    0x8010, LF_VARSTRING;       // string prefixed with u16 length
137    0x8017, LF_OCTWORD;         // i128
138    0x8018, LF_UOCTWORD;        // u128
139    0x8019, LF_DECIMAL;
140    0x801a, LF_DATE;            // 8 bytes
141    0x801b, LF_UTF8STRING;      // NUL-terminated UTF-8 string
142    0x801c, LF_REAL16;
143}
144
145impl std::fmt::Debug for Leaf {
146    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
147        if let Ok(index) = LEAF_NAMES.binary_search_by_key(self, |ii| ii.0) {
148            fmt.write_str(LEAF_NAMES[index].1)
149        } else {
150            let b0 = (self.0 & 0xff) as u8;
151            let b1 = (self.0 >> 8) as u8;
152            fn to_c(b: u8) -> char {
153                if (32..=126).contains(&b) {
154                    char::from(b)
155                } else {
156                    '_'
157                }
158            }
159
160            write!(fmt, "Leaf(??{:04x} {}{})", self.0, to_c(b0), to_c(b1))
161        }
162    }
163}
164
165impl Leaf {
166    /// True if this `Leaf` codes for an immediate numeric constant.
167    pub fn is_immediate_numeric(self) -> bool {
168        self.0 < 0x8000
169    }
170
171    /// Checks whether this `Leaf` can be used as a type record.
172    pub fn can_start_record(self) -> bool {
173        matches!(
174            self,
175            Leaf::LF_MODIFIER
176                | Leaf::LF_POINTER
177                | Leaf::LF_ARRAY
178                | Leaf::LF_CLASS
179                | Leaf::LF_STRUCTURE
180                | Leaf::LF_UNION
181                | Leaf::LF_ENUM
182                | Leaf::LF_PROCEDURE
183                | Leaf::LF_MFUNCTION
184                | Leaf::LF_VTSHAPE
185                | Leaf::LF_COBOL0
186                | Leaf::LF_COBOL1
187                | Leaf::LF_BARRAY
188                | Leaf::LF_LABEL
189                | Leaf::LF_NULL
190                | Leaf::LF_DIMARRAY
191                | Leaf::LF_VFTPATH
192                | Leaf::LF_PRECOMP
193                | Leaf::LF_ENDPRECOMP
194                | Leaf::LF_OEM
195                | Leaf::LF_OEM2
196                | Leaf::LF_ALIAS
197                | Leaf::LF_MANAGED
198                | Leaf::LF_TYPESERVER2
199        )
200    }
201
202    /// Checks whether this `Leaf` can be used within a field list record.
203    pub fn is_nested_leaf(self) -> bool {
204        matches!(
205            self,
206            Leaf::LF_SKIP
207                | Leaf::LF_ARGLIST
208                | Leaf::LF_DEFARG
209                | Leaf::LF_FIELDLIST
210                | Leaf::LF_DERIVED
211                | Leaf::LF_BITFIELD
212                | Leaf::LF_METHODLIST
213                | Leaf::LF_DIMCONU
214                | Leaf::LF_DIMCONLU
215                | Leaf::LF_DIMVARU
216                | Leaf::LF_DIMVARLU
217                | Leaf::LF_REFSYM
218        )
219    }
220
221    /// Indicates whether a given type record can contain references to other type records.
222    pub fn can_reference_types(self) -> bool {
223        matches!(
224            self,
225            Leaf::LF_MODIFIER
226                | Leaf::LF_POINTER
227                | Leaf::LF_ARRAY
228                | Leaf::LF_CLASS
229                | Leaf::LF_UNION
230                | Leaf::LF_ENUM
231                | Leaf::LF_PROCEDURE
232        )
233    }
234}