dissect.cstruct 4.8.dev3__tar.gz → 4.8.dev5__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 (77) hide show
  1. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/PKG-INFO +21 -1
  2. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/README.md +20 -0
  3. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect/cstruct/__init__.py +2 -0
  4. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect/cstruct/compiler.py +3 -1
  5. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect/cstruct/cstruct.py +5 -2
  6. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect/cstruct/exceptions.py +3 -0
  7. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect/cstruct/expression.py +0 -1
  8. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect/cstruct/parser.py +6 -5
  9. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect/cstruct/types/__init__.py +2 -0
  10. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect/cstruct/types/enum.py +2 -1
  11. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect/cstruct/types/structure.py +3 -3
  12. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect.cstruct.egg-info/PKG-INFO +21 -1
  13. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/pyproject.toml +22 -3
  14. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/_docs/conf.py +2 -0
  15. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/test_types_union.py +3 -3
  16. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/.git-blame-ignore-revs +0 -0
  17. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/.gitattributes +0 -0
  18. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/CHANGELOG.md +0 -0
  19. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/COPYRIGHT +0 -0
  20. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/LICENSE +0 -0
  21. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/MANIFEST.in +0 -0
  22. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect/cstruct/bitbuffer.py +0 -0
  23. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect/cstruct/tools/__init__.py +0 -0
  24. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect/cstruct/tools/stubgen.py +0 -0
  25. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect/cstruct/types/base.py +0 -0
  26. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect/cstruct/types/char.py +0 -0
  27. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect/cstruct/types/flag.py +0 -0
  28. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect/cstruct/types/int.py +0 -0
  29. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect/cstruct/types/leb128.py +0 -0
  30. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect/cstruct/types/packed.py +0 -0
  31. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect/cstruct/types/pointer.py +0 -0
  32. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect/cstruct/types/void.py +0 -0
  33. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect/cstruct/types/wchar.py +0 -0
  34. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect/cstruct/utils.py +0 -0
  35. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect.cstruct.egg-info/SOURCES.txt +0 -0
  36. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect.cstruct.egg-info/dependency_links.txt +0 -0
  37. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect.cstruct.egg-info/entry_points.txt +0 -0
  38. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect.cstruct.egg-info/requires.txt +0 -0
  39. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/dissect.cstruct.egg-info/top_level.txt +0 -0
  40. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/examples/disk.py +0 -0
  41. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/examples/mirai.py +0 -0
  42. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/examples/pe.py +0 -0
  43. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/examples/protobuf.py +0 -0
  44. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/examples/secdesc.py +0 -0
  45. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/setup.cfg +0 -0
  46. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/__init__.py +0 -0
  47. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/_data/testdef.txt +0 -0
  48. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/_docs/Makefile +0 -0
  49. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/_docs/__init__.py +0 -0
  50. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/_docs/index.rst +0 -0
  51. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/conftest.py +0 -0
  52. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/test_align.py +0 -0
  53. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/test_annotations.py +0 -0
  54. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/test_basic.py +0 -0
  55. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/test_benchmark.py +0 -0
  56. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/test_bitbuffer.py +0 -0
  57. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/test_bitfield.py +0 -0
  58. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/test_compiler.py +0 -0
  59. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/test_ctypes.py +0 -0
  60. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/test_expression.py +0 -0
  61. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/test_parser.py +0 -0
  62. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/test_tools_stubgen.py +0 -0
  63. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/test_types_base.py +0 -0
  64. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/test_types_char.py +0 -0
  65. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/test_types_custom.py +0 -0
  66. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/test_types_enum.py +0 -0
  67. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/test_types_flag.py +0 -0
  68. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/test_types_int.py +0 -0
  69. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/test_types_leb128.py +0 -0
  70. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/test_types_packed.py +0 -0
  71. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/test_types_pointer.py +0 -0
  72. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/test_types_structure.py +0 -0
  73. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/test_types_void.py +0 -0
  74. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/test_types_wchar.py +0 -0
  75. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/test_utils.py +0 -0
  76. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tests/utils.py +0 -0
  77. {dissect_cstruct-4.8.dev3 → dissect_cstruct-4.8.dev5}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dissect.cstruct
