dissect.cstruct 5.0.dev6__tar.gz → 5.0.dev7__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.dev6 → dissect_cstruct-5.0.dev7}/PKG-INFO +1 -1
  2. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect/cstruct/types/base.py +4 -2
  3. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect/cstruct/types/char.py +10 -4
  4. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect/cstruct/types/structure.py +2 -2
  5. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect/cstruct/types/wchar.py +7 -0
  6. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect.cstruct.egg-info/PKG-INFO +1 -1
  7. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect.cstruct.egg-info/scm_file_list.json +52 -52
  8. dissect_cstruct-5.0.dev7/dissect.cstruct.egg-info/scm_version.json +8 -0
  9. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/test_types_base.py +19 -0
  10. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/test_types_char.py +34 -0
  11. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/test_types_wchar.py +29 -0
  12. dissect_cstruct-5.0.dev6/dissect.cstruct.egg-info/scm_version.json +0 -8
  13. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/.git-blame-ignore-revs +0 -0
  14. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/.gitattributes +0 -0
  15. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/CHANGELOG.md +0 -0
  16. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/COPYRIGHT +0 -0
  17. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/LICENSE +0 -0
  18. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/MANIFEST.in +0 -0
  19. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/README.md +0 -0
  20. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect/cstruct/__init__.py +0 -0
  21. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect/cstruct/bitbuffer.py +0 -0
  22. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect/cstruct/compiler.py +0 -0
  23. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect/cstruct/cstruct.py +0 -0
  24. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect/cstruct/exception.py +0 -0
  25. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect/cstruct/expression.py +0 -0
  26. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect/cstruct/lexer.py +0 -0
  27. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect/cstruct/parser.py +0 -0
  28. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect/cstruct/tools/__init__.py +0 -0
  29. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect/cstruct/tools/stubgen.py +0 -0
  30. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect/cstruct/types/__init__.py +0 -0
  31. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect/cstruct/types/enum.py +0 -0
  32. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect/cstruct/types/flag.py +0 -0
  33. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect/cstruct/types/int.py +0 -0
  34. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect/cstruct/types/leb128.py +0 -0
  35. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect/cstruct/types/packed.py +0 -0
  36. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect/cstruct/types/pointer.py +0 -0
  37. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect/cstruct/types/void.py +0 -0
  38. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect/cstruct/util.py +0 -0
  39. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect.cstruct.egg-info/SOURCES.txt +0 -0
  40. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect.cstruct.egg-info/dependency_links.txt +0 -0
  41. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect.cstruct.egg-info/entry_points.txt +0 -0
  42. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect.cstruct.egg-info/requires.txt +0 -0
  43. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/dissect.cstruct.egg-info/top_level.txt +0 -0
  44. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/examples/disk.py +0 -0
  45. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/examples/mirai.py +0 -0
  46. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/examples/pe.py +0 -0
  47. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/examples/protobuf.py +0 -0
  48. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/examples/secdesc.py +0 -0
  49. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/pyproject.toml +0 -0
  50. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/setup.cfg +0 -0
  51. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/__init__.py +0 -0
  52. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/_data/testdef.txt +0 -0
  53. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/_docs/Makefile +0 -0
  54. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/_docs/__init__.py +0 -0
  55. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/_docs/conf.py +0 -0
  56. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/_docs/index.rst +0 -0
  57. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/conftest.py +0 -0
  58. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/test_align.py +0 -0
  59. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/test_annotations.py +0 -0
  60. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/test_basic.py +0 -0
  61. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/test_benchmark.py +0 -0
  62. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/test_bitbuffer.py +0 -0
  63. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/test_bitfield.py +0 -0
  64. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/test_compiler.py +0 -0
  65. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/test_ctypes.py +0 -0
  66. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/test_expression.py +0 -0
  67. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/test_lexer.py +0 -0
  68. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/test_parser.py +0 -0
  69. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/test_tools_stubgen.py +0 -0
  70. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/test_types_custom.py +0 -0
  71. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/test_types_enum.py +0 -0
  72. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/test_types_flag.py +0 -0
  73. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/test_types_int.py +0 -0
  74. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/test_types_leb128.py +0 -0
  75. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/test_types_packed.py +0 -0
  76. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/test_types_pointer.py +0 -0
  77. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/test_types_structure.py +0 -0
  78. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/test_types_union.py +0 -0
  79. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/test_types_void.py +0 -0
  80. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/test_utils.py +0 -0
  81. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tests/utils.py +0 -0
  82. {dissect_cstruct-5.0.dev6 → dissect_cstruct-5.0.dev7}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dissect.cstruct
