Skip to content

Commit f8f3408

Browse files
committed
feat: implement size_of to make nested field chains work
1 parent c9a7699 commit f8f3408

11 files changed

Lines changed: 72 additions & 56 deletions

File tree

libdestruct/c/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99

1010
__all__ = ["c_char", "c_uchar", "c_short", "c_ushort", "c_int", "c_uint", "c_long", "c_ulong", "c_str"]
1111

12-
import libdestruct.c.base_type_inflater # noqa: F401
12+
import libdestruct.c.base_type_inflater
1313
import libdestruct.c.ctypes_generic_field # noqa: F401

libdestruct/common/array/array_impl.py

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,15 @@
88

99
from typing import TYPE_CHECKING
1010

11-
from libdestruct.c.ctypes_generic import _ctypes_generic
1211
from libdestruct.common.array.array import array
13-
from libdestruct.common.field import Field
14-
from libdestruct.common.obj import obj
1512
from libdestruct.common.struct.struct import struct
13+
from libdestruct.common.utils import size_of
1614

1715
if TYPE_CHECKING: # pragma: no cover
1816
from collections.abc import Generator
1917

2018
from libdestruct.backing.resolver import Resolver
19+
from libdestruct.common.obj import obj
2120

2221

2322
class array_impl(array):
@@ -26,6 +25,9 @@ class array_impl(array):
2625
size: int
2726
"""The size of the array."""
2827

