dissect.cstruct 5.0.dev7__tar.gz → 5.0.dev9__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 (82) hide show
  1. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/PKG-INFO +1 -1
  2. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect/cstruct/__init__.py +12 -0
  3. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect/cstruct/bitbuffer.py +6 -6
  4. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect/cstruct/compiler.py +31 -33
  5. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect/cstruct/cstruct.py +60 -28
  6. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect/cstruct/tools/stubgen.py +5 -5
  7. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect/cstruct/types/base.py +121 -59
  8. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect/cstruct/types/char.py +5 -5
  9. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect/cstruct/types/enum.py +15 -15
  10. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect/cstruct/types/int.py +4 -4
  11. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect/cstruct/types/packed.py +26 -21
  12. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect/cstruct/types/pointer.py +24 -24
  13. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect/cstruct/types/structure.py +72 -51
  14. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect/cstruct/types/void.py +1 -1
  15. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect/cstruct/types/wchar.py +5 -5
  16. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect/cstruct/util.py +100 -3
  17. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect.cstruct.egg-info/PKG-INFO +1 -1
  18. dissect_cstruct-5.0.dev9/dissect.cstruct.egg-info/scm_version.json +8 -0
  19. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/test_align.py +13 -13
  20. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/test_basic.py +85 -13
  21. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/test_compiler.py +12 -18
  22. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/test_parser.py +34 -34
  23. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/test_types_base.py +4 -4
  24. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/test_types_custom.py +15 -14
  25. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/test_types_enum.py +4 -4
  26. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/test_types_flag.py +4 -4
  27. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/test_types_pointer.py +2 -2
  28. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/test_types_structure.py +21 -21
  29. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/test_types_union.py +12 -12
  30. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/test_utils.py +30 -0
  31. dissect_cstruct-5.0.dev7/dissect.cstruct.egg-info/scm_version.json +0 -8
  32. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/.git-blame-ignore-revs +0 -0
  33. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/.gitattributes +0 -0
  34. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/CHANGELOG.md +0 -0
  35. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/COPYRIGHT +0 -0
  36. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/LICENSE +0 -0
  37. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/MANIFEST.in +0 -0
  38. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/README.md +0 -0
  39. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect/cstruct/exception.py +0 -0
  40. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect/cstruct/expression.py +0 -0
  41. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect/cstruct/lexer.py +0 -0
  42. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect/cstruct/parser.py +0 -0
  43. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect/cstruct/tools/__init__.py +0 -0
  44. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect/cstruct/types/__init__.py +0 -0
  45. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect/cstruct/types/flag.py +0 -0
  46. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect/cstruct/types/leb128.py +0 -0
  47. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect.cstruct.egg-info/SOURCES.txt +0 -0
  48. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect.cstruct.egg-info/dependency_links.txt +0 -0
  49. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect.cstruct.egg-info/entry_points.txt +0 -0
  50. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect.cstruct.egg-info/requires.txt +0 -0
  51. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect.cstruct.egg-info/scm_file_list.json +45 -45
  52. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/dissect.cstruct.egg-info/top_level.txt +0 -0
  53. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/examples/disk.py +0 -0
  54. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/examples/mirai.py +0 -0
  55. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/examples/pe.py +0 -0
  56. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/examples/protobuf.py +0 -0
  57. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/examples/secdesc.py +0 -0
  58. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/pyproject.toml +0 -0
  59. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/setup.cfg +0 -0
  60. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/__init__.py +0 -0
  61. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/_data/testdef.txt +0 -0
  62. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/_docs/Makefile +0 -0
  63. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/_docs/__init__.py +0 -0
  64. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/_docs/conf.py +0 -0
  65. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/_docs/index.rst +0 -0
  66. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/conftest.py +0 -0
  67. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/test_annotations.py +0 -0
  68. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/test_benchmark.py +0 -0
  69. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/test_bitbuffer.py +0 -0
  70. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/test_bitfield.py +0 -0
  71. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/test_ctypes.py +0 -0
  72. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/test_expression.py +0 -0
  73. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/test_lexer.py +0 -0
  74. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/test_tools_stubgen.py +0 -0
  75. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/test_types_char.py +0 -0
  76. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/test_types_int.py +0 -0
  77. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/test_types_leb128.py +0 -0
  78. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/test_types_packed.py +0 -0
  79. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/test_types_void.py +0 -0
  80. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/test_types_wchar.py +0 -0
  81. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tests/utils.py +0 -0
  82. {dissect_cstruct-5.0.dev7 → dissect_cstruct-5.0.dev9}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dissect.cstruct
