@@ -182,6 +182,17 @@ cdef class Packer(object):
182182 self .pk.length = 0
183183 return buf
184184
185+ cpdef pack_array_header(self , size_t size):
186+ msgpack_pack_array(& self .pk, size)
187+ buf = PyBytes_FromStringAndSize(self .pk.buf, self .pk.length)
188+ self .pk.length = 0
189+ return buf
190+
191+ cpdef pack_map_header(self , size_t size):
192+ msgpack_pack_map(& self .pk, size)
193+ buf = PyBytes_FromStringAndSize(self .pk.buf, self .pk.length)
194+ self .pk.length = 0
195+ return buf
185196
186197def pack (object o , object stream , default = None , encoding = ' utf-8' , unicode_errors = ' strict' ):
187198 """
@@ -213,8 +224,12 @@ cdef extern from "unpack.h":
213224 unsigned int ct
214225 PyObject* key
215226
216- int template_execute(template_context* ctx, const_char_ptr data,
217- size_t len , size_t* off, bint construct) except - 1
227+ ctypedef int (* execute_fn)(template_context* ctx, const_char_ptr data,
228+ size_t len , size_t* off) except - 1
229+ execute_fn template_construct
230+ execute_fn template_skip
231+ execute_fn read_array_header
232+ execute_fn read_map_header
218233 void template_init(template_context* ctx)
219234 object template_data(template_context* ctx)
220235
@@ -277,7 +292,7 @@ def unpackb(object packed, object object_hook=None, object list_hook=None,
277292 PyObject_AsReadBuffer(packed, < const_void_ptr* > & buf, & buf_len)
278293
279294 init_ctx(& ctx, object_hook, object_pairs_hook, list_hook, use_list, encoding, unicode_errors)
280- ret = template_execute (& ctx, buf, buf_len, & off, 1 )
295+ ret = template_construct (& ctx, buf, buf_len, & off)
281296 if ret == 1 :
282297 obj = template_data(& ctx)
283298 if off < buf_len:
@@ -452,16 +467,13 @@ cdef class Unpacker(object):
452467 else :
453468 self .file_like = None
454469
455- cdef object _unpack(self , bint construct ):
470+ cdef object _unpack(self , execute_fn execute ):
456471 cdef int ret
457472 cdef object obj
458473 while 1 :
459- ret = template_execute (& self .ctx, self .buf, self .buf_tail, & self .buf_head, construct )
474+ ret = execute (& self .ctx, self .buf, self .buf_tail, & self .buf_head)
460475 if ret == 1 :
461- if construct:
462- obj = template_data(& self .ctx)
463- else :
464- obj = None
476+ obj = template_data(& self .ctx)
465477 template_init(& self .ctx)
466478 return obj
467479 elif ret == 0 :
@@ -474,17 +486,25 @@ cdef class Unpacker(object):
474486
475487 def unpack (self ):
476488 """ unpack one object"""
477- return self ._unpack(1 )
489+ return self ._unpack(template_construct )
478490
479491 def skip (self ):
480492 """ read and ignore one object, returning None"""
481- return self ._unpack(0 )
493+ return self ._unpack(template_skip)
494+
495+ def read_array_header (self ):
496+ """ assuming the next object is an array, return its size n, such that the next n unpack() calls will iterate over its contents."""
497+ return self ._unpack(read_array_header)
498+
499+ def read_map_header (self ):
500+ """ assuming the next object is a map, return its size n, such that the next n * 2 unpack() calls will iterate over its key-value pairs."""
501+ return self ._unpack(read_map_header)
482502
483503 def __iter__ (self ):
484504 return self
485505
486506 def __next__ (self ):
487- return self ._unpack(1 )
507+ return self ._unpack(template_construct )
488508
489509 # for debug.
490510 # def _buf(self):
0 commit comments