@@ -38,7 +38,6 @@ cdef extern from "pack.h":
38
38
int msgpack_pack_raw_body(msgpack_packer* pk, char * body, size_t l) except - 1
39
39
int msgpack_pack_ext(msgpack_packer* pk, char typecode, size_t l) except - 1
40
40
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
42
41
43
42
44
43
cdef int DEFAULT_RECURSE_LIMIT= 511
@@ -143,139 +142,133 @@ cdef class Packer:
143
142
PyMem_Free(self .pk.buf)
144
143
self .pk.buf = NULL
145
144
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 :
147
146
cdef long long llval
148
147
cdef unsigned long long ullval
149
148
cdef unsigned long ulval
150
149
cdef long longval
151
150
cdef float fval
152
151
cdef double dval
153
- cdef char * rawval
154
- cdef int ret
155
- cdef dict d
152
+ cdef const char * rawval
156
153
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
159
155
cdef Py_buffer view
160
156
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
192
174
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)
196
198
L = Py_SIZE(o)
197
199
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" )
199
201
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 :
200
239
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 :
271
268
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)
276
269
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)
279
272
280
273
cpdef pack(self , object obj):
281
274
cdef int ret
0 commit comments