diff --git a/src/dbus_fast/_private/unmarshaller.py b/src/dbus_fast/_private/unmarshaller.py index f2fb68f..80c931b 100644 --- a/src/dbus_fast/_private/unmarshaller.py +++ b/src/dbus_fast/_private/unmarshaller.py @@ -607,7 +607,7 @@ class Unmarshaller: ) else: array_length = self._uint32_unpack(self._buf, self._pos - UINT32_SIZE)[0] - child_type: SignatureType = type_.children[0] + child_type = type_._child_0 token_as_int = child_type.token_as_int if token_as_int in { @@ -631,9 +631,8 @@ class Unmarshaller: result_dict: dict[Any, Any] = {} key: str | int beginning_pos = self._pos - children = child_type.children - child_0 = children[0] - child_1 = children[1] + child_0 = child_type._child_0 + child_1 = child_type._child_1 child_0_token_as_int = child_0.token_as_int child_1_token_as_int = child_1.token_as_int # Strings with variant values are the most common case diff --git a/src/dbus_fast/signature.pxd b/src/dbus_fast/signature.pxd index eaf94e2..c99f01f 100644 --- a/src/dbus_fast/signature.pxd +++ b/src/dbus_fast/signature.pxd @@ -9,6 +9,8 @@ cdef class SignatureType: cdef public unsigned int token_as_int cdef public list children cdef str _signature + cdef public SignatureType _child_0 + cdef public SignatureType _child_1 cdef class SignatureTree: diff --git a/src/dbus_fast/signature.py b/src/dbus_fast/signature.py index ee264c4..a4bd31f 100644 --- a/src/dbus_fast/signature.py +++ b/src/dbus_fast/signature.py @@ -21,13 +21,22 @@ class SignatureType: """ _tokens = "ybnqiuxtdsogavh({" - __slots__ = ("_signature", "children", "token", "token_as_int") + __slots__ = ( + "_child_0", + "_child_1", + "_signature", + "children", + "token", + "token_as_int", + ) def __init__(self, token: str) -> None: """Init a new SignatureType.""" self.token: str = token self.token_as_int = ord(token) self.children: list[SignatureType] = [] + self._child_0: Optional[SignatureType] = None + self._child_1: Optional[SignatureType] = None self._signature: Optional[str] = None def __eq__(self, other: object) -> bool: @@ -60,6 +69,18 @@ class SignatureType: self._signature = self._collapse() return self._signature + def _add_child(self, child: "SignatureType") -> None: + """Add a child type to this type. + + :param child: The child type to add. + :type child: :class:`SignatureType` + """ + if self._child_0 is None: + self._child_0 = child + elif self._child_1 is None: + self._child_1 = child + self.children.append(child) + @staticmethod def _parse_next(signature: str) -> tuple["SignatureType", str]: if not signature: @@ -76,7 +97,7 @@ class SignatureType: (child, signature) = SignatureType._parse_next(signature[1:]) if not child: raise InvalidSignatureError("missing type for array") - self.children.append(child) + self._add_child(child) return (self, signature) if token == "(": self = SignatureType("(") @@ -85,7 +106,7 @@ class SignatureType: (child, signature) = SignatureType._parse_next(signature) if not signature: raise InvalidSignatureError('missing closing ")" for struct') - self.children.append(child) + self._add_child(child) if signature[0] == ")": return (self, signature[1:]) elif token == "{": @@ -94,13 +115,13 @@ class SignatureType: (key_child, signature) = SignatureType._parse_next(signature) if not key_child or len(key_child.children): raise InvalidSignatureError("expected a simple type for dict entry key") - self.children.append(key_child) + self._add_child(key_child) (value_child, signature) = SignatureType._parse_next(signature) if not value_child: raise InvalidSignatureError("expected a value for dict entry") if not signature or signature[0] != "}": raise InvalidSignatureError('missing closing "}" for dict entry') - self.children.append(value_child) + self._add_child(value_child) return (self, signature[1:]) # basic type diff --git a/tests/test_signature.py b/tests/test_signature.py index 61090a5..5400f76 100644 --- a/tests/test_signature.py +++ b/tests/test_signature.py @@ -23,6 +23,15 @@ def test_multiple_simple(): assert_simple_type("s", tree.types[i]) +def test_children(): + tree = SignatureTree("ss") + assert len(tree.types) == 2 + parent = tree.types[0] + assert parent.token == "s" + assert parent.signature == "s" + assert len(parent.children) == 0 + + def test_array(): tree = SignatureTree("as") assert len(tree.types) == 1 @@ -31,6 +40,11 @@ def test_array(): assert child.token == "a" assert len(child.children) == 1 assert_simple_type("s", child.children[0]) + assert child.children[0].token == "s" + assert child._child_0.signature == "s" + assert child._child_1 is None + with pytest.raises(AttributeError): + _ = child._child_1.signature def test_array_multiple(): @@ -67,6 +81,8 @@ def test_simple_struct(): assert len(child.children) == 3 for i in range(3): assert_simple_type("s", child.children[i]) + assert child._child_0.signature == "s" + assert child._child_1.signature == "s" def test_nested_struct():