Source code for pystructs.fields.struct

from __future__ import annotations
from copy import deepcopy
from typing import Dict, AnyStr, Union

from pystructs import utils
from pystructs.fields import BytesField, Field

__all__ = [
    "Struct",
]


class StructMetaclass(type):
    def __new__(mcs, name, bases, attrs: dict):
        attrs["fields"] = getattr(bases[0], "fields", {}).copy()

        attrs = utils.filter_fields(attrs)
        attrs = utils.delete_fields(attrs)

        return super().__new__(mcs, name, bases, attrs)


[docs]class Struct(BytesField, metaclass=StructMetaclass): """ `struct` implementations that inherit BytesField link fields and calculate offset and variable values automatically """ #: Reflection of fields from struct fields: "Dict[Union[AnyStr, int], Field]" = {} def __init__(self, _bytes: bytes = b"", auto_initialization=True): super().__init__(0) self.bytes = _bytes if auto_initialization: self.initialize()
[docs] def fetch(self) -> "Struct": return self
def __getattr__(self, item): try: if item not in self.fields: return getattr(super(), item) return self.fields[item].fetch() except KeyError: raise AttributeError(item)
[docs] def initialize(self, root: "Struct" = None): """ link fields and set parent, initialize each fields :param root: Struct object of root :return: """ self.__link_fields() if root is None: root = self self.fields = deepcopy(self.fields) for field in self.fields.values(): field.parent = self field.initialize(root)
def __link_fields(self): fields = list(self.fields.values()) fields_count = len(fields) for index in range(fields_count - 1): fields[index + 1].prev = fields[index] if fields_count > 0: fields[0].prev = VirtualStruct(self) @property def size(self) -> int: return sum(map(lambda x: x.size, self.fields.values()))
class VirtualStruct: def __init__(self, struct: Struct): self.__struct = struct @property def offset(self) -> int: return self.__struct.offset @property def size(self) -> int: return 0