Support mmap objects for reading with from_bytes
This commit is contained in:
@@ -29,6 +29,7 @@ import threading as _threading
|
|||||||
import socket as _socket
|
import socket as _socket
|
||||||
import random as _random
|
import random as _random
|
||||||
import collections as _collections
|
import collections as _collections
|
||||||
|
import mmap as _mmap
|
||||||
|
|
||||||
_CAPNP_VERSION_MAJOR = capnp.CAPNP_VERSION_MAJOR
|
_CAPNP_VERSION_MAJOR = capnp.CAPNP_VERSION_MAJOR
|
||||||
_CAPNP_VERSION_MINOR = capnp.CAPNP_VERSION_MINOR
|
_CAPNP_VERSION_MINOR = capnp.CAPNP_VERSION_MINOR
|
||||||
@@ -277,6 +278,8 @@ ctypedef fused PromiseTypes:
|
|||||||
cdef extern from "Python.h":
|
cdef extern from "Python.h":
|
||||||
cdef int PyObject_AsReadBuffer(object, void** b, Py_ssize_t* c)
|
cdef int PyObject_AsReadBuffer(object, void** b, Py_ssize_t* c)
|
||||||
cdef int PyObject_AsWriteBuffer(object, void** b, Py_ssize_t* c)
|
cdef int PyObject_AsWriteBuffer(object, void** b, Py_ssize_t* c)
|
||||||
|
cdef int PyObject_GetBuffer(object, Py_buffer *view, int flags)
|
||||||
|
cdef void PyBuffer_Release(Py_buffer *view)
|
||||||
|
|
||||||
# Templated classes are weird in cython. I couldn't put it in a pxd header for some reason
|
# Templated classes are weird in cython. I couldn't put it in a pxd header for some reason
|
||||||
cdef extern from "capnp/list.h" namespace " ::capnp":
|
cdef extern from "capnp/list.h" namespace " ::capnp":
|
||||||
@@ -3682,6 +3685,19 @@ cdef class _AlignedBuffer:
|
|||||||
if self.allocated:
|
if self.allocated:
|
||||||
free(self.buf)
|
free(self.buf)
|
||||||
|
|
||||||
|
|
||||||
|
@cython.internal
|
||||||
|
cdef class _BufferView:
|
||||||
|
cdef Py_buffer view
|
||||||
|
cdef char * buf
|
||||||
|
|
||||||
|
def __init__(self, other):
|
||||||
|
PyObject_GetBuffer(other, &self.view, 0)
|
||||||
|
self.buf = <char*>self.view.buf
|
||||||
|
|
||||||
|
def __dealloc__(self):
|
||||||
|
PyBuffer_Release(&self.view)
|
||||||
|
|
||||||
@cython.internal
|
@cython.internal
|
||||||
cdef class _FlatArrayMessageReader(_MessageReader):
|
cdef class _FlatArrayMessageReader(_MessageReader):
|
||||||
cdef object _object_to_pin
|
cdef object _object_to_pin
|
||||||
@@ -3698,7 +3714,13 @@ cdef class _FlatArrayMessageReader(_MessageReader):
|
|||||||
if sz % 8 != 0:
|
if sz % 8 != 0:
|
||||||
raise ValueError("input length must be a multiple of eight bytes")
|
raise ValueError("input length must be a multiple of eight bytes")
|
||||||
|
|
||||||
cdef char * ptr = buf
|
cdef char * ptr
|
||||||
|
if type(buf) == _mmap.mmap:
|
||||||
|
view = _BufferView(buf)
|
||||||
|
ptr = <char*>view.view.buf
|
||||||
|
self._object_to_pin = view
|
||||||
|
else:
|
||||||
|
ptr = buf
|
||||||
if (<uintptr_t>ptr) % 8 != 0:
|
if (<uintptr_t>ptr) % 8 != 0:
|
||||||
aligned = _AlignedBuffer(buf)
|
aligned = _AlignedBuffer(buf)
|
||||||
ptr = aligned.buf
|
ptr = aligned.buf
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import platform
|
|||||||
import test_regression
|
import test_regression
|
||||||
import tempfile
|
import tempfile
|
||||||
import pickle
|
import pickle
|
||||||
|
import mmap
|
||||||
|
|
||||||
this_dir = os.path.dirname(__file__)
|
this_dir = os.path.dirname(__file__)
|
||||||
|
|
||||||
@@ -40,6 +41,20 @@ def test_roundtrip_bytes(all_types):
|
|||||||
msg = all_types.TestAllTypes.from_bytes(message_bytes)
|
msg = all_types.TestAllTypes.from_bytes(message_bytes)
|
||||||
test_regression.check_all_types(msg)
|
test_regression.check_all_types(msg)
|
||||||
|
|
||||||
|
def test_roundtrip_bytes_mmap(all_types):
|
||||||
|
msg = all_types.TestAllTypes.new_message()
|
||||||
|
test_regression.init_all_types(msg)
|
||||||
|
|
||||||
|
with tempfile.TemporaryFile() as f:
|
||||||
|
msg.write(f)
|
||||||
|
length = f.tell()
|
||||||
|
|
||||||
|
f.seek(0)
|
||||||
|
memory = mmap.mmap(f.fileno(), length)
|
||||||
|
|
||||||
|
msg = all_types.TestAllTypes.from_bytes(memory)
|
||||||
|
test_regression.check_all_types(msg)
|
||||||
|
|
||||||
def test_roundtrip_bytes_packed(all_types):
|
def test_roundtrip_bytes_packed(all_types):
|
||||||
msg = all_types.TestAllTypes.new_message()
|
msg = all_types.TestAllTypes.new_message()
|
||||||
test_regression.init_all_types(msg)
|
test_regression.init_all_types(msg)
|
||||||
|
|||||||
Reference in New Issue
Block a user