3
- Version: 4.8.dev3
3
+ Version: 4.8.dev5
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-Expression: Apache-2.0
@@ -238,6 +238,26 @@ The API to access enum and flag members and their values in the same way as the
238
238
  ### Custom types
239
239
  You can implement your own types by subclassing `BaseType`, and adding them to your cstruct instance with `add_custom_type(name, type, size, alignment, ...)`
240
240
 
241
+ ### Dynamic length fields
242
+ To read all remaining data in the provided buffer/stream, you can use the magic `EOF` size variable. This will automatically expand until the end of the stream has been reached and works for any field type. For example:
243
+
244
+ ```python
245
+ from dissect.cstruct import cstruct
246
+
247
+ eof_def = """
248
+ struct example {
249
+ uint32 magic;
250
+ char data[EOF];
251
+ };
252
+ """
253
+
254
+ c_eof = cstruct().load(eof_def)
255
+
256
+ example = c_eof.example(b"9\x05\x00\x00arbitrary length data")
257
+ assert example.magic == 1337
258
+ assert example.data == b"arbitrary length data"
259
+ ```
260
+
241
261
  ### Custom definition parsers
242
262
  Don't like the C-like definition syntax? Write your own syntax parser!
243
263
 
@@ -210,6 +210,26 @@ The API to access enum and flag members and their values in the same way as the
210
210
  ### Custom types
211
211
  You can implement your own types by subclassing `BaseType`, and adding them to your cstruct instance with `add_custom_type(name, type, size, alignment, ...)`
212
212
 
213
+ ### Dynamic length fields
214
+ To read all remaining data in the provided buffer/stream, you can use the magic `EOF` size variable. This will automatically expand until the end of the stream has been reached and works for any field type. For example:
215
+
216
+ ```python
217
+ from dissect.cstruct import cstruct
218
+
219
+ eof_def = """
220
+ struct example {
221
+ uint32 magic;
222
+ char data[EOF];
223
+ };
224
+ """
225
+
226
+ c_eof = cstruct().load(eof_def)
227
+
228
+ example = c_eof.example(b"9\x05\x00\x00arbitrary length data")
229
+ assert example.magic == 1337
230
+ assert example.data == b"arbitrary length data"
231
+ ```
232
+
213
233
  ### Custom definition parsers
214
234
  Don't like the C-like definition syntax? Write your own syntax parser!
215
235
 
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from dissect.cstruct.bitbuffer import BitBuffer
2
4
  from dissect.cstruct.cstruct import cstruct, ctypes, ctypes_type
