"""Module with bytes list operations implementation."""
__all__ = ["Endianness", "bytes_list_to_int", "int_to_bytes_list"]
from typing import Optional
from aenum import StrEnum
from .enums import ValidatedEnum
from .common_types import RawBytesListAlias, RawBytesAlias, validate_raw_bytes
from .custom_exceptions import InconsistentArgumentsError
[docs]
class Endianness(StrEnum, ValidatedEnum):
"""
Endianness values definitions.
`Endianness <https://en.wikipedia.org/wiki/Endianness>`_ determines order of bytes in a bytes sequence.
"""
LITTLE_ENDIAN: "Endianness" = "little" # type: ignore
"""Little Endian stores the most significant byte at the largest memory address and the least significant byte
at the smallest."""
BIG_ENDIAN: "Endianness" = "big" # type: ignore
"""Big Endian stores the most significant byte at the smallest memory address and the least significant byte
at the largest."""
[docs]
def bytes_list_to_int(bytes_list: RawBytesAlias, endianness: Endianness = Endianness.BIG_ENDIAN) -> int:
"""
Convert a list of bytes to integer value.
:param bytes_list: List of bytes to convert.
:param endianness: Order of bytes to use.
:return: The integer value represented by provided list of bytes.
"""
validate_raw_bytes(bytes_list)
return int.from_bytes(bytes=bytes_list, byteorder=Endianness.validate_member(endianness).value)
[docs]
def int_to_bytes_list(int_value: int,
list_size: Optional[int] = None,
endianness: Endianness = Endianness.BIG_ENDIAN) -> RawBytesListAlias:
"""
Convert integer value to a list of bytes.
:param int_value: Integer value to convert.
:param list_size: Size of the output list. Use None to use the smallest possible list size.
:param endianness: Order of bytes to use.
:raise TypeError: At least one provided value has invalid type.
:raise ValueError: At least one provided value is out of range.
:raise InconsistentArgumentsError: Provided value of `list_size` is too small to contain entire `int_value`.
:raise NotImplementedError: There is missing implementation for the provided Endianness.
Please create an issue in our `Issues Tracking System <https://github.com/mdabrowski1990/uds/issues>`_
with detailed description if you face this error.
:return: The value of bytes list that represents the provided integer value.
"""
if not isinstance(int_value, int):
raise TypeError(f"Provided `int_value` is not int type. Actual type: {type(int_value)}")
if int_value < 0:
raise ValueError(f"Provided `int_value` is negative and it cannot be converted. Actual value: {int_value}")
if list_size is not None:
if not isinstance(list_size, int):
raise TypeError(f"Provided `list_size` is not int type. Actual type: {type(list_size)}")
if list_size <= 0:
raise ValueError(f"Provided `list_size` is not greater than zero. Actual value: {list_size}")
Endianness.validate_member(endianness)
bytes_number = max(1, (int_value.bit_length() + 7) // 8)
list_size = list_size or bytes_number
if list_size < bytes_number:
raise InconsistentArgumentsError(f"Provided value of `list_size` is too small to contain all byte of int_value."
f"Actual values: int_value={int_value}, list_size={list_size}")
hex_value = "".join(["{", f":0{2 * bytes_number}X", "}"]).format(int_value)
bytes_list = list(bytes.fromhex(hex_value))
bytes_list = ([0] * (list_size - len(bytes_list))) + bytes_list
if endianness == Endianness.BIG_ENDIAN:
return bytes_list
if endianness == Endianness.LITTLE_ENDIAN:
return bytes_list[::-1]
raise NotImplementedError(f"Implementation missing for: {endianness}.")