# Copyright 2023 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from dataclasses
import dataclass, field
from typing
import Tuple
@dataclass(init=
False)
class Address:
address: bytes = field(default=bytes([
0,
0,
0,
0,
0,
0]))
def __init__(self, address=
None):
if not address:
self.address = bytes([
0,
0,
0,
0,
0,
0])
elif isinstance(address, Address):
self.address = address.address
elif isinstance(address, str):
self.address = bytes([int(b,
16)
for b
in address.split(
':')])
elif isinstance(address, (bytes, list))
and len(address) ==
6:
self.address = bytes(address)
elif isinstance(address, bytes):
address = address.decode(
'utf-8')
self.address = bytes([int(b,
16)
for b
in address.split(
':')])
else:
raise Exception(f
'unsupported address type: {address}')
def parse(span: bytes) -> Tuple[
'Address', bytes]:
assert len(span) >=
6
return (Address(bytes(reversed(span[:
6]))), span[
6:])
def parse_all(span: bytes) ->
'Address':
assert len(span) ==
6
return Address(bytes(reversed(span)))
def serialize(self) -> bytes:
return bytes(reversed(self.address))
def is_resolvable(self) -> bool:
return (self.address[
0] &
0xc0) ==
0x40
def is_non_resolvable(self) -> bool:
return (self.address[
0] &
0xc0) ==
0x00
def is_static_identity(self) -> bool:
return (self.address[
0] &
0xc0) ==
0xc0
def __repr__(self) -> str:
return ':'.join([f
'{b:02x}' for b
in self.address])
@property
def size(self) -> int:
return 6
@dataclass
class ClassOfDevice:
class_of_device: int =
0
def parse(span: bytes) -> Tuple[
'Address', bytes]:
assert len(span) >=
3
return (ClassOfDevice(int.from_bytes(span[:
3], byteorder=
'little')), span[
3:])
def parse_all(span: bytes) ->
'Address':
assert len(span) ==
3
return ClassOfDevice(int.from_bytes(span, byteorder=
'little'))
def serialize(self) -> bytes:
return int.to_bytes(self.class_of_device, length=
3, byteorder=
'little')
@property
def size(self) -> int:
return 3