serial.py 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import struct
  2. def write_u8(by, v):
  3. assert v < 2**256
  4. by += v.to_bytes(1, 'little')
  5. def write_u16(by, v):
  6. assert v < 2**(2*256)
  7. by += v.to_bytes(2, 'little')
  8. def write_u32(by, v):
  9. assert v < 2**(4*256)
  10. by += v.to_bytes(4, 'little')
  11. def write_u64(by, v):
  12. assert v < 2**(8*256)
  13. by += v.to_bytes(8, 'little')
  14. def write_f32(by, v):
  15. by += struct.pack("<f", v)
  16. def encode_varint(by, v):
  17. if v <= 0xfc:
  18. write_u8(by, v)
  19. elif v <= 0xffff:
  20. write_u8(by, 0xfd)
  21. write_u16(by, v)
  22. elif v <= 0xffffffff:
  23. write_u8(by, 0xfe)
  24. write_u32(by, v)
  25. else:
  26. write_u8(by, 0xff)
  27. write_u64(by, v)
  28. def encode_str(by, s):
  29. data = s.encode("utf-8")
  30. encode_buf(by, data)
  31. def encode_buf(by, buf):
  32. encode_varint(by, len(buf))
  33. by += buf
  34. def encode_opt(by, val, write_fn):
  35. if val is None:
  36. write_u8(by, 0)
  37. else:
  38. write_u8(by, 1)
  39. write_fn(by)
  40. # Cursor for bytearray type
  41. class Cursor:
  42. def __init__(self, by):
  43. self.by = by
  44. self.i = 0
  45. def read(self, n):
  46. slice = self.by[self.i:self.i+n]
  47. self.i += n
  48. if self.i > len(self.by):
  49. raise Exception("invalid read")
  50. return slice
  51. def read_u8(cur):
  52. b = cur.read(1)
  53. return int.from_bytes(b, "little")
  54. def read_u16(cur):
  55. b = cur.read(2)
  56. return int.from_bytes(b, "little")
  57. def read_u32(cur):
  58. b = cur.read(4)
  59. return int.from_bytes(b, "little")
  60. def read_u64(cur):
  61. b = cur.read(8)
  62. return int.from_bytes(b, "little")
  63. def read_f32(cur):
  64. by = cur.read(4)
  65. return struct.unpack("<f", by)[0]
  66. def decode_varint(cur):
  67. n = read_u8(cur)
  68. match n:
  69. case 0xff:
  70. x = read_u64(cur)
  71. assert x >= 0x100000000
  72. return x
  73. case 0xfe:
  74. x = read_u32(cur)
  75. assert x >= 0x10000
  76. return x
  77. case 0xfd:
  78. x = read_u16(cur)
  79. assert x >= 0xfd
  80. return x
  81. return n
  82. def decode_str(cur):
  83. return decode_buf(cur).decode("utf-8")
  84. def decode_buf(cur):
  85. size = decode_varint(cur)
  86. return cur.read(size)
  87. def decode_opt(cur, read_fn):
  88. is_some = bool(read_u8(cur))
  89. if is_some:
  90. return read_fn(cur)
  91. else:
  92. return None
  93. def decode_arr(cur, read_fn):
  94. arr_len = decode_varint(cur)
  95. vals = []
  96. for _ in range(arr_len):
  97. vals.append(read_fn(cur))
  98. return vals