Skip to main content

PDC Struct

Tests codecov PyPI version Python Version License: MIT

PDC Struct is a Pydantic extension that enables binary serialization of Pydantic models for efficient data exchange and C-compatible binary protocols. It combines Pydantic's powerful validation capabilities with Python's struct module to create a seamless bridge between high-level Python data models and low-level binary formats.

Features

  • 🔄 Two Operating Modes:
    • C-Compatible mode for direct interop with C structs
    • Dynamic mode for flexible Python-to-Python communication
  • 🛡️ Type Safety: Full Pydantic validation combined with struct packing rules
  • 🌍 Cross-Platform: Configurable endianness and alignment
  • 📦 Rich Type Support: Integers, floats, strings, enums, UUIDs, IP addresses and more
  • 🔍 Validation: Strong type checking and boundary validation
  • 🧪 Well-Tested: Comprehensive test suite covering edge cases

Installation

pip install pdc-struct

Or install from source:

pip install git+https://github.com/boxcake/pdc_struct.git

Requirements:

  • Python 3.11+
  • Pydantic 2.0+

Quick Start

Here's an example using PDC Struct to implement ARP (Address Resolution Protocol) packet handling:

from enum import IntEnum
from ipaddress import IPv4Address  
from pydantic import Field
from pdc_struct import StructModel, StructConfig, StructMode, ByteOrder
from pdc_struct.c_types import UInt8, UInt16

class HardwareType(IntEnum):
    """ARP Hardware Types"""
    ETHERNET = 1
    IEEE802 = 6
    ARCNET = 7 
    FRAME_RELAY = 15
    ATM = 16

class Operation(IntEnum):
    """ARP Operation Codes"""  
    REQUEST = 1
    REPLY = 2

class ARPPacket(StructModel):
    """ARP Packet Structure (RFC 826)"""
    
    hardware_type: HardwareType = Field(
        description="Hardware type"
    )
    
    protocol_type: UInt16 = Field(
        default=0x0800,  # IPv4
        description="Protocol type (0x0800 for IPv4)" 
    )
    
    hw_addr_len: UInt8 = Field(
        default=6,  # MAC address length
        description="Hardware address length"
    )
    proto_addr_len: UInt8 = Field(  
        default=4,  # IPv4 address length
        description="Protocol address length"
    )
    
    operation: Operation = Field(
        description="Operation code"
    )
    
    sender_hw_addr: bytes = Field(
        struct_length=6, 
        description="Sender hardware address (MAC)"
    )
    sender_proto_addr: IPv4Address = Field(
        description="Sender protocol address (IPv4)"
    )
    target_hw_addr: bytes = Field(
        struct_length=6,
        description="Target hardware address (MAC)"  
    )
    target_proto_addr: IPv4Address = Field(
        description="Target protocol address (IPv4)"
    )
    
    struct_config = StructConfig(
        mode=StructMode.C_COMPATIBLE,  # Fixed size for network protocol  
        byte_order=ByteOrder.BIG_ENDIAN  # Network byte order
    )

# Example usage
packet = ARPPacket(
    hardware_type=HardwareType.ETHERNET,
    operation=Operation.REQUEST,  
    sender_hw_addr=b'\x00\x11"3DUf',
    sender_proto_addr=IPv4Address('192.168.1.100'),
    target_hw_addr=b'\x00\x00\x00\x00\x00\x00', 
    target_proto_addr=IPv4Address('192.168.1.1')
)
binary_data = packet.to_bytes()

# Decode received data
received = ARPPacket.from_bytes(binary_data)
print(received.dict())

Core Classes

StructModel

Base class for binary-serializable models. Define fields and configuration:

class MyModel(StructModel):
    field1: int
    field2: str = Field(max_length=10)

    struct_config = StructConfig(...)

Class Methods:

  • struct_format_string() -> str: Returns the struct format string
  • struct_size() -> int: Returns the size in bytes of the packed structure
  • from_bytes(data: bytes) -> StructModel: Creates a model instance from bytes

Instance Methods:

  • to_bytes() -> bytes: Converts the model instance to bytes

StructConfig

Configuration for struct packing/unpacking behavior.

StructConfig(
    mode: StructMode = StructMode.DYNAMIC,  
    version: StructVersion = StructVersion.V1,
    byte_order: ByteOrder = ByteOrder.LITTLE_ENDIAN,
)

Parameters:

  • mode: Determines packing mode (C_COMPATIBLE or DYNAMIC)
  • version: Protocol version for future compatibility
  • byte_order: Byte ordering for numeric values

Operating Modes

C_COMPATIBLE Mode

Designed for interoperability with C structs:

  • Fixed struct size
  • Optional fields require defaults
  • Null-terminated strings
  • No headers or metadata

DYNAMIC Mode

Optimized for Python-to-Python communication:

  • Variable-length structures
    • Truly optional fields (no defaults required)
    • Efficient bitmap field tracking
    • Version headers for compatibility

Type System

PDC Struct supports key Python types:

Python Type Struct Format Size
int 'i' 4 bytes
float 'd' 8 bytes
bool '?' 1 byte
str 's' Varies
bytes 's' Varies
Enum 'i' 4 bytes
IPv4Address '4s' 4 bytes
IPv6Address '16s' 16 bytes
UUID '16s' 16 bytes

Fixed-width integer types are also available:

  • Int8, UInt8, Int16, UInt16

Error Handling

PDC Struct provides specific exceptions:

  • StructPackError: Serialization errors
    • StructUnpackError: Deserialization errors

Contributing

Contributions are welcome! Please submit issues and pull requests on GitHub.

License

PDC Struct is open source, licensed under the MIT License.

Metadata

Release files for pdc-struct 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pdc-struct 1.0.0
File Size Uploaded
pdc_struct-1.0.0.tar.gz 90.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pdc-struct 1.0.0
File Interpreter ABI Platform
pdc_struct-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 124.4 kB

Release files / pdc_struct-1.0.0.tar.gz

Download URL pdc_struct-1.0.0.tar.gz
Size 90.6 kB
Tags Source
SHA-256 checksum
How to use checksums
e3c6370ccbd9c9c2bc8397fbbd3c397680f6c2df7dec0c40c85367312b0f45b6
BLAKE2b-256 checksum
How to use checksums
ff3af701999cfa7f9a937a6d54f33e468a66ac6d88389e252ecf2e4ad7e1568f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jan 15, 2026.

Transparency log

Release files / pdc_struct-1.0.0-py3-none-any.whl

Download URL pdc_struct-1.0.0-py3-none-any.whl
Size 33.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b9d9960027d09e18c484f02eb48058932b2475bc819f932136708065aad23795
BLAKE2b-256 checksum
How to use checksums
813048b8e54a9fa878350ce088f1bdb9fe5b9f47da8a9255effbcc267b4881d4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jan 15, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page