go-ethereum/rlp.py

57 lines
1.6 KiB
Python

def binary_length(n):
if n == 0: return 0
else: return 1 + binary_length(n / 256)
def to_binary_array(n,L=None):
if L is None: L = binary_length(n)
if n == 0: return []
else:
x = to_binary_array(n / 256)
x.append(n % 256)
return x
def to_binary(n,L=None): return ''.join([chr(x) for x in to_binary_array(n,L)])
def from_binary(b):
if len(b) == 0: return 0
else: return from_binary(b[:-1]) * 256 + ord(b[-1])
def num_to_var_int(n):
if n < 253: s = [n]
elif n < 2**16: s = [253] + list(to_binary_array(n,2))
elif n < 2**32: s = [254] + list(to_binary_array(n,4))
elif n < 2**64: s = [255] + list(to_binary_array(n,8))
else: raise Exception("number too big")
return ''.join([chr(x) for x in s])
def __decode(s):
o = []
index = [0]
def read_var_int():
si = ord(s[index[0]])
index[0] += 1
if si < 253: return si
elif si == 253: read = 2
elif si == 254: read = 4
elif si == 255: read = 8
index[0] += read
return from_binary(s[index[0]-read:index[0]])
while index[0] < len(s):
tp = s[index[0]]
index[0] += 1
L = read_var_int()
item = s[index[0]:index[0]+L]
if tp == '\x00': o.append(item)
else: o.append(__decode(item))
index[0] += L
return o
def decode(s): return __decode(s)[0]
def encode(s):
if isinstance(s,(int,long)): return encode(to_binary(s))
if isinstance(s,str): return '\x00'+num_to_var_int(len(s))+s
else:
x = ''.join([encode(x) for x in s])
return '\x01'+num_to_var_int(len(x))+x