fixed swapped param of TypedStruct, to keep the order of the sucons in a container when printing

added TypedBitStruct
This commit is contained in:
Tim Rid 2020-12-16 21:39:45 +01:00
parent 907b812d72
commit 12d94f89e4
2 changed files with 50 additions and 11 deletions

View file

@ -1,7 +1,7 @@
from enum import IntEnum
from typing import Any, Type, Dict, TYPE_CHECKING, TypeVar, Union
import typing
from construct.core import Construct, Adapter, Struct
from construct.core import Construct, Adapter, Struct, BitStruct
from construct.lib.containers import Container
@ -95,12 +95,12 @@ else:
if TYPE_CHECKING:
class TypedContainer(Container[Any]):
...
ContainerType = TypeVar("ContainerType", bound=TypedContainer)
else:
class TypedContainer(Container):
pass
if TYPE_CHECKING:
ContainerType = TypeVar("ContainerType", bound=TypedContainer)
class TypedStruct(Adapter[Container[Any], Dict[str, Any], ContainerType, Dict[str, Any]]):
def __init__(self, container_type: Type[ContainerType], swapped: bool = False) -> None: ...
else:
@ -109,6 +109,7 @@ else:
if not issubclass(container_type, TypedContainer):
raise TypeError("the subcon has to be a TypedContainer")
self.container_type = container_type
self.swapped = swapped
# extract the construct formats from the struct_type
subcons = {}
@ -123,12 +124,48 @@ else:
super(TypedStruct, self).__init__(Struct(**subcons))
def _decode(self, obj, context, path):
return self.container_type(obj)
if self.swapped:
return self.container_type({k: v for k, v in reversed(list(obj.items()))})
else:
return self.container_type(obj)
def _encode(self, obj, context, path):
return obj
if TYPE_CHECKING:
class TypedBitStruct(Adapter[Container[Any], Dict[str, Any], ContainerType, Dict[str, Any]]):
def __init__(self, container_type: Type[ContainerType], swapped: bool = False) -> None: ...
else:
class TypedBitStruct(Adapter):
def __init__(self, container_type, swapped = False):
if not issubclass(container_type, TypedContainer):
raise TypeError("the subcon has to be a TypedContainer")
self.container_type = container_type
self.swapped = swapped
# extract the construct formats from the struct_type
subcons = {}
subcon_formats = typing.get_type_hints(container_type)
subcon_items = subcon_formats.items()
if swapped:
subcon_items = reversed(subcon_items)
for subcon_name, subcon_format in subcon_items:
subcons[subcon_name] = subcon_format
# init Adatper with a Struct as subcon
super(TypedBitStruct, self).__init__(BitStruct(**subcons))
def _decode(self, obj, context, path):
if self.swapped:
return self.container_type({k: v for k, v in reversed(list(obj.items()))})
else:
return self.container_type(obj)
def _encode(self, obj, context, path):
return obj
# TODO: TypedUnion
# TODO: AnonymSubcon:
# TODO: TypedLazyStruct
# TODO: TypedSequence: Based on typing.namedtuple
# TODO: FocusedSeq: Based on typing.namedtuple

View file

@ -25,17 +25,15 @@ def test_typed_struct():
b: Subcon(Int8ub)
common(TypedStruct(Container1), b"\x00\x01\x02", Container1(a=1, b=2), 3)
class Container1Swapped(TypedContainer):
a: Subcon(Int16ub)
b: Subcon(Int8ub)
common(
TypedStruct(Container1Swapped, swapped=True),
TypedStruct(Container1, swapped=True),
b"\x02\x00\x01",
Container(a=1, b=2),
3,
)
normal = TypedStruct(Container1)
swapped = TypedStruct(Container1, swapped=True)
assert str(normal.parse(b"\x00\x01\x02")) == str(swapped.parse(b"\x02\x00\x01"))
class Container2(TypedContainer):
class InnerContainer(TypedContainer):
@ -81,6 +79,10 @@ def test_typed_struct():
assert d.build({}) == d.build({})
def test_typed_bit_struct():
assert False
def test_enum():
class E(enum.IntEnum):
a = 1