mirror of
https://github.com/msgpack/msgpack-python.git
synced 2025-10-27 07:34:11 +00:00
fallback: support packing ExtType
This commit is contained in:
parent
37c2ad63af
commit
e3fee4db5f
3 changed files with 131 additions and 81 deletions
|
|
@ -2,9 +2,31 @@
|
||||||
from msgpack._version import version
|
from msgpack._version import version
|
||||||
from msgpack.exceptions import *
|
from msgpack.exceptions import *
|
||||||
|
|
||||||
from collections import namedtuple
|
|
||||||
|
|
||||||
ExtType = namedtuple('ExtType', 'code data')
|
class ExtType(object):
|
||||||
|
__slots__ = ('code', 'data')
|
||||||
|
|
||||||
|
def __init__(self, code, data):
|
||||||
|
if not isinstance(code, int):
|
||||||
|
raise TypeError("code must be int")
|
||||||
|
if not isinstance(data, bytes):
|
||||||
|
raise TypeError("data must be bytes")
|
||||||
|
if not 0 <= code <= 127:
|
||||||
|
raise ValueError("code must be 0~127")
|
||||||
|
self.code = code
|
||||||
|
self.data = data
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
if not isinstance(other, ExtType):
|
||||||
|
return NotImplemented
|
||||||
|
return self.code == other.code and self.data == other.data
|
||||||
|
|
||||||
|
def __hash__(self):
|
||||||
|
return self.code ^ hash(self.data)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "msgpack.ExtType(%r, %r)" % (self.code, self.data)
|
||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
if os.environ.get('MSGPACK_PUREPYTHON'):
|
if os.environ.get('MSGPACK_PUREPYTHON'):
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,6 @@ cdef extern from "pack.h":
|
||||||
cdef int DEFAULT_RECURSE_LIMIT=511
|
cdef int DEFAULT_RECURSE_LIMIT=511
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cdef class Packer(object):
|
cdef class Packer(object):
|
||||||
"""
|
"""
|
||||||
MessagePack Packer
|
MessagePack Packer
|
||||||
|
|
@ -185,8 +184,8 @@ cdef class Packer(object):
|
||||||
if ret != 0: break
|
if ret != 0: break
|
||||||
elif isinstance(o, ExtType):
|
elif isinstance(o, ExtType):
|
||||||
# This should be before Tuple because ExtType is namedtuple.
|
# This should be before Tuple because ExtType is namedtuple.
|
||||||
longval = o[0]
|
longval = o.code
|
||||||
rawval = o[1]
|
rawval = o.data
|
||||||
L = len(o[1])
|
L = len(o[1])
|
||||||
ret = msgpack_pack_ext(&self.pk, longval, L)
|
ret = msgpack_pack_ext(&self.pk, longval, L)
|
||||||
ret = msgpack_pack_raw_body(&self.pk, rawval, L)
|
ret = msgpack_pack_raw_body(&self.pk, rawval, L)
|
||||||
|
|
|
||||||
|
|
@ -506,6 +506,8 @@ class Packer(object):
|
||||||
self._default = default
|
self._default = default
|
||||||
|
|
||||||
def _pack(self, obj, nest_limit=DEFAULT_RECURSE_LIMIT, isinstance=isinstance):
|
def _pack(self, obj, nest_limit=DEFAULT_RECURSE_LIMIT, isinstance=isinstance):
|
||||||
|
default_used = False
|
||||||
|
while True:
|
||||||
if nest_limit < 0:
|
if nest_limit < 0:
|
||||||
raise PackValueError("recursion limit exceeded")
|
raise PackValueError("recursion limit exceeded")
|
||||||
if obj is None:
|
if obj is None:
|
||||||
|
|
@ -570,6 +572,31 @@ class Packer(object):
|
||||||
if self._use_float:
|
if self._use_float:
|
||||||
return self._buffer.write(struct.pack(">Bf", 0xca, obj))
|
return self._buffer.write(struct.pack(">Bf", 0xca, obj))
|
||||||
return self._buffer.write(struct.pack(">Bd", 0xcb, obj))
|
return self._buffer.write(struct.pack(">Bd", 0xcb, obj))
|
||||||
|
if isinstance(obj, ExtType):
|
||||||
|
code = obj.code
|
||||||
|
data = obj.data
|
||||||
|
assert isinstance(code, int)
|
||||||
|
assert isinstance(data, bytes)
|
||||||
|
L = len(data)
|
||||||
|
if L == 1:
|
||||||
|
self._buffer.write(b'\xd4')
|
||||||
|
elif L == 2:
|
||||||
|
self._buffer.write(b'\xd5')
|
||||||
|
elif L == 4:
|
||||||
|
self._buffer.write(b'\xd6')
|
||||||
|
elif L == 8:
|
||||||
|
self._buffer.write(b'\xd7')
|
||||||
|
elif L == 16:
|
||||||
|
self._buffer.write(b'\xd8')
|
||||||
|
elif L <= 0xff:
|
||||||
|
self._buffer.write(struct.pack(">BB", 0xc7, L))
|
||||||
|
elif L <= 0xffff:
|
||||||
|
self._buffer.write(struct.pack(">BH", 0xc8, L))
|
||||||
|
else:
|
||||||
|
self._buffer.write(struct.pack(">BI", 0xc9, L))
|
||||||
|
self._buffer.write(struct.pack("b", code))
|
||||||
|
self._buffer.write(data)
|
||||||
|
return
|
||||||
if isinstance(obj, (list, tuple)):
|
if isinstance(obj, (list, tuple)):
|
||||||
n = len(obj)
|
n = len(obj)
|
||||||
self._fb_pack_array_header(n)
|
self._fb_pack_array_header(n)
|
||||||
|
|
@ -579,8 +606,10 @@ class Packer(object):
|
||||||
if isinstance(obj, dict):
|
if isinstance(obj, dict):
|
||||||
return self._fb_pack_map_pairs(len(obj), dict_iteritems(obj),
|
return self._fb_pack_map_pairs(len(obj), dict_iteritems(obj),
|
||||||
nest_limit - 1)
|
nest_limit - 1)
|
||||||
if self._default is not None:
|
if not default_used and self._default is not None:
|
||||||
return self._pack(self._default(obj), nest_limit - 1)
|
obj = self._default(obj)
|
||||||
|
default_used = 1
|
||||||
|
continue
|
||||||
raise TypeError("Cannot serialize %r" % obj)
|
raise TypeError("Cannot serialize %r" % obj)
|
||||||
|
|
||||||
def pack(self, obj):
|
def pack(self, obj):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue