Functional Weave
Code in TypeScript

validation.gs1-check-digit@1.0.0

impl/python/gs1_check_digit.py

1,009 bytes · the Python implementation · view raw

def _ascii_digits(value: object) -> bool:
    # Compare against ASCII explicitly: str.isdigit() accepts Arabic-Indic and
    # superscript digits, which the other two languages would reject.
    return isinstance(value, str) and value != "" and all("0" <= ch <= "9" for ch in value)


def gs1_check_digit(data: str) -> int:
    """The GS1 mod-10 check digit for `data`, the digits of a GS1 key without
    its check digit.

    One rule serves every key length because the weights are counted from the
    right: 3, 1, 3, 1 ... starting with the digit that will sit next to the
    check digit. Counting from the left instead only works for EAN-13 and the
    other even-length data strings.
    """
    if not _ascii_digits(data):
        raise ValueError("GS1 data must be one or more ASCII digits, received %r" % (data,))
    total = 0
    weight = 3
    for ch in reversed(data):
        total = (total + (ord(ch) - 48) * weight) % 10
        weight = 1 if weight == 3 else 3
    return (10 - total) % 10