Reads a single instruction from `fio` and returns it, or ``None`` if
    the stream is empty.

    :param fio: Any file-like object providing ``read()``.
    :param start_pos: The current position in the stream.

def read_instruction(fio, start_pos):
    """
    Reads a single instruction from `fio` and returns it, or ``None`` if
    the stream is empty.

    :param fio: Any file-like object providing ``read()``.
    :param start_pos: The current position in the stream.
    """
    op = fio.read(1)

    if not op:
        return None

    op = ord(op)

    ins = opcode_table[op]
    operands = ins['operands']
    name = ins['mnemonic']

    final_operands = []
    # Most opcodes have simple operands.
    if operands:
        for fmt, type_ in operands:
            final_operands.append(
                Operand(
                    type_,
                    fmt.value.unpack(fio.read(fmt.value.size))[0]
                )
            )
    # Special case for lookupswitch.
    elif op == 0xAB:
        # Get rid of the alignment padding.
        padding = 4 - (start_pos + 1) % 4
        padding = padding if padding != 4 else 0
        fio.read(padding)

        # Default branch address and branch count.
        default, npairs = unpack('>ii', fio.read(8))

        pairs = {}
        for _ in repeat(None, npairs):
            match, offset = unpack('>ii', fio.read(8))
            pairs[match] = offset

        final_operands.append(pairs)
        final_operands.append(Operand(OperandTypes.BRANCH, default))
    # Special case for tableswitch
    elif op == 0xAA:
        # Get rid of the alignment padding.
        padding = 4 - (start_pos + 1) % 4
        padding = padding if padding != 4 else 0
        fio.read(padding)

        default, low, high = unpack('>iii', fio.read(12))
        final_operands.append(Operand(OperandTypes.BRANCH, default))
        final_operands.append(Operand(OperandTypes.LITERAL, low))
        final_operands.append(Operand(OperandTypes.LITERAL, high))

        for _ in repeat(None, high - low + 1):
            offset = unpack('>i', fio.read(4))[0]
            final_operands.append(Operand(OperandTypes.BRANCH, offset))
    # Special case for the wide prefix
    elif op == 0xC4:
        real_op = unpack('>B', fio.read(1))[0]
        ins = opcode_table[real_op]
        name = ins['mnemonic']

        final_operands.append(Operand(
            OperandTypes.LOCAL_INDEX,
            unpack('>H', fio.read(2))[0]
        ))
        # Further special case for iinc.
        if real_op == 0x84:
            final_operands.append(Operand(
                OperandTypes.LITERAL,
                unpack('>H', fio.read(2))[0]
            ))

    return Instruction(name, op, final_operands, start_pos)