28+
item_size: int
29+
"""The size of each item in the array."""
30+
2931
def __init__(
3032
self: array_impl,
3133
resolver: Resolver,
@@ -37,15 +39,8 @@ def __init__(
3739

3840
self.backing_type = backing_type
3941
self._count = count
40-
41-
if hasattr(backing_type, "size"):
42-
self.size = self.backing_type.size * self._count
43-
self.item_size = self.backing_type.size
44-
elif callable(backing_type):
45-
self.size = 8 * self._count
46-
self.item_size = 8
47-
else:
48-
raise NotImplementedError("Unsupported backing type.")
42+
self.item_size = size_of(self.backing_type)
43+
self.size = self.item_size * self._count
4944

5045
def count(self: array_impl) -> int:
5146
"""Get the size of the array."""

libdestruct/common/array/linear_array_field.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@
1010

1111
from libdestruct.common.array.array_field import ArrayField
1212
from libdestruct.common.array.array_impl import array_impl
13+
from libdestruct.common.utils import size_of
1314

14-
if TYPE_CHECKING: # pragma: no cover
15+
if TYPE_CHECKING: # pragma: no cover
1516
from libdestruct.backing.resolver import Resolver
1617
from libdestruct.common.array.array import array
1718
from libdestruct.common.obj import obj
@@ -32,3 +33,7 @@ def inflate(self: LinearArrayField, resolver: Resolver) -> array:
3233
resolver: The backing resolver for the object.
3334
"""
3435
return array_impl(resolver, self.item, self.size)
36+
37+
def get_size(self: LinearArrayField) -> int:
38+
"""Returns the size of the object inflated by this field."""
39+
return size_of(self.item) * self.size

libdestruct/common/enum/int_enum_field.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,7 @@ def inflate(self: IntEnumField, resolver: Resolver) -> int:
5454
resolver: The backing resolver for the object.
5555
"""
5656
return enum(resolver, self.enum, self.backing_type, self.lenient)
57+
58+
def get_size(self: IntEnumField) -> int:
59+
"""Returns the size of the object inflated by this field."""
60+
return self.backing_type.size

libdestruct/common/field.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from abc import ABC, abstractmethod
1010
from typing import TYPE_CHECKING
1111

12-
if TYPE_CHECKING: # pragma: no cover
12+
if TYPE_CHECKING: # pragma: no cover
1313
from libdestruct.backing.resolver import Resolver
1414
from libdestruct.common.obj import obj
1515

@@ -26,3 +26,7 @@ def inflate(self: Field, resolver: Resolver) -> obj:
2626
Args:
2727
resolver: The backing resolver for the object.
2828
"""
29+
30+
@abstractmethod
31+
def get_size(self: Field) -> int:
32+
"""Returns the size of the object inflated by this field."""

libdestruct/common/ptr/ptr_factory.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@
88

99
from typing import TYPE_CHECKING
1010

11-
from libdestruct.common.ptr.ptr_struct_field import PtrStructField
11+
from libdestruct.common.ptr.ptr_field import PtrField
1212

1313
if TYPE_CHECKING: # pragma: no cover
1414
from libdestruct.common.field import Field
1515
from libdestruct.common.obj import obj
1616

1717

18-
def ptr_to(item: obj | Field) -> PtrStructField:
18+
def ptr_to(item: obj | Field) -> PtrField:
1919
"""Crafts a struct member which is a pointer to an object."""
20-
return PtrStructField(item)
20+
return PtrField(item)
2121

2222

23-
def ptr_to_self() -> PtrStructField:
23+
def ptr_to_self() -> PtrField:
2424
"""Crafts a struct member which is a pointer to a struct of the same type."""
25-
return PtrStructField(None)
25+
return PtrField(None)

libdestruct/common/ptr/ptr_struct_field.py renamed to libdestruct/common/ptr/ptr_field.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,26 @@
1010

1111
from libdestruct.common.field import Field
1212
from libdestruct.common.ptr.ptr import ptr
13-
from libdestruct.common.struct.struct_field import StructField
1413

1514
if TYPE_CHECKING: # pragma: no cover
1615
from libdestruct.backing.resolver import Resolver
1716
from libdestruct.common.obj import obj
1817

1918

20-
class PtrStructField(StructField):
19+
class PtrField(Field):
2120
"""A generator for a field of a struct."""
2221

2322
base_type: type[obj] = ptr
2423

25-
def __init__(self: PtrStructField, backing_type: type | Field) -> None:
24+
def __init__(self: PtrField, backing_type: type | Field) -> None:
2625
"""Initialize a pointer field.
2726
2827
Args:
2928
backing_type: The type of the object the pointer points to.
3029
"""
3130
self.backing_type = backing_type
3231

33-
def inflate(self: PtrStructField, resolver: Resolver) -> obj:
32+
def inflate(self: PtrField, resolver: Resolver) -> obj:
3433
"""Inflate the field.
3534
3635
Args:
@@ -40,3 +39,7 @@ def inflate(self: PtrStructField, resolver: Resolver) -> obj:
4039
return ptr(resolver, self.backing_type.inflate)
4140

4241
return ptr(resolver, self.backing_type)
42+
43+
def get_size(self: PtrField) -> int:
44+
"""Returns the size of the object inflated by this field."""
45+
return ptr.size

libdestruct/common/struct/struct_field_inflater.py renamed to libdestruct/common/ptr/ptr_field_inflater.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from typing import TYPE_CHECKING
1010

11-
from libdestruct.common.ptr.ptr_struct_field import PtrStructField
11+
from libdestruct.common.ptr.ptr_field import PtrField
1212
from libdestruct.common.type_registry import TypeRegistry
1313

1414
if TYPE_CHECKING: # pragma: no cover
@@ -21,7 +21,7 @@
2121

2222

2323
def ptr_field_inflater(
24-
field: PtrStructField,
24+
field: PtrField,
2525
_: type[obj],
2626
owner: tuple[obj, type[obj]] | None,
2727
) -> Callable[[Resolver], obj]:
@@ -37,4 +37,4 @@ def ptr_field_inflater(
3737
return field.inflate
3838

3939

40-
registry.register_instance_handler(PtrStructField, ptr_field_inflater)
40+
registry.register_instance_handler(PtrField, ptr_field_inflater)

libdestruct/common/struct/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@
1010

1111
__all__ = ["struct", "struct_impl", "ptr_to", "ptr_to_self"]
1212

13-
import libdestruct.common.struct.struct_field_inflater
13+
import libdestruct.common.ptr.ptr_field_inflater
1414
import libdestruct.common.struct.struct_inflater # noqa: F401

libdestruct/common/struct/struct_field.py

Lines changed: 0 additions & 28 deletions
This file was deleted.

0 commit comments

Comments
 (0)