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

        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``.
        MqttSuback
            Object extracted from ``f``.
        """
        assert header.packet_type == MqttControlPacketType.suback

        decoder = mqtt_io.FileDecoder(mqtt_io.LimitReader(f, header.remaining_len))
        packet_id, = decoder.unpack(mqtt_io.FIELD_PACKET_ID)

        results = []
        while header.remaining_len > decoder.num_bytes_consumed:
            result, = decoder.unpack(mqtt_io.FIELD_U8)
            try:
                results.append(SubscribeResult(result))
            except ValueError:
                raise DecodeError('Unsupported result {:02x}.'.format(result))

        assert header.remaining_len == decoder.num_bytes_consumed

        return decoder.num_bytes_consumed, MqttSuback(packet_id, results)
Generates a `MqttSuback` packet given a
        `MqttFixedHeader`.  This method asserts that header.packet_type
        is `suback`.

        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``.
        MqttSuback
            Object extracted from ``f``.