3
- Version: 5.0.dev6
3
+ Version: 5.0.dev7
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
@@ -294,8 +294,10 @@ class BaseArray(BaseType):
294
294
  if cls.null_terminated:
295
295
  return cls.type._write_0(stream, data, endian=endian)
296
296
 
297
- if not cls.dynamic and cls.num_entries != (actual_size := len(data)):
298
- raise ArraySizeError(f"Expected static array size {cls.num_entries}, got {actual_size} instead.")
297
+ if not cls.dynamic and (remaining := cls.num_entries - (actual_size := len(data))):
298
+ if remaining < 0:
299
+ raise ArraySizeError(f"Expected static array size {cls.num_entries}, got {actual_size} instead.")
300
+ data = data + [cls.type.__default__()] * remaining
299
301
 
300
302
  return cls.type._write_array(stream, data, endian=endian)
301
303
 
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from typing import TYPE_CHECKING, Any, BinaryIO
4
4
 
5
+ from dissect.cstruct.exception import ArraySizeError
5
6
  from dissect.cstruct.types.base import EOF, BaseArray, BaseType
6
7
 
7
8
  if TYPE_CHECKING:
@@ -22,15 +23,20 @@ class CharArray(bytes, BaseArray):
22
23
  return type.__call__(cls, super()._read(stream, context=context, endian=endian))
23
24
 
24
25
  @classmethod
25
- def _write(cls, stream: BinaryIO, data: bytes, *, endian: Endianness) -> int:
26
- if isinstance(data, list) and data and isinstance(data[0], int):
26
+ def _write(cls, stream: BinaryIO, data: bytes | str | list[int], *, endian: Endianness) -> int:
27
+ if isinstance(data, list):
27
28
  data = bytes(data)
28
-
29
29
  elif isinstance(data, str):
30
30
  data = data.encode("latin-1")
31
31
 
32
32
  if cls.null_terminated:
33
- return stream.write(data + b"\x00")
33
+ data += b"\x00"
34
+
35
+ if not cls.dynamic and (remaining := cls.num_entries - (actual_size := len(data))):
36
+ if remaining < 0:
37
+ raise ArraySizeError(f"Expected static array size {cls.num_entries}, got {actual_size} instead.")
38
+ data += b"\x00" * remaining
39
+
34
40
  return stream.write(data)
35
41
 
36
42
 
@@ -252,7 +252,7 @@ class StructureMetaType(MetaType):
252
252
  offset = stream.tell()
253
253
 
254
254
  if field.offset is not None and offset != struct_start + field.offset:
255
- # Field is at a specific offset, either alligned or added that way
255
+ # Field is at a specific offset, either aligned or added that way
256
256
  offset = struct_start + field.offset
257
257
  stream.seek(offset)
258
258
 
@@ -318,7 +318,7 @@ class StructureMetaType(MetaType):
318
318
  offset = stream.tell()
319
319
 
320
320
  if field.offset is not None and offset < struct_start + field.offset:
321
- # Field is at a specific offset, either alligned or added that way
321
+ # Field is at a specific offset, either aligned or added that way
322
322
  stream.write(b"\x00" * (struct_start + field.offset - offset))
323
323
  offset = struct_start + field.offset
324
324
 
@@ -3,6 +3,7 @@ from __future__ import annotations
3
3
  import sys
4
4
  from typing import TYPE_CHECKING, Any, BinaryIO, ClassVar
5
5
 
6
+ from dissect.cstruct.exception import ArraySizeError
6
7
  from dissect.cstruct.types.base import EOF, BaseArray, BaseType
