diff options
author | folz <joachim.folz@dfki.de> | 2015-11-12 11:49:19 +0100 |
---|---|---|
committer | folz <joachim.folz@dfki.de> | 2016-01-25 13:25:10 +0100 |
commit | 31adc5a3c09a5f3506db192e1fb8b7ca4b72d974 (patch) | |
tree | 69574385716479ace1e9c76235ca96b75d887aa3 | |
parent | 8036cb4e0e8e971c4396b5a8162aeff5b3459aa5 (diff) | |
download | msgpack-python-31adc5a3c09a5f3506db192e1fb8b7ca4b72d974.tar.gz |
Support packing memoryview objects
-rw-r--r-- | msgpack/_packer.pyx | 17 | ||||
-rw-r--r-- | msgpack/fallback.py | 6 | ||||
-rw-r--r-- | test/test_memoryview.py | 12 |
3 files changed, 33 insertions, 2 deletions
diff --git a/msgpack/_packer.pyx b/msgpack/_packer.pyx index c3ef1a4..b19d462 100644 --- a/msgpack/_packer.pyx +++ b/msgpack/_packer.pyx @@ -10,6 +10,11 @@ from msgpack.exceptions import PackValueError from msgpack import ExtType +cdef extern from "Python.h": + + int PyMemoryView_Check(object obj) + + cdef extern from "pack.h": struct msgpack_packer: char* buf @@ -132,6 +137,7 @@ cdef class Packer(object): cdef size_t L cdef int default_used = 0 cdef bint strict_types = self.strict_types + cdef Py_buffer view if nest_limit < 0: raise PackValueError("recursion limit exceeded.") @@ -231,6 +237,17 @@ cdef class Packer(object): for v in o: ret = self._pack(v, nest_limit-1) if ret != 0: break + elif PyMemoryView_Check(o): + if PyObject_GetBuffer(o, &view, PyBUF_SIMPLE) != 0: + raise ValueError("could not get buffer for memoryview") + L = view.len + if L > (2**32)-1: + PyBuffer_Release(&view); + raise ValueError("memoryview is too large") + ret = msgpack_pack_bin(&self.pk, L) + if ret == 0: + ret = msgpack_pack_raw_body(&self.pk, <char*>view.buf, L) + PyBuffer_Release(&view); elif not default_used and self._default: o = self._default(o) default_used = 1 diff --git a/msgpack/fallback.py b/msgpack/fallback.py index 40c54a8..348e017 100644 --- a/msgpack/fallback.py +++ b/msgpack/fallback.py @@ -36,6 +36,8 @@ if hasattr(sys, 'pypy_version_info'): else: self.builder = StringBuilder() def write(self, s): + if isinstance(s, memoryview): + s = s.tobytes() self.builder.append(s) def getvalue(self): return self.builder.build() @@ -682,7 +684,7 @@ class Packer(object): default_used = True continue raise PackValueError("Integer value out of range") - if self._use_bin_type and check(obj, bytes): + if self._use_bin_type and check(obj, (bytes, memoryview)): n = len(obj) if n <= 0xff: self._buffer.write(struct.pack('>BB', 0xc4, n)) @@ -693,7 +695,7 @@ class Packer(object): else: raise PackValueError("Bytes is too large") return self._buffer.write(obj) - if check(obj, (Unicode, bytes)): + if check(obj, (Unicode, bytes, memoryview)): if check(obj, Unicode): if self._encoding is None: raise TypeError( diff --git a/test/test_memoryview.py b/test/test_memoryview.py new file mode 100644 index 0000000..aed5069 --- /dev/null +++ b/test/test_memoryview.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python +# coding: utf-8 + + +from msgpack import packb, unpackb + + +def test_pack_memoryview(): + data = bytearray(range(256)) + view = memoryview(data) + unpacked = unpackb(packb(view)) + assert data == unpacked |