@@ -48,6 +48,9 @@ def getvalue(self):
4848 PackValueError ,
4949 ExtraData )
5050
51+ from msgpack import ExtType
52+
53+
5154EX_SKIP = 0
5255EX_CONSTRUCT = 1
5356EX_READ_ARRAY_HEADER = 2
@@ -58,8 +61,9 @@ def getvalue(self):
5861TYPE_MAP = 2
5962TYPE_RAW = 3
6063TYPE_BIN = 4
64+ TYPE_EXT = 5
6165
62- DEFAULT_RECURSE_LIMIT = 511
66+ DEFAULT_RECURSE_LIMIT = 511
6367
6468def unpack (stream , ** kwargs ):
6569 """
@@ -112,6 +116,9 @@ class Unpacker(object):
112116 should be callable and Unpacker calls it with a list of key-value pairs
113117 after deserializing a map.
114118
119+ `ext_hook` is callback for ext (User defined) type. It called with two
120+ arguments: (code, bytes). default: `msgpack.ExtType`
121+
115122 `encoding` is the encoding used for decoding msgpack bytes. If it is
116123 None (default), msgpack bytes are deserialized to Python bytes.
117124
@@ -143,7 +150,8 @@ class Unpacker(object):
143150
144151 def __init__ (self , file_like = None , read_size = 0 , use_list = True ,
145152 object_hook = None , object_pairs_hook = None , list_hook = None ,
146- encoding = None , unicode_errors = 'strict' , max_buffer_size = 0 ):
153+ encoding = None , unicode_errors = 'strict' , max_buffer_size = 0 ,
154+ ext_hook = ExtType ):
147155 if file_like is None :
148156 self ._fb_feeding = True
149157 else :
@@ -167,6 +175,7 @@ def __init__(self, file_like=None, read_size=0, use_list=True,
167175 self ._list_hook = list_hook
168176 self ._object_hook = object_hook
169177 self ._object_pairs_hook = object_pairs_hook
178+ self ._ext_hook = ext_hook
170179
171180 if list_hook is not None and not callable (list_hook ):
172181 raise ValueError ('`list_hook` is not callable' )
@@ -177,6 +186,8 @@ def __init__(self, file_like=None, read_size=0, use_list=True,
177186 if object_hook is not None and object_pairs_hook is not None :
178187 raise ValueError ("object_pairs_hook and object_hook are mutually "
179188 "exclusive" )
189+ if not callable (ext_hook ):
190+ raise ValueError ("`ext_hook` is not callable" )
180191
181192 def feed (self , next_bytes ):
182193 if isinstance (next_bytes , array .array ):
@@ -278,6 +289,30 @@ def _read_header(self, execute=EX_CONSTRUCT, write_bytes=None):
278289 obj = False
279290 elif b == 0xc3 :
280291 obj = True
292+ elif b == 0xc4 :
293+ typ = TYPE_BIN
294+ n = struct .unpack ("B" , self ._fb_read (1 , write_bytes ))[0 ]
295+ obj = self ._fb_read (n , write_bytes )
296+ elif b == 0xc5 :
297+ typ = TYPE_BIN
298+ n = struct .unpack (">H" , self ._fb_read (2 , write_bytes ))[0 ]
299+ obj = self ._fb_read (n , write_bytes )
300+ elif b == 0xc6 :
301+ typ = TYPE_BIN
302+ n = struct .unpack (">I" , self ._fb_read (4 , write_bytes ))[0 ]
303+ obj = self ._fb_read (n , write_bytes )
304+ elif b == 0xc7 : # ext 8
305+ typ = TYPE_EXT
306+ L , n = struct .unpack ('Bb' , self ._fb_read (2 , write_bytes ))
307+ obj = self ._fb_read (L , write_bytes )
308+ elif b == 0xc8 : # ext 16
309+ typ = TYPE_EXT
310+ L , n = struct .unpack ('>Hb' , self ._fb_read (3 , write_bytes ))
311+ obj = self ._fb_read (L , write_bytes )
312+ elif b == 0xc9 : # ext 32
313+ typ = TYPE_EXT
314+ L , n = struct .unpack ('>Ib' , self ._fb_read (5 , write_bytes ))
315+ obj = self ._fb_read (L , write_bytes )
281316 elif b == 0xca :
282317 obj = struct .unpack (">f" , self ._fb_read (4 , write_bytes ))[0 ]
283318 elif b == 0xcb :
@@ -298,30 +333,33 @@ def _read_header(self, execute=EX_CONSTRUCT, write_bytes=None):
298333 obj = struct .unpack (">i" , self ._fb_read (4 , write_bytes ))[0 ]
299334 elif b == 0xd3 :
300335 obj = struct .unpack (">q" , self ._fb_read (8 , write_bytes ))[0 ]
336+ elif b == 0xd4 : # fixext 1
337+ typ = TYPE_EXT
338+ n , obj = struct .unpack ('b1s' , self ._fb_read (2 , write_bytes ))
339+ elif b == 0xd5 : # fixext 2
340+ typ = TYPE_EXT
341+ n , obj = struct .unpack ('b2s' , self ._fb_read (3 , write_bytes ))
342+ elif b == 0xd6 : # fixext 4
343+ typ = TYPE_EXT
344+ n , obj = struct .unpack ('b4s' , self ._fb_read (5 , write_bytes ))
345+ elif b == 0xd7 : # fixext 8
346+ typ = TYPE_EXT
347+ n , obj = struct .unpack ('b8s' , self ._fb_read (9 , write_bytes ))
348+ elif b == 0xd8 : # fixext 16
349+ typ = TYPE_EXT
350+ n , obj = struct .unpack ('b16s' , self ._fb_read (17 , write_bytes ))
301351 elif b == 0xd9 :
352+ typ = TYPE_RAW
302353 n = struct .unpack ("B" , self ._fb_read (1 , write_bytes ))[0 ]
303354 obj = self ._fb_read (n , write_bytes )
304- typ = TYPE_RAW
305355 elif b == 0xda :
356+ typ = TYPE_RAW
306357 n = struct .unpack (">H" , self ._fb_read (2 , write_bytes ))[0 ]
307358 obj = self ._fb_read (n , write_bytes )
308- typ = TYPE_RAW
309359 elif b == 0xdb :
310- n = struct .unpack (">I" , self ._fb_read (4 , write_bytes ))[0 ]
311- obj = self ._fb_read (n , write_bytes )
312360 typ = TYPE_RAW
313- elif b == 0xc4 :
314- n = struct .unpack ("B" , self ._fb_read (1 , write_bytes ))[0 ]
315- obj = self ._fb_read (n , write_bytes )
316- typ = TYPE_BIN
317- elif b == 0xc5 :
318- n = struct .unpack (">H" , self ._fb_read (2 , write_bytes ))[0 ]
319- obj = self ._fb_read (n , write_bytes )
320- typ = TYPE_BIN
321- elif b == 0xc6 :
322361 n = struct .unpack (">I" , self ._fb_read (4 , write_bytes ))[0 ]
323362 obj = self ._fb_read (n , write_bytes )
324- typ = TYPE_BIN
325363 elif b == 0xdc :
326364 n = struct .unpack (">H" , self ._fb_read (2 , write_bytes ))[0 ]
327365 typ = TYPE_ARRAY
@@ -390,6 +428,8 @@ def _fb_unpack(self, execute=EX_CONSTRUCT, write_bytes=None):
390428 if self ._encoding is not None :
391429 obj = obj .decode (self ._encoding , self ._unicode_errors )
392430 return obj
431+ if typ == TYPE_EXT :
432+ return self ._ext_hook (n , obj )
393433 if typ == TYPE_BIN :
394434 return obj
395435 assert typ == TYPE_IMMEDIATE
0 commit comments