@@ -5,8 +5,11 @@ from cpython cimport *
5
5
from libc.stdlib cimport *
6
6
from libc.string cimport *
7
7
from libc.limits cimport *
8
+ from libc.stdint cimport int8_t
8
9
9
10
from msgpack.exceptions import PackValueError
11
+ from msgpack import ExtType
12
+
10
13
11
14
cdef extern from " pack.h" :
12
15
struct msgpack_packer:
@@ -29,11 +32,11 @@ cdef extern from "pack.h":
29
32
int msgpack_pack_raw(msgpack_packer* pk, size_t l)
30
33
int msgpack_pack_bin(msgpack_packer* pk, size_t l)
31
34
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)
32
36
33
37
cdef int DEFAULT_RECURSE_LIMIT= 511
34
38
35
39
36
-
37
40
cdef class Packer(object ):
38
41
"""
39
42
MessagePack Packer
@@ -118,77 +121,87 @@ cdef class Packer(object):
118
121
cdef int ret
119
122
cdef dict d
120
123
cdef size_t L
124
+ cdef int default_used = 0
121
125
122
126
if nest_limit < 0 :
123
127
raise PackValueError(" recursion limit exceeded." )
124
128
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)
154
191
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
192
205
193
206
cpdef pack(self , object obj):
194
207
cdef int ret
@@ -202,6 +215,10 @@ cdef class Packer(object):
202
215
self .pk.length = 0
203
216
return buf
204
217
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
+
205
222
def pack_array_header (self , size_t size ):
206
223
cdef int ret = msgpack_pack_array(& self .pk, size)
207
224
if ret == - 1 :
0 commit comments