automatically find the best format to encode extended types

This commit is contained in:
Antonio Cuni 2013-10-18 15:45:50 +02:00
parent 522c4bfc79
commit c727440ba5
2 changed files with 38 additions and 8 deletions

View file

@ -545,13 +545,29 @@ class Packer(object):
# overridden by subclasses # overridden by subclasses
return None return None
def pack_extended_type(self, fmt, typecode, data): def pack_extended_type(self, typecode, data):
# for now we support only this. We should add support for the other
# fixext/ext formats
assert fmt == "ext 32"
assert 0 <= typecode <= 127 assert 0 <= typecode <= 127
N = len(data) n = len(data)
self._buffer.write(struct.pack('>BIB', 0xc9, N, typecode)) if n == 1:
header = struct.pack(">BB", 0xd4, typecode) # fixext 1
elif n == 2:
header = struct.pack(">BB", 0xd5, typecode) # fixext 2
elif n == 4:
header = struct.pack(">BB", 0xd6, typecode) # fixext 4
elif n == 8:
header = struct.pack(">BB", 0xd7, typecode) # fixext 8
elif n == 16:
header = struct.pack(">BB", 0xd8, typecode) # fixext 16
elif n <= 2**8-1:
header = struct.pack(">BBB", 0xc7, n, typecode) # ext 8
elif n <= 2**16-1:
header = struct.pack(">BHB", 0xc8, n, typecode) # ext 16
elif n <= 2**32-1:
header = struct.pack(">BIB", 0xc9, n, typecode) # ext 32
else:
raise PackValueError("ext data too large")
#
self._buffer.write(header)
self._buffer.write(data) self._buffer.write(data)
def pack(self, obj): def pack(self, obj):

View file

@ -1,14 +1,28 @@
import array import array
import struct
import msgpack import msgpack
def test_pack_extended_type():
def p(s):
packer = msgpack.Packer()
packer.pack_extended_type(0x42, s)
return packer._buffer.getvalue()
assert p('A') == '\xd4\x42A' # fixext 1
assert p('AB') == '\xd5\x42AB' # fixext 2
assert p('ABCD') == '\xd6\x42ABCD' # fixext 4
assert p('ABCDEFGH') == '\xd7\x42ABCDEFGH' # fixext 8
assert p('A'*16) == '\xd8\x42' + 'A'*16 # fixext 16
assert p('ABC') == '\xc7\x03\x42ABC' # ext 8
assert p('A'*0x0123) == '\xc8\x01\x23\x42' + 'A'*0x0123 # ext 16
assert p('A'*0x00012345) == '\xc9\x00\x01\x23\x45\x42' + 'A'*0x00012345 # ext 32
def test_extension_type(): def test_extension_type():
class MyPacker(msgpack.Packer): class MyPacker(msgpack.Packer):
def handle_unknown_type(self, obj): def handle_unknown_type(self, obj):
if isinstance(obj, array.array): if isinstance(obj, array.array):
fmt = "ext 32"
typecode = 123 # application specific typecode typecode = 123 # application specific typecode
data = obj.tostring() data = obj.tostring()
self.pack_extended_type(fmt, typecode, data) self.pack_extended_type(typecode, data)
return True return True
class MyUnpacker(msgpack.Unpacker): class MyUnpacker(msgpack.Unpacker):