a TypedStruct is always parsed to an object of the container_type

This commit is contained in:
Tim Rid 2020-12-12 12:12:54 +01:00
parent 29f6af7936
commit a564ff55fd
4 changed files with 55 additions and 9 deletions

View file

@ -57,6 +57,15 @@ __all__ = [
'FixedSized',
'Flag',
'FlagsEnum',
"Float16b",
"Float16l",
"Float16n",
"Float32b",
"Float32l",
"Float32n",
"Float64b",
"Float64l",
"Float64n",
'FocusedSeq',
'FormatField',
'FormatFieldError',
@ -75,6 +84,36 @@ __all__ = [
'IndexFieldError',
'Indexing',
'Int',
"Int8sb",
"Int8sl",
"Int8sn",
"Int8ub",
"Int8ul",
"Int8un",
"Int16sb",
"Int16sl",
"Int16sn",
"Int16ub",
"Int16ul",
"Int16un",
"Int24sb",
"Int24sl",
"Int24sn",
"Int24ub",
"Int24ul",
"Int24un",
"Int32sb",
"Int32sl",
"Int32sn",
"Int32ub",
"Int32ul",
"Int32un",
"Int64sb",
"Int64sl",
"Int64sn",
"Int64ub",
"Int64ul",
"Int64un",
'IntegerError',
'Lazy',
'LazyArray',
@ -176,6 +215,4 @@ __all__ = [
'VarInt',
'version',
'version_string',
]
__all__ += ["Int%s%s%s" % (n,us,bln) for n in (8,16,24,32,64) for us in "us" for bln in "bln"]
__all__ += ["Float%s%s" % (n,bln) for n in (16,32,64) for bln in "bln"]
]

View file

@ -101,13 +101,14 @@ else:
if TYPE_CHECKING:
ContainerType = TypeVar("ContainerType", bound=TypedContainer)
class TypedStruct(Construct[ContainerType, Dict[str, Any]]):
class TypedStruct(Adapter[Container[Any], Dict[str, Any], ContainerType, Dict[str, Any]]):
def __init__(self, container_type: Type[ContainerType], swapped: bool = False) -> None: ...
else:
class TypedStruct(Struct):
class TypedStruct(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
# extract the construct formats from the struct_type
subcons = {}
@ -118,4 +119,11 @@ else:
for subcon_name, subcon_format in subcon_items:
subcons[subcon_name] = subcon_format
super(TypedStruct, self).__init__(**subcons)
# init Adatper with a Struct as subcon
super(TypedStruct, self).__init__(Struct(**subcons))
def _decode(self, obj, context, path):
return self.container_type(obj)
def _encode(self, obj, context, path):
return obj

View file

@ -32,6 +32,7 @@ def raises(func, *args, **kw):
def common(format, datasample, objsample, sizesample=SizeofError, **kw):
obj = format.parse(datasample, **kw)
assert obj == objsample
assert isinstance(obj, type(objsample))
data = format.build(objsample, **kw)
assert data == datasample
# following are implied by above (re-parse and re-build)

View file

@ -2,7 +2,7 @@
import enum
from .declarativeunittest import common, raises
from construct.core import (
from construct import (
Int8ub,
Int16ub,
Const,
@ -26,12 +26,12 @@ def test_typed_struct():
common(TypedStruct(Container1), b"\x00\x01\x02", Container1(a=1, b=2), 3)
class Container1Reversing(TypedContainer):
class Container1Swapped(TypedContainer):
a: Subcon(Int16ub)
b: Subcon(Int8ub)
common(
TypedStruct(Container1Reversing, swapped=True),
TypedStruct(Container1Swapped, swapped=True),
b"\x02\x00\x01",
Container(a=1, b=2),
3,