3
5
  from dissect.cstruct.exceptions import (
@@ -11,7 +11,6 @@ from typing import TYPE_CHECKING
11
11
  from dissect.cstruct.bitbuffer import BitBuffer
12
12
  from dissect.cstruct.types import (
13
13
  Array,
14
- BaseType,
15
14
  Char,
16
15
  CharArray,
17
16
  Flag,
@@ -34,6 +33,9 @@ if TYPE_CHECKING:
34
33
  from types import MethodType
35
34
 
36
35
  from dissect.cstruct.cstruct import cstruct
36
+ from dissect.cstruct.types import (
37
+ BaseType,
38
+ )
37
39
  from dissect.cstruct.types.structure import Field
38
40
 
39
41
  SUPPORTED_TYPES = (
@@ -12,12 +12,10 @@ from dissect.cstruct.expression import Expression
12
12
  from dissect.cstruct.parser import CStyleParser, TokenParser
13
13
  from dissect.cstruct.types import (
14
14
  LEB128,
15
- Array,
16
15
  BaseArray,
17
16
  BaseType,
18
17
  Char,
19
18
  Enum,
20
- Field,
21
19
  Flag,
22
20
  Int,
23
21
  Packed,
@@ -32,6 +30,11 @@ if TYPE_CHECKING:
32
30
  from collections.abc import Iterable
33
31
  from typing import TypeAlias
34
32
 
33
+ from dissect.cstruct.types import (
34
+ Array,
35
+ Field,
36
+ )
37
+
35
38
 
36
39
  T = TypeVar("T", bound=BaseType)
37
40
 
@@ -1,3 +1,6 @@
1
+ from __future__ import annotations
2
+
3
+
1
4
  class Error(Exception):
2
5
  pass
3
6
 
@@ -225,7 +225,6 @@ class Expression:
225
225
 
226
226
  def evaluate(self, cs: cstruct, context: dict[str, int] | None = None) -> int:
227
227
  """Evaluates an expression using a Shunting-Yard implementation."""
228
-
229
228
  self.stack = []
230
229
  self.queue = []
231
230
  operators = set(self.binary_operators.keys()) | set(self.unary_operators.keys())
@@ -11,10 +11,11 @@ from dissect.cstruct.exceptions import (
11
11
  ParserError,
12
12
  )
13
13
  from dissect.cstruct.expression import Expression
14
- from dissect.cstruct.types import BaseArray, BaseType, Field, Structure
14
+ from dissect.cstruct.types import BaseArray, Field, Structure
15
15
 
16
16
  if TYPE_CHECKING:
17
17
  from dissect.cstruct import cstruct
18
+ from dissect.cstruct.types import BaseType
18
19
 
19
20
 
20
21
  class Parser:
@@ -37,7 +38,8 @@ class Parser:
37
38
 
38
39
 
39
40
  class TokenParser(Parser):
40
- """
41
+ """Definition parser for C-like structure syntax.
42
+
41
43
  Args:
42
44
  cs: An instance of cstruct.
43
45
  compiled: Whether structs should be compiled or not.
@@ -421,8 +423,7 @@ class TokenParser(Parser):
421
423
 
422
424
  @staticmethod
423
425
  def _lineno(tok: Token) -> int:
424
- """Quick and dirty line number calculator"""
425
-
426
+ """Quick and dirty line number calculator."""
426
427
  match = tok.match
427
428
  return match.string.count("\n", 0, match.start()) + 1
428
429
 
@@ -474,7 +475,7 @@ class TokenParser(Parser):
474
475
 
475
476
 
476
477
  class CStyleParser(Parser):
477
- """Definition parser for C-like structure syntax.
478
+ """Definition parser for C-like structure syntax (legacy parser).
478
479
 
479
480
  Args:
480
481
  cs: An instance of cstruct
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from dissect.cstruct.types.base import Array, BaseArray, BaseType, MetaType
2
4
  from dissect.cstruct.types.char import Char, CharArray
3
5
  from dissect.cstruct.types.enum import Enum
@@ -5,12 +5,13 @@ from enum import Enum as _Enum
5
5
  from enum import EnumMeta, IntEnum, IntFlag
6
6
  from typing import TYPE_CHECKING, Any, BinaryIO, TypeVar, overload
7
7
 
8
- from dissect.cstruct.types.base import Array, BaseType, MetaType
8
+ from dissect.cstruct.types.base import BaseType, MetaType
9
9
 
10
10
  if TYPE_CHECKING:
11
11
  from typing_extensions import Self
12
12
 
13
13
  from dissect.cstruct.cstruct import cstruct
14
+ from dissect.cstruct.types.base import Array
14
15
 
15
16
 
16
17
  PY_311 = sys.version_info >= (3, 11, 0)
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import io
4
4
  from collections import ChainMap
5
- from collections.abc import Callable, MutableMapping
5
+ from collections.abc import MutableMapping
6
6
  from contextlib import contextmanager
7
7
  from enum import Enum
8
8
  from functools import lru_cache
@@ -23,7 +23,7 @@ from dissect.cstruct.types.enum import EnumMetaType
23
23
  from dissect.cstruct.types.pointer import Pointer
24
24
 
25
25
  if TYPE_CHECKING:
26
- from collections.abc import Iterator, Mapping
26
+ from collections.abc import Callable, Iterator, Mapping
27
27
  from types import FunctionType
28
28
 
29
29
  from typing_extensions import Self
@@ -139,7 +139,7 @@ class StructureMetaType(MetaType):
139
139
 
140
140
  if cls.__compiled__:
141
141
  # If the previous class was compiled try to compile this too
142
- from dissect.cstruct import compiler # noqa: PLC0415
142
+ from dissect.cstruct import compiler
143
143
 
144
144
  try:
145
145
  classdict["_read"] = compiler.Compiler(cls.cs).compile_read(fields, cls.__name__, align=cls.__align__)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dissect.cstruct
3
- Version: 4.8.dev3
3
+ Version: 4.8.dev5
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-Expression: Apache-2.0
@@ -238,6 +238,26 @@ The API to access enum and flag members and their values in the same way as the
238
238
  ### Custom types
239
239
  You can implement your own types by subclassing `BaseType`, and adding them to your cstruct instance with `add_custom_type(name, type, size, alignment, ...)`
240
240
 
241
+ ### Dynamic length fields
242
+ To read all remaining data in the provided buffer/stream, you can use the magic `EOF` size variable. This will automatically expand until the end of the stream has been reached and works for any field type. For example:
243
+
244
+ ```python
245
+ from dissect.cstruct import cstruct
246
+
247
+ eof_def = """
248
+ struct example {
249
+ uint32 magic;
250
+ char data[EOF];
251
+ };
252
+ """
253
+
254
+ c_eof = cstruct().load(eof_def)
255
+
256
+ example = c_eof.example(b"9\x05\x00\x00arbitrary length data")
257
+ assert example.magic == 1337
258
+ assert example.data == b"arbitrary length data"
259
+ ```
260
+
241
261
  ### Custom definition parsers
242
262
  Don't like the C-like definition syntax? Write your own syntax parser!
243
263
 
@@ -94,7 +94,7 @@ select = [
94
94
  "SLOT",
95
95
  "SIM",
96
96
  "TID",
97
- "TCH",
97
+ "TC",
98
98
  "PTH",
99
99
  "PLC",
100
100
  "TRY",
@@ -102,16 +102,35 @@ select = [
102
102
  "PERF",
103
103
  "FURB",
104
104
  "RUF",
105
+ "D"
105
106
  ]
106
- ignore = ["E203", "B904", "UP024", "ANN002", "ANN003", "ANN204", "ANN401", "SIM105", "TRY003"]
107
+
108
+ ignore = [
109
+ "E203", "B904", "UP024", "ANN002", "ANN003", "ANN204", "ANN401", "SIM105", "TRY003", "PLC0415",
110
+ # Ignore some pydocstyle rules for now as they require a larger cleanup
111
+ "D1",
112
+ "D205",
113
+ "D301",
114
+ "D417",
115
+ # Seems bugged: https://github.com/astral-sh/ruff/issues/16824
116
+ "D402",
117
+ ]
118
+ future-annotations = true
119
+
120
+ [tool.ruff.lint.pydocstyle]
121
+ convention = "google"
122
+
123
+ [tool.ruff.lint.flake8-type-checking]
124
+ strict = true
107
125
 
108
126
  [tool.ruff.lint.per-file-ignores]
109
- "tests/**" = ["S101", "PLC0415"]
127
+ "tests/**" = ["S101"]
110
128
  "tests/_docs/**" = ["INP001"]
111
129
 
112
130
  [tool.ruff.lint.isort]
113
131
  known-first-party = ["dissect.cstruct"]
114
132
  known-third-party = ["dissect"]
133
+ required-imports = ["from __future__ import annotations"]
115
134
 
116
135
  [tool.setuptools.packages.find]
117
136
  include = ["dissect.*"]
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  project = "dissect.cstruct"
2
4
 
3
5
  extensions = [
@@ -444,7 +444,7 @@ def test_union_default(cs: cstruct) -> None:
444
444
 
445
445
 
446
446
  def test_union_default_dynamic(cs: cstruct) -> None:
447
- """initialization of a dynamic union is not yet supported"""
447
+ """Initialization of a dynamic union is not yet supported."""
448
448
  cdef = """
449
449
  union test {
450
450
  uint8 x;
@@ -472,7 +472,7 @@ def test_union_default_dynamic(cs: cstruct) -> None:
472
472
 
473
473
 
474
474
  def test_union_partial_initialization(cs: cstruct) -> None:
475
- """partial initialization of a union should fill in the rest with appropriate values"""
475
+ """Partial initialization of a union should fill in the rest with appropriate values."""
476
476
  cdef = """
477
477
  union test {
478
478
  uint8 a;
@@ -518,7 +518,7 @@ def test_union_partial_initialization(cs: cstruct) -> None:
518
518
 
519
519
 
520
520
  def test_union_partial_initialization_dynamic(cs: cstruct) -> None:
521
- """partial initialization of a dynamic union should fill in the rest with appropriate values"""
521
+ """Partial initialization of a dynamic union should fill in the rest with appropriate values."""
522
522
  cdef = """
523
523
  union test {
524
524
  uint8 x;