dissect.cstruct 4.2.dev1__tar.gz → 4.3.dev2__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 (67) hide show
  1. {dissect_cstruct-4.2.dev1/dissect.cstruct.egg-info → dissect_cstruct-4.3.dev2}/PKG-INFO +1 -1
  2. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/dissect/cstruct/cstruct.py +1 -1
  3. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/dissect/cstruct/types/base.py +23 -15
  4. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/dissect/cstruct/types/char.py +6 -6
  5. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/dissect/cstruct/types/enum.py +5 -5
  6. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/dissect/cstruct/types/int.py +2 -2
  7. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/dissect/cstruct/types/leb128.py +2 -2
  8. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/dissect/cstruct/types/packed.py +3 -3
  9. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/dissect/cstruct/types/pointer.py +9 -5
  10. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/dissect/cstruct/types/structure.py +201 -70
  11. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/dissect/cstruct/types/void.py +8 -1
  12. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/dissect/cstruct/types/wchar.py +6 -6
  13. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2/dissect.cstruct.egg-info}/PKG-INFO +1 -1
  14. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/test_basic.py +0 -95
  15. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/test_types_base.py +7 -3
  16. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/test_types_char.py +6 -0
  17. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/test_types_custom.py +24 -7
  18. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/test_types_enum.py +29 -0
  19. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/test_types_flag.py +14 -0
  20. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/test_types_int.py +13 -3
  21. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/test_types_leb128.py +8 -0
  22. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/test_types_packed.py +41 -24
  23. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/test_types_pointer.py +16 -2
  24. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/test_types_structure.py +222 -1
  25. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/test_types_union.py +197 -5
  26. dissect_cstruct-4.3.dev2/tests/test_types_void.py +65 -0
  27. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/test_types_wchar.py +6 -0
  28. dissect_cstruct-4.2.dev1/tests/test_types_void.py +0 -13
  29. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/COPYRIGHT +0 -0
  30. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/LICENSE +0 -0
  31. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/MANIFEST.in +0 -0
  32. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/README.md +0 -0
  33. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/dissect/cstruct/__init__.py +0 -0
  34. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/dissect/cstruct/bitbuffer.py +0 -0
  35. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/dissect/cstruct/compiler.py +0 -0
  36. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/dissect/cstruct/exceptions.py +0 -0
  37. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/dissect/cstruct/expression.py +0 -0
  38. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/dissect/cstruct/parser.py +0 -0
  39. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/dissect/cstruct/types/__init__.py +0 -0
  40. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/dissect/cstruct/types/flag.py +0 -0
  41. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/dissect/cstruct/utils.py +0 -0
  42. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/dissect.cstruct.egg-info/SOURCES.txt +0 -0
  43. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/dissect.cstruct.egg-info/dependency_links.txt +0 -0
  44. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/dissect.cstruct.egg-info/top_level.txt +0 -0
  45. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/examples/disk.py +0 -0
  46. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/examples/mirai.py +0 -0
  47. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/examples/pe.py +0 -0
  48. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/examples/protobuf.py +0 -0
  49. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/examples/secdesc.py +0 -0
  50. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/pyproject.toml +0 -0
  51. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/setup.cfg +0 -0
  52. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/__init__.py +0 -0
  53. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/conftest.py +0 -0
  54. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/data/testdef.txt +0 -0
  55. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/docs/Makefile +0 -0
  56. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/docs/conf.py +0 -0
  57. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/docs/index.rst +0 -0
  58. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/test_align.py +0 -0
  59. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/test_bitbuffer.py +0 -0
  60. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/test_bitfield.py +0 -0
  61. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/test_compiler.py +0 -0
  62. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/test_ctypes.py +0 -0
  63. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/test_expression.py +0 -0
  64. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/test_parser.py +0 -0
  65. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/test_utils.py +0 -0
  66. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tests/utils.py +0 -0
  67. {dissect_cstruct-4.2.dev1 → dissect_cstruct-4.3.dev2}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dissect.cstruct
