1use super::*;
4use tracing::error;
5
6#[derive(Clone)]
9pub struct FieldList<'a> {
10 #[allow(missing_docs)]
11 pub bytes: &'a [u8],
12}
13
14impl<'a> FieldList<'a> {
15 pub fn iter(&self) -> IterFields<'a> {
17 IterFields { bytes: self.bytes }
18 }
19}
20
21impl<'a> Debug for FieldList<'a> {
22 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
23 if f.alternate() {
24 let mut list = f.debug_list();
25 for f in self.iter() {
26 list.entry(&f);
27 }
28 list.finish()
29 } else {
30 f.write_str("FieldList")
31 }
32 }
33}
34
35pub struct IterFields<'a> {
37 #[allow(missing_docs)]
38 pub bytes: &'a [u8],
39}
40
41#[derive(Clone, Debug)]
43#[allow(missing_docs)]
44pub enum Field<'a> {
45 BaseClass(BaseClass<'a>),
46 DirectVirtualBaseClass(DirectVirtualBaseClass<'a>),
47 IndirectVirtualBaseClass(IndirectVirtualBaseClass<'a>),
48 Enumerate(Enumerate<'a>),
49 FriendFn(FriendFn<'a>),
50 Index(TypeIndex),
51 Member(Member<'a>),
52 StaticMember(StaticMember<'a>),
53 Method(Method<'a>),
54 NestedType(NestedType<'a>),
55 VFuncTable(TypeIndex),
56 FriendClass(TypeIndex),
57 OneMethod(OneMethod<'a>),
58 VFuncOffset(VFuncOffset),
59 NestedTypeEx(NestedTypeEx<'a>),
60}
61
62#[derive(Clone, Debug)]
63#[allow(missing_docs)]
64pub struct NestedType<'a> {
65 pub nested_ty: TypeIndex,
66 pub name: &'a BStr,
67}
68
69impl<'a> Parse<'a> for NestedType<'a> {
70 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
71 p.skip(2)?; Ok(Self {
73 nested_ty: p.type_index()?,
74 name: p.strz()?,
75 })
76 }
77}
78
79#[derive(Clone, Debug)]
80#[allow(missing_docs)]
81pub struct BaseClass<'a> {
82 pub attr: u16,
83 pub ty: TypeIndex,
84 pub offset: Number<'a>,
85}
86
87impl<'a> Parse<'a> for BaseClass<'a> {
88 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
89 let attr = p.u16()?;
90 let ty = p.type_index()?;
91 let offset = p.number()?;
92 Ok(BaseClass { attr, ty, offset })
93 }
94}
95
96#[allow(missing_docs)]
98#[repr(C)]
99#[derive(Clone, Debug, IntoBytes, FromBytes, Immutable, KnownLayout, Unaligned)]
100pub struct VirtualBaseClassFixed {
101 pub attr: U16<LE>,
102 pub btype: TypeIndexLe,
103 pub vbtype: TypeIndexLe,
104}
105
106#[allow(missing_docs)]
107#[derive(Clone, Debug)]
108pub struct DirectVirtualBaseClass<'a> {
109 pub fixed: &'a VirtualBaseClassFixed,
110 pub vbpoff: Number<'a>,
111 pub vboff: Number<'a>,
112}
113
114impl<'a> Parse<'a> for DirectVirtualBaseClass<'a> {
115 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
116 Ok(Self {
117 fixed: p.get()?,
118 vbpoff: p.number()?,
119 vboff: p.number()?,
120 })
121 }
122}
123
124#[allow(missing_docs)]
125#[derive(Clone, Debug)]
126pub struct IndirectVirtualBaseClass<'a> {
127 pub fixed: &'a VirtualBaseClassFixed,
128 pub vbpoff: Number<'a>,
129 pub vboff: Number<'a>,
130}
131
132impl<'a> Parse<'a> for IndirectVirtualBaseClass<'a> {
133 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
134 let fixed = p.get()?;
135 let vbpoff = p.number()?;
136 let vboff = p.number()?;
137 Ok(Self {
138 fixed,
139 vbpoff,
140 vboff,
141 })
142 }
143}
144
145#[allow(missing_docs)]
146#[derive(Clone)]
147pub struct Enumerate<'a> {
148 pub attr: u16,
149 pub value: Number<'a>,
150 pub name: &'a BStr,
151}
152
153impl<'a> Parse<'a> for Enumerate<'a> {
154 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
155 Ok(Self {
156 attr: p.u16()?,
157 value: p.number()?,
158 name: p.strz()?,
159 })
160 }
161}
162
163impl<'a> Debug for Enumerate<'a> {
164 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
165 write!(f, "{} = {}", self.name, self.value)
166 }
167}
168
169#[allow(missing_docs)]
170#[derive(Clone, Debug)]
171pub struct FriendFn<'a> {
172 pub ty: TypeIndex,
173 pub name: &'a BStr,
174}
175
176impl<'a> Parse<'a> for FriendFn<'a> {
177 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
178 p.skip(2)?; Ok(Self {
180 ty: p.type_index()?,
181 name: p.strz()?,
182 })
183 }
184}
185
186#[allow(missing_docs)]
187#[derive(Clone, Debug)]
188pub struct OneMethod<'a> {
189 pub attr: u16,
190 pub ty: TypeIndex,
191 pub vbaseoff: u32,
192 pub name: &'a BStr,
193}
194
195impl<'a> Parse<'a> for OneMethod<'a> {
196 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
197 let attr = p.u16()?;
198 let ty = p.type_index()?;
199 let vbaseoff = if introduces_virtual(attr) {
200 p.u32()?
201 } else {
202 0
203 };
204 let name = p.strz()?;
205 Ok(OneMethod {
206 attr,
207 ty,
208 vbaseoff,
209 name,
210 })
211 }
212}
213
214#[allow(missing_docs)]
215#[derive(Clone, Debug)]
216pub struct VFuncOffset {
217 pub vtable_ty: TypeIndex,
218 pub offset: u32,
219}
220
221impl<'a> Parse<'a> for VFuncOffset {
222 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
223 p.skip(2)?; let vtable_ty = p.type_index()?;
225 let offset = p.u32()?;
226 Ok(Self { vtable_ty, offset })
227 }
228}
229
230#[allow(missing_docs)]
231#[derive(Clone, Debug)]
232pub struct NestedTypeEx<'a> {
233 pub attr: u16,
234 pub ty: TypeIndex,
235 pub name: &'a BStr,
236}
237
238impl<'a> Parse<'a> for NestedTypeEx<'a> {
239 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
240 let attr = p.u16()?;
241 let ty = p.type_index()?;
242 let name = p.strz()?;
243 Ok(Self { attr, ty, name })
244 }
245}
246
247#[allow(missing_docs)]
248#[derive(Clone, Debug)]
249pub struct Member<'a> {
250 pub attr: u16,
251 pub ty: TypeIndex,
252 pub offset: Number<'a>,
253 pub name: &'a BStr,
254}
255
256impl<'a> Parse<'a> for Member<'a> {
257 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
258 Ok(Self {
259 attr: p.u16()?,
260 ty: p.type_index()?,
261 offset: p.number()?,
262 name: p.strz()?,
263 })
264 }
265}
266
267#[allow(missing_docs)]
268#[derive(Clone, Debug)]
269pub struct StaticMember<'a> {
270 pub attr: u16,
271 pub ty: TypeIndex,
272 pub name: &'a BStr,
273}
274
275impl<'a> Parse<'a> for StaticMember<'a> {
276 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
277 Ok(Self {
278 attr: p.u16()?,
279 ty: p.type_index()?,
280 name: p.strz()?,
281 })
282 }
283}
284
285#[allow(missing_docs)]
286#[derive(Clone, Debug)]
287pub struct Method<'a> {
288 pub count: u16,
289 pub methods: TypeIndex,
290 pub name: &'a BStr,
291}
292
293impl<'a> Parse<'a> for Method<'a> {
294 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
295 Ok(Self {
296 count: p.u16()?,
297 methods: p.type_index()?,
298 name: p.strz()?,
299 })
300 }
301}
302
303impl<'a> Iterator for IterFields<'a> {
304 type Item = Field<'a>;
305
306 fn next(&mut self) -> Option<Self::Item> {
307 if self.bytes.is_empty() {
308 return None;
309 }
310 let mut p = Parser::new(self.bytes);
311
312 let rest = p.peek_rest();
313
314 let mut padding_len = 0;
316 while padding_len < rest.len() && rest[padding_len] >= 0xf0 {
317 padding_len += 1;
318 }
319 if padding_len > 0 {
320 let _ = p.skip(padding_len);
321 }
322
323 if p.is_empty() {
324 return None;
325 }
326
327 match Field::parse(&mut p) {
328 Ok(f) => {
329 self.bytes = p.into_rest();
330 Some(f)
331 }
332 Err(ParserError) => None,
333 }
334 }
335}
336
337impl<'a> Field<'a> {
338 pub fn parse(p: &mut Parser<'a>) -> Result<Self, ParserError> {
347 let item_kind = Leaf(p.u16()?);
348
349 Ok(match item_kind {
350 Leaf::LF_BCLASS => Self::BaseClass(p.parse()?),
351 Leaf::LF_VBCLASS => Self::DirectVirtualBaseClass(p.parse()?),
352 Leaf::LF_IVBCLASS => Self::IndirectVirtualBaseClass(p.parse()?),
353 Leaf::LF_ENUMERATE => Self::Enumerate(p.parse()?),
354 Leaf::LF_FRIENDFCN => Self::FriendFn(p.parse()?),
355
356 Leaf::LF_INDEX => {
357 p.skip(2)?; let ty = p.type_index()?;
359 Self::Index(ty)
360 }
361
362 Leaf::LF_MEMBER => Self::Member(p.parse()?),
363 Leaf::LF_STMEMBER => Self::StaticMember(p.parse()?),
364 Leaf::LF_METHOD => Self::Method(p.parse()?),
365 Leaf::LF_NESTEDTYPE => Self::NestedType(p.parse()?),
366
367 Leaf::LF_VFUNCTAB => {
368 p.skip(2)?; let vtable_ty = p.type_index()?;
370 Self::VFuncTable(vtable_ty)
371 }
372
373 Leaf::LF_FRIENDCLS => {
374 p.skip(2)?; let ty = p.type_index()?; Self::FriendClass(ty)
377 }
378
379 Leaf::LF_ONEMETHOD => Self::OneMethod(p.parse()?),
380 Leaf::LF_VFUNCOFF => Self::VFuncOffset(p.parse()?),
381 Leaf::LF_NESTEDTYPEEX => Self::NestedTypeEx(p.parse()?),
382
383 unknown_item_kind => {
384 error!(?unknown_item_kind, "unrecognized item within LF_FIELDLIST",);
385 return Err(ParserError::new());
386 }
387 })
388 }
389}