Beispiel #1
0
    def __init__(self,
                 name,
                 fields,
                 mode=starstruct.modes.Mode.Native,
                 alignment=1):
        """
        Initialize a StarStruct object.

        Creates 2 internal items, a format string which is used to call the
        struct module functions for packing and unpacking data, and a
        namedtuple instance which is used to organize the data provided to the
        pack functions and returned from the unpack functions.
        """

        # The name must be a string, this is provided to the
        # collections.namedtuple constructor when creating the namedtuple class.
        if not name or not isinstance(name, str):
            raise TypeError('invalid name: {}'.format(name))

        self.name = name
        self.mode = mode
        self.alignment = alignment

        # The structure definition must be a list of
        #   ('name', 'format', <optional>)
        # tuples
        if not isinstance(fields, list) \
                or not all(isinstance(x, tuple) for x in fields):
            raise TypeError('invalid fields: {}'.format(fields))

        if not isinstance(mode, starstruct.modes.Mode):
            raise TypeError('invalid mode: {}'.format(mode))

        # Create an ordered dictionary (so element order is preserved) out of
        # the individual message fields.  Ensure that there are no duplicate
        # field names.
        self._elements = collections.OrderedDict()
        for field in fields:
            if field[0] not in self._elements:
                if isinstance(field[0], str):
                    self._elements[field[0]] = Element.factory(
                        field, mode, alignment)
                elif isinstance(field[0], bytes):
                    self._elements[field[0].decode('utf-8')] = Element.factory(
                        field, mode, alignment)
                else:
                    raise NotImplementedError
            else:
                raise TypeError('duplicate field {} in {}'.format(
                    field[0], fields))

        # Validate all of the elements of this message
        for elem in self._elements.values():
            elem.validate(self._elements)

        # Now that the format has been validated, create a named tuple with the
        # correct fields.
        named_fields = [
            elem.name for elem in self._elements.values() if elem.name
        ]
        self._tuple = StarTuple(self.name, named_fields, self._elements)