3
- Version: 4.2.dev1
3
+ Version: 4.3.dev2
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
@@ -321,7 +321,7 @@ class cstruct:
321
321
  size: int | None,
322
322
  *,
323
323
  alignment: int | None = None,
324
- attrs: dict[str, Any] = None,
324
+ attrs: dict[str, Any] | None = None,
325
325
  ) -> type[BaseType]:
326
326
  """Create a new type class bound to this cstruct instance.
327
327
 
@@ -36,14 +36,14 @@ class MetaType(type):
36
36
  if len(args) == 1 and not isinstance(args[0], cls):
37
37
  stream = args[0]
38
38
 
39
- if hasattr(stream, "read"):
39
+ if _is_readable_type(stream):
40
40
  return cls._read(stream)
41
41
 
42
42
  if issubclass(cls, bytes) and isinstance(stream, bytes) and len(stream) == cls.size:
43
43
  # Shortcut for char/bytes type
44
44
  return type.__call__(cls, *args, **kwargs)
45
45
 
46
- if isinstance(stream, (bytes, memoryview, bytearray)):
46
+ if _is_buffer_type(stream):
47
47
  return cls.reads(stream)
48
48
 
49
49
  return type.__call__(cls, *args, **kwargs)
@@ -59,7 +59,7 @@ class MetaType(type):
59
59
 
60
60
  return cls.size
61
61
 
62
- def default(cls) -> BaseType:
62
+ def __default__(cls) -> BaseType:
63
63
  """Return the default value of this type."""
64
64
  return cls()
65
65
 
@@ -83,7 +83,7 @@ class MetaType(type):
83
83
  Returns:
84
84
  The parsed value of this type.
85
85
  """
86
- if isinstance(obj, (bytes, memoryview, bytearray)):
86
+ if _is_buffer_type(obj):
87
87
  return cls.reads(obj)
88
88
 
89
89
  return cls._read(obj)
@@ -113,7 +113,7 @@ class MetaType(type):
113
113
  cls._write(out, value)
114
114
  return out.getvalue()
115
115
 
116
- def _read(cls, stream: BinaryIO, context: dict[str, Any] = None) -> BaseType:
116
+ def _read(cls, stream: BinaryIO, context: dict[str, Any] | None = None) -> BaseType:
117
117
  """Internal function for reading value.
118
118
 
119
119
  Must be implemented per type.
@@ -124,7 +124,7 @@ class MetaType(type):
124
124
  """
125
125
  raise NotImplementedError()
126
126
 
127
- def _read_array(cls, stream: BinaryIO, count: int, context: dict[str, Any] = None) -> list[BaseType]:
127
+ def _read_array(cls, stream: BinaryIO, count: int, context: dict[str, Any] | None = None) -> list[BaseType]:
128
128
  """Internal function for reading array values.
129
129
 
130
130
  Allows type implementations to do optimized reading for their type.
@@ -145,7 +145,7 @@ class MetaType(type):
145
145
 
146
146
  return [cls._read(stream, context) for _ in range(count)]
147
147
 
148
- def _read_0(cls, stream: BinaryIO, context: dict[str, Any] = None) -> list[BaseType]:
148
+ def _read_0(cls, stream: BinaryIO, context: dict[str, Any] | None = None) -> list[BaseType]:
149
149
  """Internal function for reading null-terminated data.
150
150
 
151
151
  "Null" is type specific, so must be implemented per type.
@@ -179,7 +179,7 @@ class MetaType(type):
179
179
  stream: The stream to read from.
180
180
  array: The array to write.
