def dumps(obj): """ Dump a struct into a message, returned as a string of bytes. The message is encoded using the recommended capnp format for serializing messages over a stream. It always uses a single segment. """ if obj._is_compact(): # fast path. On CPython, the real speedup comes from the fact that we # do not create a temporary SegmentBuilder. The memcpy vs copy_pointer # difference seems negligible, for small objects at least. start = obj._data_offset end = obj._get_end() end = (end + (8 - 1)) & -8 # Round up to 8-byte boundary p = ptr.new_struct(0, obj._data_size, obj._ptrs_size) return obj._seg.dump_message(p, start, end) else: builder = SegmentBuilder() builder.allocate( 16) # reserve space for segment header+the root pointer builder.copy_from_struct(8, Struct, obj) segment_count = 1 segment_size = (builder.get_length() - 8) / 8 # subtract the segment header # and convert to words builder.write_uint32(0, segment_count - 1) builder.write_uint32(4, segment_size) return builder.as_string()
def test_null_pointers(self): NULL = b'\x00\x00\x00\x00\x00\x00\x00\x00' # NULL pointer buf = SegmentBuilder() pos = buf.allocate(24) buf.copy_from_struct(0, Struct, None) buf.alloc_text(8, None) buf.copy_from_list(16, PrimitiveItemType(Types.int64), None) s = buf.as_string() assert s == NULL*3
def compact(self): """ Return a compact version of the struct. In case the struct was inside a bigger message, it "extracts" it into a new message which contains only the needed pieces. """ builder = SegmentBuilder() pos = builder.allocate(8) builder.copy_from_struct(pos, Struct, self) buf = builder.as_string() t = type(self) res = t.__new__(t) res._init_from_buffer(buf, 8, self._data_size, self._ptrs_size) return res
def dumps(obj, fastpath=True): """ Dump a struct into a message, returned as a string of bytes. The message is encoded using the recommended capnp format for serializing messages over a stream. It always uses a single segment. By default, it tries to follow a fast path: it checks if the object is "compact" (as defined by capnpy/visit.py) and, is so, uses a fast memcpy to dump the whole message. If the fast path can be taken, it is approximately 5x faster on CPython and 10x faster on PyPy. However, if the object is **not** compact, the fast path check makes it ~2x slower. If you are sure that the object is not compact, you can disable the check by passing ``fastpath=False``. """ if fastpath: # try the fast path: if the object is compact, we can dump the # object with a fast memcpy end = obj._get_end() else: end = -1 # if end != -1: # fast path. On CPython, the real speedup comes from the fact that we # do not create a temporary SegmentBuilder. The memcpy vs copy_pointer # difference seems negligible, for small objects at least. start = obj._data_offset p = ptr.new_struct(0, obj._data_size, obj._ptrs_size) return obj._seg.dump_message(p, start, end) else: builder = SegmentBuilder() builder.allocate( 16) # reserve space for segment header+the root pointer builder.copy_from_struct(8, Struct, obj) segment_count = 1 segment_size = (builder.get_length() - 8) / 8 # subtract the segment header # and convert to words builder.write_uint32(0, segment_count - 1) builder.write_uint32(4, segment_size) return builder.as_string()