def apply_patches(data, patches):
    """Applies a set of patches to a block of data.

    :param data: The data to apply the patches to.
    :param patches: Patches to apply as a dictionary. Keys are offsets, values are patch data.
    :return: A patched version of the input data.
    """
    new_data = bytearray()

    working_offset = 0
    for offset in sorted(patches.keys()):
        if working_offset > offset:
            raise RuntimeError(f"Could not apply patch to {offset}; already at {working_offset}!")

        # Check if there's missing data between our working position and the next patch
        if working_offset < offset:
            new_data.extend(data[working_offset:offset])

        # Now that we're caught up, plop the patch in, and update the working offset.
        patch = patches[offset]
        new_data.extend(patch)
        working_offset = offset + len(patch)

    # Now that the patches are applied, add whatever is left of the file.
    new_data.extend(data[working_offset:])

    # Return the patched data as a tuple so it's immutable.
    return tuple(new_data)