Skip to content

Commit 6f466dc

Browse files
committed
Move all internal attributes to dunder attributes
1 parent 599b5e9 commit 6f466dc

22 files changed

Lines changed: 344 additions & 225 deletions

dissect/cstruct/bitbuffer.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ def __init__(self, stream: BinaryIO, *, endian: str):
1919

2020
def read(self, field_type: type[BaseType], bits: int) -> int:
2121
if self._remaining == 0 or self._type != field_type:
22-
if field_type.size is None:
22+
if field_type.__size__ is None:
2323
raise ValueError("Reading variable-length fields is unsupported")
2424

2525
self._type = field_type
26-
self._remaining = field_type.size * 8
26+
self._remaining = field_type.__size__ * 8
2727
self._buffer = field_type._read(self.stream, endian=self.endian)
2828

2929
if isinstance(self._buffer, bytes):
@@ -51,17 +51,17 @@ def write(self, field_type: type[BaseType], data: int, bits: int) -> None:
5151
if self._type:
5252
self.flush()
5353

54-
if field_type.size is None:
54+
if field_type.__size__ is None:
5555
raise ValueError("Writing variable-length fields is unsupported")
5656

57-
self._remaining = field_type.size * 8
57+
self._remaining = field_type.__size__ * 8
5858
self._type = field_type
5959

60-
if self._type is None or self._type.size is None:
60+
if self._type is None or self._type.__size__ is None:
6161
raise ValueError("Invalid state")
6262

6363
if self.endian == "<":
64-
self._buffer |= data << (self._type.size * 8 - self._remaining)
64+
self._buffer |= data << (self._type.__size__ * 8 - self._remaining)
6565
else:
6666
self._buffer |= data << (self._remaining - bits)
6767

dissect/cstruct/compiler.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060

6161

6262
def compile(structure: type[Structure]) -> type[Structure]:
63-
return Compiler(structure.cs).compile(structure)
63+
return Compiler(structure.__cs__).compile(structure)
6464

6565

6666
class Compiler:
@@ -119,7 +119,7 @@ def generate_source(self) -> str:
119119
"""
120120

121121
if any(field.bits for field in self.fields):
122-
preamble += "bit_reader = BitBuffer(stream, endian=endian)\n"
122+
preamble += "bit_reader = BitBuffer(stream, endian=cls.__cs__.endian)\n"
123123

124124
read_code = "\n".join(self._generate_fields())
125125

@@ -224,22 +224,22 @@ def align_to_field(field: Field) -> Iterator[str]:
224224
yield from flush()
225225

226226
if self.align:
227-
yield f"stream.seek(-stream.tell() & (cls.alignment - 1), {io.SEEK_CUR})"
227+
yield f"stream.seek(-stream.tell() & (cls.__alignment__ - 1), {io.SEEK_CUR})"
228228

229229
def _generate_structure(self, field: Field) -> Iterator[str]:
230230
template = f"""
231-
{"_s = stream.tell()" if field.type.dynamic else ""}
231+
{"_s = stream.tell()" if field.type.__dynamic__ else ""}
232232
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 ""}
233+
{f's["{field._name}"] = stream.tell() - _s' if field.type.__dynamic__ else ""}
234234
"""
235235

236236
yield dedent(template)
237237

238238
def _generate_array(self, field: Field) -> Iterator[str]:
239239
template = f"""
240-
{"_s = stream.tell()" if field.type.dynamic else ""}
240+
{"_s = stream.tell()" if field.type.__dynamic__ else ""}
241241
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 ""}
242+
{f's["{field._name}"] = stream.tell() - _s' if field.type.__dynamic__ else ""}
243243
"""
244244

245245
yield dedent(template)
@@ -253,8 +253,8 @@ def _generate_bits(self, field: Field) -> Iterator[str]:
253253
field_type = field_type.type
254254

255255
if issubclass(field_type, Char):
256-
field_type = field_type.cs.uint8
257-
lookup = "cls.cs.uint8"
256+
field_type = field_type.__cs__.uint8
257+
lookup = "cls.__cs__.uint8"
258258

259259
template = f"""
260260
_t = {lookup}
@@ -283,13 +283,13 @@ def _generate_packed(self, fields: list[Field]) -> Iterator[str]:
283283
read_type = _get_read_type(self.cs, field_type.type)
284284

285285
if issubclass(read_type, (Char, Wchar, Int)):
286-
count *= read_type.size
286+
count *= read_type.__size__
287287
getter = f"buf[{size}:{size + count}]"
288288
else:
289289
getter = f"data[{slice_index}:{slice_index + count}]"
290290
slice_index += count
291291
elif issubclass(read_type, (Char, Wchar, Int)):
292-
getter = f"buf[{size}:{size + read_type.size}]"
292+
getter = f"buf[{size}:{size + read_type.__size__}]"
293293
else:
294294
getter = f"data[{slice_index}]"
295295
slice_index += 1
@@ -308,8 +308,8 @@ def _generate_packed(self, fields: list[Field]) -> Iterator[str]:
308308

