dissect.cstruct 4.6.dev4__tar.gz → 4.6.dev6__tar.gz

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.
Files changed (76) hide show
  1. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/PKG-INFO +1 -1
  2. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/parser.py +2 -2
  3. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/tools/stubgen.py +3 -0
  4. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/types/structure.py +39 -9
  5. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect.cstruct.egg-info/PKG-INFO +1 -1
  6. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_parser.py +16 -1
  7. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_tools_stubgen.py +20 -0
  8. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/.git-blame-ignore-revs +0 -0
  9. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/.gitattributes +0 -0
  10. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/CHANGELOG.md +0 -0
  11. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/COPYRIGHT +0 -0
  12. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/LICENSE +0 -0
  13. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/MANIFEST.in +0 -0
  14. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/README.md +0 -0
  15. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/__init__.py +0 -0
  16. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/bitbuffer.py +0 -0
  17. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/compiler.py +0 -0
  18. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/cstruct.py +0 -0
  19. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/exceptions.py +0 -0
  20. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/expression.py +0 -0
  21. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/tools/__init__.py +0 -0
  22. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/types/__init__.py +0 -0
  23. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/types/base.py +0 -0
  24. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/types/char.py +0 -0
  25. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/types/enum.py +0 -0
  26. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/types/flag.py +0 -0
  27. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/types/int.py +0 -0
  28. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/types/leb128.py +0 -0
  29. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/types/packed.py +0 -0
  30. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/types/pointer.py +0 -0
  31. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/types/void.py +0 -0
  32. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/types/wchar.py +0 -0
  33. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/utils.py +0 -0
  34. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect.cstruct.egg-info/SOURCES.txt +0 -0
  35. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect.cstruct.egg-info/dependency_links.txt +0 -0
  36. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect.cstruct.egg-info/entry_points.txt +0 -0
  37. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect.cstruct.egg-info/requires.txt +0 -0
  38. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect.cstruct.egg-info/top_level.txt +0 -0
  39. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/examples/disk.py +0 -0
  40. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/examples/mirai.py +0 -0
  41. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/examples/pe.py +0 -0
  42. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/examples/protobuf.py +0 -0
  43. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/examples/secdesc.py +0 -0
  44. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/pyproject.toml +0 -0
  45. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/setup.cfg +0 -0
  46. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/__init__.py +0 -0
  47. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/_data/testdef.txt +0 -0
  48. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/_docs/Makefile +0 -0
  49. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/_docs/__init__.py +0 -0
  50. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/_docs/conf.py +0 -0
  51. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/_docs/index.rst +0 -0
  52. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/conftest.py +0 -0
  53. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_align.py +0 -0
  54. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_annotations.py +0 -0
  55. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_basic.py +0 -0
  56. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_bitbuffer.py +0 -0
  57. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_bitfield.py +0 -0
  58. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_compiler.py +0 -0
  59. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_ctypes.py +0 -0
  60. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_expression.py +0 -0
  61. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_types_base.py +0 -0
  62. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_types_char.py +0 -0
  63. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_types_custom.py +0 -0
  64. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_types_enum.py +0 -0
  65. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_types_flag.py +0 -0
  66. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_types_int.py +0 -0
  67. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_types_leb128.py +0 -0
  68. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_types_packed.py +0 -0
  69. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_types_pointer.py +0 -0
  70. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_types_structure.py +0 -0
  71. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_types_union.py +0 -0
  72. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_types_void.py +0 -0
  73. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_types_wchar.py +0 -0
  74. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_utils.py +0 -0
  75. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/utils.py +0 -0
  76. {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dissect.cstruct
3
- Version: 4.6.dev4
3
+ Version: 4.6.dev6
4
4
  Summary: A Dissect module implementing a parser for C-like structures: structure parsing in Python made easy
5
5
  Author-email: Dissect Team <dissect@fox-it.com>
6
6
  License: Apache License 2.0
@@ -314,11 +314,11 @@ class TokenParser(Parser):
314
314
  tokens.eol()
315
315
  break
316
316
 
317
- if tokens.next not in (self.TOK.NAME, self.TOK.DEFS):
317
+ if tokens.next not in (self.TOK.NAME, self.TOK.DEFS, self.TOK.IDENTIFIER):
318
318
  break
319
319
 
320
320
  ntoken = tokens.consume()
321
- if ntoken == self.TOK.NAME:
321
+ if ntoken in (self.TOK.NAME, self.TOK.IDENTIFIER):
322
322
  names.append(ntoken.value.strip())
323
323
  elif ntoken == self.TOK.DEFS:
324
324
  names.extend([name.strip() for name in ntoken.value.strip().split(",")])
@@ -92,6 +92,9 @@ def generate_cstruct_stub(cs: cstruct, module_prefix: str = "", cls_name: str =
92
92
  stub = f"{name}: TypeAlias = {typedef.__name__}"
93
93
  elif issubclass(typedef, (types.Enum, types.Flag)):
94
94
  stub = generate_enum_stub(typedef, cs_prefix=cs_prefix, module_prefix=module_prefix)
95
+ elif issubclass(typedef, types.Pointer):
96
+ typehint = generate_typehint(typedef, prefix=cs_prefix, module_prefix=module_prefix)
97
+ stub = f"{name}: TypeAlias = {typehint}"
95
98
  elif issubclass(typedef, types.Structure):
96
99
  stub = generate_structure_stub(typedef, cs_prefix=cs_prefix, module_prefix=module_prefix)
97
100
  elif issubclass(typedef, types.BaseType):
@@ -828,13 +828,13 @@ def _generate_structure__init__(fields: list[Field]) -> FunctionType:
828
828
  Args:
829
829
  fields: List of field names.
830
830
  """
831
- field_names = [field._name for field in fields]
831
+ mapping = _generate_co_mapping(fields)
832
832
 
833
- template: FunctionType = _make_structure__init__(len(field_names))
833
+ template: FunctionType = _make_structure__init__(len(fields))
834
834
  return type(template)(
835
835
  template.__code__.replace(
836
- co_names=tuple(chain.from_iterable(zip((f"__{name}_default__" for name in field_names), field_names))),
837
- co_varnames=("self", *field_names),
836
+ co_names=_remap_co_values(template.__code__.co_names, mapping),
837
+ co_varnames=_remap_co_values(template.__code__.co_varnames, mapping),
838
838
  ),
839
839
  template.__globals__ | {f"__{field._name}_default__": field.type.__default__() for field in fields},
840
840
  argdefs=template.__defaults__,
@@ -847,20 +847,50 @@ def _generate_union__init__(fields: list[Field]) -> FunctionType:
847
847
  Args:
848
848
  fields: List of field names.
849
849
  """
850
- field_names = [field._name for field in fields]
850
+ mapping = _generate_co_mapping(fields)
851
851
 
852
- template: FunctionType = _make_union__init__(len(field_names))
852
+ template: FunctionType = _make_union__init__(len(fields))
853
853
  return type(template)(
854
854
  template.__code__.replace(
855
- co_consts=(None, *field_names),
856
- co_names=("object", "__setattr__", *(f"__{name}_default__" for name in field_names)),
857
- co_varnames=("self", *field_names),
855
+ co_consts=_remap_co_values(template.__code__.co_consts, mapping),
856
+ co_names=_remap_co_values(template.__code__.co_names, mapping),
857
+ co_varnames=_remap_co_values(template.__code__.co_varnames, mapping),
858
858
  ),
859
859
  template.__globals__ | {f"__{field._name}_default__": field.type.__default__() for field in fields},
860
860
  argdefs=template.__defaults__,
861
861
  )
862
862
 
863
863
 
864
+ def _generate_co_mapping(fields: list[Field]) -> dict[str, str]:
865
+ """Generates a mapping of generated code object names to field names.
866
+
867
+ The generated code uses names like ``_0``, ``_1``, etc. for fields, and ``_0_default``, ``_1_default``, etc.
868
+ for default initializer values. Return a mapping of these names to the actual field names.
869
+
870
+ Args:
871
+ fields: List of field names.
872
+ """
873
+ return {
874
+ key: value
875
+ for i, field in enumerate(fields)
876
+ for key, value in [(f"_{i}", field._name), (f"_{i}_default", f"__{field._name}_default__")]
877
+ }
878
+
879
+
880
+ def _remap_co_values(value: tuple[Any, ...], mapping: dict[str, str]) -> tuple[Any, ...]:
881
+ """Remaps code object values using a mapping.
882
+
883
+ This is used to replace generated code object names with actual field names.
884
+
885
+ Args:
886
+ value: The original code object values.
887
+ mapping: A mapping of generated code object names to field names.
888
+ """
889
+ # Only attempt to remap if the value is a string, otherwise return it as is
890
+ # This is to avoid issues with trying to remap non-hashable types, and we only need to replace strings anyway
891
+ return tuple(mapping.get(v, v) if isinstance(v, str) else v for v in value)
892
+
893
+
864
894
  def _generate__eq__(fields: list[str]) -> FunctionType:
865
895
  """Generates an ``__eq__`` method for a class with the specified fields.
866
896
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dissect.cstruct
3
- Version: 4.6.dev4
3
+ Version: 4.6.dev6
4
4
  Summary: A Dissect module implementing a parser for C-like structures: structure parsing in Python made easy
5
5
  Author-email: Dissect Team <dissect@fox-it.com>
6
6
  License: Apache License 2.0
@@ -7,7 +7,7 @@ import pytest
7
7
 
8
8
  from dissect.cstruct.exceptions import ParserError
9
9
  from dissect.cstruct.parser import TokenParser
10
- from dissect.cstruct.types import BaseArray, Pointer
10
+ from dissect.cstruct.types import BaseArray, Pointer, Structure
11
11
  from tests.utils import verify_compiled
12
12
 
13
13
  if TYPE_CHECKING:
@@ -149,3 +149,18 @@ def test_includes(cs: cstruct) -> None:
149
149
  assert cs.myStruct.__name__ == "myStruct"
150
150
  assert len(cs.myStruct.fields) == 1
151
151
  assert cs.myStruct.fields.get("charVal")
152
+
153
+
154
+ def test_typedef_pointer(cs: cstruct) -> None:
155
+ cdef = """
156
+ typedef struct _IMAGE_DATA_DIRECTORY {
157
+ DWORD VirtualAddress;
158
+ DWORD Size;
159
+ } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
160
+ """
161
+ cs.load(cdef)
162
+
163
+ assert issubclass(cs._IMAGE_DATA_DIRECTORY, Structure)
164
+ assert cs.IMAGE_DATA_DIRECTORY is cs._IMAGE_DATA_DIRECTORY
165
+ assert issubclass(cs.PIMAGE_DATA_DIRECTORY, Pointer)
166
+ assert cs.PIMAGE_DATA_DIRECTORY.type == cs._IMAGE_DATA_DIRECTORY
@@ -319,6 +319,26 @@ def test_generate_structure_stub(cs: cstruct, cdef: str, expected: str) -> None:
319
319
  """,
320
320
  id="define literals",
321
321
  ),
322
+ pytest.param(
323
+ """
324
+ typedef struct _Test {
325
+ uint8 a;
326
+ } Test, *pTest;
327
+ """,
328
+ """
329
+ class cstruct(cstruct):
330
+ class _Test(Structure):
331
+ a: cstruct.uint8
332
+ @overload
333
+ def __init__(self, a: cstruct.uint8 | None = ...): ...
334
+ @overload
335
+ def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ...
336
+
337
+ Test: TypeAlias = _Test
338
+ pTest: TypeAlias = Pointer[cstruct._Test]
339
+ """,
340
+ id="pointer alias",
341
+ ),
322
342
  ],
323
343
  )
324
344
  def test_generate_cstruct_stub(cs: cstruct, cdef: str, expected: str) -> None: