@@ -24,6 +24,7 @@ cdef extern from "unpack.h":
2424 PyObject* object_hook
2525 bint has_pairs_hook # call object_hook with k-v pairs
2626 PyObject* list_hook
27+ PyObject* ext_type_hook
2728 char * encoding
2829 char * unicode_errors
2930
@@ -45,6 +46,7 @@ cdef extern from "unpack.h":
4546
4647cdef inline init_ctx(unpack_context * ctx,
4748 object object_hook, object object_pairs_hook, object list_hook,
49+ object ext_type_hook,
4850 bint use_list, char * encoding, char * unicode_errors):
4951 unpack_init(ctx)
5052 ctx.user.use_list = use_list
@@ -71,9 +73,17 @@ cdef inline init_ctx(unpack_context *ctx,
7173 raise TypeError (" list_hook must be a callable." )
7274 ctx.user.list_hook = < PyObject* > list_hook
7375
76+ if ext_type_hook is not None :
77+ if not PyCallable_Check(ext_type_hook):
78+ raise TypeError (" ext_type_hook must be a callable." )
79+ ctx.user.ext_type_hook = < PyObject* > ext_type_hook
80+
7481 ctx.user.encoding = encoding
7582 ctx.user.unicode_errors = unicode_errors
7683
84+ def default_read_extended_type (typecode , data ):
85+ raise NotImplementedError (" Cannot decode extended type with typecode=%d " % typecode)
86+
7787def unpackb (object packed , object object_hook = None , object list_hook = None ,
7888 bint use_list = 1 , encoding = None , unicode_errors = " strict" ,
7989 object_pairs_hook = None ,
@@ -106,7 +116,8 @@ def unpackb(object packed, object object_hook=None, object list_hook=None,
106116 unicode_errors = unicode_errors.encode(' ascii' )
107117 cerr = PyBytes_AsString(unicode_errors)
108118
109- init_ctx(& ctx, object_hook, object_pairs_hook, list_hook, use_list, cenc, cerr)
119+ init_ctx(& ctx, object_hook, object_pairs_hook, list_hook, default_read_extended_type,
120+ use_list, cenc, cerr)
110121 ret = unpack_construct(& ctx, buf, buf_len, & off)
111122 if ret == 1 :
112123 obj = unpack_data(& ctx)
@@ -248,7 +259,10 @@ cdef class Unpacker(object):
248259 self .unicode_errors = unicode_errors
249260 cerr = PyBytes_AsString(self .unicode_errors)
250261
251- init_ctx(& self .ctx, object_hook, object_pairs_hook, list_hook, use_list, cenc, cerr)
262+ ext_type_hook = self .read_extended_type
263+ Py_INCREF(ext_type_hook)
264+ init_ctx(& self .ctx, object_hook, object_pairs_hook, list_hook,
265+ ext_type_hook, use_list, cenc, cerr)
252266
253267 def feed (self , object next_bytes ):
254268 """ Append `next_bytes` to internal buffer."""
@@ -358,6 +372,24 @@ cdef class Unpacker(object):
358372 """
359373 return self ._unpack(unpack_construct, write_bytes)
360374
375+ def unpack_one (self , object write_bytes = None ):
376+ """
377+ unpack one object
378+
379+ If write_bytes is not None, it will be called with parts of the raw
380+ message as it is unpacked.
381+
382+ Raises `UnpackValueError` if there are no more bytes to unpack.
383+ Raises ``ExtraData`` if there are still bytes left after the unpacking.
384+ """
385+ try :
386+ result = self .unpack()
387+ except OutOfData:
388+ raise UnpackValueError(" Data is not enough" )
389+ if self .buf_head < self .buf_tail:
390+ raise ExtraData(result, self .buf[self .buf_head:])
391+ return result
392+
361393 def skip (self , object write_bytes = None ):
362394 """
363395 read and ignore one object, returning None
@@ -385,6 +417,9 @@ cdef class Unpacker(object):
385417 """
386418 return self ._unpack(read_map_header, write_bytes)
387419
420+ def read_extended_type (self , typecode , data ):
421+ return default_read_extended_type(typecode, data)
422+
388423 def __iter__ (self ):
389424 return self
390425
0 commit comments