@@ -5,8 +5,11 @@ from cpython cimport *
55from libc.stdlib cimport *
66from libc.string cimport *
77from libc.limits cimport *
8+ from libc.stdint cimport int8_t
89
910from msgpack.exceptions import PackValueError
11+ from msgpack import ExtType
12+
1013
1114cdef extern from " pack.h" :
1215 struct msgpack_packer:
@@ -29,11 +32,11 @@ cdef extern from "pack.h":
2932 int msgpack_pack_raw(msgpack_packer* pk, size_t l)
3033 int msgpack_pack_bin(msgpack_packer* pk, size_t l)
3134 int msgpack_pack_raw_body(msgpack_packer* pk, char * body, size_t l)
35+ int msgpack_pack_ext(msgpack_packer* pk, int8_t typecode, size_t l)
3236
3337cdef int DEFAULT_RECURSE_LIMIT= 511
3438
3539
36-
3740cdef class Packer(object ):
3841 """
3942 MessagePack Packer
@@ -118,77 +121,87 @@ cdef class Packer(object):
118121 cdef int ret
119122 cdef dict d
120123 cdef size_t L
124+ cdef int default_used = 0
121125
122126 if nest_limit < 0 :
123127 raise PackValueError(" recursion limit exceeded." )
124128
125- if o is None :
126- ret = msgpack_pack_nil(& self .pk)
127- elif isinstance (o, bool ):
128- if o:
129- ret = msgpack_pack_true(& self .pk)
130- else :
131- ret = msgpack_pack_false(& self .pk)
132- elif PyLong_Check(o):
133- if o > 0 :
134- ullval = o
135- ret = msgpack_pack_unsigned_long_long(& self .pk, ullval)
136- else :
137- llval = o
138- ret = msgpack_pack_long_long(& self .pk, llval)
139- elif PyInt_Check(o):
140- longval = o
141- ret = msgpack_pack_long(& self .pk, longval)
142- elif PyFloat_Check(o):
143- if self .use_float:
144- fval = o
145- ret = msgpack_pack_float(& self .pk, fval)
146- else :
147- dval = o
148- ret = msgpack_pack_double(& self .pk, dval)
149- elif PyBytes_Check(o):
150- rawval = o
151- L = len (o)
152- ret = msgpack_pack_bin(& self .pk, L)
153- if ret == 0 :
129+ while True :
130+ if o is None :
131+ ret = msgpack_pack_nil(& self .pk)
132+ elif isinstance (o, bool ):
133+ if o:
134+ ret = msgpack_pack_true(& self .pk)
135+ else :
136+ ret = msgpack_pack_false(& self .pk)
137+ elif PyLong_Check(o):
138+ if o > 0 :
139+ ullval = o
140+ ret = msgpack_pack_unsigned_long_long(& self .pk, ullval)
141+ else :
142+ llval = o
143+ ret = msgpack_pack_long_long(& self .pk, llval)
144+ elif PyInt_Check(o):
145+ longval = o
146+ ret = msgpack_pack_long(& self .pk, longval)
147+ elif PyFloat_Check(o):
148+ if self .use_float:
149+ fval = o
150+ ret = msgpack_pack_float(& self .pk, fval)
151+ else :
152+ dval = o
153+ ret = msgpack_pack_double(& self .pk, dval)
154+ elif PyBytes_Check(o):
155+ rawval = o
156+ L = len (o)
157+ ret = msgpack_pack_bin(& self .pk, L)
158+ if ret == 0 :
159+ ret = msgpack_pack_raw_body(& self .pk, rawval, L)
160+ elif PyUnicode_Check(o):
161+ if not self .encoding:
162+ raise TypeError (" Can't encode unicode string: no encoding is specified" )
163+ o = PyUnicode_AsEncodedString(o, self .encoding, self .unicode_errors)
164+ rawval = o
165+ ret = msgpack_pack_raw(& self .pk, len (o))
166+ if ret == 0 :
167+ ret = msgpack_pack_raw_body(& self .pk, rawval, len (o))
168+ elif PyDict_CheckExact(o):
169+ d = < dict > o
170+ ret = msgpack_pack_map(& self .pk, len (d))
171+ if ret == 0 :
172+ for k, v in d.iteritems():
173+ ret = self ._pack(k, nest_limit- 1 )
174+ if ret != 0 : break
175+ ret = self ._pack(v, nest_limit- 1 )
176+ if ret != 0 : break
177+ elif PyDict_Check(o):
178+ ret = msgpack_pack_map(& self .pk, len (o))
179+ if ret == 0 :
180+ for k, v in o.items():
181+ ret = self ._pack(k, nest_limit- 1 )
182+ if ret != 0 : break
183+ ret = self ._pack(v, nest_limit- 1 )
184+ if ret != 0 : break
185+ elif isinstance (o, ExtType):
186+ # This should be before Tuple because ExtType is namedtuple.
187+ longval = o.code
188+ rawval = o.data
189+ L = len (o.data)
190+ ret = msgpack_pack_ext(& self .pk, longval, L)
154191 ret = msgpack_pack_raw_body(& self .pk, rawval, L)
155- elif PyUnicode_Check(o):
156- if not self .encoding:
157- raise TypeError (" Can't encode unicode string: no encoding is specified" )
158- o = PyUnicode_AsEncodedString(o, self .encoding, self .unicode_errors)
159- rawval = o
160- ret = msgpack_pack_raw(& self .pk, len (o))
161- if ret == 0 :
162- ret = msgpack_pack_raw_body(& self .pk, rawval, len (o))
163- elif PyDict_CheckExact(o):
164- d = < dict > o
165- ret = msgpack_pack_map(& self .pk, len (d))
166- if ret == 0 :
167- for k, v in d.iteritems():
168- ret = self ._pack(k, nest_limit- 1 )
169- if ret != 0 : break
170- ret = self ._pack(v, nest_limit- 1 )
171- if ret != 0 : break
172- elif PyDict_Check(o):
173- ret = msgpack_pack_map(& self .pk, len (o))
174- if ret == 0 :
175- for k, v in o.items():
176- ret = self ._pack(k, nest_limit- 1 )
177- if ret != 0 : break
178- ret = self ._pack(v, nest_limit- 1 )
179- if ret != 0 : break
180- elif PyTuple_Check(o) or PyList_Check(o):
181- ret = msgpack_pack_array(& self .pk, len (o))
182- if ret == 0 :
183- for v in o:
184- ret = self ._pack(v, nest_limit- 1 )
185- if ret != 0 : break
186- elif self ._default:
187- o = self ._default(o)
188- ret = self ._pack(o, nest_limit- 1 )
189- else :
190- raise TypeError (" can't serialize %r " % (o,))
191- return ret
192+ elif PyTuple_Check(o) or PyList_Check(o):
193+ ret = msgpack_pack_array(& self .pk, len (o))
194+ if ret == 0 :
195+ for v in o:
196+ ret = self ._pack(v, nest_limit- 1 )
197+ if ret != 0 : break
198+ elif not default_used and self ._default:
199+ o = self ._default(o)
200+ default_used = 1
201+ continue
202+ else :
203+ raise TypeError (" can't serialize %r " % (o,))
204+ return ret
192205
193206 cpdef pack(self , object obj):
194207 cdef int ret
@@ -202,6 +215,10 @@ cdef class Packer(object):
202215 self .pk.length = 0
203216 return buf
204217
218+ def pack_ext_type (self , typecode , data ):
219+ msgpack_pack_ext(& self .pk, typecode, len (data))
220+ msgpack_pack_raw_body(& self .pk, data, len (data))
221+
205222 def pack_array_header (self , size_t size ):
206223 cdef int ret = msgpack_pack_array(& self .pk, size)
207224 if ret == - 1 :
0 commit comments