1# Copyright 2023 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15from dataclasses import dataclass, field 16from typing import Tuple 17 18 19@dataclass(init=False) 20class Address: 21 address: bytes = field(default=bytes([0, 0, 0, 0, 0, 0])) 22 23 def __init__(self, address=None): 24 if not address: 25 self.address = bytes([0, 0, 0, 0, 0, 0]) 26 elif isinstance(address, Address): 27 self.address = address.address 28 elif isinstance(address, str): 29 self.address = bytes([int(b, 16) for b in address.split(':')]) 30 elif isinstance(address, (bytes, list)) and len(address) == 6: 31 self.address = bytes(address) 32 elif isinstance(address, bytes): 33 address = address.decode('utf-8') 34 self.address = bytes([int(b, 16) for b in address.split(':')]) 35 else: 36 raise Exception(f'unsupported address type: {address}') 37 38 def parse(span: bytes) -> Tuple['Address', bytes]: 39 assert len(span) >= 6 40 return (Address(bytes(reversed(span[:6]))), span[6:]) 41 42 def parse_all(span: bytes) -> 'Address': 43 assert len(span) == 6 44 return Address(bytes(reversed(span))) 45 46 def serialize(self) -> bytes: 47 return bytes(reversed(self.address)) 48 49 def is_resolvable(self) -> bool: 50 return (self.address[0] & 0xc0) == 0x40 51 52 def is_non_resolvable(self) -> bool: 53 return (self.address[0] & 0xc0) == 0x00 54 55 def is_static_identity(self) -> bool: 56 return (self.address[0] & 0xc0) == 0xc0 57 58 def __repr__(self) -> str: 59 return ':'.join([f'{b:02x}' for b in self.address]) 60 61 @property 62 def size(self) -> int: 63 return 6 64 65 66@dataclass 67class ClassOfDevice: 68 class_of_device: int = 0 69 70 def parse(span: bytes) -> Tuple['Address', bytes]: 71 assert len(span) >= 3 72 return (ClassOfDevice(int.from_bytes(span[:3], byteorder='little')), span[3:]) 73 74 def parse_all(span: bytes) -> 'Address': 75 assert len(span) == 3 76 return ClassOfDevice(int.from_bytes(span, byteorder='little')) 77 78 def serialize(self) -> bytes: 79 return int.to_bytes(self.class_of_device, length=3, byteorder='little') 80 81 @property 82 def size(self) -> int: 83 return 3 84