1#[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; 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; 0x1401, LF_VBCLASS; 0x1402, LF_IVBCLASS; 0x1404, LF_INDEX; 0x1409, LF_VFUNCTAB; 0x140c, LF_VFUNCOFF; 0x1502, LF_ENUMERATE; 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; 0x150d, LF_MEMBER; 0x150e, LF_STMEMBER; 0x150f, LF_METHOD; 0x1510, LF_NESTEDTYPE; 0x1511, LF_ONEMETHOD; 0x1512, LF_NESTEDTYPEEX;0x1514, LF_MANAGED;
87 0x1515, LF_TYPESERVER2;
88 0x1519, LF_INTERFACE;
89 0x151d, LF_VFTABLE;
90
91 0x1601, LF_FUNC_ID; 0x1602, LF_MFUNC_ID; 0x1603, LF_BUILDINFO; 0x1604, LF_SUBSTR_LIST; 0x1605, LF_STRING_ID; 0x1606, LF_UDT_SRC_LINE;
104
105 0x1607, LF_UDT_MOD_SRC_LINE;
108
109 0x1608, LF_CLASS2; 0x1609, LF_STRUCTURE2; 0x160a, LF_UNION2; 0x160b, LF_INTERFACE2; 0x8000, LF_CHAR; 0x8001, LF_SHORT; 0x8002, LF_USHORT; 0x8003, LF_LONG; 0x8004, LF_ULONG; 0x8005, LF_REAL32; 0x8006, LF_REAL64; 0x8007, LF_REAL80;
128 0x8008, LF_REAL128;
129 0x8009, LF_QUADWORD; 0x800a, LF_UQUADWORD; 0x800b, LF_REAL48;
132 0x800c, LF_COMPLEX32;
133 0x800d, LF_COMPLEX64;
134 0x800e, LF_COMPLEX80;
135 0x800f, LF_COMPLEX128;
136 0x8010, LF_VARSTRING; 0x8017, LF_OCTWORD; 0x8018, LF_UOCTWORD; 0x8019, LF_DECIMAL;
140 0x801a, LF_DATE; 0x801b, LF_UTF8STRING; 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 pub fn is_immediate_numeric(self) -> bool {
168 self.0 < 0x8000
169 }
170
171 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 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 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}