dissect.cstruct 5.0.dev7__py3-none-any.whl → 5.0.dev9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dissect/cstruct/__init__.py +12 -0
- dissect/cstruct/bitbuffer.py +6 -6
- dissect/cstruct/compiler.py +31 -33
- dissect/cstruct/cstruct.py +60 -28
- dissect/cstruct/tools/stubgen.py +5 -5
- dissect/cstruct/types/base.py +121 -59
- dissect/cstruct/types/char.py +5 -5
- dissect/cstruct/types/enum.py +15 -15
- dissect/cstruct/types/int.py +4 -4
- dissect/cstruct/types/packed.py +26 -21
- dissect/cstruct/types/pointer.py +24 -24
- dissect/cstruct/types/structure.py +72 -51
- dissect/cstruct/types/void.py +1 -1
- dissect/cstruct/types/wchar.py +5 -5
- dissect/cstruct/util.py +100 -3
- {dissect_cstruct-5.0.dev7.dist-info → dissect_cstruct-5.0.dev9.dist-info}/METADATA +1 -1
- dissect_cstruct-5.0.dev9.dist-info/RECORD +30 -0
- dissect_cstruct-5.0.dev7.dist-info/RECORD +0 -32
- dissect_cstruct-5.0.dev7.dist-info/scm_file_list.json +0 -78
- dissect_cstruct-5.0.dev7.dist-info/scm_version.json +0 -8
- {dissect_cstruct-5.0.dev7.dist-info → dissect_cstruct-5.0.dev9.dist-info}/WHEEL +0 -0
- {dissect_cstruct-5.0.dev7.dist-info → dissect_cstruct-5.0.dev9.dist-info}/entry_points.txt +0 -0
- {dissect_cstruct-5.0.dev7.dist-info → dissect_cstruct-5.0.dev9.dist-info}/licenses/COPYRIGHT +0 -0
- {dissect_cstruct-5.0.dev7.dist-info → dissect_cstruct-5.0.dev9.dist-info}/licenses/LICENSE +0 -0
- {dissect_cstruct-5.0.dev7.dist-info → dissect_cstruct-5.0.dev9.dist-info}/top_level.txt +0 -0
dissect/cstruct/__init__.py
CHANGED
|
@@ -30,12 +30,18 @@ from dissect.cstruct.types import (
|
|
|
30
30
|
)
|
|
31
31
|
from dissect.cstruct.util import (
|
|
32
32
|
dumpstruct,
|
|
33
|
+
f16,
|
|
34
|
+
f32,
|
|
35
|
+
f64,
|
|
33
36
|
hexdump,
|
|
34
37
|
p8,
|
|
35
38
|
p16,
|
|
36
39
|
p32,
|
|
37
40
|
p64,
|
|
38
41
|
pack,
|
|
42
|
+
pf16,
|
|
43
|
+
pf32,
|
|
44
|
+
pf64,
|
|
39
45
|
swap,
|
|
40
46
|
swap16,
|
|
41
47
|
swap32,
|
|
@@ -75,12 +81,18 @@ __all__ = [
|
|
|
75
81
|
"ctypes",
|
|
76
82
|
"ctypes_type",
|
|
77
83
|
"dumpstruct",
|
|
84
|
+
"f16",
|
|
85
|
+
"f32",
|
|
86
|
+
"f64",
|
|
78
87
|
"hexdump",
|
|
79
88
|
"p8",
|
|
80
89
|
"p16",
|
|
81
90
|
"p32",
|
|
82
91
|
"p64",
|
|
83
92
|
"pack",
|
|
93
|
+
"pf16",
|
|
94
|
+
"pf32",
|
|
95
|
+
"pf64",
|
|
84
96
|
"swap",
|
|
85
97
|
"swap16",
|
|
86
98
|
"swap32",
|
dissect/cstruct/bitbuffer.py
CHANGED
|
@@ -19,11 +19,11 @@ class BitBuffer:
|
|
|
19
19
|
|
|
20
20
|
def read(self, field_type: type[BaseType], bits: int) -> int:
|
|
21
21
|
if self._remaining == 0 or self._type != field_type:
|
|
22
|
-
if field_type.
|
|
22
|
+
if field_type.__size__ is None:
|
|
23
23
|
raise ValueError("Reading variable-length fields is unsupported")
|
|
24
24
|
|
|
25
25
|
self._type = field_type
|
|
26
|
-
self._remaining = field_type.
|
|
26
|
+
self._remaining = field_type.__size__ * 8
|
|
27
27
|
self._buffer = field_type._read(self.stream, endian=self.endian)
|
|
28
28
|
|
|
29
29
|
if isinstance(self._buffer, bytes):
|
|
@@ -51,17 +51,17 @@ class BitBuffer:
|
|
|
51
51
|
if self._type:
|
|
52
52
|
self.flush()
|
|
53
53
|
|
|
54
|
-
if field_type.
|
|
54
|
+
if field_type.__size__ is None:
|
|
55
55
|
raise ValueError("Writing variable-length fields is unsupported")
|
|
56
56
|
|
|
57
|
-
self._remaining = field_type.
|
|
57
|
+
self._remaining = field_type.__size__ * 8
|
|
58
58
|
self._type = field_type
|
|
59
59
|
|
|
60
|
-
if self._type is None or self._type.
|
|
60
|
+
if self._type is None or self._type.__size__ is None:
|
|
61
61
|
raise ValueError("Invalid state")
|
|
62
62
|
|
|
63
63
|
if self.endian == "<":
|
|
64
|
-
self._buffer |= data << (self._type.
|
|
64
|
+
self._buffer |= data << (self._type.__size__ * 8 - self._remaining)
|
|
65
65
|
else:
|
|
66
66
|
self._buffer |= data << (self._remaining - bits)
|
|
67
67
|
|
dissect/cstruct/compiler.py
CHANGED
|
@@ -11,6 +11,7 @@ from typing import TYPE_CHECKING
|
|
|
11
11
|
from dissect.cstruct.bitbuffer import BitBuffer
|
|
12
12
|
from dissect.cstruct.types import (
|
|
13
13
|
Array,
|
|
14
|
+
BaseArray,
|
|
14
15
|
Char,
|
|
15
16
|
CharArray,
|
|
16
17
|
Flag,
|
|
@@ -24,18 +25,15 @@ from dissect.cstruct.types import (
|
|
|
24
25
|
Wchar,
|
|
25
26
|
WcharArray,
|
|
26
27
|
)
|
|
27
|
-
from dissect.cstruct.types.base import BaseArray
|
|
28
28
|
from dissect.cstruct.types.enum import EnumMetaType
|
|
29
|
-
from dissect.cstruct.
|
|
29
|
+
from dissect.cstruct.util import _struct
|
|
30
30
|
|
|
31
31
|
if TYPE_CHECKING:
|
|
32
32
|
from collections.abc import Iterator
|
|
33
33
|
from types import MethodType
|
|
34
34
|
|
|
35
35
|
from dissect.cstruct.cstruct import cstruct
|
|
36
|
-
from dissect.cstruct.types import
|
|
37
|
-
BaseType,
|
|
38
|
-
)
|
|
36
|
+
from dissect.cstruct.types import BaseType
|
|
39
37
|
from dissect.cstruct.types.structure import Field
|
|
40
38
|
|
|
41
39
|
SUPPORTED_TYPES = (
|
|
@@ -60,7 +58,7 @@ python_compile = compile
|
|
|
60
58
|
|
|
61
59
|
|
|
62
60
|
def compile(structure: type[Structure]) -> type[Structure]:
|
|
63
|
-
return Compiler(structure.
|
|
61
|
+
return Compiler(structure.__cs__).compile(structure)
|
|
64
62
|
|
|
65
63
|
|
|
66
64
|
class Compiler:
|
|
@@ -165,7 +163,7 @@ class _ReadSourceGenerator:
|
|
|
165
163
|
field_type = field.type
|
|
166
164
|
|
|
167
165
|
if isinstance(field_type, EnumMetaType):
|
|
168
|
-
field_type = field_type.
|
|
166
|
+
field_type = field_type.__type__
|
|
169
167
|
|
|
170
168
|
if not issubclass(field_type, SUPPORTED_TYPES):
|
|
171
169
|
raise TypeError(f"Unsupported type for compiler: {field_type}")
|
|
@@ -190,7 +188,7 @@ class _ReadSourceGenerator:
|
|
|
190
188
|
|
|
191
189
|
# Array of structures and multi-dimensional arrays
|
|
192
190
|
elif issubclass(field_type, (Array, CharArray, WcharArray)) and (
|
|
193
|
-
issubclass(field_type.
|
|
191
|
+
issubclass(field_type.__type__, Structure) or issubclass(field_type.__type__, BaseArray) or is_dynamic
|
|
194
192
|
):
|
|
195
193
|
yield from flush()
|
|
196
194
|
yield from align_to_field(field)
|
|
@@ -224,22 +222,22 @@ class _ReadSourceGenerator:
|
|
|
224
222
|
yield from flush()
|
|
225
223
|
|
|
226
224
|
if self.align:
|
|
227
|
-
yield f"stream.seek(-stream.tell() & (cls.
|
|
225
|
+
yield f"stream.seek(-stream.tell() & (cls.__alignment__ - 1), {io.SEEK_CUR})"
|
|
228
226
|
|
|
229
227
|
def _generate_structure(self, field: Field) -> Iterator[str]:
|
|
230
228
|
template = f"""
|
|
231
|
-
{"_s = stream.tell()" if field.type.
|
|
229
|
+
{"_s = stream.tell()" if field.type.__dynamic__ else ""}
|
|
232
230
|
r["{field._name}"] = {self._map_field(field)}._read(stream, context=r, endian=endian)
|
|
233
|
-
{f's["{field._name}"] = stream.tell() - _s' if field.type.
|
|
231
|
+
{f's["{field._name}"] = stream.tell() - _s' if field.type.__dynamic__ else ""}
|
|
234
232
|
"""
|
|
235
233
|
|
|
236
234
|
yield dedent(template)
|
|
237
235
|
|
|
238
236
|
def _generate_array(self, field: Field) -> Iterator[str]:
|
|
239
237
|
template = f"""
|
|
240
|
-
{"_s = stream.tell()" if field.type.
|
|
238
|
+
{"_s = stream.tell()" if field.type.__dynamic__ else ""}
|
|
241
239
|
r["{field._name}"] = {self._map_field(field)}._read(stream, context=r, endian=endian)
|
|
242
|
-
{f's["{field._name}"] = stream.tell() - _s' if field.type.
|
|
240
|
+
{f's["{field._name}"] = stream.tell() - _s' if field.type.__dynamic__ else ""}
|
|
243
241
|
"""
|
|
244
242
|
|
|
245
243
|
yield dedent(template)
|
|
@@ -249,12 +247,12 @@ class _ReadSourceGenerator:
|
|
|
249
247
|
read_type = "_t"
|
|
250
248
|
field_type = field.type
|
|
251
249
|
if issubclass(field_type, (Enum, Flag)):
|
|
252
|
-
read_type += ".
|
|
253
|
-
field_type = field_type.
|
|
250
|
+
read_type += ".__type__"
|
|
251
|
+
field_type = field_type.__type__
|
|
254
252
|
|
|
255
253
|
if issubclass(field_type, Char):
|
|
256
|
-
field_type = field_type.
|
|
257
|
-
lookup = "cls.
|
|
254
|
+
field_type = field_type.__cs__.uint8
|
|
255
|
+
lookup = "cls.__cs__.uint8"
|
|
258
256
|
|
|
259
257
|
template = f"""
|
|
260
258
|
_t = {lookup}
|
|
@@ -279,17 +277,17 @@ class _ReadSourceGenerator:
|
|
|
279
277
|
read_type = _get_read_type(self.cs, field_type)
|
|
280
278
|
|
|
281
279
|
if issubclass(field_type, (Array, CharArray, WcharArray)):
|
|
282
|
-
count = field_type.
|
|
283
|
-
read_type = _get_read_type(self.cs, field_type.
|
|
280
|
+
count = field_type.__num_entries__
|
|
281
|
+
read_type = _get_read_type(self.cs, field_type.__type__)
|
|
284
282
|
|
|
285
283
|
if issubclass(read_type, (Char, Wchar, Int)):
|
|
286
|
-
count *= read_type.
|
|
284
|
+
count *= read_type.__size__
|
|
287
285
|
getter = f"buf[{size}:{size + count}]"
|
|
288
286
|
else:
|
|
289
287
|
getter = f"data[{slice_index}:{slice_index + count}]"
|
|
290
288
|
slice_index += count
|
|
291
289
|
elif issubclass(read_type, (Char, Wchar, Int)):
|
|
292
|
-
getter = f"buf[{size}:{size + read_type.
|
|
290
|
+
getter = f"buf[{size}:{size + read_type.__size__}]"
|
|
293
291
|
else:
|
|
294
292
|
getter = f"data[{slice_index}]"
|
|
295
293
|
slice_index += 1
|
|
@@ -304,13 +302,13 @@ class _ReadSourceGenerator:
|
|
|
304
302
|
# Create the final reading code
|
|
305
303
|
if issubclass(field_type, Array):
|
|
306
304
|
reads.append(f"_t = {self._map_field(field)}")
|
|
307
|
-
reads.append("_et = _t.
|
|
305
|
+
reads.append("_et = _t.__type__")
|
|
308
306
|
|
|
309
|
-
if issubclass(field_type.
|
|
307
|
+
if issubclass(field_type.__type__, Int):
|
|
310
308
|
reads.append(f"_b = {getter}")
|
|
311
|
-
item_parser = parser_template.format(type="_et", getter=f"_b[i:i + {field_type.
|
|
312
|
-
list_comp = f"[{item_parser} for i in range(0, {count}, {field_type.
|
|
313
|
-
elif issubclass(field_type.
|
|
309
|
+
item_parser = parser_template.format(type="_et", getter=f"_b[i:i + {field_type.__type__.__size__}]")
|
|
310
|
+
list_comp = f"[{item_parser} for i in range(0, {count}, {field_type.__type__.__size__})]"
|
|
311
|
+
elif issubclass(field_type.__type__, Pointer):
|
|
314
312
|
item_parser = "_et.__new__(_et, e, stream, context=r, endian=endian)"
|
|
315
313
|
list_comp = f"[{item_parser} for e in {getter}]"
|
|
316
314
|
else:
|
|
@@ -329,7 +327,7 @@ class _ReadSourceGenerator:
|
|
|
329
327
|
reads.append(f'r["{field._name}"] = {parser}')
|
|
330
328
|
reads.append("") # Generates a newline in the resulting code
|
|
331
329
|
|
|
332
|
-
size += field_type.
|
|
330
|
+
size += field_type.__size__
|
|
333
331
|
|
|
334
332
|
fmt = _optimize_struct_fmt(info)
|
|
335
333
|
if fmt == "x" or (len(fmt) == 2 and fmt[1] == "x"):
|
|
@@ -372,19 +370,19 @@ def _generate_struct_info(cs: cstruct, fields: list[Field], align: bool = False)
|
|
|
372
370
|
|
|
373
371
|
# Array of more complex types are handled elsewhere
|
|
374
372
|
if issubclass(read_type, (Array, CharArray, WcharArray)):
|
|
375
|
-
count = read_type.
|
|
376
|
-
read_type = _get_read_type(cs, read_type.
|
|
373
|
+
count = read_type.__num_entries__
|
|
374
|
+
read_type = _get_read_type(cs, read_type.__type__)
|
|
377
375
|
|
|
378
376
|
# Take the pack char for Packed
|
|
379
377
|
if issubclass(read_type, Packed):
|
|
380
|
-
yield field, count, read_type.
|
|
378
|
+
yield field, count, read_type.__fmt__
|
|
381
379
|
|
|
382
380
|
# Other types are byte based
|
|
383
381
|
# We don't actually unpack anything here but slice directly out of the buffer
|
|
384
382
|
elif issubclass(read_type, (Char, Wchar, Int)):
|
|
385
|
-
yield field, count * read_type.
|
|
383
|
+
yield field, count * read_type.__size__, "x"
|
|
386
384
|
|
|
387
|
-
size = count * read_type.
|
|
385
|
+
size = count * read_type.__size__
|
|
388
386
|
imaginary_offset += size
|
|
389
387
|
if current_offset is not None:
|
|
390
388
|
current_offset += size
|
|
@@ -418,7 +416,7 @@ def _optimize_struct_fmt(info: Iterator[tuple[Field, int, str]]) -> str:
|
|
|
418
416
|
|
|
419
417
|
def _get_read_type(cs: cstruct, type_: type[BaseType]) -> type[BaseType]:
|
|
420
418
|
if issubclass(type_, (Enum, Flag)):
|
|
421
|
-
type_ = type_.
|
|
419
|
+
type_ = type_.__type__
|
|
422
420
|
|
|
423
421
|
if issubclass(type_, Pointer):
|
|
424
422
|
type_ = cs.pointer
|
dissect/cstruct/cstruct.py
CHANGED
|
@@ -206,7 +206,28 @@ class cstruct:
|
|
|
206
206
|
if load:
|
|
207
207
|
self.load(load)
|
|
208
208
|
|
|
209
|
-
def __getattr__(
|
|
209
|
+
def __getattr__(
|
|
210
|
+
self, attr: str
|
|
211
|
+
) -> (
|
|
212
|
+
type[
|
|
213
|
+
LEB128
|
|
214
|
+
| BaseType
|
|
215
|
+
| Char
|
|
216
|
+
| Enum
|
|
217
|
+
| Flag
|
|
218
|
+
| Int
|
|
219
|
+
| Packed[int]
|
|
220
|
+
| Packed[float]
|
|
221
|
+
| Pointer
|
|
222
|
+
| Structure
|
|
223
|
+
| Union
|
|
224
|
+
| Void
|
|
225
|
+
| Wchar
|
|
226
|
+
]
|
|
227
|
+
| int
|
|
228
|
+
| str
|
|
229
|
+
| bytes
|
|
230
|
+
):
|
|
210
231
|
try:
|
|
211
232
|
return self.consts[attr]
|
|
212
233
|
except KeyError:
|
|
@@ -227,7 +248,7 @@ class cstruct:
|
|
|
227
248
|
# Update types to point to the new cstruct instance
|
|
228
249
|
for name, type_ in self.types.items():
|
|
229
250
|
new_type = copy.copy(type_)
|
|
230
|
-
new_type.
|
|
251
|
+
new_type.__cs__ = cs
|
|
231
252
|
cs.add_type(name, new_type, replace=True)
|
|
232
253
|
|
|
233
254
|
for name, value in self.consts.items():
|
|
@@ -288,8 +309,10 @@ class cstruct:
|
|
|
288
309
|
"""
|
|
289
310
|
# In cstruct 5.0 we changed the function signature of _read and _write
|
|
290
311
|
# Check if the function signature is compatible, and warn if not
|
|
291
|
-
for type_to_check in (type_, type_.
|
|
292
|
-
type_name = type_.__name__ + (
|
|
312
|
+
for type_to_check in (type_, type_.__ArrayType__):
|
|
313
|
+
type_name = type_.__name__ + (
|
|
314
|
+
f".{type_.__ArrayType__.__name__}" if type_to_check is type_.__ArrayType__ else ""
|
|
315
|
+
)
|
|
293
316
|
|
|
294
317
|
for method in ("_read", "_read_array", "_read_0", "_write", "_write_array", "_write_0"):
|
|
295
318
|
if not hasattr(type_to_check, method):
|
|
@@ -481,10 +504,10 @@ class cstruct:
|
|
|
481
504
|
attrs = attrs or {}
|
|
482
505
|
attrs.update(
|
|
483
506
|
{
|
|
484
|
-
"
|
|
485
|
-
"
|
|
486
|
-
"
|
|
487
|
-
"
|
|
507
|
+
"__cs__": self,
|
|
508
|
+
"__size__": size,
|
|
509
|
+
"__dynamic__": size is None,
|
|
510
|
+
"__alignment__": alignment or size,
|
|
488
511
|
}
|
|
489
512
|
)
|
|
490
513
|
return types.new_class(name, bases, {}, lambda ns: ns.update(attrs))
|
|
@@ -494,37 +517,37 @@ class cstruct:
|
|
|
494
517
|
if num_entries is None:
|
|
495
518
|
null_terminated = True
|
|
496
519
|
size = None
|
|
497
|
-
elif isinstance(num_entries, Expression) or type_.
|
|
520
|
+
elif isinstance(num_entries, Expression) or type_.__dynamic__:
|
|
498
521
|
size = None
|
|
499
522
|
else:
|
|
500
|
-
if type_.
|
|
523
|
+
if type_.__size__ is None:
|
|
501
524
|
raise ValueError(f"Cannot create array of dynamic type: {type_.__name__}")
|
|
502
|
-
size = num_entries * type_.
|
|
525
|
+
size = num_entries * type_.__size__
|
|
503
526
|
|
|
504
527
|
name = f"{type_.__name__}[]" if null_terminated else f"{type_.__name__}[{num_entries}]"
|
|
505
528
|
|
|
506
|
-
bases = (type_.
|
|
529
|
+
bases = (type_.__ArrayType__,)
|
|
507
530
|
|
|
508
531
|
attrs = {
|
|
509
|
-
"
|
|
510
|
-
"
|
|
511
|
-
"
|
|
532
|
+
"__type__": type_,
|
|
533
|
+
"__num_entries__": num_entries,
|
|
534
|
+
"__null_terminated__": null_terminated,
|
|
512
535
|
}
|
|
513
536
|
|
|
514
|
-
return cast("type[Array]", self._make_type(name, bases, size, alignment=type_.
|
|
537
|
+
return cast("type[Array]", self._make_type(name, bases, size, alignment=type_.__alignment__, attrs=attrs))
|
|
515
538
|
|
|
516
539
|
def _make_int_type(self, name: str, size: int, signed: bool, *, alignment: int | None = None) -> type[Int]:
|
|
517
540
|
return cast("type[Int]", self._make_type(name, (Int,), size, alignment=alignment, attrs={"signed": signed}))
|
|
518
541
|
|
|
519
|
-
def _make_packed_type(self, name: str,
|
|
542
|
+
def _make_packed_type(self, name: str, fmt: str, base: type, *, alignment: int | None = None) -> type[Packed]:
|
|
520
543
|
return cast(
|
|
521
544
|
"type[Packed]",
|
|
522
545
|
self._make_type(
|
|
523
546
|
name,
|
|
524
547
|
(base, Packed),
|
|
525
|
-
struct.calcsize(
|
|
548
|
+
struct.calcsize(fmt),
|
|
526
549
|
alignment=alignment,
|
|
527
|
-
attrs={"
|
|
550
|
+
attrs={"__fmt__": fmt},
|
|
528
551
|
),
|
|
529
552
|
)
|
|
530
553
|
|
|
@@ -538,9 +561,9 @@ class cstruct:
|
|
|
538
561
|
return self._make_type(
|
|
539
562
|
f"{target.__name__}*",
|
|
540
563
|
(Pointer,),
|
|
541
|
-
self.pointer.
|
|
542
|
-
alignment=self.pointer.
|
|
543
|
-
attrs={"
|
|
564
|
+
self.pointer.__size__,
|
|
565
|
+
alignment=self.pointer.__alignment__,
|
|
566
|
+
attrs={"__type__": target},
|
|
544
567
|
)
|
|
545
568
|
|
|
546
569
|
def _make_struct(
|
|
@@ -557,7 +580,7 @@ class cstruct:
|
|
|
557
580
|
(base,),
|
|
558
581
|
None,
|
|
559
582
|
attrs={
|
|
560
|
-
"
|
|
583
|
+
"__members__": fields,
|
|
561
584
|
"__align__": align,
|
|
562
585
|
"__anonymous__": anonymous,
|
|
563
586
|
},
|
|
@@ -568,6 +591,15 @@ class cstruct:
|
|
|
568
591
|
) -> type[Structure]:
|
|
569
592
|
return self._make_struct(name, fields, align=align, anonymous=anonymous, base=Union)
|
|
570
593
|
|
|
594
|
+
@property
|
|
595
|
+
def typedefs(self) -> dict[str, type[BaseType]]:
|
|
596
|
+
warnings.warn(
|
|
597
|
+
"The 'typedefs' property is deprecated, use 'types' instead.",
|
|
598
|
+
DeprecationWarning,
|
|
599
|
+
stacklevel=2,
|
|
600
|
+
)
|
|
601
|
+
return self.types
|
|
602
|
+
|
|
571
603
|
if TYPE_CHECKING:
|
|
572
604
|
# ruff: noqa: PYI042
|
|
573
605
|
_int = int
|
|
@@ -749,8 +781,8 @@ def ctypes_type(type_: type[BaseType]) -> Any:
|
|
|
749
781
|
"d": _ctypes.c_double,
|
|
750
782
|
}
|
|
751
783
|
|
|
752
|
-
if issubclass(type_, Packed) and type_.
|
|
753
|
-
return mapping[type_.
|
|
784
|
+
if issubclass(type_, Packed) and type_.__fmt__ in mapping:
|
|
785
|
+
return mapping[type_.__fmt__]
|
|
754
786
|
|
|
755
787
|
if issubclass(type_, Char):
|
|
756
788
|
return _ctypes.c_char
|
|
@@ -759,11 +791,11 @@ def ctypes_type(type_: type[BaseType]) -> Any:
|
|
|
759
791
|
return _ctypes.c_wchar
|
|
760
792
|
|
|
761
793
|
if issubclass(type_, BaseArray):
|
|
762
|
-
subtype = ctypes_type(type_.
|
|
763
|
-
return subtype * type_.
|
|
794
|
+
subtype = ctypes_type(type_.__type__)
|
|
795
|
+
return subtype * type_.__num_entries__
|
|
764
796
|
|
|
765
797
|
if issubclass(type_, Pointer):
|
|
766
|
-
subtype = ctypes_type(type_.
|
|
798
|
+
subtype = ctypes_type(type_.__type__)
|
|
767
799
|
return _ctypes.POINTER(subtype)
|
|
768
800
|
|
|
769
801
|
if issubclass(type_, Structure):
|
dissect/cstruct/tools/stubgen.py
CHANGED
|
@@ -121,9 +121,9 @@ def generate_typehint(
|
|
|
121
121
|
if issubclass(type_, types.WcharArray):
|
|
122
122
|
return f"{module_prefix}WcharArray"
|
|
123
123
|
if issubclass(type_, types.Pointer):
|
|
124
|
-
return f"{module_prefix}Pointer[{generate_typehint(type_.
|
|
124
|
+
return f"{module_prefix}Pointer[{generate_typehint(type_.__type__, prefix, module_prefix)}]"
|
|
125
125
|
if issubclass(type_, types.Array):
|
|
126
|
-
return f"{module_prefix}Array[{generate_typehint(type_.
|
|
126
|
+
return f"{module_prefix}Array[{generate_typehint(type_.__type__, prefix, module_prefix)}]"
|
|
127
127
|
return f"{prefix}{type_.__name__}"
|
|
128
128
|
|
|
129
129
|
|
|
@@ -159,15 +159,15 @@ def generate_structure_stub(
|
|
|
159
159
|
indent = " " * 4
|
|
160
160
|
|
|
161
161
|
args = ["self"]
|
|
162
|
-
for field_name, field in structure.
|
|
162
|
+
for field_name, field in structure.__members__.items():
|
|
163
163
|
inlined = False
|
|
164
164
|
|
|
165
165
|
# If it's a structure and not globally defined, add an inline stub for it
|
|
166
166
|
nested_type = field.type
|
|
167
167
|
while issubclass(nested_type, types.BaseArray):
|
|
168
|
-
nested_type = nested_type.
|
|
168
|
+
nested_type = nested_type.__type__
|
|
169
169
|
|
|
170
|
-
if issubclass(nested_type, types.Structure) and nested_type.__name__ not in structure.
|
|
170
|
+
if issubclass(nested_type, types.Structure) and nested_type.__name__ not in structure.__cs__.types:
|
|
171
171
|
inlined = True
|
|
172
172
|
inline_stub = generate_structure_stub(nested_type, cs_prefix=cs_prefix, module_prefix=module_prefix)
|
|
173
173
|
|