You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

119 lines
2.5 KiB

9 years ago
9 years ago
  1. # the decoder works off a reader
  2. # the encoder returns bytearray
  3. def hex2bytes(h):
  4. return bytearray(h.decode('hex'))
  5. def bytes2hex(b):
  6. if type(b) in (str, str):
  7. return "".join([hex(ord(c))[2:].zfill(2) for c in b])
  8. else:
  9. return bytes2hex(b.decode())
  10. # expects uvarint64 (no crazy big nums!)
  11. def uvarint_size(i):
  12. if i == 0:
  13. return 0
  14. for j in range(1, 8):
  15. if i < 1 << j * 8:
  16. return j
  17. return 8
  18. # expects i < 2**size
  19. def encode_big_endian(i, size):
  20. if size == 0:
  21. return bytearray()
  22. return encode_big_endian(i // 256, size - 1) + bytearray([i % 256])
  23. def decode_big_endian(reader, size):
  24. if size == 0:
  25. return 0
  26. firstByte = reader.read(1)[0]
  27. return firstByte * (256 ** (size - 1)) + decode_big_endian(reader, size - 1)
  28. # ints are max 16 bytes long
  29. def encode_varint(i):
  30. negate = False
  31. if i < 0:
  32. negate = True
  33. i = -i
  34. size = uvarint_size(i)
  35. if size == 0:
  36. return bytearray([0])
  37. big_end = encode_big_endian(i, size)
  38. if negate:
  39. size += 0xF0
  40. return bytearray([size]) + big_end
  41. # returns the int and whats left of the byte array
  42. def decode_varint(reader):
  43. size = reader.read(1)[0]
  44. if size == 0:
  45. return 0
  46. negate = True if size > int(0xF0) else False
  47. if negate:
  48. size = size - 0xF0
  49. i = decode_big_endian(reader, size)
  50. if negate:
  51. i = i * (-1)
  52. return i
  53. def encode_string(s):
  54. size = encode_varint(len(s))
  55. return size + bytearray(s, 'utf8')
  56. def decode_string(reader):
  57. length = decode_varint(reader)
  58. raw_data = reader.read(length)
  59. return raw_data.decode()
  60. def encode_list(s):
  61. b = bytearray()
  62. list(map(b.extend, list(map(encode, s))))
  63. return encode_varint(len(s)) + b
  64. def encode(s):
  65. print('encoding', repr(s))
  66. if s is None:
  67. return bytearray()
  68. if isinstance(s, int):
  69. return encode_varint(s)
  70. elif isinstance(s, str):
  71. return encode_string(s)
  72. elif isinstance(s, list):
  73. return encode_list(s)
  74. elif isinstance(s, bytearray):
  75. return encode_string(s)
  76. else:
  77. print("UNSUPPORTED TYPE!", type(s), s)
  78. if __name__ == '__main__':
  79. ns = [100, 100, 1000, 256]
  80. ss = [2, 5, 5, 2]
  81. bs = list(map(encode_big_endian, ns, ss))
  82. ds = list(map(decode_big_endian, bs, ss))
  83. print(ns)
  84. print([i[0] for i in ds])
  85. ss = ["abc", "hi there jim", "ok now what"]
  86. e = list(map(encode_string, ss))
  87. d = list(map(decode_string, e))
  88. print(ss)
  89. print([i[0] for i in d])