@@ -38,7 +38,6 @@ cdef extern from "pack.h":
3838 int msgpack_pack_raw_body(msgpack_packer* pk, char * body, size_t l) except - 1
3939 int msgpack_pack_ext(msgpack_packer* pk, char typecode, size_t l) except - 1
4040 int msgpack_pack_timestamp(msgpack_packer* x, long long seconds, unsigned long nanoseconds) except - 1
41- int msgpack_pack_unicode(msgpack_packer* pk, object o, long long limit) except - 1
4241
4342
4443cdef int DEFAULT_RECURSE_LIMIT= 511
@@ -143,139 +142,133 @@ cdef class Packer:
143142 PyMem_Free(self .pk.buf)
144143 self .pk.buf = NULL
145144
146- cdef int _pack (self , object o, int nest_limit = DEFAULT_RECURSE_LIMIT ) except - 1 :
145+ cdef int _pack_inner (self , object o, bint will_default, int nest_limit) except - 1 :
147146 cdef long long llval
148147 cdef unsigned long long ullval
149148 cdef unsigned long ulval
150149 cdef long longval
151150 cdef float fval
152151 cdef double dval
153- cdef char * rawval
154- cdef int ret
155- cdef dict d
152+ cdef const char * rawval
156153 cdef Py_ssize_t L
157- cdef int default_used = 0
158- cdef bint strict_types = self .strict_types
154+ cdef bool strict_types = self .strict_types
159155 cdef Py_buffer view
160156
161- if nest_limit < 0 :
162- raise ValueError (" recursion limit exceeded." )
163-
164- while True :
165- if o is None :
166- msgpack_pack_nil(& self .pk)
167- elif o is True :
168- msgpack_pack_true(& self .pk)
169- elif o is False :
170- msgpack_pack_false(& self .pk)
171- elif PyLong_CheckExact(o) if strict_types else PyLong_Check(o):
172- # PyInt_Check(long) is True for Python 3.
173- # So we should test long before int.
174- try :
175- if o > 0 :
176- ullval = o
177- msgpack_pack_unsigned_long_long(& self .pk, ullval)
178- else :
179- llval = o
180- msgpack_pack_long_long(& self .pk, llval)
181- except OverflowError as oe:
182- if not default_used and self ._default is not None :
183- o = self ._default(o)
184- default_used = True
185- continue
186- else :
187- raise OverflowError (" Integer value out of range" )
188- elif PyFloat_CheckExact(o) if strict_types else PyFloat_Check(o):
189- if self .use_float:
190- fval = o
191- msgpack_pack_float(& self .pk, fval)
157+ if o is None :
158+ msgpack_pack_nil(& self .pk)
159+ elif o is True :
160+ msgpack_pack_true(& self .pk)
161+ elif o is False :
162+ msgpack_pack_false(& self .pk)
163+ elif PyLong_CheckExact(o) if strict_types else PyLong_Check(o):
164+ try :
165+ if o > 0 :
166+ ullval = o
167+ msgpack_pack_unsigned_long_long(& self .pk, ullval)
168+ else :
169+ llval = o
170+ msgpack_pack_long_long(& self .pk, llval)
171+ except OverflowError as oe:
172+ if will_default:
173+ return - 2
192174 else :
193- dval = o
194- msgpack_pack_double(& self .pk, dval)
195- elif PyBytesLike_CheckExact(o) if strict_types else PyBytesLike_Check(o):
175+ raise OverflowError (" Integer value out of range" )
176+ elif PyFloat_CheckExact(o) if strict_types else PyFloat_Check(o):
177+ if self .use_float:
178+ fval = o
179+ msgpack_pack_float(& self .pk, fval)
180+ else :
181+ dval = o
182+ msgpack_pack_double(& self .pk, dval)
183+ elif PyBytesLike_CheckExact(o) if strict_types else PyBytesLike_Check(o):
184+ L = Py_SIZE(o)
185+ if L > ITEM_LIMIT:
186+ PyErr_Format(ValueError , b" %.200s object is too large" , Py_TYPE(o).tp_name)
187+ return - 1
188+ rawval = o
189+ msgpack_pack_bin(& self .pk, L)
190+ msgpack_pack_raw_body(& self .pk, rawval, L)
191+ elif PyUnicode_CheckExact(o) if strict_types else PyUnicode_Check(o):
192+ if self .unicode_errors == NULL :
193+ rawval = PyUnicode_AsUTF8AndSize(o, & L)
194+ if L > ITEM_LIMIT:
195+ raise ValueError (" unicode string is too large" )
196+ else :
197+ o = PyUnicode_AsEncodedString(o, NULL , self .unicode_errors)
196198 L = Py_SIZE(o)
197199 if L > ITEM_LIMIT:
198- PyErr_Format( ValueError , b " %.200s object is too large" , Py_TYPE(o).tp_name )
200+ raise ValueError ( " unicode string is too large" )
199201 rawval = o
202+ msgpack_pack_raw(& self .pk, L)
203+ msgpack_pack_raw_body(& self .pk, rawval, L)
204+ elif PyDict_CheckExact(o) if strict_types else PyDict_Check(o):
205+ L = len (o)
206+ if L > ITEM_LIMIT:
207+ raise ValueError (" dict is too large" )
208+ msgpack_pack_map(& self .pk, L)
209+ for k, v in o.items():
210+ self ._pack(k, nest_limit)
211+ self ._pack(v, nest_limit)
212+ elif type (o) is ExtType if strict_types else isinstance (o, ExtType):
213+ # This should be before Tuple because ExtType is namedtuple.
214+ longval = o.code
215+ rawval = o.data
216+ L = len (o.data)
217+ if L > ITEM_LIMIT:
218+ raise ValueError (" EXT data is too large" )
219+ msgpack_pack_ext(& self .pk, longval, L)
220+ msgpack_pack_raw_body(& self .pk, rawval, L)
221+ elif type (o) is Timestamp:
222+ llval = o.seconds
223+ ulval = o.nanoseconds
224+ msgpack_pack_timestamp(& self .pk, llval, ulval)
225+ elif PyList_CheckExact(o) if strict_types else (PyTuple_Check(o) or PyList_Check(o)):
226+ L = Py_SIZE(o)
227+ if L > ITEM_LIMIT:
228+ raise ValueError (" list is too large" )
229+ msgpack_pack_array(& self .pk, L)
230+ for v in o:
231+ self ._pack(v, nest_limit)
232+ elif PyMemoryView_Check(o):
233+ PyObject_GetBuffer(o, & view, PyBUF_SIMPLE)
234+ L = view.len
235+ if L > ITEM_LIMIT:
236+ PyBuffer_Release(& view);
237+ raise ValueError (" memoryview is too large" )
238+ try :
200239 msgpack_pack_bin(& self .pk, L)
201- msgpack_pack_raw_body(& self .pk, rawval, L)
202- elif PyUnicode_CheckExact(o) if strict_types else PyUnicode_Check(o):
203- if self .unicode_errors == NULL :
204- ret = msgpack_pack_unicode(& self .pk, o, ITEM_LIMIT);
205- if ret == - 2 :
206- raise ValueError (" unicode string is too large" )
207- else :
208- o = PyUnicode_AsEncodedString(o, NULL , self .unicode_errors)
209- L = Py_SIZE(o)
210- if L > ITEM_LIMIT:
211- raise ValueError (" unicode string is too large" )
212- msgpack_pack_raw(& self .pk, L)
213- rawval = o
214- msgpack_pack_raw_body(& self .pk, rawval, L)
215- elif PyDict_CheckExact(o):
216- d = < dict > o
217- L = len (d)
218- if L > ITEM_LIMIT:
219- raise ValueError (" dict is too large" )
220- msgpack_pack_map(& self .pk, L)
221- for k, v in d.items():
222- self ._pack(k, nest_limit- 1 )
223- self ._pack(v, nest_limit- 1 )
224- elif not strict_types and PyDict_Check(o):
225- L = len (o)
226- if L > ITEM_LIMIT:
227- raise ValueError (" dict is too large" )
228- msgpack_pack_map(& self .pk, L)
229- for k, v in o.items():
230- self ._pack(k, nest_limit- 1 )
231- self ._pack(v, nest_limit- 1 )
232- elif type (o) is ExtType if strict_types else isinstance (o, ExtType):
233- # This should be before Tuple because ExtType is namedtuple.
234- longval = o.code
235- rawval = o.data
236- L = len (o.data)
237- if L > ITEM_LIMIT:
238- raise ValueError (" EXT data is too large" )
239- msgpack_pack_ext(& self .pk, longval, L)
240- msgpack_pack_raw_body(& self .pk, rawval, L)
241- elif type (o) is Timestamp:
242- llval = o.seconds
243- ulval = o.nanoseconds
244- msgpack_pack_timestamp(& self .pk, llval, ulval)
245- elif PyList_CheckExact(o) if strict_types else (PyTuple_Check(o) or PyList_Check(o)):
246- L = Py_SIZE(o)
247- if L > ITEM_LIMIT:
248- raise ValueError (" list is too large" )
249- msgpack_pack_array(& self .pk, L)
250- for v in o:
251- ret = self ._pack(v, nest_limit- 1 )
252- elif PyMemoryView_Check(o):
253- PyObject_GetBuffer(o, & view, PyBUF_SIMPLE)
254- L = view.len
255- if L > ITEM_LIMIT:
256- PyBuffer_Release(& view);
257- raise ValueError (" memoryview is too large" )
258- try :
259- msgpack_pack_bin(& self .pk, L)
260- msgpack_pack_raw_body(& self .pk, < char * > view.buf, L)
261- finally :
262- PyBuffer_Release(& view);
263- elif self .datetime and PyDateTime_CheckExact(o) and datetime_tzinfo(o) is not None :
264- delta = o - epoch
265- if not PyDelta_CheckExact(delta):
266- raise ValueError (" failed to calculate delta" )
267- llval = timedelta_days(delta) * < long long > (24 * 60 * 60 ) + timedelta_seconds(delta)
268- ulval = timedelta_microseconds(delta) * 1000
269- msgpack_pack_timestamp(& self .pk, llval, ulval)
270- elif not default_used and self ._default:
240+ msgpack_pack_raw_body(& self .pk, < char * > view.buf, L)
241+ finally :
242+ PyBuffer_Release(& view);
243+ elif self .datetime and PyDateTime_CheckExact(o) and datetime_tzinfo(o) is not None :
244+ delta = o - epoch
245+ if not PyDelta_CheckExact(delta):
246+ raise ValueError (" failed to calculate delta" )
247+ llval = timedelta_days(delta) * < long long > (24 * 60 * 60 ) + timedelta_seconds(delta)
248+ ulval = timedelta_microseconds(delta) * 1000
249+ msgpack_pack_timestamp(& self .pk, llval, ulval)
250+ elif will_default:
251+ return - 2
252+ elif self .datetime and PyDateTime_CheckExact(o):
253+ # this should be later than will_default
254+ PyErr_Format(ValueError , b" can not serialize '%.200s ' object where tzinfo=None" , Py_TYPE(o).tp_name)
255+ return - 1
256+ else :
257+ PyErr_Format(TypeError , b" can not serialize '%.200s ' object" , Py_TYPE(o).tp_name)
258+ return - 1
259+
260+ cdef int _pack(self , object o, int nest_limit = DEFAULT_RECURSE_LIMIT) except - 1 :
261+ cdef int ret
262+ if nest_limit < 0 :
263+ raise ValueError (" recursion limit exceeded." )
264+ nest_limit -= 1
265+ if self ._default is not None :
266+ ret = self ._pack_inner(o, 1 , nest_limit)
267+ if ret == - 2 :
271268 o = self ._default(o)
272- default_used = 1
273- continue
274- elif self .datetime and PyDateTime_CheckExact(o):
275- PyErr_Format(ValueError , b" can not serialize '%.200s ' object where tzinfo=None" , Py_TYPE(o).tp_name)
276269 else :
277- PyErr_Format( TypeError , b " can not serialize ' %.200s ' object " , Py_TYPE(o).tp_name)
278- return ret
270+ return ret
271+ return self ._pack_inner(o, 0 , nest_limit)
279272
280273 cpdef pack(self , object obj):
281274 cdef int ret
0 commit comments