181
181
  """
182
- return cls._write_array(stream, array + [cls()])
182
+ return cls._write_array(stream, array + [cls.__default__()])
183
183
 
184
184
 
185
185
  class _overload:
@@ -225,7 +225,12 @@ class ArrayMetaType(MetaType):
225
225
  num_entries: int | Expression | None
226
226
  null_terminated: bool
227
227
 
228
- def _read(cls, stream: BinaryIO, context: dict[str, Any] = None) -> Array:
228
+ def __default__(cls) -> BaseType:
229
+ return type.__call__(
230
+ cls, [cls.type.__default__()] * (cls.num_entries if isinstance(cls.num_entries, int) else 0)
231
+ )
232
+
233
+ def _read(cls, stream: BinaryIO, context: dict[str, Any] | None = None) -> Array:
229
234
  if cls.null_terminated:
230
235
  return cls.type._read_0(stream, context)
231
236
 
@@ -243,11 +248,6 @@ class ArrayMetaType(MetaType):
243
248
 
244
249
  return cls.type._read_array(stream, num, context)
245
250
 
246
- def default(cls) -> BaseType:
247
- return type.__call__(
248
- cls, [cls.type.default() for _ in range(0 if cls.dynamic or cls.null_terminated else cls.num_entries)]
249
- )
250
-
251
251
 
252
252
  class Array(list, BaseType, metaclass=ArrayMetaType):
253
253
  """Implements a fixed or dynamically sized array type.