3
- Version: 5.0.dev7
3
+ Version: 5.0.dev9
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
@@ -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",
@@ -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.size is None:
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.size * 8
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.size is None:
54
+ if field_type.__size__ is None:
55
55
  raise ValueError("Writing variable-length fields is unsupported")
56
56
 
57
- self._remaining = field_type.size * 8
57
+ self._remaining = field_type.__size__ * 8
58
58
  self._type = field_type
59
59
 
60
- if self._type is None or self._type.size is None:
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.size * 8 - self._remaining)
64
+ self._buffer |= data << (self._type.__size__ * 8 - self._remaining)
65
65
  else:
66
66
  self._buffer |= data << (self._remaining - bits)
67
67
 
@@ -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.types.packed import _struct
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.cs).compile(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.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.type, Structure) or issubclass(field_type.type, BaseArray) or is_dynamic
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.alignment - 1), {io.SEEK_CUR})"
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.dynamic else ""}
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.dynamic else ""}
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.dynamic else ""}
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.dynamic else ""}
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 += ".type"
253
- field_type = field_type.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.cs.uint8
257
- lookup = "cls.cs.uint8"
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.num_entries
283
- read_type = _get_read_type(self.cs, field_type.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.size
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.size}]"
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.type")
305
+ reads.append("_et = _t.__type__")
308
306
 
309
- if issubclass(field_type.type, Int):
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.type.size}]")
312
- list_comp = f"[{item_parser} for i in range(0, {count}, {field_type.type.size})]"
313
- elif issubclass(field_type.type, Pointer):
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.size
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.num_entries
376
- read_type = _get_read_type(cs, read_type.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.packchar
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.size, "x"
383
+ yield field, count * read_type.__size__, "x"
386
384
 
387
- size = count * read_type.size
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_.type
419
+ type_ = type_.__type__
422
420
 
423
421
  if issubclass(type_, Pointer):
424
422
  type_ = cs.pointer
@@ -206,7 +206,28 @@ class cstruct:
206
206
  if load:
207
207
  self.load(load)
208
208
 
209
- def __getattr__(self, attr: str) -> Any:
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.cs = cs
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_.ArrayType):
292
- type_name = type_.__name__ + (f".{type_.ArrayType.__name__}" if type_to_check is type_.ArrayType else "")
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
- "cs": self,
485
- "size": size,
486
- "dynamic": size is None,
487
- "alignment": alignment or size,
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_.dynamic:
520
+ elif isinstance(num_entries, Expression) or type_.__dynamic__:
498
521
  size = None
499
522
  else:
500
- if type_.size is None:
523
+ if type_.__size__ is None:
501
524
  raise ValueError(f"Cannot create array of dynamic type: {type_.__name__}")
502
- size = num_entries * type_.size
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_.ArrayType,)
529
+ bases = (type_.__ArrayType__,)
507
530
 
508
531
  attrs = {
509
- "type": type_,
510
- "num_entries": num_entries,
511
- "null_terminated": null_terminated,
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_.alignment, attrs=attrs))
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, packchar: str, base: type, *, alignment: int | None = None) -> type[Packed]:
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(packchar),
548
+ struct.calcsize(fmt),
526
549
  alignment=alignment,
527
- attrs={"packchar": packchar},
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.size,
542
- alignment=self.pointer.alignment,
543
- attrs={"type": target},
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
- "fields": fields,
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_.packchar in mapping:
753
- return mapping[type_.packchar]
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_.type)
763
- return subtype * type_.num_entries
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_.type)
798
+ subtype = ctypes_type(type_.__type__)
767
799
  return _ctypes.POINTER(subtype)
768
800
 
769
801
  if issubclass(type_, Structure):
@@ -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_.type, prefix, module_prefix)}]"
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_.type, prefix, module_prefix)}]"
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.fields.items():
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.type
168
+ nested_type = nested_type.__type__
169
169
 
170
- if issubclass(nested_type, types.Structure) and nested_type.__name__ not in structure.cs.types:
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