Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: speed up marshalling headers #142

Merged
merged 2 commits into from
Nov 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions src/dbus_fast/_private/marshaller.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,28 @@ cdef class Marshaller:
cdef bytearray _buf
cdef object body

cpdef unsigned int align(self, unsigned int n)
cpdef align(self, unsigned int n)

@cython.locals(
offset=cython.ulong,
)
cdef unsigned int _align(self, unsigned int n)

cpdef write_boolean(self, object boolean, object _type)

@cython.locals(
written=cython.uint,
)
cdef unsigned int _write_boolean(self, object boolean)

cpdef write_string(self, str value, object _type)

@cython.locals(
value_len=cython.uint,
signature_len=cython.uint,
written=cython.uint,
)
cpdef write_string(self, str value, object _type)
cdef unsigned int _write_string(self, str value)

@cython.locals(
signature_len=cython.uint,
Expand Down Expand Up @@ -57,12 +66,14 @@ cdef class Marshaller:
)
cdef unsigned int _write_struct(self, object array, object type)

cpdef write_variant(self, object variant, object type)

@cython.locals(
written=cython.uint,
signature=cython.str,
signature_bytes=cython.bytes,
)
cpdef write_variant(self, object variant, object type)
cdef unsigned int _write_variant(self, object variant, object type)

@cython.locals(
written=cython.uint,
Expand Down
68 changes: 38 additions & 30 deletions src/dbus_fast/_private/marshaller.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ def _align(self, n):
return offset

def write_boolean(self, boolean: bool, type_: SignatureType) -> int:
return self._write_boolean(boolean)

def _write_boolean(self, boolean: bool) -> int:
written = self._align(4)
self._buf += PACKED_BOOL_TRUE if boolean else PACKED_BOOL_FALSE
return written + 4
Expand All @@ -47,23 +50,29 @@ def _write_signature(self, signature_bytes) -> int:
signature_len = len(signature_bytes)
buf = self._buf
buf.append(signature_len)
buf.extend(signature_bytes)
buf += signature_bytes
buf.append(0)
return signature_len + 2

def write_string(self, value, type_: SignatureType) -> int:
return self._write_string(value)

def _write_string(self, value) -> int:
value_bytes = value.encode()
value_len = len(value)
written = self._align(4) + 4
buf = self._buf
buf.extend(PACK_UINT32(value_len))
buf.extend(value_bytes)
buf += PACK_UINT32(value_len)
buf += value_bytes
written += value_len
buf.append(0)
written += 1
return written

def write_variant(self, variant: Variant, type_: SignatureType) -> int:
return self._write_variant(variant, type_)

def _write_variant(self, variant: Variant, type_: SignatureType) -> int:
signature = variant.signature
signature_bytes = signature.encode()
written = self._write_signature(signature_bytes)
Expand All @@ -84,7 +93,7 @@ def _write_array(
buf = self._buf
offset = len(buf)
written += self._align(4) + 4
buf.extend(PACKED_UINT32_ZERO)
buf += PACKED_UINT32_ZERO
child_type = type_.children[0]
token = child_type.token

Expand All @@ -98,7 +107,7 @@ def _write_array(
array_len += self.write_dict_entry([key, value], child_type)
elif token == "y":
array_len = len(array)
buf.extend(array)
buf += array
elif token == "(":
for value in array:
array_len += self._write_struct(value, child_type)
Expand All @@ -107,7 +116,7 @@ def _write_array(
if not writer:
for value in array:
array_len += self._align(size) + size
buf.extend(packer(value)) # type: ignore[misc]
buf += packer(value) # type: ignore[misc]
else:
for value in array:
array_len += writer(self, value, child_type)
Expand Down Expand Up @@ -135,12 +144,28 @@ def write_dict_entry(self, dict_entry: List[Any], type_: SignatureType) -> int:

def _write_single(self, type_: SignatureType, body: Any) -> int:
t = type_.token
writer, packer, size = self._writers[t]
if not writer:
written = self._align(size)
self._buf.extend(packer(body)) # type: ignore[misc]
return written + size
return writer(self, body, type_)
if t == "y":
self._buf.append(body)
return 1
elif t == "u":
written = self._align(4)
self._buf += PACK_UINT32(body)
return written + 4
elif t == "a":
return self._write_array(body, type_)
elif t == "s" or t == "o":
return self._write_string(body)
elif t == "v":
return self._write_variant(body, type_)
elif t == "b":
return self._write_boolean(body)
else:
writer, packer, size = self._writers[t]
if not writer:
written = self._align(size)
self._buf += packer(body) # type: ignore[misc]
return written + size
return writer(self, body, type_)

def marshall(self) -> bytearray:
"""Marshalls the body into a byte array"""
Expand All @@ -154,26 +179,9 @@ def marshall(self) -> bytearray:

def _construct_buffer(self) -> None:
self._buf.clear()
writers = self._writers
body = self.body
buf = self._buf
for i, type_ in enumerate(self.signature_tree.types):
t = type_.token
if t == "y":
buf.append(body[i])
elif t == "u":
self._align(4)
buf.extend(PACK_UINT32(body[i]))
elif t == "a":
self._write_array(body[i], type_)
else:
writer, packer, size = writers[t]
if not writer:
if size != 1:
self._align(size)
buf.extend(packer(body[i])) # type: ignore[misc]
else:
writer(self, body[i], type_)
self._write_single(type_, body[i])

_writers: Dict[
str,
Expand Down