Decode variable integer using algorithm similar to that described
    in MQTT Version 3.1.1 line 297.

    Parameters
    ----------
    f: file
        Object with a read method.
    max_bytes: int or None
        If a varint cannot be constructed using `max_bytes` or fewer
        from f then raises a `DecodeError`.  If None then there is no
        maximum number of bytes.

    Raises
    -------
    DecodeError
        When length is greater than max_bytes.
    UnderflowDecodeError
        When file ends before enough bytes can be read to construct the
        varint.

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

def decode_varint(f, max_bytes=4):
    """Decode variable integer using algorithm similar to that described
    in MQTT Version 3.1.1 line 297.

    Parameters
    ----------
    f: file
        Object with a read method.
    max_bytes: int or None
        If a varint cannot be constructed using `max_bytes` or fewer
        from f then raises a `DecodeError`.  If None then there is no
        maximum number of bytes.

    Raises
    -------
    DecodeError
        When length is greater than max_bytes.
    UnderflowDecodeError
        When file ends before enough bytes can be read to construct the
        varint.

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

    """
    num_bytes_consumed = 0

    value = 0
    m = 1

    while True:
        buf = f.read(1)
        if len(buf) == 0:
            raise UnderflowDecodeError()

        (u8,) = FIELD_U8.unpack(buf)
        value += (u8 & 0x7f) * m
        m *= 0x80
        num_bytes_consumed += 1

        if u8 & 0x80 == 0:
            # No further bytes
            break
        elif max_bytes is not None and num_bytes_consumed >= max_bytes:
            raise DecodeError('Variable integer contained more than maximum bytes ({}).'.format(max_bytes))

    return num_bytes_consumed, value