summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorINADA Naoki <songofacandy@gmail.com>2013-10-17 11:29:36 +0900
committerINADA Naoki <songofacandy@gmail.com>2013-10-17 11:29:36 +0900
commitd9439204c77a0ab58248c0b78237f16c4496647c (patch)
treef584032fb92cd7f19d15df089dcca4b6e977f0bf
parentf162bf6f79d7a50e10530e42630b063af3bb8eb1 (diff)
downloadmsgpack-python-d9439204c77a0ab58248c0b78237f16c4496647c.tar.gz
Add ext type support to fallback.Unpacker.
-rw-r--r--msgpack/__init__.py4
-rw-r--r--msgpack/fallback.py72
2 files changed, 60 insertions, 16 deletions
diff --git a/msgpack/__init__.py b/msgpack/__init__.py
index 7f0519e..79107b6 100644
--- a/msgpack/__init__.py
+++ b/msgpack/__init__.py
@@ -2,6 +2,10 @@
from msgpack._version import version
from msgpack.exceptions import *
+from collections import namedtuple
+
+ExtType = namedtuple('ExtType', 'code data')
+
import os
if os.environ.get('MSGPACK_PUREPYTHON'):
from msgpack.fallback import Packer, unpack, unpackb, Unpacker
diff --git a/msgpack/fallback.py b/msgpack/fallback.py
index 901c6c8..074fcba 100644
--- a/msgpack/fallback.py
+++ b/msgpack/fallback.py
@@ -48,6 +48,9 @@ from msgpack.exceptions import (
PackValueError,
ExtraData)
+from msgpack import ExtType
+
+
EX_SKIP = 0
EX_CONSTRUCT = 1
EX_READ_ARRAY_HEADER = 2
@@ -58,8 +61,9 @@ TYPE_ARRAY = 1
TYPE_MAP = 2
TYPE_RAW = 3
TYPE_BIN = 4
+TYPE_EXT = 5
-DEFAULT_RECURSE_LIMIT=511
+DEFAULT_RECURSE_LIMIT = 511
def unpack(stream, **kwargs):
"""
@@ -112,6 +116,9 @@ class Unpacker(object):
should be callable and Unpacker calls it with a list of key-value pairs
after deserializing a map.
+ `ext_hook` is callback for ext (User defined) type. It called with two
+ arguments: (code, bytes). default: `msgpack.ExtType`
+
`encoding` is the encoding used for decoding msgpack bytes. If it is
None (default), msgpack bytes are deserialized to Python bytes.
@@ -143,7 +150,8 @@ class Unpacker(object):
def __init__(self, file_like=None, read_size=0, use_list=True,
object_hook=None, object_pairs_hook=None, list_hook=None,
- encoding=None, unicode_errors='strict', max_buffer_size=0):
+ encoding=None, unicode_errors='strict', max_buffer_size=0,
+ ext_hook=ExtType):
if file_like is None:
self._fb_feeding = True
else:
@@ -167,6 +175,7 @@ class Unpacker(object):
self._list_hook = list_hook
self._object_hook = object_hook
self._object_pairs_hook = object_pairs_hook
+ self._ext_hook = ext_hook
if list_hook is not None and not callable(list_hook):
raise ValueError('`list_hook` is not callable')
@@ -177,6 +186,8 @@ class Unpacker(object):
if object_hook is not None and object_pairs_hook is not None:
raise ValueError("object_pairs_hook and object_hook are mutually "
"exclusive")
+ if not callable(ext_hook):
+ raise ValueError("`ext_hook` is not callable")
def feed(self, next_bytes):
if isinstance(next_bytes, array.array):
@@ -278,6 +289,30 @@ class Unpacker(object):
obj = False
elif b == 0xc3:
obj = True
+ elif b == 0xc4:
+ typ = TYPE_BIN
+ n = struct.unpack("B", self._fb_read(1, write_bytes))[0]
+ obj = self._fb_read(n, write_bytes)
+ elif b == 0xc5:
+ typ = TYPE_BIN
+ n = struct.unpack(">H", self._fb_read(2, write_bytes))[0]
+ obj = self._fb_read(n, write_bytes)
+ elif b == 0xc6:
+ typ = TYPE_BIN
+ n = struct.unpack(">I", self._fb_read(4, write_bytes))[0]
+ obj = self._fb_read(n, write_bytes)
+ elif b == 0xc7: # ext 8
+ typ = TYPE_EXT
+ L, n = struct.unpack('Bb', self._fb_read(2, write_bytes))
+ obj = self._fb_read(L, write_bytes)
+ elif b == 0xc8: # ext 16
+ typ = TYPE_EXT
+ L, n = struct.unpack('>Hb', self._fb_read(3, write_bytes))
+ obj = self._fb_read(L, write_bytes)
+ elif b == 0xc9: # ext 32
+ typ = TYPE_EXT
+ L, n = struct.unpack('>Ib', self._fb_read(5, write_bytes))
+ obj = self._fb_read(L, write_bytes)
elif b == 0xca:
obj = struct.unpack(">f", self._fb_read(4, write_bytes))[0]
elif b == 0xcb:
@@ -298,30 +333,33 @@ class Unpacker(object):
obj = struct.unpack(">i", self._fb_read(4, write_bytes))[0]
elif b == 0xd3:
obj = struct.unpack(">q", self._fb_read(8, write_bytes))[0]
+ elif b == 0xd4: # fixext 1
+ typ = TYPE_EXT
+ n, obj = struct.unpack('b1s', self._fb_read(2, write_bytes))
+ elif b == 0xd5: # fixext 2
+ typ = TYPE_EXT
+ n, obj = struct.unpack('b2s', self._fb_read(3, write_bytes))
+ elif b == 0xd6: # fixext 4
+ typ = TYPE_EXT
+ n, obj = struct.unpack('b4s', self._fb_read(5, write_bytes))
+ elif b == 0xd7: # fixext 8
+ typ = TYPE_EXT
+ n, obj = struct.unpack('b8s', self._fb_read(9, write_bytes))
+ elif b == 0xd8: # fixext 16
+ typ = TYPE_EXT
+ n, obj = struct.unpack('b16s', self._fb_read(17, write_bytes))
elif b == 0xd9:
+ typ = TYPE_RAW
n = struct.unpack("B", self._fb_read(1, write_bytes))[0]
obj = self._fb_read(n, write_bytes)
- typ = TYPE_RAW
elif b == 0xda:
+ typ = TYPE_RAW
n = struct.unpack(">H", self._fb_read(2, write_bytes))[0]
obj = self._fb_read(n, write_bytes)
- typ = TYPE_RAW
elif b == 0xdb:
- n = struct.unpack(">I", self._fb_read(4, write_bytes))[0]
- obj = self._fb_read(n, write_bytes)
typ = TYPE_RAW
- elif b == 0xc4:
- n = struct.unpack("B", self._fb_read(1, write_bytes))[0]
- obj = self._fb_read(n, write_bytes)
- typ = TYPE_BIN
- elif b == 0xc5:
- n = struct.unpack(">H", self._fb_read(2, write_bytes))[0]
- obj = self._fb_read(n, write_bytes)
- typ = TYPE_BIN
- elif b == 0xc6:
n = struct.unpack(">I", self._fb_read(4, write_bytes))[0]
obj = self._fb_read(n, write_bytes)
- typ = TYPE_BIN
elif b == 0xdc:
n = struct.unpack(">H", self._fb_read(2, write_bytes))[0]
typ = TYPE_ARRAY
@@ -390,6 +428,8 @@ class Unpacker(object):
if self._encoding is not None:
obj = obj.decode(self._encoding, self._unicode_errors)
return obj
+ if typ == TYPE_EXT:
+ return self._ext_hook(n, obj)
if typ == TYPE_BIN:
return obj
assert typ == TYPE_IMMEDIATE