7
8
 
8
9
  if TYPE_CHECKING:
@@ -26,6 +27,12 @@ class WcharArray(str, BaseArray):
26
27
  def _write(cls, stream: BinaryIO, data: str, *, endian: Endianness) -> int:
27
28
  if cls.null_terminated:
28
29
  data += "\x00"
30
+
31
+ if not cls.dynamic and (remaining := cls.num_entries - (actual_size := len(data))):
32
+ if remaining < 0:
33
+ raise ArraySizeError(f"Expected static array size {cls.num_entries}, got {actual_size} instead.")
34
+ data += "\x00" * remaining
35
+
29
36
  return stream.write(data.encode(Wchar.__encoding_map__[endian]))
30
37
 
31
38
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dissect.cstruct
3
- Version: 5.0.dev6
3
+ Version: 5.0.dev7
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
@@ -1,78 +1,78 @@
1
1
  {
2
2
  "files": [
3
- "README.md",
4
- "tox.ini",
5
- "LICENSE",
6
- "pyproject.toml",
3
+ ".gitignore",
7
4
  "COPYRIGHT",
5
+ "README.md",
8
6
  "CHANGELOG.md",
9
7
  ".git-blame-ignore-revs",
8
+ "tox.ini",
10
9
  ".gitattributes",
10
+ "pyproject.toml",
11
11
  "MANIFEST.in",
12
- ".gitignore",
13
- "dissect/cstruct/cstruct.py",
14
- "dissect/cstruct/__init__.py",
12
+ "LICENSE",
13
+ ".github/pull_request_template.md",
14
+ ".github/workflows/dissect-ci.yml",
15
+ "dissect/cstruct/parser.py",
15
16
  "dissect/cstruct/compiler.py",
16
- "dissect/cstruct/expression.py",
17
17
  "dissect/cstruct/exception.py",
18
- "dissect/cstruct/parser.py",
19
- "dissect/cstruct/lexer.py",
20
- "dissect/cstruct/bitbuffer.py",
21
18
  "dissect/cstruct/util.py",
22
- "dissect/cstruct/types/int.py",
23
- "dissect/cstruct/types/__init__.py",
24
- "dissect/cstruct/types/leb128.py",
25
- "dissect/cstruct/types/flag.py",
26
- "dissect/cstruct/types/void.py",
27
- "dissect/cstruct/types/char.py",
19
+ "dissect/cstruct/cstruct.py",
20
+ "dissect/cstruct/bitbuffer.py",
21
+ "dissect/cstruct/lexer.py",
22
+ "dissect/cstruct/expression.py",
23
+ "dissect/cstruct/__init__.py",
24
+ "dissect/cstruct/types/base.py",
28
25
  "dissect/cstruct/types/pointer.py",
29
26
  "dissect/cstruct/types/structure.py",
27
+ "dissect/cstruct/types/void.py",
28
+ "dissect/cstruct/types/int.py",
29
+ "dissect/cstruct/types/flag.py",
30
+ "dissect/cstruct/types/packed.py",
30
31
  "dissect/cstruct/types/enum.py",
31
- "dissect/cstruct/types/base.py",
32
+ "dissect/cstruct/types/char.py",
32
33
  "dissect/cstruct/types/wchar.py",
33
- "dissect/cstruct/types/packed.py",
34
- "dissect/cstruct/tools/__init__.py",
34
+ "dissect/cstruct/types/leb128.py",
35
+ "dissect/cstruct/types/__init__.py",
35
36
  "dissect/cstruct/tools/stubgen.py",
36
- "tests/test_types_char.py",
37
- "tests/test_ctypes.py",
38
- "tests/test_types_custom.py",
39
- "tests/__init__.py",
40
- "tests/test_types_leb128.py",
41
- "tests/test_types_union.py",
42
- "tests/test_tools_stubgen.py",
43
- "tests/test_basic.py",
44
- "tests/test_lexer.py",
45
- "tests/test_types_int.py",
46
- "tests/test_expression.py",
47
- "tests/utils.py",
48
- "tests/test_align.py",
49
- "tests/test_utils.py",
50
- "tests/test_compiler.py",
37
+ "dissect/cstruct/tools/__init__.py",
38
+ "examples/secdesc.py",
39
+ "examples/pe.py",
40
+ "examples/mirai.py",
41
+ "examples/protobuf.py",
42
+ "examples/disk.py",
51
43
  "tests/test_types_enum.py",
44
+ "tests/test_types_pointer.py",
45
+ "tests/test_types_leb128.py",
46
+ "tests/test_annotations.py",
52
47
  "tests/test_types_wchar.py",
53
- "tests/test_bitfield.py",
54
- "tests/test_types_structure.py",
55
48
  "tests/test_parser.py",
56
- "tests/test_annotations.py",
49
+ "tests/test_ctypes.py",
50
+ "tests/test_bitbuffer.py",
57
51
  "tests/conftest.py",
58
- "tests/test_types_void.py",
52
+ "tests/test_types_packed.py",
53
+ "tests/test_types_structure.py",
54
+ "tests/test_types_union.py",
55
+ "tests/test_expression.py",
56
+ "tests/test_tools_stubgen.py",
57
+ "tests/test_types_custom.py",
58
+ "tests/utils.py",
59
+ "tests/test_lexer.py",
59
60
  "tests/test_types_flag.py",
60
61
  "tests/test_benchmark.py",
61
- "tests/test_types_pointer.py",
62
- "tests/test_types_packed.py",
62
+ "tests/test_types_char.py",
63
+ "tests/test_compiler.py",
64
+ "tests/test_types_int.py",
65
+ "tests/test_types_void.py",
63
66
  "tests/test_types_base.py",
64
- "tests/test_bitbuffer.py",
65
- "tests/_data/testdef.txt",
66
- "tests/_docs/__init__.py",
67
+ "tests/test_align.py",
68
+ "tests/test_basic.py",
69
+ "tests/test_bitfield.py",
70
+ "tests/test_utils.py",
71
+ "tests/__init__.py",
72
+ "tests/_docs/conf.py",
67
73
  "tests/_docs/Makefile",
68
74
  "tests/_docs/index.rst",
69
- "tests/_docs/conf.py",
70
- "examples/secdesc.py",
71
- "examples/disk.py",
72
- "examples/pe.py",
73
- "examples/mirai.py",
74
- "examples/protobuf.py",
75
- ".github/pull_request_template.md",
76
- ".github/workflows/dissect-ci.yml"
75
+ "tests/_docs/__init__.py",
76
+ "tests/_data/testdef.txt"
77
77
  ]
78
78
  }
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "5.0.dev0",
3
+ "distance": 7,
4
+ "node": "g32253fe9f286383a8bda6b953c7c85571cd89833",
5
+ "dirty": true,
6
+ "branch": "main",
7
+ "node_date": "2026-07-20"
8
+ }
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import io
3
4
  from typing import TYPE_CHECKING, BinaryIO
