Skip to content

StructConfig

StructConfig controls how StructModel and BitFieldModel classes pack and unpack binary data. Every model class can have its own independent configuration.

Overview

Configuration is set by creating a StructConfig instance as a class variable:

from pdc_struct import StructModel, StructConfig, StructMode, ByteOrder

class MyPacket(StructModel):
    # ... fields ...

    struct_config = StructConfig(
        mode=StructMode.C_COMPATIBLE,
        byte_order=ByteOrder.BIG_ENDIAN
    )

Configuration Options

Parameter Type Default Description
mode StructMode DYNAMIC Serialization mode (C-compatible or dynamic)
version StructVersion V1 Protocol version for dynamic mode headers
byte_order ByteOrder System default Endianness for multi-byte values
bit_width int None Bit width for BitFieldModel (8, 16, or 32)
propagate_byte_order bool True Apply byte order to nested structs
metadata dict {} Custom metadata for application use

Mode Selection Guide

C_COMPATIBLE Mode

Use when interfacing with C code or requiring fixed-size binary layouts:

struct_config = StructConfig(
    mode=StructMode.C_COMPATIBLE,
    byte_order=ByteOrder.LITTLE_ENDIAN
)

Characteristics:

  • No header bytes in output
  • Fixed struct size
  • Optional fields must have defaults
  • Strings are null-terminated, fixed-length

DYNAMIC Mode

Use for Python-to-Python communication with flexibility:

struct_config = StructConfig(
    mode=StructMode.DYNAMIC,
    byte_order=ByteOrder.BIG_ENDIAN
)

Characteristics:

  • 4-byte header with version and flags
  • Supports truly optional fields (can be None)
  • Field presence tracked via bitmap
  • More space-efficient for sparse data

Byte Order

The byte_order parameter controls how multi-byte values (integers, floats) are serialized:

from pdc_struct import ByteOrder

# Network protocols typically use big-endian
struct_config = StructConfig(byte_order=ByteOrder.BIG_ENDIAN)

# x86/x64 systems use little-endian
struct_config = StructConfig(byte_order=ByteOrder.LITTLE_ENDIAN)

# Match current system (not recommended for cross-platform)
struct_config = StructConfig(byte_order=ByteOrder.NATIVE)

Default Byte Order

If not specified, byte_order defaults to the system's native byte order. For cross-platform compatibility, always specify byte order explicitly.

BitFieldModel Configuration

For BitFieldModel classes, you must specify bit_width:

from pdc_struct import BitFieldModel, StructConfig, StructMode

class StatusFlags(BitFieldModel):
    ready: bool = Bit(0)
    error: bool = Bit(1)

    struct_config = StructConfig(
        mode=StructMode.C_COMPATIBLE,
        bit_width=8  # Pack into a single byte
    )

Valid values for bit_width: 8, 16, or 32

Class Reference

StructConfig

Configuration for struct packing/unpacking.

Each model class gets its own independent configuration. Config values are set by creating a new StructConfig instance as a class variable.

Example

from pdc_struct import StructModel, StructConfig, StructMode, ByteOrder

