feat: improve unmarshall performance for SignatureType (#436)
This commit is contained in:
parent
2ae89b1dd9
commit
e0aeeacf8d
@ -607,7 +607,7 @@ class Unmarshaller:
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
array_length = self._uint32_unpack(self._buf, self._pos - UINT32_SIZE)[0]
|
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
|
token_as_int = child_type.token_as_int
|
||||||
|
|
||||||
if token_as_int in {
|
if token_as_int in {
|
||||||
@ -631,9 +631,8 @@ class Unmarshaller:
|
|||||||
result_dict: dict[Any, Any] = {}
|
result_dict: dict[Any, Any] = {}
|
||||||
key: str | int
|
key: str | int
|
||||||
beginning_pos = self._pos
|
beginning_pos = self._pos
|
||||||
children = child_type.children
|
child_0 = child_type._child_0
|
||||||
child_0 = children[0]
|
child_1 = child_type._child_1
|
||||||
child_1 = children[1]
|
|
||||||
child_0_token_as_int = child_0.token_as_int
|
child_0_token_as_int = child_0.token_as_int
|
||||||
child_1_token_as_int = child_1.token_as_int
|
child_1_token_as_int = child_1.token_as_int
|
||||||
# Strings with variant values are the most common case
|
# Strings with variant values are the most common case
|
||||||
|
|||||||
@ -9,6 +9,8 @@ cdef class SignatureType:
|
|||||||
cdef public unsigned int token_as_int
|
cdef public unsigned int token_as_int
|
||||||
cdef public list children
|
cdef public list children
|
||||||
cdef str _signature
|
cdef str _signature
|
||||||
|
cdef public SignatureType _child_0
|
||||||
|
cdef public SignatureType _child_1
|
||||||
|
|
||||||
|
|
||||||
cdef class SignatureTree:
|
cdef class SignatureTree:
|
||||||
|
|||||||
@ -21,13 +21,22 @@ class SignatureType:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
_tokens = "ybnqiuxtdsogavh({"
|
_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:
|
def __init__(self, token: str) -> None:
|
||||||
"""Init a new SignatureType."""
|
"""Init a new SignatureType."""
|
||||||
self.token: str = token
|
self.token: str = token
|
||||||
self.token_as_int = ord(token)
|
self.token_as_int = ord(token)
|
||||||
self.children: list[SignatureType] = []
|
self.children: list[SignatureType] = []
|
||||||
|
self._child_0: Optional[SignatureType] = None
|
||||||
|
self._child_1: Optional[SignatureType] = None
|
||||||
self._signature: Optional[str] = None
|
self._signature: Optional[str] = None
|
||||||
|
|
||||||
def __eq__(self, other: object) -> bool:
|
def __eq__(self, other: object) -> bool:
|
||||||
@ -60,6 +69,18 @@ class SignatureType:
|
|||||||
self._signature = self._collapse()
|
self._signature = self._collapse()
|
||||||
return self._signature
|
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
|
@staticmethod
|
||||||
def _parse_next(signature: str) -> tuple["SignatureType", str]:
|
def _parse_next(signature: str) -> tuple["SignatureType", str]:
|
||||||
if not signature:
|
if not signature:
|
||||||
@ -76,7 +97,7 @@ class SignatureType:
|
|||||||
(child, signature) = SignatureType._parse_next(signature[1:])
|
(child, signature) = SignatureType._parse_next(signature[1:])
|
||||||
if not child:
|
if not child:
|
||||||
raise InvalidSignatureError("missing type for array")
|
raise InvalidSignatureError("missing type for array")
|
||||||
self.children.append(child)
|
self._add_child(child)
|
||||||
return (self, signature)
|
return (self, signature)
|
||||||
if token == "(":
|
if token == "(":
|
||||||
self = SignatureType("(")
|
self = SignatureType("(")
|
||||||
@ -85,7 +106,7 @@ class SignatureType:
|
|||||||
(child, signature) = SignatureType._parse_next(signature)
|
(child, signature) = SignatureType._parse_next(signature)
|
||||||
if not signature:
|
if not signature:
|
||||||
raise InvalidSignatureError('missing closing ")" for struct')
|
raise InvalidSignatureError('missing closing ")" for struct')
|
||||||
self.children.append(child)
|
self._add_child(child)
|
||||||
if signature[0] == ")":
|
if signature[0] == ")":
|
||||||
return (self, signature[1:])
|
return (self, signature[1:])
|
||||||
elif token == "{":
|
elif token == "{":
|
||||||
@ -94,13 +115,13 @@ class SignatureType:
|
|||||||
(key_child, signature) = SignatureType._parse_next(signature)
|
(key_child, signature) = SignatureType._parse_next(signature)
|
||||||
if not key_child or len(key_child.children):
|
if not key_child or len(key_child.children):
|
||||||
raise InvalidSignatureError("expected a simple type for dict entry key")
|
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)
|
(value_child, signature) = SignatureType._parse_next(signature)
|
||||||
if not value_child:
|
if not value_child:
|
||||||
raise InvalidSignatureError("expected a value for dict entry")
|
raise InvalidSignatureError("expected a value for dict entry")
|
||||||
if not signature or signature[0] != "}":
|
if not signature or signature[0] != "}":
|
||||||
raise InvalidSignatureError('missing closing "}" for dict entry')
|
raise InvalidSignatureError('missing closing "}" for dict entry')
|
||||||
self.children.append(value_child)
|
self._add_child(value_child)
|
||||||
return (self, signature[1:])
|
return (self, signature[1:])
|
||||||
|
|
||||||
# basic type
|
# basic type
|
||||||
|
|||||||
@ -23,6 +23,15 @@ def test_multiple_simple():
|
|||||||
assert_simple_type("s", tree.types[i])
|
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():
|
def test_array():
|
||||||
tree = SignatureTree("as")
|
tree = SignatureTree("as")
|
||||||
assert len(tree.types) == 1
|
assert len(tree.types) == 1
|
||||||
@ -31,6 +40,11 @@ def test_array():
|
|||||||
assert child.token == "a"
|
assert child.token == "a"
|
||||||
assert len(child.children) == 1
|
assert len(child.children) == 1
|
||||||
assert_simple_type("s", child.children[0])
|
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():
|
def test_array_multiple():
|
||||||
@ -67,6 +81,8 @@ def test_simple_struct():
|
|||||||
assert len(child.children) == 3
|
assert len(child.children) == 3
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
assert_simple_type("s", child.children[i])
|
assert_simple_type("s", child.children[i])
|
||||||
|
assert child._child_0.signature == "s"
|
||||||
|
assert child._child_1.signature == "s"
|
||||||
|
|
||||||
|
|
||||||
def test_nested_struct():
|
def test_nested_struct():
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user