Esempio n. 1
0
    def from_stream(cls, stream: BinaryIO, *, strict=True) -> 'Struct':
        rv = cls()
        map_field = cls._field_by_number[1]

        while True:
            # checking for end of message
            try:
                decode_header(stream)
            except MessageDecodeError:
                break

            key, value = map_field.decode(stream)
            rv.set_value(key, value)

        return rv
Esempio n. 2
0
    def test_decode(self, value, expected_value):
        stream = io.BytesIO(value)
        number, wire_type = decode_header(stream)

        assert number == 1
        assert wire_type == 2

        data = Repeated(Int32, number=1, packed=True).decode(stream)
        print('\n>>>', data)
Esempio n. 3
0
def test_field_header(field_type: Type[Field], expected_wire_type):
    assert field_type.wire_type == expected_wire_type

    field_number = 2 * 32
    encoded_header = field_type(number=field_number).header
    stream = io.BytesIO(encoded_header)
    number, wire_type = decode_header(stream)

    assert number == field_number
    assert wire_type == expected_wire_type
Esempio n. 4
0
def test_enum_field_header(color_field):
    expected_wire_type = 0

    assert color_field.wire_type == expected_wire_type

    encoded_header = color_field.header

    stream = io.BytesIO(encoded_header)
    number, wire_type = decode_header(stream)

    assert number == color_field.number
    assert wire_type == expected_wire_type
Esempio n. 5
0
    def from_stream(cls: Type[T], stream: BinaryIO, *, strict=True) -> T:
        """
        :param stream:
        :param strict: when strict is False MessageDecodeError won't be raised in case a required field was not read
        :return: Message of type T
        """
        message_fields = {}

        while True:
            # checking for end of message
            try:
                number, wire_type = decode_header(stream)
            except MessageDecodeError:
                break

            if number in cls._field_by_number:
                field = cls._field_by_number[number]

                if field.wire_type != wire_type:
                    raise MessageDecodeError(
                        f"Field {field.name} has wire_type={field.wire_type}, "
                        f"read wire_type={wire_type} instead")

                if isinstance(field, Repeated) and not field.packed:
                    message_fields.setdefault(field.name,
                                              []).append(field.decode(stream))
                elif isinstance(field, MapField):
                    key, value = field.decode(stream)
                    message_fields.setdefault(field.name, {})[key] = value
                else:
                    message_fields[field.name] = field.decode(stream)
            else:
                # read and discard unknown field
                wire_type_to_decoder[wire_type](stream)

        if strict:
            # TODO: when adding field to Message if the field is required
            #  put it to Message._required_fields to simplify the following check
            for key, field, in cls._field_by_name.items():
                if getattr(field, 'required', False) and not getattr(
                        field, 'default', None) and key not in message_fields:
                    raise MessageDecodeError(f"Missing required field {key}")

        return cls(**message_fields)