hexadecimal.py 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. # String encodings and numeric representations
  2. import binascii
  3. import re
  4. from typing import (
  5. Any,
  6. AnyStr,
  7. )
  8. from eth_typing import (
  9. HexStr,
  10. )
  11. from .types import (
  12. is_string,
  13. is_text,
  14. )
  15. _HEX_REGEXP = re.compile("(0[xX])?[0-9a-fA-F]*")
  16. def decode_hex(value: str) -> bytes:
  17. if not is_text(value):
  18. raise TypeError("Value must be an instance of str")
  19. non_prefixed = remove_0x_prefix(HexStr(value))
  20. # unhexlify will only accept bytes type someday
  21. ascii_hex = non_prefixed.encode("ascii")
  22. return binascii.unhexlify(ascii_hex)
  23. def encode_hex(value: AnyStr) -> HexStr:
  24. if not is_string(value):
  25. raise TypeError("Value must be an instance of str or unicode")
  26. elif isinstance(value, (bytes, bytearray)):
  27. ascii_bytes = value
  28. else:
  29. ascii_bytes = value.encode("ascii")
  30. binary_hex = binascii.hexlify(ascii_bytes)
  31. return add_0x_prefix(HexStr(binary_hex.decode("ascii")))
  32. def is_0x_prefixed(value: str) -> bool:
  33. if not is_text(value):
  34. raise TypeError(
  35. f"is_0x_prefixed requires text typed arguments. Got: {repr(value)}"
  36. )
  37. return value.startswith(("0x", "0X"))
  38. def remove_0x_prefix(value: HexStr) -> HexStr:
  39. if is_0x_prefixed(value):
  40. return HexStr(value[2:])
  41. return value
  42. def add_0x_prefix(value: HexStr) -> HexStr:
  43. if is_0x_prefixed(value):
  44. return value
  45. return HexStr("0x" + value)
  46. def is_hexstr(value: Any) -> bool:
  47. if not is_text(value) or not value:
  48. return False
  49. return _HEX_REGEXP.fullmatch(value) is not None
  50. def is_hex(value: Any) -> bool:
  51. if not is_text(value):
  52. raise TypeError(f"is_hex requires text typed arguments. Got: {repr(value)}")
  53. if not value:
  54. return False
  55. return _HEX_REGEXP.fullmatch(value) is not None