309309
if issubclass(field_type.type, Int):
310310
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})]"
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__})]"
313313
elif issubclass(field_type.type, Pointer):
314314
item_parser = "_et.__new__(_et, e, stream, context=r, endian=endian)"
315315
list_comp = f"[{item_parser} for e in {getter}]"
@@ -329,7 +329,7 @@ def _generate_packed(self, fields: list[Field]) -> Iterator[str]:
329329
reads.append(f'r["{field._name}"] = {parser}')
330330
reads.append("") # Generates a newline in the resulting code
331331

332-
size += field_type.size
332+
size += field_type.__size__
333333

334334
fmt = _optimize_struct_fmt(info)
335335
if fmt == "x" or (len(fmt) == 2 and fmt[1] == "x"):
@@ -382,9 +382,9 @@ def _generate_struct_info(cs: cstruct, fields: list[Field], align: bool = False)
382382
# Other types are byte based
383383
# We don't actually unpack anything here but slice directly out of the buffer
384384
elif issubclass(read_type, (Char, Wchar, Int)):
385-
yield field, count * read_type.size, "x"
385+
yield field, count * read_type.__size__, "x"
386386

387-
size = count * read_type.size
387+
size = count * read_type.__size__
388388
imaginary_offset += size
389389
if current_offset is not None:
390390
current_offset += size

dissect/cstruct/cstruct.py

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,28 @@ def __init__(self, load: str = "", *, endian: AllowedEndianness = "<", pointer:
206206
if load:
207207
self.load(load)
208208

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+
):
210231
try:
211232
return self.consts[attr]
212233
except KeyError:
@@ -227,7 +248,7 @@ def __copy__(self) -> cstruct:
227248
# Update types to point to the new cstruct instance
228249
for name, type_ in self.types.items():
229250
new_type = copy.copy(type_)
230-
new_type.cs = cs
251+
new_type.__cs__ = cs
231252
cs.add_type(name, new_type, replace=True)
232253

233254
for name, value in self.consts.items():
@@ -481,10 +502,10 @@ def _make_type(
481502
attrs = attrs or {}
482503
attrs.update(
483504
{
484-
"cs": self,
485-
"size": size,
486-
"dynamic": size is None,
487-
"alignment": alignment or size,
505+
"__cs__": self,
506+
"__size__": size,
507+
"__dynamic__": size is None,
508+
"__alignment__": alignment or size,
488509
}
489510
)
490511
return types.new_class(name, bases, {}, lambda ns: ns.update(attrs))
@@ -494,12 +515,12 @@ def _make_array(self, type_: T, num_entries: int | Expression | None) -> type[Ar
494515
if num_entries is None:
495516
null_terminated = True
496517
size = None
497-
elif isinstance(num_entries, Expression) or type_.dynamic:
518+
elif isinstance(num_entries, Expression) or type_.__dynamic__:
498519
size = None
499520
else:
500-
if type_.size is None:
521+
if type_.__size__ is None:
501522
raise ValueError(f"Cannot create array of dynamic type: {type_.__name__}")
502-
size = num_entries * type_.size
523+
size = num_entries * type_.__size__
503524

504525
name = f"{type_.__name__}[]" if null_terminated else f"{type_.__name__}[{num_entries}]"
505526

@@ -511,7 +532,7 @@ def _make_array(self, type_: T, num_entries: int | Expression | None) -> type[Ar
511532
"null_terminated": null_terminated,
512533
}
513534

514-
return cast("type[Array]", self._make_type(name, bases, size, alignment=type_.alignment, attrs=attrs))
535+
return cast("type[Array]", self._make_type(name, bases, size, alignment=type_.__alignment__, attrs=attrs))
515536

516537
def _make_int_type(self, name: str, size: int, signed: bool, *, alignment: int | None = None) -> type[Int]:
517538
return cast("type[Int]", self._make_type(name, (Int,), size, alignment=alignment, attrs={"signed": signed}))
@@ -538,8 +559,8 @@ def _make_pointer(self, target: type[BaseType]) -> type[Pointer]:
538559
return self._make_type(
539560
f"{target.__name__}*",
540561
(Pointer,),
541-
self.pointer.size,
542-
alignment=self.pointer.alignment,
562+
self.pointer.__size__,
563+
alignment=self.pointer.__alignment__,
543564
attrs={"type": target},
544565
)
545566

dissect/cstruct/tools/stubgen.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,15 +159,15 @@ def generate_structure_stub(
159159
indent = " " * 4
160160

161161
args = ["self"]
162-
for field_name, field in structure.fields.items():
162+
for field_name, field in structure.__members__.items():
163163
inlined = False
164164

165165
# If it's a structure and not globally defined, add an inline stub for it
166166
nested_type = field.type
167167
while issubclass(nested_type, types.BaseArray):
168168
nested_type = nested_type.type
169169

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:
171171
inlined = True
172172
inline_stub = generate_structure_stub(nested_type, cs_prefix=cs_prefix, module_prefix=module_prefix)
173173

0 commit comments

Comments
 (0)