@@ -305,6 +305,8 @@ cdef class Unpacker:
305305 Raises ``OutOfData`` when *packed* is incomplete.
306306 Raises ``FormatError`` when *packed* is not valid msgpack.
307307 Raises ``StackError`` when *packed* contains too nested.
308+ Raises ``RuntimeError`` when ``feed()`` is called while unpacking
309+ is in progress (e.g. from a hook).
308310 Other exceptions can be raised during unpacking.
309311 """
310312 cdef unpack_context ctx
@@ -318,6 +320,7 @@ cdef class Unpacker:
318320 cdef object unicode_errors
319321 cdef Py_ssize_t max_buffer_size
320322 cdef uint64_t stream_offset
323+ cdef bint _unpacking
321324
322325 def __dealloc__ (self ):
323326 unpack_clear(& self .ctx)
@@ -381,6 +384,7 @@ cdef class Unpacker:
381384 self .buf_head = 0
382385 self .buf_tail = 0
383386 self .stream_offset = 0
387+ self ._unpacking = False
384388
385389 if unicode_errors is not None :
386390 self .unicode_errors = unicode_errors
@@ -398,6 +402,11 @@ cdef class Unpacker:
398402 cdef char * buf
399403 cdef Py_ssize_t buf_len
400404
405+ if self ._unpacking:
406+ raise RuntimeError (
407+ " Unpacker.feed() cannot be called while unpacking is in progress"
408+ )
409+
401410 if self .file_like is not None :
402411 raise AssertionError (
403412 " unpacker.feed() is not be able to use with `file_like`." )
@@ -465,36 +474,40 @@ cdef class Unpacker:
465474 cdef object obj
466475 cdef Py_ssize_t prev_head
467476
468- while 1 :
469- prev_head = self .buf_head
470- if prev_head < self .buf_tail:
471- ret = execute(& self .ctx, self .buf, self .buf_tail, & self .buf_head)
472- self .stream_offset += self .buf_head - prev_head
473- else :
474- ret = 0
475-
476- if ret == 1 :
477- obj = unpack_data(& self .ctx)
478- unpack_init(& self .ctx)
479- return obj
480- if ret == 0 :
481- if self .file_like is not None :
482- self .read_from_file()
483- continue
484- if iter :
485- raise StopIteration (" No more data to unpack." )
477+ self ._unpacking = True
478+ try :
479+ while 1 :
480+ prev_head = self .buf_head
481+ if prev_head < self .buf_tail:
482+ ret = execute(& self .ctx, self .buf, self .buf_tail, & self .buf_head)
483+ self .stream_offset += self .buf_head - prev_head
486484 else :
487- raise OutOfData(" No more data to unpack." )
488-
489- unpack_clear(& self .ctx)
490- if ret == - 2 :
491- raise FormatError
492- elif ret == - 3 :
493- raise StackError
494- elif PyErr_Occurred():
495- raise
496- else :
497- raise ValueError (" Unpack failed: error = %d " % (ret,))
485+ ret = 0
486+
487+ if ret == 1 :
488+ obj = unpack_data(& self .ctx)
489+ unpack_init(& self .ctx)
490+ return obj
491+ if ret == 0 :
492+ if self .file_like is not None :
493+ self .read_from_file()
494+ continue
495+ if iter :
496+ raise StopIteration (" No more data to unpack." )
497+ else :
498+ raise OutOfData(" No more data to unpack." )
499+
500+ unpack_clear(& self .ctx)
501+ if ret == - 2 :
502+ raise FormatError
503+ elif ret == - 3 :
504+ raise StackError
505+ elif PyErr_Occurred():
506+ raise
507+ else :
508+ raise ValueError (" Unpack failed: error = %d " % (ret,))
509+ finally :
510+ self ._unpacking = False
498511
499512 @cython.critical_section
500513 def read_bytes (self , Py_ssize_t nbytes ):
0 commit comments