def _rpmvercmp(a: str, b: str):
    """ This function is backported from C function `rpmvercmp`.
    https://github.com/rpm-software-management/rpm/blob/9e4caf0fc536d1244b298abd9dc4c535b6560d69/rpmio/rpmvercmp.c#L16
    """
    if a == b:
        return 0
    str1 = a + "\0"
    str2 = b + "\0"
    one = 0
    two = 0
    while str1[one] != "\0" or str2[two] != "\0":
        while str1[one] != "\0" and not str1[one].isalnum() and str1[one] not in ["~", "^"]:
            one += 1
        while str2[two] != "\0" and not str2[two].isalnum() and str2[two] not in ["~", "^"]:
            two += 1
        # handle the tilde separator, it sorts before everything else
        if str1[one] == "~" or str2[two] == "~":
            if str1[one] != "~":
                return 1
            if str2[two] != "~":
                return -1
            one += 1
            two += 1
            continue
        # Handle caret separator. Concept is the same as tilde,
        # except that if one of the strings ends (base version),
        # the other is considered as higher version.
        if str1[one] == "^" or str2[two] == "^":
            if str1[one] == "\0":
                return -1
            if str2[two] == "\0":
                return 1
            if str1[one] != "^":
                return 1
            if str2[two] != "^":
                return -1
            one += 1
            two += 1
            continue
        # If we ran to the end of either, we are finished with the loop
        if not (str1[one] != "\0" and str2[two] != "\0"):
            break

        p = one
        q = two

        # grab first completely alpha or completely numeric segment
        # leave one and two pointing to the start of the alpha or numeric
        # segment and walk str1 and str2 to end of segment
        if str1[p].isdigit():
            while(str1[p] != "\0" and str1[p].isdigit()):
                p += 1
            while(str2[q] != "\0" and str2[q].isdigit()):
                q += 1
            isnum = 1
        else:
            while(str1[p] != "\0" and str1[p].isalpha()):
                p += 1
            while(str2[q] != "\0" and str2[q].isalpha()):
                q += 1
            isnum = 0

        # this cannot happen, as we previously tested to make sure that
        # the first string has a non-null segment
        if one == p:
            return -1  # arbitrary

        # take care of the case where the two version segments are
        # different types: one numeric, the other alpha (i.e. empty)
        # numeric segments are always newer than alpha segments
        if two == q:
            return 1 if isnum else -1

        if isnum:
            # throw away any leading zeros - it's a number, right?
            while str1[one] == "0":
                one += 1
            while str2[two] == "0":
                two += 1
            # whichever number has more digits wins
            onelen = p - one
            twolen = q - two
            if onelen > twolen:
                return 1
            if onelen < twolen:
                return -1

        # strcmp will return which one is greater - even if the two
        # segments are alpha or if they are numeric.  don't return
        # if they are equal because there might be more segments to
        # compare

        if str1[one:p] < str2[two:q]:
            return -1
        if str1[one:p] > str2[two:q]:
            return 1

        one = p
        two = q

    # this catches the case where all numeric and alpha segments have
    # compared identically but the segment sepparating characters were
    # different

    if str1[one] == "\0" and str2[two] == "\0":
        return 0

    # whichever version still has characters left over wins
    return -1 if str1[one] == "\0" else 1