diff --git a/capnp/helpers/helpers.pxd b/capnp/helpers/helpers.pxd index 9cdf503..69c0a01 100644 --- a/capnp/helpers/helpers.pxd +++ b/capnp/helpers/helpers.pxd @@ -1,5 +1,7 @@ from .capnp.includes.capnp_cpp cimport Maybe, DynamicStruct, Request, PyPromise, VoidPromise, PyPromiseArray, RemotePromise, DynamicCapability, InterfaceSchema, EnumSchema, StructSchema, DynamicValue, Capability, RpcSystem, MessageBuilder, MessageReader, TwoPartyVatNetwork, PyRestorer, AnyPointer, DynamicStruct_Builder +from .capnp.includes.schema_cpp cimport ByteArray + from non_circular cimport reraise_kj_exception from cpython.ref cimport PyObject @@ -30,3 +32,6 @@ cdef extern from "../helpers/rpcHelper.h": Capability.Client restoreHelper(RpcSystem&, AnyPointer.Reader&) Capability.Client restoreHelper(RpcSystem&, AnyPointer.Builder&) RpcSystem makeRpcClientWithRestorer(TwoPartyVatNetwork&, PyRestorer&) + +cdef extern from "../helpers/serialize.h": + ByteArray messageToPackedBytes(MessageBuilder &) \ No newline at end of file diff --git a/capnp/helpers/serialize.h b/capnp/helpers/serialize.h new file mode 100644 index 0000000..8393c7d --- /dev/null +++ b/capnp/helpers/serialize.h @@ -0,0 +1,20 @@ +#pragma once + +#include "kj/io.h" +#include "capnp/dynamic.h" +#include "capnp/serialize-packed.h" + +kj::Array< ::capnp::byte> messageToPackedBytes(capnp::MessageBuilder & message) +{ + auto segments = message.getSegmentsForOutput(); + size_t totalSize = segments.size() / 2 + 1; + + for (auto& segment: segments) { + totalSize += segment.size(); + } + + kj::Array result = kj::heapArray(totalSize * 8); + kj::ArrayOutputStream out(result.asPtr()); + capnp::writePackedMessage(out, message); + return heapArray(out.getArray()); // TODO: make this non-copying somehow +} \ No newline at end of file diff --git a/capnp/includes/schema_cpp.pxd b/capnp/includes/schema_cpp.pxd index 2c06ed2..1e75042 100644 --- a/capnp/includes/schema_cpp.pxd +++ b/capnp/includes/schema_cpp.pxd @@ -716,6 +716,9 @@ cdef extern from "kj/array.h" namespace " ::kj": cdef cppclass WordArray " ::kj::Array< ::capnp::word>": word* begin() size_t size() + cdef cppclass ByteArray " ::kj::Array< ::capnp::byte>": + char* begin() + size_t size() cdef extern from "kj/array.h" namespace " ::kj": cdef cppclass InputStream: diff --git a/capnp/lib/capnp.pyx b/capnp/lib/capnp.pyx index a169864..6e840a1 100644 --- a/capnp/lib/capnp.pyx +++ b/capnp/lib/capnp.pyx @@ -940,7 +940,11 @@ cdef class _DynamicStructBuilder: cpdef to_bytes_packed(_DynamicStructBuilder self) except +reraise_kj_exception: self._check_write() cdef _MessageBuilder builder = self._parent - return _message_to_packed_bytes(builder) + array = helpers.messageToPackedBytes(deref(builder.thisptr)) + cdef const char* ptr = array.begin() + cdef bytes ret = ptr[:array.size()] + self._is_written = True + return ret cdef _get(self, field): cdef C_DynamicValue.Builder value = self.thisptr.get(field)