new setting in TStruct: "add_offsets"

This commit is contained in:
Tim Rid 2021-02-20 21:42:39 +01:00
parent e902748656
commit a4741e2bf2
2 changed files with 28 additions and 5 deletions

View file

@ -87,7 +87,7 @@ class _TStruct(Adapter[t.Any, t.Any, ContainerType, BuildTypes]):
"""
def __init__(
self, container_type: t.Type[ContainerType], swapped: bool = False
self, container_type: t.Type[ContainerType], swapped: bool = False, add_offsets: bool = False
) -> None:
if not issubclass(container_type, TContainerBase):
raise TypeError(
@ -101,6 +101,7 @@ class _TStruct(Adapter[t.Any, t.Any, ContainerType, BuildTypes]):
)
self.container_type = container_type
self.swapped = swapped
self.add_offsets = add_offsets
# get all fields from the dataclass
fields = dataclasses.fields(self.container_type)
@ -110,6 +111,8 @@ class _TStruct(Adapter[t.Any, t.Any, ContainerType, BuildTypes]):
# extract the construct formats from the struct_type
subcon_fields = {}
for field in fields:
if add_offsets:
subcon_fields[f"@{field.name}"] = cs.Tell
subcon_fields[field.name] = field.metadata["subcon"]
# init adatper
@ -175,7 +178,7 @@ class TStruct(_TStruct[ContainerType, ContainerType]):
if t.TYPE_CHECKING:
def __new__(
cls, container_type: t.Type[ContainerType], swapped: bool = False
cls, container_type: t.Type[ContainerType], swapped: bool = False, add_offsets: bool = False
) -> "TStruct[ContainerType]":
...
@ -193,7 +196,7 @@ class TBitStruct(_TStruct[ContainerType, ContainerType]):
if t.TYPE_CHECKING:
def __new__(
cls, container_type: t.Type[ContainerType], swapped: bool = False
cls, container_type: t.Type[ContainerType], swapped: bool = False, add_offsets: bool = False
) -> "TBitStruct[ContainerType]":
...

View file

@ -108,6 +108,24 @@ def test_tstruct_swapped() -> None:
assert str(normal.parse(b"\x00\x01\x02")) == str(swapped.parse(b"\x02\x00\x01"))
def test_tstruct_add_offsets() -> None:
@dataclasses.dataclass
class TestContainer(cst.TContainerBase):
a: int = cst.TStructField(cs.Int16ub)
b: int = cst.TStructField(cs.Int8ub)
common(
cst.TStruct(TestContainer, add_offsets=True),
b"\x00\x01\x02",
TestContainer(a=1, b=2),
3,
)
c = cst.TStruct(TestContainer, add_offsets=True)
obj = c.parse(b"\x00\x01\x02")
assert obj["@a"] == 0
assert obj["@b"] == 2
def test_tstruct_nested() -> None:
@dataclasses.dataclass
class TestContainer(cst.TContainerBase):
@ -247,8 +265,10 @@ def test_tstruct_doc() -> None:
assert format.subcon.a.docs == "This is the documentation of a"
assert format.subcon.b.docs == "This is the documentation of b\nwhich is multiline"
assert format.subcon.c.docs == "This is the documentation of c\nwhich is also multiline"
assert (
format.subcon.c.docs
== "This is the documentation of c\nwhich is also multiline"
)
@pytest.mark.xfail(reason="not implemented yet")