4
5
 
5
6
  import pytest
@@ -20,6 +21,24 @@ def test_array_size_mismatch(cs: cstruct) -> None:
20
21
  assert cs.uint8[2]([1, 2]).dumps()
21
22
 
22
23
 
24
+ def test_array_write_padding(cs: cstruct) -> None:
25
+ buf = io.BytesIO()
26
+ cs.uint8[4]._write(buf, [1, 2], endian=cs.endian)
27
+ assert buf.getvalue() == b"\x01\x02\x00\x00"
28
+
29
+ cdef = """
30
+ struct point {
31
+ uint8 x;
32
+ uint8 y;
33
+ };
34
+ """
35
+ cs.load(cdef)
36
+
37
+ buf = io.BytesIO()
38
+ cs.point[4]._write(buf, [cs.point(x=1, y=2)], endian=cs.endian)
39
+ assert buf.getvalue() == b"\x01\x02" + b"\x00\x00" * 3
40
+
41
+
23
42
  def test_eof(cs: cstruct, compiled: bool) -> None:
24
43
  cdef = """
25
44
  struct test_char {
@@ -5,6 +5,8 @@ from typing import TYPE_CHECKING
5
5
 
6
6
  import pytest
7
7
 
8
+ from dissect.cstruct.exception import ArraySizeError
9
+
8
10
  if TYPE_CHECKING:
9
11
  from dissect.cstruct.cstruct import cstruct
10
12
 
@@ -36,6 +38,38 @@ def test_char_array_write(cs: cstruct) -> None:
36
38
  assert cs.char[None](buf).dumps() == b"AAAA\x00"
37
39
 
38
40
 
41
+ def test_char_array_write_padding(cs: cstruct) -> None:
42
+ buf = io.BytesIO()
43
+ cs.char[8]._write(buf, "hi", endian=cs.endian)
44
+ assert buf.getvalue() == b"hi\x00\x00\x00\x00\x00\x00"
45
+
46
+ cdef = """
47
+ struct test_struct {
48
+ int x;
49
+ char y[8];
50
+ char z[16];
51
+ };
52
+ """
53
+ cs.load(cdef)
54
+
55
+ obj = cs.test_struct()
56
+ obj.x = 4
57
+ obj.y = "hi"
58
+ obj.z = "bye"
59
+
60
+ assert len(obj.dumps()) == len(cs.test_struct)
61
+ assert (
62
+ obj.dumps()
63
+ == b"\x04\x00\x00\x00hi\x00\x00\x00\x00\x00\x00bye\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
64
+ )
65
+
66
+
67
+ def test_char_array_write_size_error(cs: cstruct) -> None:
68
+ buf = io.BytesIO()
69
+ with pytest.raises(ArraySizeError):
70
+ cs.char[4]._write(buf, b"toolong", endian=cs.endian)
71
+
72
+
39
73
  def test_char_eof(cs: cstruct) -> None:
40
74
  with pytest.raises(EOFError):
41
75
  cs.char(b"")
@@ -5,6 +5,8 @@ from typing import TYPE_CHECKING
5
5
 
6
6
  import pytest
7
7
 
8
+ from dissect.cstruct.exception import ArraySizeError
9
+
8
10
  if TYPE_CHECKING:
9
11
  from dissect.cstruct.cstruct import cstruct
10
12
 
@@ -38,6 +40,33 @@ def test_wchar_array_write(cs: cstruct) -> None:
38
40
  assert cs.wchar[None](buf).dumps() == b"A\x00A\x00A\x00A\x00\x00\x00"
39
41
 
40
42
 
43
+ def test_wchar_array_write_padding(cs: cstruct) -> None:
44
+ buf = io.BytesIO()
45
+ cs.wchar[8]._write(buf, "hi", endian=cs.endian)
46
+ assert buf.getvalue() == b"h\x00i\x00" + b"\x00" * 12
47
+
48
+ cdef = """
49
+ struct test_struct {
50
+ int x;
51
+ wchar y[8];
52
+ wchar z[16];
53
+ };
54
+ """
55
+ cs.load(cdef)
56
+ obj = cs.test_struct()
57
+ obj.x = 4
58
+ obj.y = "hi"
59
+ obj.z = "bye"
60
+ assert len(obj.dumps()) == len(cs.test_struct)
61
+ assert obj.dumps() == b"\x04\x00\x00\x00h\x00i\x00" + (b"\x00" * 12) + b"b\x00y\x00e\x00" + (b"\x00" * 26)
62
+
63
+
64
+ def test_wchar_array_write_size_error(cs: cstruct) -> None:
65
+ buf = io.BytesIO()
66
+ with pytest.raises(ArraySizeError):
67
+ cs.wchar[4]._write(buf, "toolong", endian=cs.endian)
68
+
69
+
41
70
  def test_wchar_be_read(cs: cstruct) -> None:
42
71
  cs.endian = ">"
43
72
 
@@ -1,8 +0,0 @@
1
- {
2
- "tag": "5.0.dev0",
3
- "distance": 6,
4
- "node": "g8fd15061a9f9618417a62277bc6f2d625768fdd2",
5
- "dirty": true,
6
- "branch": "main",
7
- "node_date": "2026-07-16"
8
- }