1use crate::{
9 CustDataEntry, Error, FuncRecord, GuidEntry, ImpFile, ImpInfo, NameEntry, ParameterInfo,
10 RefRecord, TypeInfoEntry, TypeLib, VarRecord,
11 util::{read_i32_le, read_u16_le, read_u32_le},
12};
13
14pub struct TypeInfoIter<'a> {
18 lib: &'a TypeLib<'a>,
19 index: usize,
20}
21
22impl<'a> TypeInfoIter<'a> {
23 pub(crate) fn new(lib: &'a TypeLib<'a>) -> Self {
25 Self { lib, index: 0 }
26 }
27}
28
29impl<'a> Iterator for TypeInfoIter<'a> {
30 type Item = Result<TypeInfoEntry<'a>, Error>;
31
32 fn next(&mut self) -> Option<Self::Item> {
33 if self.index >= self.lib.typeinfo_count() {
34 return None;
35 }
36 let result = self.lib.typeinfo(self.index);
37 self.index += 1;
38 Some(result)
39 }
40
41 fn size_hint(&self) -> (usize, Option<usize>) {
42 let rem = self.lib.typeinfo_count() - self.index;
43 (rem, Some(rem))
44 }
45}
46
47pub struct FuncIter<'a> {
49 data: &'a [u8],
50 pos: usize,
51 end: usize,
52 remaining: usize,
53}
54
55impl<'a> FuncIter<'a> {
56 pub(crate) fn new(data: &'a [u8], pos: usize, end: usize, remaining: usize) -> Self {
58 Self {
59 data,
60 pos,
61 end,
62 remaining,
63 }
64 }
65}
66
67impl<'a> Iterator for FuncIter<'a> {
68 type Item = FuncRecord<'a>;
69
70 fn next(&mut self) -> Option<Self::Item> {
71 if self.remaining == 0 || self.pos >= self.end {
72 return None;
73 }
74 let info_raw = read_u32_le(self.data, self.pos)?;
75 let size = (info_raw & 0xFFFF) as usize;
76 if size < FuncRecord::BASE_SIZE {
77 return None;
78 }
79 let end = self.pos.checked_add(size)?;
80 if end > self.data.len() {
81 return None;
82 }
83 let record = FuncRecord::new(&self.data[self.pos..end]);
84 self.pos = end;
85 self.remaining -= 1;
86 Some(record)
87 }
88
89 fn size_hint(&self) -> (usize, Option<usize>) {
90 (0, Some(self.remaining))
91 }
92}
93
94pub struct VarIter<'a> {
96 data: &'a [u8],
97 pos: usize,
98 end: usize,
99 remaining: usize,
100}
101
102impl<'a> VarIter<'a> {
103 pub(crate) fn new(data: &'a [u8], pos: usize, end: usize, remaining: usize) -> Self {
105 Self {
106 data,
107 pos,
108 end,
109 remaining,
110 }
111 }
112}
113
114impl<'a> Iterator for VarIter<'a> {
115 type Item = VarRecord<'a>;
116
117 fn next(&mut self) -> Option<Self::Item> {
118 if self.remaining == 0 || self.pos >= self.end {
119 return None;
120 }
121 let info_raw = read_u32_le(self.data, self.pos)?;
122 let size = (info_raw & 0xFFFF) as usize;
123 if size < VarRecord::BASE_SIZE {
124 return None;
125 }
126 let end = self.pos.checked_add(size)?;
127 if end > self.data.len() {
128 return None;
129 }
130 let record = VarRecord::new(&self.data[self.pos..end]);
131 self.pos = end;
132 self.remaining -= 1;
133 Some(record)
134 }
135
136 fn size_hint(&self) -> (usize, Option<usize>) {
137 (0, Some(self.remaining))
138 }
139}
140
141pub struct ParamIter<'a> {
143 data: &'a [u8],
144 pos: usize,
145 remaining: usize,
146}
147
148impl<'a> ParamIter<'a> {
149 pub(crate) fn new(data: &'a [u8], pos: usize, remaining: usize) -> Self {
151 Self {
152 data,
153 pos,
154 remaining,
155 }
156 }
157}
158
159impl<'a> Iterator for ParamIter<'a> {
160 type Item = ParameterInfo<'a>;
161
162 fn next(&mut self) -> Option<Self::Item> {
163 if self.remaining == 0 {
164 return None;
165 }
166 let end = self.pos.checked_add(ParameterInfo::SIZE)?;
167 if end > self.data.len() {
168 return None;
169 }
170 let param = ParameterInfo::new(&self.data[self.pos..end]);
171 self.pos = end;
172 self.remaining -= 1;
173 Some(param)
174 }
175
176 fn size_hint(&self) -> (usize, Option<usize>) {
177 (self.remaining, Some(self.remaining))
178 }
179}
180
181impl ExactSizeIterator for ParamIter<'_> {}
182
183pub struct GuidEntryIter<'a> {
185 data: &'a [u8],
186 pos: usize,
187 end: usize,
188}
189
190impl<'a> GuidEntryIter<'a> {
191 pub(crate) fn new(data: &'a [u8], pos: usize, end: usize) -> Self {
193 Self { data, pos, end }
194 }
195}
196
197impl<'a> Iterator for GuidEntryIter<'a> {
198 type Item = GuidEntry<'a>;
199
200 fn next(&mut self) -> Option<Self::Item> {
201 let end = self.pos.checked_add(GuidEntry::SIZE)?;
202 if end > self.end || end > self.data.len() {
203 return None;
204 }
205 let entry = GuidEntry::new(&self.data[self.pos..end]);
206 self.pos = end;
207 Some(entry)
208 }
209}
210
211pub struct NameIter<'a> {
216 data: &'a [u8],
217 pos: usize,
218 end: usize,
219 seg_start: usize,
220}
221
222impl<'a> NameIter<'a> {
223 pub(crate) fn new(data: &'a [u8], pos: usize, end: usize, seg_start: usize) -> Self {
225 Self {
226 data,
227 pos,
228 end,
229 seg_start,
230 }
231 }
232}
233
234impl<'a> Iterator for NameIter<'a> {
235 type Item = NameEntry<'a>;
236
237 fn next(&mut self) -> Option<Self::Item> {
238 let header_end = self.pos.checked_add(12)?;
240 if header_end > self.end || header_end > self.data.len() {
241 return None;
242 }
243 let hreftype = read_i32_le(self.data, self.pos)?;
244 let next_hash = read_i32_le(self.data, self.pos + 4)?;
245 let namelen = *self.data.get(self.pos + 8)? as usize;
246 let flags = *self.data.get(self.pos + 9)?;
247 let hashcode = read_u16_le(self.data, self.pos + 10)?;
248 let name_start = header_end;
249 let name_end = name_start.checked_add(namelen)?;
250 if name_end > self.data.len() {
251 return None;
252 }
253 let offset = self.pos - self.seg_start;
254 let name = std::str::from_utf8(self.data.get(name_start..name_end)?).ok()?;
255 let padded = (namelen + 3) & !3;
257 self.pos = name_start.checked_add(padded)?;
258 Some(NameEntry::new(
259 offset, name, hreftype, next_hash, flags, hashcode,
260 ))
261 }
262}
263
264pub struct ImplTypeIter<'a> {
269 data: &'a [u8],
270 seg_offset: usize,
271 next_offset: i32,
272}
273
274impl<'a> ImplTypeIter<'a> {
275 pub(crate) fn new(data: &'a [u8], seg_offset: usize, next_offset: i32) -> Self {
277 Self {
278 data,
279 seg_offset,
280 next_offset,
281 }
282 }
283}
284
285impl<'a> Iterator for ImplTypeIter<'a> {
286 type Item = RefRecord<'a>;
287
288 fn next(&mut self) -> Option<Self::Item> {
289 if self.next_offset < 0 {
290 return None;
291 }
292 let abs = self.seg_offset.checked_add(self.next_offset as usize)?;
293 let end = abs.checked_add(RefRecord::SIZE)?;
294 if end > self.data.len() {
295 return None;
296 }
297 let rec = RefRecord::new(&self.data[abs..end]);
298 self.next_offset = rec.onext();
299 Some(rec)
300 }
301}
302
303pub struct ImpInfoIter<'a> {
305 data: &'a [u8],
306 pos: usize,
307 end: usize,
308}
309
310impl<'a> ImpInfoIter<'a> {
311 pub(crate) fn new(data: &'a [u8], pos: usize, end: usize) -> Self {
313 Self { data, pos, end }
314 }
315}
316
317impl<'a> Iterator for ImpInfoIter<'a> {
318 type Item = ImpInfo<'a>;
319
320 fn next(&mut self) -> Option<Self::Item> {
321 let end = self.pos.checked_add(ImpInfo::SIZE)?;
322 if end > self.end || end > self.data.len() {
323 return None;
324 }
325 let entry = ImpInfo::new(&self.data[self.pos..end]);
326 self.pos = end;
327 Some(entry)
328 }
329}
330
331pub struct ImpFileIter<'a> {
336 data: &'a [u8],
337 pos: usize,
338 end: usize,
339}
340
341impl<'a> ImpFileIter<'a> {
342 pub(crate) fn new(data: &'a [u8], pos: usize, end: usize) -> Self {
344 Self { data, pos, end }
345 }
346}
347
348impl<'a> Iterator for ImpFileIter<'a> {
349 type Item = ImpFile<'a>;
350
351 fn next(&mut self) -> Option<Self::Item> {
352 if self.pos.checked_add(ImpFile::HEADER_SIZE)? > self.end {
353 return None;
354 }
355 let size_field = read_u16_le(self.data, self.pos + 0x0C)?;
356 let name_len = (size_field >> 2) as usize;
357 let unpadded = ImpFile::HEADER_SIZE + name_len;
358 let entry_size = (unpadded + 3) & !3;
359 let end = self.pos.checked_add(entry_size)?;
360 if end > self.end || end > self.data.len() {
361 return None;
362 }
363 let entry = ImpFile::new(&self.data[self.pos..end]);
364 self.pos = end;
365 Some(entry)
366 }
367}
368
369pub struct CustDataIter<'a> {
374 data: &'a [u8],
375 seg_offset: usize,
376 next_offset: i32,
377}
378
379impl<'a> CustDataIter<'a> {
380 pub(crate) fn new(data: &'a [u8], seg_offset: usize, next_offset: i32) -> Self {
382 Self {
383 data,
384 seg_offset,
385 next_offset,
386 }
387 }
388}
389
390impl<'a> Iterator for CustDataIter<'a> {
391 type Item = CustDataEntry<'a>;
392
393 fn next(&mut self) -> Option<Self::Item> {
394 if self.next_offset < 0 {
395 return None;
396 }
397 let abs = self.seg_offset.checked_add(self.next_offset as usize)?;
398 let end = abs.checked_add(CustDataEntry::SIZE)?;
399 if end > self.data.len() {
400 return None;
401 }
402 let entry = CustDataEntry::new(&self.data[abs..end]);
403 self.next_offset = entry.next();
404 Some(entry)
405 }
406}