String Format

Format characters struct.unpack_from()

Format character

Description

d

signed char (8 bits)

i

unsigned char (8 bits)

h

signed short (16 bits)

H

unsigned short (16 bits)

I

signed int (32 bits)

L

unsigned int (32 bits)

q

signed long long (64 bits)

Q

unsigned long long (64 bits)

f

single precision (32-bit) floating-point number

d

double precision (64-bit) floating-point number

s

string of characters terminated by a null byte (ASCII)

p

pointer to a structure

b

singed byte (8 bits)

B

unsigned byte (8bits)

!

Big Endian

>

Little Endian

Alternative String Format Creation

For parsing packet data I used a simplified approach using a dictionary storing the most important Symbols.

 1string_format: Dict[int, str] = {
 2   1: '{}s',
 3   8: 'B',
 4   16: 'H',
 5   32: 'I',
 6   64: 'Q'
 7}
 8
 9def bld_str_fmt(bit_list: List[int]) -> str:
10   return '>' + ''.join([string_format[1].format(bits // 8) if bits not in string_format.keys() else string_format[bits] for bits in bit_list])
11
12bld_str_fmt([8, 8, 16, 16, 16, 8, 8, 16, 32, 32])

The bld_str_fmt() function effectively clarifies the extraction of specific bit groups into contiguous segments using struct.unpack_from(). The build function consistently employs little-endian byte order, which is appropriate since all conversions are performed in this format. It identifies integers from the provided list and replaces them with corresponding values from the pre-defined dictionary. If the key is not found, the integer is divided by 8 (truncated integer division) and suffixed with “s”. For instance, while parsing an IPv6 address, which occupies 128 bits, dividing 128 by 8 yields 16, resulting in the format “16s”.