77"""
88import struct
99
10+ from mmap import mmap
11+ from typing import cast , Dict , List , Tuple , Union
12+
1013from maxminddb .errors import InvalidDatabaseError
14+ from maxminddb .file import FileBuffer
15+ from maxminddb .types import Record
1116
1217
1318class Decoder : # pylint: disable=too-few-public-methods
1419 """Decoder for the data section of the MaxMind DB"""
1520
16- def __init__ (self , database_buffer , pointer_base = 0 , pointer_test = False ):
21+ def __init__ (
22+ self ,
23+ database_buffer : Union [FileBuffer , mmap , bytes ],
24+ pointer_base : int = 0 ,
25+ pointer_test : bool = False ,
26+ ) -> None :
1727 """Created a Decoder for a MaxMind DB
1828
1929 Arguments:
@@ -25,35 +35,37 @@ def __init__(self, database_buffer, pointer_base=0, pointer_test=False):
2535 self ._buffer = database_buffer
2636 self ._pointer_base = pointer_base
2737
28- def _decode_array (self , size , offset ) :
38+ def _decode_array (self , size : int , offset : int ) -> Tuple [ List [ Record ], int ] :
2939 array = []
3040 for _ in range (size ):
3141 (value , offset ) = self .decode (offset )
3242 array .append (value )
3343 return array , offset
3444
35- def _decode_boolean (self , size , offset ): # pylint: disable=no-self-use
45+ def _decode_boolean ( # pylint: disable=no-self-use
46+ self , size : int , offset : int
47+ ) -> Tuple [bool , int ]:
3648 return size != 0 , offset
3749
38- def _decode_bytes (self , size , offset ) :
50+ def _decode_bytes (self , size : int , offset : int ) -> Tuple [ bytes , int ] :
3951 new_offset = offset + size
4052 return self ._buffer [offset :new_offset ], new_offset
4153
42- def _decode_double (self , size , offset ) :
54+ def _decode_double (self , size : int , offset : int ) -> Tuple [ float , int ] :
4355 self ._verify_size (size , 8 )
4456 new_offset = offset + size
4557 packed_bytes = self ._buffer [offset :new_offset ]
4658 (value ,) = struct .unpack (b"!d" , packed_bytes )
4759 return value , new_offset
4860
49- def _decode_float (self , size , offset ) :
61+ def _decode_float (self , size : int , offset : int ) -> Tuple [ float , int ] :
5062 self ._verify_size (size , 4 )
5163 new_offset = offset + size
5264 packed_bytes = self ._buffer [offset :new_offset ]
5365 (value ,) = struct .unpack (b"!f" , packed_bytes )
5466 return value , new_offset
5567
56- def _decode_int32 (self , size , offset ) :
68+ def _decode_int32 (self , size : int , offset : int ) -> Tuple [ int , int ] :
5769 if size == 0 :
5870 return 0 , offset
5971 new_offset = offset + size
@@ -64,15 +76,15 @@ def _decode_int32(self, size, offset):
6476 (value ,) = struct .unpack (b"!i" , packed_bytes )
6577 return value , new_offset
6678
67- def _decode_map (self , size , offset ) :
68- container = {}
79+ def _decode_map (self , size : int , offset : int ) -> Tuple [ Dict [ str , Record ], int ] :
80+ container : Dict [ str , Record ] = {}
6981 for _ in range (size ):
7082 (key , offset ) = self .decode (offset )
7183 (value , offset ) = self .decode (offset )
72- container [key ] = value
84+ container [cast ( str , key ) ] = value
7385 return container , offset
7486
75- def _decode_pointer (self , size , offset ) :
87+ def _decode_pointer (self , size : int , offset : int ) -> Tuple [ Record , int ] :
7688 pointer_size = (size >> 3 ) + 1
7789
7890 buf = self ._buffer [offset : offset + pointer_size ]
@@ -95,12 +107,12 @@ def _decode_pointer(self, size, offset):
95107 (value , _ ) = self .decode (pointer )
96108 return value , new_offset
97109
98- def _decode_uint (self , size , offset ) :
110+ def _decode_uint (self , size : int , offset : int ) -> Tuple [ int , int ] :
99111 new_offset = offset + size
100112 uint_bytes = self ._buffer [offset :new_offset ]
101113 return int .from_bytes (uint_bytes , "big" ), new_offset
102114
103- def _decode_utf8_string (self , size , offset ) :
115+ def _decode_utf8_string (self , size : int , offset : int ) -> Tuple [ str , int ] :
104116 new_offset = offset + size
105117 return self ._buffer [offset :new_offset ].decode ("utf-8" ), new_offset
106118
@@ -120,7 +132,7 @@ def _decode_utf8_string(self, size, offset):
120132 15 : _decode_float ,
121133 }
122134
123- def decode (self , offset ) :
135+ def decode (self , offset : int ) -> Tuple [ Record , int ] :
124136 """Decode a section of the data section starting at offset
125137
126138 Arguments:
@@ -143,7 +155,7 @@ def decode(self, offset):
143155 (size , new_offset ) = self ._size_from_ctrl_byte (ctrl_byte , new_offset , type_num )
144156 return decoder (self , size , new_offset )
145157
146- def _read_extended (self , offset ) :
158+ def _read_extended (self , offset : int ) -> Tuple [ int , int ] :
147159 next_byte = self ._buffer [offset ]
148160 type_num = next_byte + 7
149161 if type_num < 7 :
@@ -155,14 +167,16 @@ def _read_extended(self, offset):
155167 return type_num , offset + 1
156168
157169 @staticmethod
158- def _verify_size (expected , actual ) :
170+ def _verify_size (expected : int , actual : int ) -> None :
159171 if expected != actual :
160172 raise InvalidDatabaseError (
161173 "The MaxMind DB file's data section contains bad data "
162174 "(unknown data type or corrupt data)"
163175 )
164176
165- def _size_from_ctrl_byte (self , ctrl_byte , offset , type_num ):
177+ def _size_from_ctrl_byte (
178+ self , ctrl_byte : int , offset : int , type_num : int
179+ ) -> Tuple [int , int ]:
166180 size = ctrl_byte & 0x1F
167181 if type_num == 1 or size < 29 :
168182 return size , offset
0 commit comments