mirror of
https://github.com/google/bumble.git
synced 2026-05-08 03:58:01 +00:00
uuid: add separator to to_hex_str + type hints
This commit is contained in:
@@ -152,7 +152,12 @@ class UUID:
|
|||||||
BASE_UUID = bytes.fromhex('00001000800000805F9B34FB')[::-1] # little-endian
|
BASE_UUID = bytes.fromhex('00001000800000805F9B34FB')[::-1] # little-endian
|
||||||
UUIDS: List[UUID] = [] # Registry of all instances created
|
UUIDS: List[UUID] = [] # Registry of all instances created
|
||||||
|
|
||||||
def __init__(self, uuid_str_or_int, name=None):
|
uuid_bytes: bytes
|
||||||
|
name: Optional[str]
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self, uuid_str_or_int: Union[str, int], name: Optional[str] = None
|
||||||
|
) -> None:
|
||||||
if isinstance(uuid_str_or_int, int):
|
if isinstance(uuid_str_or_int, int):
|
||||||
self.uuid_bytes = struct.pack('<H', uuid_str_or_int)
|
self.uuid_bytes = struct.pack('<H', uuid_str_or_int)
|
||||||
else:
|
else:
|
||||||
@@ -172,7 +177,7 @@ class UUID:
|
|||||||
self.uuid_bytes = bytes(reversed(bytes.fromhex(uuid_str)))
|
self.uuid_bytes = bytes(reversed(bytes.fromhex(uuid_str)))
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
def register(self):
|
def register(self) -> UUID:
|
||||||
# Register this object in the class registry, and update the entry's name if
|
# Register this object in the class registry, and update the entry's name if
|
||||||
# it wasn't set already
|
# it wasn't set already
|
||||||
for uuid in self.UUIDS:
|
for uuid in self.UUIDS:
|
||||||
@@ -196,22 +201,22 @@ class UUID:
|
|||||||
raise ValueError('only 2, 4 and 16 bytes are allowed')
|
raise ValueError('only 2, 4 and 16 bytes are allowed')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_16_bits(cls, uuid_16, name=None):
|
def from_16_bits(cls, uuid_16: int, name: Optional[str] = None) -> UUID:
|
||||||
return cls.from_bytes(struct.pack('<H', uuid_16), name)
|
return cls.from_bytes(struct.pack('<H', uuid_16), name)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_32_bits(cls, uuid_32, name=None):
|
def from_32_bits(cls, uuid_32: int, name: Optional[str] = None) -> UUID:
|
||||||
return cls.from_bytes(struct.pack('<I', uuid_32), name)
|
return cls.from_bytes(struct.pack('<I', uuid_32), name)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse_uuid(cls, uuid_as_bytes, offset):
|
def parse_uuid(cls, uuid_as_bytes: bytes, offset: int) -> Tuple[int, UUID]:
|
||||||
return len(uuid_as_bytes), cls.from_bytes(uuid_as_bytes[offset:])
|
return len(uuid_as_bytes), cls.from_bytes(uuid_as_bytes[offset:])
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse_uuid_2(cls, uuid_as_bytes, offset):
|
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])
|
return offset + 2, cls.from_bytes(uuid_as_bytes[offset : offset + 2])
|
||||||
|
|
||||||
def to_bytes(self, force_128=False):
|
def to_bytes(self, force_128: bool = False) -> bytes:
|
||||||
'''
|
'''
|
||||||
Serialize UUID in little-endian byte-order
|
Serialize UUID in little-endian byte-order
|
||||||
'''
|
'''
|
||||||
@@ -227,7 +232,7 @@ class UUID:
|
|||||||
else:
|
else:
|
||||||
assert False, "unreachable"
|
assert False, "unreachable"
|
||||||
|
|
||||||
def to_pdu_bytes(self):
|
def to_pdu_bytes(self) -> bytes:
|
||||||
'''
|
'''
|
||||||
Convert to bytes for use in an ATT PDU.
|
Convert to bytes for use in an ATT PDU.
|
||||||
According to Vol 3, Part F - 3.2.1 Attribute Type:
|
According to Vol 3, Part F - 3.2.1 Attribute Type:
|
||||||
@@ -236,11 +241,11 @@ class UUID:
|
|||||||
'''
|
'''
|
||||||
return self.to_bytes(force_128=(len(self.uuid_bytes) == 4))
|
return self.to_bytes(force_128=(len(self.uuid_bytes) == 4))
|
||||||
|
|
||||||
def to_hex_str(self) -> str:
|
def to_hex_str(self, separator: str = '') -> str:
|
||||||
if len(self.uuid_bytes) == 2 or len(self.uuid_bytes) == 4:
|
if len(self.uuid_bytes) == 2 or len(self.uuid_bytes) == 4:
|
||||||
return bytes(reversed(self.uuid_bytes)).hex().upper()
|
return bytes(reversed(self.uuid_bytes)).hex().upper()
|
||||||
|
|
||||||
return ''.join(
|
return separator.join(
|
||||||
[
|
[
|
||||||
bytes(reversed(self.uuid_bytes[12:16])).hex(),
|
bytes(reversed(self.uuid_bytes[12:16])).hex(),
|
||||||
bytes(reversed(self.uuid_bytes[10:12])).hex(),
|
bytes(reversed(self.uuid_bytes[10:12])).hex(),
|
||||||
@@ -250,10 +255,10 @@ class UUID:
|
|||||||
]
|
]
|
||||||
).upper()
|
).upper()
|
||||||
|
|
||||||
def __bytes__(self):
|
def __bytes__(self) -> bytes:
|
||||||
return self.to_bytes()
|
return self.to_bytes()
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other: object) -> bool:
|
||||||
if isinstance(other, UUID):
|
if isinstance(other, UUID):
|
||||||
return self.to_bytes(force_128=True) == other.to_bytes(force_128=True)
|
return self.to_bytes(force_128=True) == other.to_bytes(force_128=True)
|
||||||
|
|
||||||
@@ -262,35 +267,19 @@ class UUID:
|
|||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self) -> int:
|
||||||
return hash(self.uuid_bytes)
|
return hash(self.uuid_bytes)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
|
result = self.to_hex_str(separator='-')
|
||||||
if len(self.uuid_bytes) == 2:
|
if len(self.uuid_bytes) == 2:
|
||||||
uuid = struct.unpack('<H', self.uuid_bytes)[0]
|
result = 'UUID-16:' + result
|
||||||
result = f'UUID-16:{uuid:04X}'
|
|
||||||
elif len(self.uuid_bytes) == 4:
|
elif len(self.uuid_bytes) == 4:
|
||||||
uuid = struct.unpack('<I', self.uuid_bytes)[0]
|
result = 'UUID-32:' + result
|
||||||
result = f'UUID-32:{uuid:08X}'
|
|
||||||
else:
|
|
||||||
result = '-'.join(
|
|
||||||
[
|
|
||||||
bytes(reversed(self.uuid_bytes[12:16])).hex(),
|
|
||||||
bytes(reversed(self.uuid_bytes[10:12])).hex(),
|
|
||||||
bytes(reversed(self.uuid_bytes[8:10])).hex(),
|
|
||||||
bytes(reversed(self.uuid_bytes[6:8])).hex(),
|
|
||||||
bytes(reversed(self.uuid_bytes[0:6])).hex(),
|
|
||||||
]
|
|
||||||
).upper()
|
|
||||||
|
|
||||||
if self.name is not None:
|
if self.name is not None:
|
||||||
return result + f' ({self.name})'
|
result += f' ({self.name})'
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return str(self)
|
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Common UUID constants
|
# Common UUID constants
|
||||||
|
|||||||
@@ -247,7 +247,7 @@ class TemplateService(Service):
|
|||||||
to expose their UUID as a class property
|
to expose their UUID as a class property
|
||||||
'''
|
'''
|
||||||
|
|
||||||
UUID = None
|
UUID: Optional[UUID] = None
|
||||||
|
|
||||||
def __init__(self, characteristics, primary=True):
|
def __init__(self, characteristics, primary=True):
|
||||||
super().__init__(self.UUID, characteristics, primary)
|
super().__init__(self.UUID, characteristics, primary)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Imports
|
# Imports
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
from bumble.core import AdvertisingData, get_dict_key_by_value
|
from bumble.core import AdvertisingData, UUID, get_dict_key_by_value
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
def test_ad_data():
|
def test_ad_data():
|
||||||
@@ -49,6 +49,24 @@ def test_get_dict_key_by_value():
|
|||||||
assert get_dict_key_by_value(dictionary, 3) is None
|
assert get_dict_key_by_value(dictionary, 3) is None
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
def test_uuid_to_hex_str() -> None:
|
||||||
|
assert UUID("b5ea").to_hex_str() == "B5EA"
|
||||||
|
assert UUID("df5ce654").to_hex_str() == "DF5CE654"
|
||||||
|
assert (
|
||||||
|
UUID("df5ce654-e059-11ed-b5ea-0242ac120002").to_hex_str()
|
||||||
|
== "DF5CE654E05911EDB5EA0242AC120002"
|
||||||
|
)
|
||||||
|
assert UUID("b5ea").to_hex_str('-') == "B5EA"
|
||||||
|
assert UUID("df5ce654").to_hex_str('-') == "DF5CE654"
|
||||||
|
assert (
|
||||||
|
UUID("df5ce654-e059-11ed-b5ea-0242ac120002").to_hex_str('-')
|
||||||
|
== "DF5CE654-E059-11ED-B5EA-0242AC120002"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
test_ad_data()
|
test_ad_data()
|
||||||
|
test_get_dict_key_by_value()
|
||||||
|
test_uuid_to_hex_str()
|
||||||
|
|||||||
Reference in New Issue
Block a user