diff --git a/bumble/core.py b/bumble/core.py index 3be09deb..3cc6d0a8 100644 --- a/bumble/core.py +++ b/bumble/core.py @@ -19,6 +19,7 @@ import dataclasses import enum +import functools import struct from collections.abc import Iterable from typing import ( @@ -273,13 +274,8 @@ def parse_uuid(cls, uuid_as_bytes: bytes, offset: int) -> tuple[int, UUID]: def parse_uuid_2(cls, uuid_as_bytes: bytes, offset: int) -> tuple[int, UUID]: return offset + 2, cls.from_bytes(uuid_as_bytes[offset : offset + 2]) - def to_bytes(self, force_128: bool = False) -> bytes: - ''' - Serialize UUID in little-endian byte-order - ''' - if not force_128: - return self.uuid_bytes - + @functools.cached_property + def uuid_128_bytes(self) -> bytes: match len(self.uuid_bytes): case 2: return self.BASE_UUID + self.uuid_bytes + bytes([0, 0]) @@ -290,6 +286,15 @@ def to_bytes(self, force_128: bool = False) -> bytes: case _: assert False, "unreachable" + def to_bytes(self, force_128: bool = False) -> bytes: + ''' + Serialize UUID in little-endian byte-order + ''' + if not force_128: + return self.uuid_bytes + + return self.uuid_128_bytes + def to_pdu_bytes(self) -> bytes: ''' Convert to bytes for use in an ATT PDU. @@ -318,7 +323,7 @@ def __bytes__(self) -> bytes: def __eq__(self, other: object) -> bool: if isinstance(other, UUID): - return self.to_bytes(force_128=True) == other.to_bytes(force_128=True) + return self.uuid_128_bytes == other.uuid_128_bytes if isinstance(other, str): return UUID(other) == self @@ -326,7 +331,7 @@ def __eq__(self, other: object) -> bool: return False def __hash__(self) -> int: - return hash(self.uuid_bytes) + return hash(self.uuid_128_bytes) def __str__(self) -> str: result = self.to_hex_str(separator='-') diff --git a/tests/core_test.py b/tests/core_test.py index 02ebbaab..0d9f980a 100644 --- a/tests/core_test.py +++ b/tests/core_test.py @@ -73,6 +73,14 @@ def test_uuid_to_hex_str() -> None: ) +# ----------------------------------------------------------------------------- +def test_uuid_hash() -> None: + uuid = UUID("1234") + uuid_128_bytes = UUID.from_bytes(uuid.to_bytes(force_128=True)) + assert uuid in {uuid_128_bytes} + assert uuid_128_bytes in {uuid} + + # ----------------------------------------------------------------------------- def test_appearance() -> None: a = Appearance(Appearance.Category.COMPUTER, Appearance.ComputerSubcategory.LAPTOP)