Created
September 25, 2024 06:42
-
-
Save khubo/c12df9e8f78f18bf3633d72cb00bb4d3 to your computer and use it in GitHub Desktop.
basic bencode decoder
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Decode: | |
def __init__(self, content: bytes): | |
pass | |
self.content = content | |
self.current_pos = 0 | |
self.data = {} | |
def current(self) -> int: | |
return self.content[self.current_pos] | |
def next(self) -> int | None: | |
if self.current_pos < len(self.content) - 1: | |
self.current_pos += 1 | |
return self.content[self.current_pos] | |
else: | |
return None | |
# the parse methods follow | |
def parse_dict(self): | |
result = {} | |
# should always be a key value pair | |
# key will be a string | |
# value can be anything. | |
self.next() | |
try: | |
while self.current() != ord('e'): | |
key = self.parse_bytes() | |
value = self.parse_function(self.current())() | |
result[key.decode()] = value | |
self.next() | |
return result | |
except Exception as e: | |
print(e) | |
raise Exception("invalid character while parsing the dict") | |
def parse_list(self): | |
ch = self.next() | |
values = [] | |
while ch and ch != ord('e'): | |
values.append(self.parse_function(ch)()) | |
ch = self.current() | |
self.next() | |
return values | |
def parse_int(self): | |
next_ch = self.next() | |
number = "" | |
while next_ch and next_ch != ord('e'): | |
number += chr(next_ch) | |
next_ch = self.next() | |
self.next() | |
return int(number) | |
def parse_bytes(self): | |
num_bytes = chr(self.current()) | |
while self.next() != ord(':'): | |
num_bytes += chr(self.current()) | |
self.next() | |
byte_string = b"" | |
for _ in range(int(num_bytes)): | |
byte_string += chr(self.current()).encode() | |
self.next() | |
return byte_string | |
def parse_function(self, a: int): | |
if a == ord('d'): | |
return self.parse_dict | |
if a == ord('l'): | |
return self.parse_list | |
if a == ord('i'): | |
return self.parse_int | |
if a >= ord('0') and a <= ord('9'): | |
return self.parse_bytes | |
raise Exception('invalid delimeter') | |
def parse_content(self): | |
""" | |
method that parse the content of byte string. | |
""" | |
current_ch = self.current() | |
result = self.parse_function(current_ch)() | |
self.data = result | |
return self.data |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment