Move bencode to voussoirkit.
This commit is contained in:
parent
35b04a57e1
commit
adf8d305db
1 changed files with 0 additions and 147 deletions
|
@ -1,147 +0,0 @@
|
||||||
'''
|
|
||||||
A Python 3 translation of bcode.py
|
|
||||||
https://pypi.python.org/pypi/bcode/0.5
|
|
||||||
'''
|
|
||||||
|
|
||||||
def bencode(data):
|
|
||||||
'''
|
|
||||||
Encode python types to bencode.
|
|
||||||
'''
|
|
||||||
if data is None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
data_type = type(data)
|
|
||||||
|
|
||||||
encoders = {
|
|
||||||
bytes: encode_bytes,
|
|
||||||
float: encode_float,
|
|
||||||
int: encode_int,
|
|
||||||
dict: encode_dict,
|
|
||||||
}
|
|
||||||
|
|
||||||
encoder = encoders.get(data_type, None)
|
|
||||||
if encoder is None:
|
|
||||||
try:
|
|
||||||
return encode_iterator(iter(data))
|
|
||||||
except TypeError:
|
|
||||||
raise ValueError('Invalid field type %s' % data_type)
|
|
||||||
return encoder(data)
|
|
||||||
|
|
||||||
def encode_bytes(data):
|
|
||||||
return b'%d:%s' % (len(data), data)
|
|
||||||
|
|
||||||
def encode_dict(data):
|
|
||||||
result = []
|
|
||||||
keys = list(data.keys())
|
|
||||||
keys.sort()
|
|
||||||
for key in keys:
|
|
||||||
result.append(bencode(key))
|
|
||||||
result.append(bencode(data[key]))
|
|
||||||
result = b''.join(result)
|
|
||||||
return b'd%se' % result
|
|
||||||
|
|
||||||
def encode_float(data):
|
|
||||||
return encode_bytes(str(data).encode())
|
|
||||||
|
|
||||||
def encode_int(data):
|
|
||||||
return b'i%de' % data
|
|
||||||
|
|
||||||
def encode_iterator(data):
|
|
||||||
result = []
|
|
||||||
for item in data:
|
|
||||||
result.append(bencode(item))
|
|
||||||
result = b''.join(result)
|
|
||||||
return b'l%se' % result
|
|
||||||
|
|
||||||
|
|
||||||
# =============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
def bdecode(data):
|
|
||||||
'''
|
|
||||||
Decode bencode to python types.
|
|
||||||
|
|
||||||
Returns a dictionary
|
|
||||||
{
|
|
||||||
'result': the decoded item
|
|
||||||
'remainder': what's left of the input text
|
|
||||||
}
|
|
||||||
'''
|
|
||||||
if data is None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
#data = data.strip()
|
|
||||||
if isinstance(data, str):
|
|
||||||
data = data.encode('utf-8')
|
|
||||||
|
|
||||||
identifier = data[0:1]
|
|
||||||
if identifier == b'i':
|
|
||||||
return decode_int(data)
|
|
||||||
|
|
||||||
if identifier.isdigit():
|
|
||||||
return decode_bytes(data)
|
|
||||||
|
|
||||||
if identifier == b'l':
|
|
||||||
return decode_list(data)
|
|
||||||
|
|
||||||
if identifier == b'd':
|
|
||||||
return decode_dict(data)
|
|
||||||
|
|
||||||
raise ValueError('Invalid initial delimiter "%s"' % identifier)
|
|
||||||
|
|
||||||
def decode_bytes(data):
|
|
||||||
#print('Decoding bytes from', data[:100])
|
|
||||||
start = data.find(b':') + 1
|
|
||||||
size = int(data[:start-1])
|
|
||||||
end = start + size
|
|
||||||
text = data[start:end]
|
|
||||||
if len(text) < size:
|
|
||||||
raise ValueError('Actual length %d is less than declared length %d' % len(text), size)
|
|
||||||
remainder = data[end:]
|
|
||||||
return {'result': text, 'remainder': remainder}
|
|
||||||
|
|
||||||
def decode_dict(data):
|
|
||||||
#print('Decoding dict from', data[:100])
|
|
||||||
result = {}
|
|
||||||
|
|
||||||
# slice leading d
|
|
||||||
remainder = data[1:]
|
|
||||||
while remainder[0:1] != b'e':
|
|
||||||
temp = bdecode(remainder)
|
|
||||||
key = temp['result']
|
|
||||||
remainder = temp['remainder']
|
|
||||||
|
|
||||||
temp = bdecode(remainder)
|
|
||||||
value = temp['result']
|
|
||||||
remainder = temp['remainder']
|
|
||||||
result[key] = value
|
|
||||||
|
|
||||||
# slice ending e
|
|
||||||
remainder = remainder[1:]
|
|
||||||
return {'result': result, 'remainder': remainder}
|
|
||||||
|
|
||||||
def decode_int(data):
|
|
||||||
#print('Decoding int from', data[:100])
|
|
||||||
end = data.find(b'e')
|
|
||||||
if end == -1:
|
|
||||||
raise ValueError('Missing end delimiter "e"')
|
|
||||||
|
|
||||||
# slice leading i and closing e
|
|
||||||
result = int(data[1:end])
|
|
||||||
remainder = data[end+1:]
|
|
||||||
return {'result': result, 'remainder': remainder}
|
|
||||||
|
|
||||||
def decode_list(data):
|
|
||||||
#print('Decoding list from', data[:100])
|
|
||||||
result = []
|
|
||||||
|
|
||||||
# slice leading l
|
|
||||||
remainder = data[1:]
|
|
||||||
while remainder[0:1] != b'e':
|
|
||||||
item = bdecode(remainder)
|
|
||||||
result.append(item['result'])
|
|
||||||
remainder = item['remainder']
|
|
||||||
|
|
||||||
# slice ending e
|
|
||||||
remainder = remainder[1:]
|
|
||||||
return {'result': result, 'remainder': remainder}
|
|
Loading…
Reference in a new issue