Generates a `MqttPublish` packet given a
        `MqttFixedHeader`.  This method asserts that header.packet_type
        is `publish`.

        Parameters
        ----------
        header: MqttFixedHeader
        f: file
            Object with a read method.

        Raises
        ------
        DecodeError
            When there are extra bytes at the end of the packet.

        Returns
        -------
        int
            Number of bytes consumed from ``f``.
        MqttPublish
            Object extracted from ``f``.

def decode_body(cls, header, f):
        """Generates a `MqttPublish` packet given a
        `MqttFixedHeader`.  This method asserts that header.packet_type
        is `publish`.

        Parameters
        ----------
        header: MqttFixedHeader
        f: file
            Object with a read method.

        Raises
        ------
        DecodeError
            When there are extra bytes at the end of the packet.

        Returns
        -------
        int
            Number of bytes consumed from ``f``.
        MqttPublish
            Object extracted from ``f``.
        """
        assert header.packet_type == MqttControlPacketType.publish

        dupe = bool(header.flags & 0x08)
        retain = bool(header.flags & 0x01)
        qos = ((header.flags & 0x06) >> 1)

        if qos == 0 and dupe:
            # The DUP flag MUST be set to 0 for all QoS 0 messages
            # [MQTT-3.3.1-2]
            raise DecodeError("Unexpected dupe=True for qos==0 message [MQTT-3.3.1-2].")

        decoder = mqtt_io.FileDecoder(mqtt_io.LimitReader(f, header.remaining_len))
        num_bytes_consumed, topic_name = decoder.unpack_utf8()

        if qos != 0:
            # See MQTT 3.1.1 section 3.3.2.2
            # See https://github.com/kcallin/mqtt-codec/issues/5
            packet_id, = decoder.unpack(mqtt_io.FIELD_PACKET_ID)
        else:
            packet_id = 0

        payload_len = header.remaining_len - decoder.num_bytes_consumed
        payload = decoder.read(payload_len)

        return decoder.num_bytes_consumed, MqttPublish(packet_id, topic_name, payload, dupe, qos, retain)