@@ -1040,6 +1040,70 @@ def bencode(obj: object) -> bytes:
10401040 raise NotImplementedError (f"bencode not implemented for { type (obj )} " )
10411041
10421042
1043+ class Bdecoder :
1044+ def __init__ (self , msg : str ) -> None :
1045+ self .msg : str = msg
1046+ self .idx : int = 0
1047+
1048+ def peek (self ) -> str :
1049+ return self .msg [self .idx ]
1050+
1051+ def read (self ) -> str :
1052+ c = self .peek ()
1053+ self .idx += 1
1054+ return c
1055+
1056+ def decode_int (self ) -> int :
1057+ buf = ""
1058+ while (c := self .read ()) != "e" :
1059+ buf += c
1060+ return int (buf )
1061+
1062+ def decode_list (self ) -> typing .List [Any ]:
1063+ result = []
1064+ while self .peek () != "e" :
1065+ result .append (self .decode ())
1066+ assert self .read () == "e"
1067+ return result
1068+
1069+ def decode_dict (self ) -> typing .Dict [Any , Any ]:
1070+ result : Dict [Any , Any ] = {}
1071+ while self .peek () != "e" :
1072+ key = self .decode ()
1073+ value = self .decode ()
1074+ result [key ] = value
1075+ assert self .read () == "e"
1076+ return result
1077+
1078+ def decode_str (self , start : str ) -> str :
1079+ len_buf = start
1080+ while (c := self .peek ()) != ":" :
1081+ assert c .isdigit ()
1082+ len_buf += c
1083+ self .read ()
1084+ assert self .read () == ":"
1085+ buf = ""
1086+ for _ in range (int (len_buf )):
1087+ buf += self .read ()
1088+ return buf
1089+
1090+ def decode (self ) -> object :
1091+ ty = self .read ()
1092+ if ty == "i" :
1093+ return self .decode_int ()
1094+ if ty == "l" :
1095+ return self .decode_list ()
1096+ if ty == "d" :
1097+ return self .decode_dict ()
1098+ if ty .isdigit ():
1099+ return self .decode_str (ty )
1100+ raise NotImplementedError (ty )
1101+
1102+
1103+ def bdecode (msg : str ) -> object :
1104+ return Bdecoder (msg ).decode ()
1105+
1106+
10431107def serialize (obj : Object ) -> bytes :
10441108 return bencode (obj .serialize ())
10451109
@@ -2733,6 +2797,33 @@ def test_bencode_dict_sorts_keys(self) -> None:
27332797 self .assertEqual (bencode (d ), b"d1:ai2e1:bi1ee" )
27342798
27352799
2800+ class BdecodeTests (unittest .TestCase ):
2801+ def test_bdecode_int (self ) -> None :
2802+ self .assertEqual (bdecode ("i123e" ), 123 )
2803+
2804+ def test_bdecode_bool (self ) -> None :
2805+ # TODO(max): Should we discriminate between bool and int?
2806+ self .assertEqual (bdecode ("i1e" ), 1 )
2807+
2808+ def test_bdecode_negative_int (self ) -> None :
2809+ self .assertEqual (bdecode ("i-123e" ), - 123 )
2810+
2811+ def test_bdecode_bytes (self ) -> None :
2812+ self .assertEqual (bdecode ("3:abc" ), "abc" )
2813+
2814+ def test_bdecode_empty_list (self ) -> None :
2815+ self .assertEqual (bdecode ("le" ), [])
2816+
2817+ def test_bdecode_list_of_ints (self ) -> None :
2818+ self .assertEqual (bdecode ("li1ei2ei3ee" ), [1 , 2 , 3 ])
2819+
2820+ def test_bdecode_list_of_lists (self ) -> None :
2821+ self .assertEqual (bdecode ("lli1ei2eeli3ei4eee" ), [[1 , 2 ], [3 , 4 ]])
2822+
2823+ def test_bdecode_dict_sorts_keys (self ) -> None :
2824+ self .assertEqual (bdecode ("d1:ai2e1:bi1ee" ), {"b" : 1 , "a" : 2 })
2825+
2826+
27362827class ObjectSerializeTests (unittest .TestCase ):
27372828 def test_serialize_int (self ) -> None :
27382829 obj = Int (123 )
0 commit comments