1,204 bytes · the Python implementation · view raw
from typing import List
def _digit_value(ch: str) -> int:
# Compared by character range rather than int(ch, 16), which would accept# full-width and other scripts' digits that the other languages refuse.if"0" <= ch <= "9":
return ord(ch) - 48if"a" <= ch <= "f":
return ord(ch) - 87if"A" <= ch <= "F":
return ord(ch) - 55return -1def hex_decode(text: str) -> List[int]:
"""Hexadecimal text back to bytes, either case, strictly. A 0x prefix, whitespace or an odd digit count is an error, not skipped. """ifnot isinstance(text, str):
raise TypeError("hex text must be a string")
# Characters are checked before the length, so the answer for non-ASCII# input does not depend on how a language counts its length.
digits = []
for ch in text:
d = _digit_value(ch)
if d < 0:
raise ValueError("hex text may only contain the digits 0-9, a-f and A-F")
digits.append(d)
if len(digits) % 2 != 0:
raise ValueError("hex text must have an even number of digits, received %d" % len(digits))
return [digits[i] * 16 + digits[i + 1] for i in range(0, len(digits), 2)]