57 lines
1.3 KiB
Python
57 lines
1.3 KiB
Python
from ethereum.utils import safe_ord as ord
|
|
|
|
# 0100000101010111010000110100100101001001 -> ASCII
|
|
def decode_bin(x):
|
|
o = bytearray(len(x) // 8)
|
|
for i in range(0, len(x), 8):
|
|
v = 0
|
|
for c in x[i:i+8]:
|
|
v = v * 2 + c
|
|
o[i//8] = v
|
|
return bytes(o)
|
|
|
|
|
|
# ASCII -> 0100000101010111010000110100100101001001
|
|
def encode_bin(x):
|
|
o = b''
|
|
for c in x:
|
|
c = ord(c)
|
|
p = bytearray(8)
|
|
for i in range(8):
|
|
p[7-i] = c % 2
|
|
c //= 2
|
|
o += p
|
|
return o
|
|
|
|
two_bits = [bytes([0,0]), bytes([0,1]),
|
|
bytes([1,0]), bytes([1,1])]
|
|
prefix00 = bytes([0,0])
|
|
prefix100000 = bytes([1,0,0,0,0,0])
|
|
|
|
|
|
# Encodes a sequence of 0s and 1s into tightly packed bytes
|
|
def encode_bin_path(b):
|
|
b2 = bytes((4 - len(b)) % 4) + b
|
|
prefix = two_bits[len(b) % 4]
|
|
if len(b2) % 8 == 4:
|
|
return decode_bin(prefix00 + prefix + b2)
|
|
else:
|
|
return decode_bin(prefix100000 + prefix + b2)
|
|
|
|
|
|
# Decodes bytes into a sequence of 0s and 1s
|
|
def decode_bin_path(p):
|
|
p = encode_bin(p)
|
|
if p[0] == 1:
|
|
p = p[4:]
|
|
assert p[0:2] == prefix00
|
|
L = two_bits.index(p[2:4])
|
|
return p[4+((4 - L) % 4):]
|
|
|
|
def common_prefix_length(a, b):
|
|
o = 0
|
|
while o < len(a) and o < len(b) and a[o] == b[o]:
|
|
o += 1
|
|
return o
|
|
|