@@ -261,7 +261,7 @@ class Array(list, BaseType, metaclass=ArrayMetaType):
261
261
  """
262
262
 
263
263
  @classmethod
264
- def _read(cls, stream: BinaryIO, context: dict[str, Any] = None) -> Array:
264
+ def _read(cls, stream: BinaryIO, context: dict[str, Any] | None = None) -> Array:
265
265
  return cls(ArrayMetaType._read(cls, stream, context))
266
266
 
267
267
  @classmethod
@@ -275,5 +275,13 @@ class Array(list, BaseType, metaclass=ArrayMetaType):
275
275
  return cls.type._write_array(stream, data)
276
276
 
277
277
 
278
+ def _is_readable_type(value: Any) -> bool:
279
+ return hasattr(value, "read")
280
+
281
+
282
+ def _is_buffer_type(value: Any) -> bool:
283
+ return isinstance(value, (bytes, memoryview, bytearray))
284
+
285
+
278
286
  # As mentioned in the BaseType class, we correctly set the type here
279
287
  MetaType.ArrayType = Array
@@ -9,7 +9,7 @@ class CharArray(bytes, BaseType, metaclass=ArrayMetaType):
9
9
  """Character array type for reading and writing byte strings."""
10
10
 
11
11
  @classmethod
12
- def _read(cls, stream: BinaryIO, context: dict[str, Any] = None) -> CharArray:
12
+ def _read(cls, stream: BinaryIO, context: dict[str, Any] | None = None) -> CharArray:
13
13
  return type.__call__(cls, ArrayMetaType._read(cls, stream, context))
14
14
 
15
15
  @classmethod
@@ -25,7 +25,7 @@ class CharArray(bytes, BaseType, metaclass=ArrayMetaType):
25
25
  return stream.write(data)
26
26
 
27
27
  @classmethod
28
- def default(cls) -> CharArray:
28
+ def __default__(cls) -> CharArray:
29
29
  return type.__call__(cls, b"\x00" * (0 if cls.dynamic or cls.null_terminated else cls.num_entries))
30
30
 
31
31
 
@@ -35,11 +35,11 @@ class Char(bytes, BaseType):
35
35
  ArrayType = CharArray
36
36
 
37
37
  @classmethod
38
- def _read(cls, stream: BinaryIO, context: dict[str, Any] = None) -> Char:
38
+ def _read(cls, stream: BinaryIO, context: dict[str, Any] | None = None) -> Char:
39
39
  return cls._read_array(stream, 1, context)
40
40
 
41
41
  @classmethod
42
- def _read_array(cls, stream: BinaryIO, count: int, context: dict[str, Any] = None) -> Char:
42
+ def _read_array(cls, stream: BinaryIO, count: int, context: dict[str, Any] | None = None) -> Char:
43
43
  if count == 0:
44
44
  return type.__call__(cls, b"")
45
45
 
@@ -50,7 +50,7 @@ class Char(bytes, BaseType):
50
50
  return type.__call__(cls, data)
51
51
 
52
52
  @classmethod
53
- def _read_0(cls, stream: BinaryIO, context: dict[str, Any] = None) -> Char:
53
+ def _read_0(cls, stream: BinaryIO, context: dict[str, Any] | None = None) -> Char:
54
54
  buf = []
55
55
  while True:
56
56
  byte = stream.read(1)
@@ -75,5 +75,5 @@ class Char(bytes, BaseType):
75
75
  return stream.write(data)
76
76
 
77
77
  @classmethod
78
- def default(cls) -> Char:
78
+ def __default__(cls) -> Char:
79
79
  return type.__call__(cls, b"\x00")
@@ -27,7 +27,7 @@ class EnumMetaType(EnumMeta, MetaType):
27
27
  ) -> EnumMetaType:
28
28
  if name is None:
29
29
  if value is None:
30
- value = cls.type()
30
+ value = cls.type.__default__()
31
31
 
32
32
  if not isinstance(value, int):
33
33
  # value is a parsable value
@@ -64,13 +64,13 @@ class EnumMetaType(EnumMeta, MetaType):
64
64
  return True
65
65
  return value in cls._value2member_map_
66
66
 
67
- def _read(cls, stream: BinaryIO, context: dict[str, Any] = None) -> Enum:
67
+ def _read(cls, stream: BinaryIO, context: dict[str, Any] | None = None) -> Enum:
68
68
  return cls(cls.type._read(stream, context))
69
69
 
70
- def _read_array(cls, stream: BinaryIO, count: int, context: dict[str, Any] = None) -> list[Enum]:
70
+ def _read_array(cls, stream: BinaryIO, count: int, context: dict[str, Any] | None = None) -> list[Enum]:
71
71
  return list(map(cls, cls.type._read_array(stream, count, context)))
72
72
 
73
- def _read_0(cls, stream: BinaryIO, context: dict[str, Any] = None) -> list[Enum]:
73
+ def _read_0(cls, stream: BinaryIO, context: dict[str, Any] | None = None) -> list[Enum]:
74
74
  return list(map(cls, cls.type._read_0(stream, context)))
75
75
 
76
76
  def _write(cls, stream: BinaryIO, data: Enum) -> int:
@@ -82,7 +82,7 @@ class EnumMetaType(EnumMeta, MetaType):
82
82
 
83
83
  def _write_0(cls, stream: BinaryIO, array: list[BaseType]) -> int:
84
84
  data = [entry.value if isinstance(entry, Enum) else entry for entry in array]
85
- return cls._write_array(stream, data + [cls.type()])
85
+ return cls._write_array(stream, data + [cls.type.__default__()])
86
86
 
87
87
 
88
88
  def _fix_alias_members(cls: type[Enum]) -> None:
@@ -12,7 +12,7 @@ class Int(int, BaseType):
12
12
  signed: bool
13
13
 
14
14
  @classmethod
15
- def _read(cls, stream: BinaryIO, context: dict[str, Any] = None) -> Int:
15
+ def _read(cls, stream: BinaryIO, context: dict[str, Any] | None = None) -> Int:
16
16
  data = stream.read(cls.size)
17
17
 
18
18
  if len(data) != cls.size:
@@ -21,7 +21,7 @@ class Int(int, BaseType):
21
21
  return cls.from_bytes(data, ENDIANNESS_MAP[cls.cs.endian], signed=cls.signed)
22
22
 
23
23
  @classmethod
24
- def _read_0(cls, stream: BinaryIO, context: dict[str, Any] = None) -> Int:
24
+ def _read_0(cls, stream: BinaryIO, context: dict[str, Any] | None = None) -> Int:
25
25
  result = []
26
26
 
27
27
  while True:
@@ -14,7 +14,7 @@ class LEB128(int, BaseType):
14
14
  signed: bool
15
15
 
16
16
  @classmethod
17
- def _read(cls, stream: BinaryIO, context: dict[str, Any] = None) -> LEB128:
17
+ def _read(cls, stream: BinaryIO, context: dict[str, Any] | None = None) -> LEB128:
18
18
  result = 0
19
19
  shift = 0
20
20
  while True:
@@ -35,7 +35,7 @@ class LEB128(int, BaseType):
35
35
  return cls.__new__(cls, result)
36
36
 
37
37
  @classmethod
38
- def _read_0(cls, stream: BinaryIO, context: dict[str, Any] = None) -> LEB128:
38
+ def _read_0(cls, stream: BinaryIO, context: dict[str, Any] | None = None) -> LEB128:
39
39
  result = []
40
40
 
41
41
  while True:
@@ -18,11 +18,11 @@ class Packed(BaseType):
18
18
  packchar: str
19
19
 
20
20
  @classmethod
21
- def _read(cls, stream: BinaryIO, context: dict[str, Any] = None) -> Packed:
21
+ def _read(cls, stream: BinaryIO, context: dict[str, Any] | None = None) -> Packed:
22
22
  return cls._read_array(stream, 1, context)[0]
23
23
 
24
24
  @classmethod
25
- def _read_array(cls, stream: BinaryIO, count: int, context: dict[str, Any] = None) -> list[Packed]:
25
+ def _read_array(cls, stream: BinaryIO, count: int, context: dict[str, Any] | None = None) -> list[Packed]:
26
26
  if count == EOF:
27
27
  data = stream.read()
28
28
  length = len(data)
@@ -39,7 +39,7 @@ class Packed(BaseType):
39
39
  return [cls.__new__(cls, value) for value in fmt.unpack(data)]
40
40
 
41
41
  @classmethod
42
- def _read_0(cls, stream: BinaryIO, context: dict[str, Any] = None) -> Packed:
42
+ def _read_0(cls, stream: BinaryIO, context: dict[str, Any] | None = None) -> Packed:
43
43
  result = []
44
44
 
45
45
  fmt = _struct(cls.cs.endian, cls.packchar)
@@ -12,11 +12,11 @@ class Pointer(int, BaseType):
12
12
  """Pointer to some other type."""
13
13
 
14
14
  type: MetaType
15
- _stream: BinaryIO
16
- _context: dict[str, Any]
15
+ _stream: BinaryIO | None
16
+ _context: dict[str, Any] | None
17
17
  _value: BaseType
18
18
 
19
- def __new__(cls, value: int, stream: BinaryIO, context: dict[str, Any] = None) -> Pointer:
19
+ def __new__(cls, value: int, stream: BinaryIO | None, context: dict[str, Any] | None = None) -> Pointer:
20
20
  obj = super().__new__(cls, value)
21
21
  obj._stream = stream
22
22
  obj._context = context
@@ -66,7 +66,11 @@ class Pointer(int, BaseType):
66
66
  return type.__call__(self.__class__, int.__or__(self, other), self._stream, self._context)
67
67
 
68
68
  @classmethod
69
- def _read(cls, stream: BinaryIO, context: dict[str, Any] = None) -> Pointer:
69
+ def __default__(cls) -> Pointer:
70
+ return cls.__new__(cls, cls.cs.pointer.__default__(), None, None)
71
+
72
+ @classmethod
73
+ def _read(cls, stream: BinaryIO, context: dict[str, Any] | None = None) -> Pointer:
70
74
  return cls.__new__(cls, cls.cs.pointer._read(stream, context), stream, context)
71
75
 
72
76
  @classmethod
@@ -74,7 +78,7 @@ class Pointer(int, BaseType):
74
78
  return cls.cs.pointer._write(stream, data)
75
79
 
76
80
  def dereference(self) -> Any:
77
- if self == 0:
81
+ if self == 0 or self._stream is None:
78
82
  raise NullPointerDereference()
79
83
 
80
84
  if self._value is None and not issubclass(self.type, Void):