class NetworkPacket(StructModel): ... sequence: int ... payload: bytes ... ... struct_config = StructConfig( ... mode=StructMode.C_COMPATIBLE, ... byte_order=ByteOrder.BIG_ENDIAN # Network byte order ... )

Attributes:

Name Type Description
mode

The serialization mode (C_COMPATIBLE or DYNAMIC).

version

Protocol version for DYNAMIC mode headers.

byte_order

Byte ordering for multi-byte values.

bit_width

Bit width for BitFieldModel (8, 16, or 32).

propagate_byte_order

Whether to apply byte order to nested structs.

metadata

Custom metadata dictionary for application use.

Source code in pdc_struct/models/struct_config.py
class StructConfig:
    """Configuration for struct packing/unpacking.

    Each model class gets its own independent configuration. Config values are set by
    creating a new StructConfig instance as a class variable.

    Example:
        >>> from pdc_struct import StructModel, StructConfig, StructMode, ByteOrder
        >>>
        >>> class NetworkPacket(StructModel):
        ...     sequence: int
        ...     payload: bytes
        ...
        ...     struct_config = StructConfig(
        ...         mode=StructMode.C_COMPATIBLE,
        ...         byte_order=ByteOrder.BIG_ENDIAN  # Network byte order
        ...     )

    Attributes:
        mode: The serialization mode (C_COMPATIBLE or DYNAMIC).
        version: Protocol version for DYNAMIC mode headers.
        byte_order: Byte ordering for multi-byte values.
        bit_width: Bit width for BitFieldModel (8, 16, or 32).
        propagate_byte_order: Whether to apply byte order to nested structs.
        metadata: Custom metadata dictionary for application use.
    """

    def __init__(
        self,
        mode: StructMode = StructMode.DYNAMIC,
        version: StructVersion = StructVersion.V1,
        byte_order: ByteOrder = (
            ByteOrder.LITTLE_ENDIAN
            if system_byte_order == "little"
            else ByteOrder.BIG_ENDIAN
        ),
        bit_width: Optional[int] = None,
        propagate_byte_order: bool = True,
        metadata: Dict[str, Any] = None,
    ):
        """Initialize a StructConfig with the specified options.

        Args:
            mode: Serialization mode. Use C_COMPATIBLE for fixed-size binary layouts
                compatible with C structs. Use DYNAMIC for variable-size formats with
                header metadata and optional field support. Defaults to DYNAMIC.
            version: Protocol version for DYNAMIC mode headers. Currently only V1 is
                supported. Defaults to V1.
            byte_order: Byte ordering (endianness) for multi-byte values like integers
                and floats. Defaults to the system's native byte order. For cross-platform
                compatibility, explicitly specify LITTLE_ENDIAN or BIG_ENDIAN.
            bit_width: Required for BitFieldModel classes. Specifies the packed integer
                size in bits. Must be 8, 16, or 32. Not used for StructModel classes.
            propagate_byte_order: If True, nested StructModel instances inherit the parent's
                byte order during serialization. Defaults to True.
            metadata: Optional dictionary for storing custom application-specific data.
                Not used by pdc_struct internally. Defaults to empty dict.

        Raises:
            ValueError: If bit_width is provided but not 8, 16, or 32.
        """
        self.mode = mode
        self.version = version
        self.byte_order = byte_order
        self.bit_width = bit_width
        self.metadata = metadata or {}
        self.propagate_byte_order = propagate_byte_order

        # Validate bit_width if provided
        if self.bit_width is not None and self.bit_width not in (8, 16, 32):
            raise ValueError("bit_width must be 8, 16, or 32")

__init__(mode=StructMode.DYNAMIC, version=StructVersion.V1, byte_order=ByteOrder.LITTLE_ENDIAN if system_byte_order == 'little' else ByteOrder.BIG_ENDIAN, bit_width=None, propagate_byte_order=True, metadata=None)

Initialize a StructConfig with the specified options.

Parameters:

Name Type Description Default
mode StructMode

Serialization mode. Use C_COMPATIBLE for fixed-size binary layouts compatible with C structs. Use DYNAMIC for variable-size formats with header metadata and optional field support. Defaults to DYNAMIC.

DYNAMIC
version StructVersion

Protocol version for DYNAMIC mode headers. Currently only V1 is supported. Defaults to V1.

V1
byte_order ByteOrder

Byte ordering (endianness) for multi-byte values like integers and floats. Defaults to the system's native byte order. For cross-platform compatibility, explicitly specify LITTLE_ENDIAN or BIG_ENDIAN.

LITTLE_ENDIAN if byteorder == 'little' else BIG_ENDIAN
bit_width Optional[int]

Required for BitFieldModel classes. Specifies the packed integer size in bits. Must be 8, 16, or 32. Not used for StructModel classes.

None
propagate_byte_order bool

If True, nested StructModel instances inherit the parent's byte order during serialization. Defaults to True.

True
metadata Dict[str, Any]

Optional dictionary for storing custom application-specific data. Not used by pdc_struct internally. Defaults to empty dict.

None

Raises:

Type Description
ValueError

If bit_width is provided but not 8, 16, or 32.

Source code in pdc_struct/models/struct_config.py
def __init__(
    self,
    mode: StructMode = StructMode.DYNAMIC,
    version: StructVersion = StructVersion.V1,
    byte_order: ByteOrder = (
        ByteOrder.LITTLE_ENDIAN
        if system_byte_order == "little"
        else ByteOrder.BIG_ENDIAN
    ),
    bit_width: Optional[int] = None,
    propagate_byte_order: bool = True,
    metadata: Dict[str, Any] = None,
):
    """Initialize a StructConfig with the specified options.

    Args:
        mode: Serialization mode. Use C_COMPATIBLE for fixed-size binary layouts
            compatible with C structs. Use DYNAMIC for variable-size formats with
            header metadata and optional field support. Defaults to DYNAMIC.
        version: Protocol version for DYNAMIC mode headers. Currently only V1 is
            supported. Defaults to V1.
        byte_order: Byte ordering (endianness) for multi-byte values like integers
            and floats. Defaults to the system's native byte order. For cross-platform
            compatibility, explicitly specify LITTLE_ENDIAN or BIG_ENDIAN.
        bit_width: Required for BitFieldModel classes. Specifies the packed integer
            size in bits. Must be 8, 16, or 32. Not used for StructModel classes.
        propagate_byte_order: If True, nested StructModel instances inherit the parent's
            byte order during serialization. Defaults to True.
        metadata: Optional dictionary for storing custom application-specific data.
            Not used by pdc_struct internally. Defaults to empty dict.

    Raises:
        ValueError: If bit_width is provided but not 8, 16, or 32.
    """
    self.mode = mode
    self.version = version
    self.byte_order = byte_order
    self.bit_width = bit_width
    self.metadata = metadata or {}
    self.propagate_byte_order = propagate_byte_order

    # Validate bit_width if provided
    if self.bit_width is not None and self.bit_width not in (8, 16, 32):
        raise ValueError("bit_width must be 8, 16, or 32")

See Also