I have this structure in C:
MAX_NUMBER_OF_ITEMS = 9
typedef struct {
uint64_t status;
uint8_t serial_number_of_items [MAX_NUMBER_OF_ITEMS];
uint8_t version;
} Items_Info_t;
How can I convert it to Python, specifically the part:
uint8_t number_of_items [MAX_NUMBER_OF_ITEMS]
I try to do this way:
class SensorInfo:
status: int
serial_number_of_items: List[int]
version: int
Also, how can I perform serialization using struct.pack
after that?
Create a class to encapsulate Items_Info_t
and manage its serialization/deserialization.
__init__
method initializes the object's attributes, after doing data validation to ensure that the input values are within the expected ranges.endian
parameter to both the serialize
and deserialize
methods. The default value is '<'
(little-endian).struct.pack
:
import struct
from typing import List
MAX_NUMBER_OF_ITEMS = 9
class ItemsInfo:
def __init__(self, status: int, serial_number_of_items: List[int], version: int):
if len(serial_number_of_items) != MAX_NUMBER_OF_ITEMS:
raise ValueError(f"serial_number_of_items must have {MAX_NUMBER_OF_ITEMS} elements")
if not all(0 <= item <= 255 for item in serial_number_of_items):
raise ValueError("All serial numbers must be within the range 0-255 (uint8).")
if not (0 <= version <= 255):
raise ValueError("version must be within the range 0-255 (uint8).")
if status < 0:
raise ValueError("Status must be a non-negative integer (uint64).")
self.status = status
self.serial_number_of_items = serial_number_of_items
self.version = version
def serialize(self, endian: str = '<') -> bytes:
if endian not in ('<', '>', '!'):
raise ValueError("Endian must be '<' (little-endian), '>' (big-endian), or '!' (network byte order).")
format_string = f"{endian}Q{'B' * MAX_NUMBER_OF_ITEMS}B"
return struct.pack(format_string, self.status, *self.serial_number_of_items, self.version)
@staticmethod
def deserialize(data: bytes, endian: str = '<') -> 'ItemsInfo':
if endian not in ('<', '>', '!'):
raise ValueError("Endian must be '<' (little-endian), '>' (big-endian), or '!' (network byte order).")
format_string = f"{endian}Q{'B' * MAX_NUMBER_OF_ITEMS}B"
expected_size = struct.calcsize(format_string)
if len(data) != expected_size:
raise ValueError(f"Data length is incorrect. Expected {expected_size} bytes, got {len(data)}.")
unpacked_data = struct.unpack(format_string, data)
status = unpacked_data[0]
serial_numbers = list(unpacked_data[1:1 + MAX_NUMBER_OF_ITEMS])
version = unpacked_data[-1]
return ItemsInfo(status, serial_numbers, version)
Testing
serial_numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
items_info = ItemsInfo(status=1055, serial_number_of_items=serial_numbers, version=23)
serialized_data_network = items_info.serialize(endian='!')
print("Serialized Data (network byte order):", serialized_data_network)
print("\nDeserialized Data (network byte order):")
deserialized_info_network = ItemsInfo.deserialize(serialized_data_network, endian='!')
print("Status:", deserialized_info_network.status)
print("Serial Numbers:", deserialized_info_network.serial_number_of_items)
print("Version:", deserialized_info_network.version)
Output
Serialized Data (network byte order): b'\x00\x00\x00\x00\x00\x00\x04\x1f\x01\x02\x03\x04\x05\x06\x07\x08\t\x17'
Deserialized Data (network byte order):
Status: 1055
Serial Numbers: [1, 2, 3, 4, 5, 6, 7, 8, 9]
Version: 23